Clang Project

clang_source_code/unittests/Tooling/RefactoringTest.cpp
1//===- unittest/Tooling/RefactoringTest.cpp - Refactoring unit tests ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Tooling/Refactoring.h"
10#include "ReplacementTest.h"
11#include "RewriterTestContext.h"
12#include "clang/AST/ASTConsumer.h"
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/DeclCXX.h"
15#include "clang/AST/DeclGroup.h"
16#include "clang/AST/RecursiveASTVisitor.h"
17#include "clang/Basic/Diagnostic.h"
18#include "clang/Basic/DiagnosticOptions.h"
19#include "clang/Basic/FileManager.h"
20#include "clang/Basic/LangOptions.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/Format/Format.h"
23#include "clang/Frontend/CompilerInstance.h"
24#include "clang/Frontend/FrontendAction.h"
25#include "clang/Frontend/TextDiagnosticPrinter.h"
26#include "clang/Rewrite/Core/Rewriter.h"
27#include "clang/Tooling/Refactoring/AtomicChange.h"
28#include "clang/Tooling/Tooling.h"
29#include "llvm/ADT/SmallString.h"
30#include "llvm/Support/VirtualFileSystem.h"
31#include "gtest/gtest.h"
32
33namespace clang {
34namespace tooling {
35
36TEST_F(ReplacementTest, CanDeleteAllText) {
37  FileID ID = Context.createInMemoryFile("input.cpp", "text");
38  SourceLocation Location = Context.getLocation(ID, 1, 1);
39  Replacement Replace(createReplacement(Location, 4, ""));
40  EXPECT_TRUE(Replace.apply(Context.Rewrite));
41  EXPECT_EQ("", Context.getRewrittenText(ID));
42}
43
44TEST_F(ReplacementTest, CanDeleteAllTextInTextWithNewlines) {
45  FileID ID = Context.createInMemoryFile("input.cpp", "line1\nline2\nline3");
46  SourceLocation Location = Context.getLocation(ID, 1, 1);
47  Replacement Replace(createReplacement(Location, 17, ""));
48  EXPECT_TRUE(Replace.apply(Context.Rewrite));
49  EXPECT_EQ("", Context.getRewrittenText(ID));
50}
51
52TEST_F(ReplacementTest, CanAddText) {
53  FileID ID = Context.createInMemoryFile("input.cpp", "");
54  SourceLocation Location = Context.getLocation(ID, 1, 1);
55  Replacement Replace(createReplacement(Location, 0, "result"));
56  EXPECT_TRUE(Replace.apply(Context.Rewrite));
57  EXPECT_EQ("result", Context.getRewrittenText(ID));
58}
59
60TEST_F(ReplacementTest, CanReplaceTextAtPosition) {
61  FileID ID = Context.createInMemoryFile("input.cpp",
62                                         "line1\nline2\nline3\nline4");
63  SourceLocation Location = Context.getLocation(ID, 2, 3);
64  Replacement Replace(createReplacement(Location, 12, "x"));
65  EXPECT_TRUE(Replace.apply(Context.Rewrite));
66  EXPECT_EQ("line1\nlixne4", Context.getRewrittenText(ID));
67}
68
69TEST_F(ReplacementTest, CanReplaceTextAtPositionMultipleTimes) {
70  FileID ID = Context.createInMemoryFile("input.cpp",
71                                         "line1\nline2\nline3\nline4");
72  SourceLocation Location1 = Context.getLocation(ID, 2, 3);
73  Replacement Replace1(createReplacement(Location1, 12, "x\ny\n"));
74  EXPECT_TRUE(Replace1.apply(Context.Rewrite));
75  EXPECT_EQ("line1\nlix\ny\nne4", Context.getRewrittenText(ID));
76
77  // Since the original source has not been modified, the (4, 4) points to the
78  // 'e' in the original content.
79  SourceLocation Location2 = Context.getLocation(ID, 4, 4);
80  Replacement Replace2(createReplacement(Location2, 1, "f"));
81  EXPECT_TRUE(Replace2.apply(Context.Rewrite));
82  EXPECT_EQ("line1\nlix\ny\nnf4", Context.getRewrittenText(ID));
83}
84
85TEST_F(ReplacementTest, ApplyFailsForNonExistentLocation) {
86  Replacement Replace("nonexistent-file.cpp", 0, 1, "");
87  EXPECT_FALSE(Replace.apply(Context.Rewrite));
88}
89
90TEST_F(ReplacementTest, CanRetrivePath) {
91  Replacement Replace("/path/to/file.cpp", 0, 1, "");
92  EXPECT_EQ("/path/to/file.cpp", Replace.getFilePath());
93}
94
95TEST_F(ReplacementTest, ReturnsInvalidPath) {
96  Replacement Replace1(Context.Sources, SourceLocation(), 0, "");
97  EXPECT_TRUE(Replace1.getFilePath().empty());
98
99  Replacement Replace2;
100  EXPECT_TRUE(Replace2.getFilePath().empty());
101}
102
103// Checks that an llvm::Error instance contains a ReplacementError with expected
104// error code, expected new replacement, and expected existing replacement.
105static bool checkReplacementError(llvm::Error &&Error,
106                                  replacement_error ExpectedErr,
107                                  llvm::Optional<Replacement> ExpectedExisting,
108                                  llvm::Optional<Replacement> ExpectedNew) {
109  if (!Error) {
110    llvm::errs() << "Error is a success.";
111    return false;
112  }
113  std::string ErrorMessage;
114  llvm::raw_string_ostream OS(ErrorMessage);
115  llvm::handleAllErrors(std::move(Error), [&](const ReplacementError &RE) {
116    llvm::errs() << "Handling error...\n";
117    if (ExpectedErr != RE.get())
118      OS << "Unexpected error code: " << int(RE.get()) << "\n";
119    if (ExpectedExisting != RE.getExistingReplacement()) {
120      OS << "Expected Existing != Actual Existing.\n";
121      if (ExpectedExisting.hasValue())
122        OS << "Expected existing replacement: " << ExpectedExisting->toString()
123           << "\n";
124      if (RE.getExistingReplacement().hasValue())
125        OS << "Actual existing replacement: "
126           << RE.getExistingReplacement()->toString() << "\n";
127    }
128    if (ExpectedNew != RE.getNewReplacement()) {
129      OS << "Expected New != Actual New.\n";
130      if (ExpectedNew.hasValue())
131        OS << "Expected new replacement: " << ExpectedNew->toString() << "\n";
132      if (RE.getNewReplacement().hasValue())
133        OS << "Actual new replacement: " << RE.getNewReplacement()->toString()
134           << "\n";
135    }
136  });
137  OS.flush();
138  if (ErrorMessage.empty()) return true;
139  llvm::errs() << ErrorMessage;
140  return false;
141}
142
143TEST_F(ReplacementTest, FailAddReplacements) {
144  Replacements Replaces;
145  Replacement Deletion("x.cc", 0, 10, "3");
146  auto Err = Replaces.add(Deletion);
147  EXPECT_TRUE(!Err);
148  llvm::consumeError(std::move(Err));
149
150  Replacement OverlappingReplacement("x.cc", 0, 2, "a");
151  Err = Replaces.add(OverlappingReplacement);
152  EXPECT_TRUE(checkReplacementError(std::move(Err),
153                                    replacement_error::overlap_conflict,
154                                    Deletion, OverlappingReplacement));
155
156  Replacement ContainedReplacement("x.cc", 2, 2, "a");
157  Err = Replaces.add(Replacement(ContainedReplacement));
158  EXPECT_TRUE(checkReplacementError(std::move(Err),
159                                    replacement_error::overlap_conflict,
160                                    Deletion, ContainedReplacement));
161
162  Replacement WrongPathReplacement("y.cc", 20, 2, "");
163  Err = Replaces.add(WrongPathReplacement);
164  EXPECT_TRUE(checkReplacementError(std::move(Err),
165                                    replacement_error::wrong_file_path,
166                                    Deletion, WrongPathReplacement));
167
168  EXPECT_EQ(1u, Replaces.size());
169  EXPECT_EQ(Deletion, *Replaces.begin());
170}
171
172TEST_F(ReplacementTest, DeletionInReplacements) {
173  Replacements Replaces;
174  Replacement R("x.cc", 0, 10, "3");
175  auto Err = Replaces.add(R);
176  EXPECT_TRUE(!Err);
177  llvm::consumeError(std::move(Err));
178  Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
179  EXPECT_TRUE(!Err);
180  llvm::consumeError(std::move(Err));
181  Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
182  EXPECT_TRUE(!Err);
183  llvm::consumeError(std::move(Err));
184  EXPECT_EQ(1u, Replaces.size());
185  EXPECT_EQ(R, *Replaces.begin());
186}
187
188TEST_F(ReplacementTest, OverlappingReplacements) {
189  Replacements Replaces;
190  auto Err = Replaces.add(Replacement("x.cc", 0, 3, "345"));
191  EXPECT_TRUE(!Err);
192  llvm::consumeError(std::move(Err));
193  Err = Replaces.add(Replacement("x.cc", 2, 3, "543"));
194  EXPECT_TRUE(!Err);
195  llvm::consumeError(std::move(Err));
196
197  EXPECT_EQ(1u, Replaces.size());
198  EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
199
200  Err = Replaces.add(Replacement("x.cc", 2, 1, "5"));
201  EXPECT_TRUE(!Err);
202  llvm::consumeError(std::move(Err));
203  EXPECT_EQ(1u, Replaces.size());
204  EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
205}
206
207TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {
208  Replacements Replaces;
209  // Test adding an insertion at the offset of an existing replacement.
210  auto Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
211  EXPECT_TRUE(!Err);
212  llvm::consumeError(std::move(Err));
213  Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
214  EXPECT_TRUE(!Err);
215  llvm::consumeError(std::move(Err));
216  EXPECT_EQ(Replaces.size(), 2u);
217
218  Replaces.clear();
219  // Test overlap with an existing insertion.
220  Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
221  EXPECT_TRUE(!Err);
222  llvm::consumeError(std::move(Err));
223  Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
224  EXPECT_TRUE(!Err);
225  llvm::consumeError(std::move(Err));
226  EXPECT_EQ(Replaces.size(), 2u);
227}
228
229TEST_F(ReplacementTest, MergeNewDeletions) {
230  Replacements Replaces;
231  Replacement ContainingReplacement("x.cc", 0, 10, "");
232  auto Err = Replaces.add(ContainingReplacement);
233  EXPECT_TRUE(!Err);
234  llvm::consumeError(std::move(Err));
235
236  Err = Replaces.add(Replacement("x.cc", 5, 3, ""));
237  EXPECT_TRUE(!Err);
238  llvm::consumeError(std::move(Err));
239
240  Err = Replaces.add(Replacement("x.cc", 0, 10, ""));
241  EXPECT_TRUE(!Err);
242  llvm::consumeError(std::move(Err));
243
244  Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
245  EXPECT_TRUE(!Err);
246  llvm::consumeError(std::move(Err));
247
248  EXPECT_EQ(1u, Replaces.size());
249  EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
250}
251
252TEST_F(ReplacementTest, MergeOverlappingButNotAdjacentReplacement) {
253  Replacements Replaces;
254  auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
255  EXPECT_TRUE(!Err);
256  llvm::consumeError(std::move(Err));
257
258  Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
259  EXPECT_TRUE(!Err);
260  llvm::consumeError(std::move(Err));
261
262  Replacement After = Replacement("x.cc", 10, 5, "");
263  Err = Replaces.add(After);
264  EXPECT_TRUE(!Err);
265  llvm::consumeError(std::move(Err));
266
267  Replacement ContainingReplacement("x.cc", 0, 10, "");
268  Err = Replaces.add(ContainingReplacement);
269  EXPECT_TRUE(!Err);
270  llvm::consumeError(std::move(Err));
271
272  EXPECT_EQ(2u, Replaces.size());
273  EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
274  EXPECT_EQ(*(++Replaces.begin()), After);
275}
276
277TEST_F(ReplacementTest, InsertionBeforeMergedDeletions) {
278  Replacements Replaces;
279
280  Replacement Insertion("x.cc", 0, 0, "123");
281  auto Err = Replaces.add(Insertion);
282  EXPECT_TRUE(!Err);
283  llvm::consumeError(std::move(Err));
284
285  Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
286  EXPECT_TRUE(!Err);
287  llvm::consumeError(std::move(Err));
288
289  Replacement Deletion("x.cc", 0, 10, "");
290  Err = Replaces.add(Deletion);
291  EXPECT_TRUE(!Err);
292  llvm::consumeError(std::move(Err));
293
294  EXPECT_EQ(2u, Replaces.size());
295  EXPECT_EQ(*Replaces.begin(), Insertion);
296  EXPECT_EQ(*(++Replaces.begin()), Deletion);
297}
298
299TEST_F(ReplacementTest, MergeOverlappingDeletions) {
300  Replacements Replaces;
301  auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
302  EXPECT_TRUE(!Err);
303  llvm::consumeError(std::move(Err));
304
305  Err = Replaces.add(Replacement("x.cc", 0, 5, ""));
306  EXPECT_TRUE(!Err);
307  llvm::consumeError(std::move(Err));
308
309  EXPECT_EQ(1u, Replaces.size());
310  EXPECT_EQ(Replacement("x.cc", 0, 5, ""), *Replaces.begin());
311
312  Err = Replaces.add(Replacement("x.cc", 1, 5, ""));
313  EXPECT_TRUE(!Err);
314  llvm::consumeError(std::move(Err));
315  EXPECT_EQ(1u, Replaces.size());
316  EXPECT_EQ(Replacement("x.cc", 0, 6, ""), *Replaces.begin());
317}
318
319TEST_F(ReplacementTest, FailedMergeExistingDeletions) {
320  Replacements Replaces;
321  Replacement First("x.cc", 0, 2, "");
322  auto Err = Replaces.add(First);
323  EXPECT_TRUE(!Err);
324  llvm::consumeError(std::move(Err));
325
326  Replacement Second("x.cc", 5, 5, "");
327  Err = Replaces.add(Second);
328  EXPECT_TRUE(!Err);
329  llvm::consumeError(std::move(Err));
330
331  Err = Replaces.add(Replacement("x.cc", 1, 10, ""));
332  EXPECT_TRUE(!Err);
333  llvm::consumeError(std::move(Err));
334
335  EXPECT_EQ(1u, Replaces.size());
336  EXPECT_EQ(Replacement("x.cc", 0, 11, ""), *Replaces.begin());
337}
338
339TEST_F(ReplacementTest, FailAddRegression) {
340  Replacements Replaces;
341  // Create two replacements, where the second one is an insertion of the empty
342  // string exactly at the end of the first one.
343  auto Err = Replaces.add(Replacement("x.cc", 0, 10, "1"));
344  EXPECT_TRUE(!Err);
345  llvm::consumeError(std::move(Err));
346  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
347  EXPECT_TRUE(!Err);
348  llvm::consumeError(std::move(Err));
349
350  // Make sure we find the overlap with the first entry when inserting a
351  // replacement that ends exactly at the seam of the existing replacements.
352  Replacement OverlappingReplacement("x.cc", 5, 5, "fail");
353  Err = Replaces.add(OverlappingReplacement);
354  EXPECT_TRUE(checkReplacementError(std::move(Err),
355                                    replacement_error::overlap_conflict,
356                                    *Replaces.begin(), OverlappingReplacement));
357
358  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
359  EXPECT_TRUE(!Err);
360  llvm::consumeError(std::move(Err));
361}
362
363TEST_F(ReplacementTest, InsertAtOffsetOfReplacement) {
364  Replacements Replaces;
365  auto Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
366  EXPECT_TRUE(!Err);
367  llvm::consumeError(std::move(Err));
368  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
369  EXPECT_TRUE(!Err);
370  llvm::consumeError(std::move(Err));
371  EXPECT_EQ(Replaces.size(), 2u);
372
373  Replaces.clear();
374  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
375  EXPECT_TRUE(!Err);
376  llvm::consumeError(std::move(Err));
377  Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
378  EXPECT_TRUE(!Err);
379  llvm::consumeError(std::move(Err));
380  EXPECT_EQ(Replaces.size(), 2u);
381}
382
383TEST_F(ReplacementTest, AddInsertAtOtherInsertWhenOderIndependent) {
384  Replacements Replaces;
385  auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
386  EXPECT_TRUE(!Err);
387  llvm::consumeError(std::move(Err));
388  Replacement ConflictInsertion("x.cc", 10, 0, "b");
389  Err = Replaces.add(ConflictInsertion);
390  EXPECT_TRUE(checkReplacementError(std::move(Err),
391                                    replacement_error::insert_conflict,
392                                    *Replaces.begin(), ConflictInsertion));
393
394  Replaces.clear();
395  Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
396  EXPECT_TRUE(!Err);
397  llvm::consumeError(std::move(Err));
398  Err = Replaces.add(Replacement("x.cc", 10, 0, "aa"));
399  EXPECT_TRUE(!Err);
400  llvm::consumeError(std::move(Err));
401  EXPECT_EQ(1u, Replaces.size());
402  EXPECT_EQ(Replacement("x.cc", 10, 0, "aaa"), *Replaces.begin());
403
404  Replaces.clear();
405  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
406  EXPECT_TRUE(!Err);
407  llvm::consumeError(std::move(Err));
408  Err = Replaces.add(Replacement("x.cc", 10, 3, ""));
409  EXPECT_TRUE(!Err);
410  llvm::consumeError(std::move(Err));
411  Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
412  EXPECT_TRUE(!Err);
413  llvm::consumeError(std::move(Err));
414  EXPECT_EQ(2u, Replaces.size());
415  EXPECT_EQ(Replacement("x.cc", 10, 0, ""), *Replaces.begin());
416  EXPECT_EQ(Replacement("x.cc", 10, 3, ""), *std::next(Replaces.begin()));
417}
418
419TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {
420  Replacements Replaces;
421  auto Err = Replaces.add(Replacement("x.cc", 10, 5, "a"));
422  EXPECT_TRUE(!Err);
423  llvm::consumeError(std::move(Err));
424  Err = Replaces.add(Replacement("x.cc", 8, 2, "a"));
425  EXPECT_TRUE(!Err);
426  llvm::consumeError(std::move(Err));
427  Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
428  EXPECT_TRUE(!Err);
429  llvm::consumeError(std::move(Err));
430}
431
432TEST_F(ReplacementTest, CanApplyReplacements) {
433  FileID ID = Context.createInMemoryFile("input.cpp",
434                                         "line1\nline2\nline3\nline4");
435  Replacements Replaces =
436      toReplacements({Replacement(Context.Sources,
437                                  Context.getLocation(ID, 2, 1), 5, "replaced"),
438                      Replacement(Context.Sources,
439                                  Context.getLocation(ID, 3, 1), 5, "other")});
440  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
441  EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
442}
443
444// Verifies that replacement/deletion is applied before insertion at the same
445// offset.
446TEST_F(ReplacementTest, InsertAndDelete) {
447  FileID ID = Context.createInMemoryFile("input.cpp",
448                                         "line1\nline2\nline3\nline4");
449  Replacements Replaces = toReplacements(
450      {Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 6, ""),
451       Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 0,
452                   "other\n")});
453  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
454  EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
455}
456
457TEST_F(ReplacementTest, AdjacentReplacements) {
458  FileID ID = Context.createInMemoryFile("input.cpp",
459                                         "ab");
460  Replacements Replaces = toReplacements(
461      {Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 1, "x"),
462       Replacement(Context.Sources, Context.getLocation(ID, 1, 2), 1, "y")});
463  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
464  EXPECT_EQ("xy", Context.getRewrittenText(ID));
465}
466
467TEST_F(ReplacementTest, AddDuplicateReplacements) {
468  FileID ID = Context.createInMemoryFile("input.cpp",
469                                         "line1\nline2\nline3\nline4");
470  auto Replaces = toReplacements({Replacement(
471      Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
472
473  auto Err = Replaces.add(Replacement(
474      Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));
475  EXPECT_TRUE(!Err);
476  llvm::consumeError(std::move(Err));
477
478  Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
479                                 5, "replaced"));
480  EXPECT_TRUE(!Err);
481  llvm::consumeError(std::move(Err));
482
483  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
484  EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
485}
486
487TEST_F(ReplacementTest, FailOrderDependentReplacements) {
488  FileID ID = Context.createInMemoryFile("input.cpp",
489                                         "line1\nline2\nline3\nline4");
490  auto Replaces = toReplacements({Replacement(
491      Context.Sources, Context.getLocation(ID, 2, 1), 5, "other")});
492
493  Replacement ConflictReplacement(Context.Sources,
494                                  Context.getLocation(ID, 2, 1), 5, "rehto");
495  auto Err = Replaces.add(ConflictReplacement);
496  EXPECT_TRUE(checkReplacementError(std::move(Err),
497                                    replacement_error::overlap_conflict,
498                                    *Replaces.begin(), ConflictReplacement));
499
500  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
501  EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
502}
503
504TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {
505  Replacements Replaces =
506      toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});
507
508  EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
509}
510
511TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
512  // Column limit is 20.
513  std::string Code1 = "Long *a =\n"
514                      "    new Long();\n"
515                      "long x = 1;";
516  std::string Expected1 = "auto a = new Long();\n"
517                          "long x =\n"
518                          "    12345678901;";
519  std::string Code2 = "int x = 123;\n"
520                      "int y = 0;";
521  std::string Expected2 = "int x =\n"
522                          "    1234567890123;\n"
523                          "int y = 10;";
524  StringRef File1 = "format_1.cpp";
525  StringRef File2 = "format_2.cpp";
526  FileID ID1 = Context.createInMemoryFile(File1, Code1);
527  FileID ID2 = Context.createInMemoryFile(File2, Code2);
528
529  // Scrambled the order of replacements.
530  std::map<std::string, Replacements> FileToReplaces;
531  FileToReplaces[File1] = toReplacements(
532      {tooling::Replacement(Context.Sources, Context.getLocation(ID1, 1, 1), 6,
533                            "auto "),
534       tooling::Replacement(Context.Sources, Context.getLocation(ID1, 3, 10), 1,
535                            "12345678901")});
536  FileToReplaces[File2] = toReplacements(
537      {tooling::Replacement(Context.Sources, Context.getLocation(ID2, 1, 12), 0,
538                            "4567890123"),
539       tooling::Replacement(Context.Sources, Context.getLocation(ID2, 2, 9), 1,
540                            "10")});
541  EXPECT_TRUE(
542      formatAndApplyAllReplacements(FileToReplaces, Context.Rewrite,
543                                    "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
544  EXPECT_EQ(Expected1, Context.getRewrittenText(ID1));
545  EXPECT_EQ(Expected2, Context.getRewrittenText(ID2));
546}
547
548TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
549  Replacements Replaces =
550      toReplacements({Replacement("", 0, 1, ""), Replacement("", 4, 3, " ")});
551  // Assume ' int   i;' is turned into 'int i;' and cursor is located at '|'.
552  EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0)); // |int   i;
553  EXPECT_EQ(0u, Replaces.getShiftedCodePosition(1)); //  |nt   i;
554  EXPECT_EQ(1u, Replaces.getShiftedCodePosition(2)); //  i|t   i;
555  EXPECT_EQ(2u, Replaces.getShiftedCodePosition(3)); //  in|   i;
556  EXPECT_EQ(3u, Replaces.getShiftedCodePosition(4)); //  int|  i;
557  EXPECT_EQ(3u, Replaces.getShiftedCodePosition(5)); //  int | i;
558  EXPECT_EQ(3u, Replaces.getShiftedCodePosition(6)); //  int  |i;
559  EXPECT_EQ(4u, Replaces.getShiftedCodePosition(7)); //  int   |;
560  EXPECT_EQ(5u, Replaces.getShiftedCodePosition(8)); //  int   i|
561}
562
563TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
564  Replacements Replaces = toReplacements({Replacement("", 4, 0, "\"\n\"")});
565  // Assume '"12345678"' is turned into '"1234"\n"5678"'.
566  EXPECT_EQ(3u, Replaces.getShiftedCodePosition(3)); // "123|5678"
567  EXPECT_EQ(7u, Replaces.getShiftedCodePosition(4)); // "1234|678"
568  EXPECT_EQ(8u, Replaces.getShiftedCodePosition(5)); // "12345|78"
569}
570
571TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
572  // Replace the first four characters with "abcd".
573  auto Replaces = toReplacements({Replacement("", 0, 4, "abcd")});
574  for (unsigned i = 0; i < 3; ++i)
575    EXPECT_EQ(i, Replaces.getShiftedCodePosition(i));
576}
577
578TEST(ShiftedCodePositionTest, NoReplacementText) {
579  Replacements Replaces = toReplacements({Replacement("", 0, 42, "")});
580  EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0));
581  EXPECT_EQ(0u, Replaces.getShiftedCodePosition(39));
582  EXPECT_EQ(3u, Replaces.getShiftedCodePosition(45));
583  EXPECT_EQ(0u, Replaces.getShiftedCodePosition(42));
584}
585
586class FlushRewrittenFilesTest : public ::testing::Test {
587public:
588   FlushRewrittenFilesTest() {}
589
590   ~FlushRewrittenFilesTest() override {
591    for (llvm::StringMap<std::string>::iterator I = TemporaryFiles.begin(),
592                                                E = TemporaryFiles.end();
593         I != E; ++I) {
594      llvm::StringRef Name = I->second;
595      std::error_code EC = llvm::sys::fs::remove(Name);
596      (void)EC;
597      assert(!EC);
598    }
599  }
600
601  FileID createFile(llvm::StringRef Name, llvm::StringRef Content) {
602    SmallString<1024> Path;
603    int FD;
604    std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
605    assert(!EC);
606    (void)EC;
607
608    llvm::raw_fd_ostream OutStream(FD, true);
609    OutStream << Content;
610    OutStream.close();
611    const FileEntry *File = Context.Files.getFile(Path);
612    assert(File != nullptr);
613
614    StringRef Found =
615        TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
616    assert(Found == Path);
617    (void)Found;
618    return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
619  }
620
621  std::string getFileContentFromDisk(llvm::StringRef Name) {
622    std::string Path = TemporaryFiles.lookup(Name);
623    assert(!Path.empty());
624    // We need to read directly from the FileManager without relaying through
625    // a FileEntry, as otherwise we'd read through an already opened file
626    // descriptor, which might not see the changes made.
627    // FIXME: Figure out whether there is a way to get the SourceManger to
628    // reopen the file.
629    auto FileBuffer = Context.Files.getBufferForFile(Path);
630    return (*FileBuffer)->getBuffer();
631  }
632
633  llvm::StringMap<std::string> TemporaryFiles;
634  RewriterTestContext Context;
635};
636
637TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
638  FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
639  Replacements Replaces = toReplacements({Replacement(
640      Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
641  EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
642  EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
643  EXPECT_EQ("line1\nreplaced\nline3\nline4",
644            getFileContentFromDisk("input.cpp"));
645}
646
647namespace {
648template <typename T>
649class TestVisitor : public clang::RecursiveASTVisitor<T> {
650public:
651  bool runOver(StringRef Code) {
652    return runToolOnCode(new TestAction(this), Code);
653  }
654
655protected:
656  clang::SourceManager *SM;
657  clang::ASTContext *Context;
658
659private:
660  class FindConsumer : public clang::ASTConsumer {
661  public:
662    FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}
663
664    void HandleTranslationUnit(clang::ASTContext &Context) override {
665      Visitor->TraverseDecl(Context.getTranslationUnitDecl());
666    }
667
668  private:
669    TestVisitor *Visitor;
670  };
671
672  class TestAction : public clang::ASTFrontendAction {
673  public:
674    TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}
675
676    std::unique_ptr<clang::ASTConsumer>
677    CreateASTConsumer(clang::CompilerInstance &compiler,
678                      llvm::StringRef dummy) override {
679      Visitor->SM = &compiler.getSourceManager();
680      Visitor->Context = &compiler.getASTContext();
681      /// TestConsumer will be deleted by the framework calling us.
682      return llvm::make_unique<FindConsumer>(Visitor);
683    }
684
685  private:
686    TestVisitor *Visitor;
687  };
688};
689} // end namespace
690
691void expectReplacementAt(const Replacement &Replace,
692                         StringRef File, unsigned Offset, unsigned Length) {
693  ASSERT_TRUE(Replace.isApplicable());
694  EXPECT_EQ(File, Replace.getFilePath());
695  EXPECT_EQ(Offset, Replace.getOffset());
696  EXPECT_EQ(Length, Replace.getLength());
697}
698
699class ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> {
700public:
701  bool VisitCXXRecordDecl(CXXRecordDecl *Record) {
702    if (Record->getName() == "X") {
703      Replace = Replacement(*SM, Record, "");
704    }
705    return true;
706  }
707  Replacement Replace;
708};
709
710TEST(Replacement, CanBeConstructedFromNode) {
711  ClassDeclXVisitor ClassDeclX;
712  EXPECT_TRUE(ClassDeclX.runOver("     class X;"));
713  expectReplacementAt(ClassDeclX.Replace, "input.cc", 5, 7);
714}
715
716TEST(Replacement, ReplacesAtSpellingLocation) {
717  ClassDeclXVisitor ClassDeclX;
718  EXPECT_TRUE(ClassDeclX.runOver("#define A(Y) Y\nA(class X);"));
719  expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7);
720}
721
722class CallToFVisitor : public TestVisitor<CallToFVisitor> {
723public:
724  bool VisitCallExpr(CallExpr *Call) {
725    if (Call->getDirectCallee()->getName() == "F") {
726      Replace = Replacement(*SM, Call, "");
727    }
728    return true;
729  }
730  Replacement Replace;
731};
732
733TEST(Replacement, FunctionCall) {
734  CallToFVisitor CallToF;
735  EXPECT_TRUE(CallToF.runOver("void F(); void G() { F(); }"));
736  expectReplacementAt(CallToF.Replace, "input.cc", 21, 3);
737}
738
739TEST(Replacement, TemplatedFunctionCall) {
740  CallToFVisitor CallToF;
741  EXPECT_TRUE(CallToF.runOver(
742        "template <typename T> void F(); void G() { F<int>(); }"));
743  expectReplacementAt(CallToF.Replace, "input.cc", 43, 8);
744}
745
746class NestedNameSpecifierAVisitor
747    : public TestVisitor<NestedNameSpecifierAVisitor> {
748public:
749  bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) {
750    if (NNSLoc.getNestedNameSpecifier()) {
751      if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) {
752        if (NS->getName() == "a") {
753          Replace = Replacement(*SM, &NNSLoc, "", Context->getLangOpts());
754        }
755      }
756    }
757    return TestVisitor<NestedNameSpecifierAVisitor>::TraverseNestedNameSpecifierLoc(
758        NNSLoc);
759  }
760  Replacement Replace;
761};
762
763TEST(Replacement, ColonColon) {
764  NestedNameSpecifierAVisitor VisitNNSA;
765  EXPECT_TRUE(VisitNNSA.runOver("namespace a { void f() { ::a::f(); } }"));
766  expectReplacementAt(VisitNNSA.Replace, "input.cc", 25, 5);
767}
768
769TEST(Range, overlaps) {
770  EXPECT_TRUE(Range(10, 10).overlapsWith(Range(0, 11)));
771  EXPECT_TRUE(Range(0, 11).overlapsWith(Range(10, 10)));
772  EXPECT_FALSE(Range(10, 10).overlapsWith(Range(0, 10)));
773  EXPECT_FALSE(Range(0, 10).overlapsWith(Range(10, 10)));
774  EXPECT_TRUE(Range(0, 10).overlapsWith(Range(2, 6)));
775  EXPECT_TRUE(Range(2, 6).overlapsWith(Range(0, 10)));
776}
777
778TEST(Range, contains) {
779  EXPECT_TRUE(Range(0, 10).contains(Range(0, 10)));
780  EXPECT_TRUE(Range(0, 10).contains(Range(2, 6)));
781  EXPECT_FALSE(Range(2, 6).contains(Range(0, 10)));
782  EXPECT_FALSE(Range(0, 10).contains(Range(0, 11)));
783}
784
785TEST(Range, CalculateRangesOfReplacements) {
786  // Before: aaaabbbbbbz
787  // After : bbbbbbzzzzzzoooooooooooooooo
788  Replacements Replaces = toReplacements(
789      {Replacement("foo", 0, 4, ""), Replacement("foo", 10, 1, "zzzzzz"),
790       Replacement("foo", 11, 0, "oooooooooooooooo")});
791
792  std::vector<Range> Ranges = Replaces.getAffectedRanges();
793
794  EXPECT_EQ(2ul, Ranges.size());
795  EXPECT_TRUE(Ranges[0].getOffset() == 0);
796  EXPECT_TRUE(Ranges[0].getLength() == 0);
797  EXPECT_TRUE(Ranges[1].getOffset() == 6);
798  EXPECT_TRUE(Ranges[1].getLength() == 22);
799}
800
801TEST(Range, CalculateRangesOfInsertionAroundReplacement) {
802  Replacements Replaces = toReplacements(
803      {Replacement("foo", 0, 2, ""), Replacement("foo", 0, 0, "ba")});
804
805  std::vector<Range> Ranges = Replaces.getAffectedRanges();
806
807  EXPECT_EQ(1ul, Ranges.size());
808  EXPECT_EQ(0u, Ranges[0].getOffset());
809  EXPECT_EQ(2u, Ranges[0].getLength());
810}
811
812TEST(Range, RangesAfterEmptyReplacements) {
813  std::vector<Range> Ranges = {Range(5, 6), Range(10, 5)};
814  Replacements Replaces;
815  std::vector<Range> Expected = {Range(5, 10)};
816  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
817}
818
819TEST(Range, RangesAfterReplacements) {
820  std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
821  Replacements Replaces = toReplacements({Replacement("foo", 0, 2, "1234")});
822  std::vector<Range> Expected = {Range(0, 4), Range(7, 2), Range(12, 5)};
823  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
824}
825
826TEST(Range, RangesBeforeReplacements) {
827  std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
828  Replacements Replaces = toReplacements({Replacement("foo", 20, 2, "1234")});
829  std::vector<Range> Expected = {Range(5, 2), Range(10, 5), Range(20, 4)};
830  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
831}
832
833TEST(Range, NotAffectedByReplacements) {
834  std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
835  Replacements Replaces = toReplacements({Replacement("foo", 3, 2, "12"),
836                                          Replacement("foo", 12, 2, "12"),
837                                          Replacement("foo", 20, 5, "")});
838  std::vector<Range> Expected = {Range(0, 2), Range(3, 4), Range(10, 5),
839                                 Range(20, 0)};
840  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
841}
842
843TEST(Range, RangesWithNonOverlappingReplacements) {
844  std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
845  Replacements Replaces = toReplacements({Replacement("foo", 3, 1, ""),
846                                          Replacement("foo", 6, 1, "123"),
847                                          Replacement("foo", 20, 2, "12345")});
848  std::vector<Range> Expected = {Range(0, 2), Range(3, 0), Range(4, 4),
849                                 Range(11, 5), Range(21, 5)};
850  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
851}
852
853TEST(Range, RangesWithOverlappingReplacements) {
854  std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5),
855                               Range(30, 5)};
856  Replacements Replaces = toReplacements(
857      {Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
858       Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")});
859  std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(12, 5),
860                                 Range(22, 0)};
861  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
862}
863
864TEST(Range, MergeIntoOneRange) {
865  std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
866  Replacements Replaces =
867      toReplacements({Replacement("foo", 1, 15, "1234567890")});
868  std::vector<Range> Expected = {Range(0, 15)};
869  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
870}
871
872TEST(Range, ReplacementsStartingAtRangeOffsets) {
873  std::vector<Range> Ranges = {Range(0, 2), Range(5, 5), Range(15, 5)};
874  Replacements Replaces = toReplacements(
875      {Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
876       Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")});
877  std::vector<Range> Expected = {Range(0, 2), Range(5, 9), Range(18, 2)};
878  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
879}
880
881TEST(Range, ReplacementsEndingAtRangeEnds) {
882  std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
883  Replacements Replaces = toReplacements(
884      {Replacement("foo", 6, 1, "123"), Replacement("foo", 17, 3, "12")});
885  std::vector<Range> Expected = {Range(0, 2), Range(5, 4), Range(17, 4)};
886  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
887}
888
889TEST(Range, AjacentReplacements) {
890  std::vector<Range> Ranges = {Range(0, 0), Range(15, 5)};
891  Replacements Replaces = toReplacements(
892      {Replacement("foo", 1, 2, "123"), Replacement("foo", 12, 3, "1234")});
893  std::vector<Range> Expected = {Range(0, 0), Range(1, 3), Range(13, 9)};
894  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
895}
896
897TEST(Range, MergeRangesAfterReplacements) {
898  std::vector<Range> Ranges = {Range(8, 0), Range(5, 2), Range(9, 0), Range(0, 1)};
899  Replacements Replaces = toReplacements({Replacement("foo", 1, 3, ""),
900                                          Replacement("foo", 7, 0, "12"),
901                                          Replacement("foo", 9, 2, "")});
902  std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0),
903                                 Range(8, 0)};
904  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
905}
906
907TEST(Range, ConflictingRangesBeforeReplacements) {
908  std::vector<Range> Ranges = {Range(8, 3), Range(5, 4), Range(9, 1)};
909  Replacements Replaces = toReplacements({Replacement("foo", 1, 3, "")});
910  std::vector<Range> Expected = {Range(1, 0), Range(2, 6)};
911  EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
912}
913
914class MergeReplacementsTest : public ::testing::Test {
915protected:
916  void mergeAndTestRewrite(StringRef Code, StringRef Intermediate,
917                           StringRef Result, const Replacements &First,
918                           const Replacements &Second) {
919    // These are mainly to verify the test itself and make it easier to read.
920    auto AfterFirst = applyAllReplacements(Code, First);
921    EXPECT_TRUE(static_cast<bool>(AfterFirst));
922    auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
923    EXPECT_TRUE(static_cast<bool>(InSequenceRewrite));
924    EXPECT_EQ(Intermediate, *AfterFirst);
925    EXPECT_EQ(Result, *InSequenceRewrite);
926
927    tooling::Replacements Merged = First.merge(Second);
928    auto MergedRewrite = applyAllReplacements(Code, Merged);
929    EXPECT_TRUE(static_cast<bool>(MergedRewrite));
930    EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
931    if (*InSequenceRewrite != *MergedRewrite)
932      for (tooling::Replacement M : Merged)
933        llvm::errs() << M.getOffset() << " " << M.getLength() << " "
934                     << M.getReplacementText() << "\n";
935  }
936  void mergeAndTestRewrite(StringRef Code, const Replacements &First,
937                           const Replacements &Second) {
938    auto AfterFirst = applyAllReplacements(Code, First);
939    EXPECT_TRUE(static_cast<bool>(AfterFirst));
940    auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
941    tooling::Replacements Merged = First.merge(Second);
942    auto MergedRewrite = applyAllReplacements(Code, Merged);
943    EXPECT_TRUE(static_cast<bool>(MergedRewrite));
944    EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
945    if (*InSequenceRewrite != *MergedRewrite)
946      for (tooling::Replacement M : Merged)
947        llvm::errs() << M.getOffset() << " " << M.getLength() << " "
948                     << M.getReplacementText() << "\n";
949  }
950};
951
952TEST_F(MergeReplacementsTest, Offsets) {
953  mergeAndTestRewrite("aaa", "aabab", "cacabab",
954                      toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
955                      toReplacements({{"", 0, 0, "c"}, {"", 1, 0, "c"}}));
956  mergeAndTestRewrite("aaa", "babaa", "babacac",
957                      toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "b"}}),
958                      toReplacements({{"", 4, 0, "c"}, {"", 5, 0, "c"}}));
959  mergeAndTestRewrite("aaaa", "aaa", "aac", toReplacements({{"", 1, 1, ""}}),
960                      toReplacements({{"", 2, 1, "c"}}));
961
962  mergeAndTestRewrite("aa", "bbabba", "bbabcba",
963                      toReplacements({{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}),
964                      toReplacements({{"", 4, 0, "c"}}));
965}
966
967TEST_F(MergeReplacementsTest, Concatenations) {
968  // Basic concatenations. It is important to merge these into a single
969  // replacement to ensure the correct order.
970  {
971    auto First = toReplacements({{"", 0, 0, "a"}});
972    auto Second = toReplacements({{"", 1, 0, "b"}});
973    EXPECT_EQ(toReplacements({{"", 0, 0, "ab"}}), First.merge(Second));
974  }
975  {
976    auto First = toReplacements({{"", 0, 0, "a"}});
977    auto Second = toReplacements({{"", 0, 0, "b"}});
978    EXPECT_EQ(toReplacements({{"", 0, 0, "ba"}}), First.merge(Second));
979  }
980  mergeAndTestRewrite("", "a", "ab", toReplacements({{"", 0, 0, "a"}}),
981                      toReplacements({{"", 1, 0, "b"}}));
982  mergeAndTestRewrite("", "a", "ba", toReplacements({{"", 0, 0, "a"}}),
983                      toReplacements({{"", 0, 0, "b"}}));
984}
985
986TEST_F(MergeReplacementsTest, NotChangingLengths) {
987  mergeAndTestRewrite("aaaa", "abba", "acca",
988                      toReplacements({{"", 1, 2, "bb"}}),
989                      toReplacements({{"", 1, 2, "cc"}}));
990  mergeAndTestRewrite("aaaa", "abba", "abcc",
991                      toReplacements({{"", 1, 2, "bb"}}),
992                      toReplacements({{"", 2, 2, "cc"}}));
993  mergeAndTestRewrite("aaaa", "abba", "ccba",
994                      toReplacements({{"", 1, 2, "bb"}}),
995                      toReplacements({{"", 0, 2, "cc"}}));
996  mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
997                      toReplacements({{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}),
998                      toReplacements({{"", 2, 2, "cc"}}));
999}
1000
1001TEST_F(MergeReplacementsTest, OverlappingRanges) {
1002  mergeAndTestRewrite("aaa", "bbd", "bcbcd",
1003                      toReplacements({{"", 0, 1, "bb"}, {"", 1, 2, "d"}}),
1004                      toReplacements({{"", 1, 0, "c"}, {"", 2, 0, "c"}}));
1005
1006  mergeAndTestRewrite("aaaa", "aabbaa", "acccca",
1007                      toReplacements({{"", 2, 0, "bb"}}),
1008                      toReplacements({{"", 1, 4, "cccc"}}));
1009  mergeAndTestRewrite("aaaa", "aababa", "acccca",
1010                      toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
1011                      toReplacements({{"", 1, 4, "cccc"}}));
1012  mergeAndTestRewrite("aaaaaa", "abbbba", "abba",
1013                      toReplacements({{"", 1, 4, "bbbb"}}),
1014                      toReplacements({{"", 2, 2, ""}}));
1015  mergeAndTestRewrite("aaaa", "aa", "cc",
1016                      toReplacements({{"", 1, 1, ""}, {"", 2, 1, ""}}),
1017                      toReplacements({{"", 0, 2, "cc"}}));
1018  mergeAndTestRewrite("aa", "abbba", "abcbcba",
1019                      toReplacements({{"", 1, 0, "bbb"}}),
1020                      toReplacements({{"", 2, 0, "c"}, {"", 3, 0, "c"}}));
1021
1022  mergeAndTestRewrite(
1023      "aaa", "abbab", "ccdd",
1024      toReplacements({{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}}),
1025      toReplacements({{"", 0, 2, "cc"}, {"", 2, 3, "dd"}}));
1026  mergeAndTestRewrite(
1027      "aa", "babbab", "ccdd",
1028      toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}}),
1029      toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
1030}
1031
1032TEST(DeduplicateByFileTest, PathsWithDots) {
1033  std::map<std::string, Replacements> FileToReplaces;
1034  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
1035      new llvm::vfs::InMemoryFileSystem());
1036  FileManager FileMgr(FileSystemOptions(), VFS);
1037#if !defined(_WIN32)
1038  StringRef Path1 = "a/b/.././c.h";
1039  StringRef Path2 = "a/c.h";
1040#else
1041  StringRef Path1 = "a\\b\\..\\.\\c.h";
1042  StringRef Path2 = "a\\c.h";
1043#endif
1044  EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
1045  EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
1046  FileToReplaces[Path1] = Replacements();
1047  FileToReplaces[Path2] = Replacements();
1048  FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
1049  EXPECT_EQ(1u, FileToReplaces.size());
1050  EXPECT_EQ(Path1, FileToReplaces.begin()->first);
1051}
1052
1053TEST(DeduplicateByFileTest, PathWithDotSlash) {
1054  std::map<std::string, Replacements> FileToReplaces;
1055  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
1056      new llvm::vfs::InMemoryFileSystem());
1057  FileManager FileMgr(FileSystemOptions(), VFS);
1058#if !defined(_WIN32)
1059  StringRef Path1 = "./a/b/c.h";
1060  StringRef Path2 = "a/b/c.h";
1061#else
1062  StringRef Path1 = ".\\a\\b\\c.h";
1063  StringRef Path2 = "a\\b\\c.h";
1064#endif
1065  EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
1066  EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
1067  FileToReplaces[Path1] = Replacements();
1068  FileToReplaces[Path2] = Replacements();
1069  FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
1070  EXPECT_EQ(1u, FileToReplaces.size());
1071  EXPECT_EQ(Path1, FileToReplaces.begin()->first);
1072}
1073
1074TEST(DeduplicateByFileTest, NonExistingFilePath) {
1075  std::map<std::string, Replacements> FileToReplaces;
1076  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS(
1077      new llvm::vfs::InMemoryFileSystem());
1078  FileManager FileMgr(FileSystemOptions(), VFS);
1079#if !defined(_WIN32)
1080  StringRef Path1 = "./a/b/c.h";
1081  StringRef Path2 = "a/b/c.h";
1082#else
1083  StringRef Path1 = ".\\a\\b\\c.h";
1084  StringRef Path2 = "a\\b\\c.h";
1085#endif
1086  FileToReplaces[Path1] = Replacements();
1087  FileToReplaces[Path2] = Replacements();
1088  FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
1089  EXPECT_TRUE(FileToReplaces.empty());
1090}
1091
1092class AtomicChangeTest : public ::testing::Test {
1093  protected:
1094    void SetUp() override {
1095      DefaultFileID = Context.createInMemoryFile("input.cpp", DefaultCode);
1096      DefaultLoc = Context.Sources.getLocForStartOfFile(DefaultFileID)
1097                       .getLocWithOffset(20);
1098       (0) . __assert_fail ("DefaultLoc.isValid() && \"Default location must be valid.\"", "/home/seafit/code_projects/clang_source/clang/unittests/Tooling/RefactoringTest.cpp", 1098, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(DefaultLoc.isValid() && "Default location must be valid.");
1099    }
1100
1101    RewriterTestContext Context;
1102    std::string DefaultCode = std::string(100, 'a');
1103    unsigned DefaultOffset = 20;
1104    SourceLocation DefaultLoc;
1105    FileID DefaultFileID;
1106};
1107
1108TEST_F(AtomicChangeTest, AtomicChangeToYAML) {
1109  AtomicChange Change(Context.Sources, DefaultLoc);
1110  llvm::Error Err =
1111      Change.insert(Context.Sources, DefaultLoc, "aa", /*InsertAfter=*/false);
1112  ASSERT_TRUE(!Err);
1113  Err = Change.insert(Context.Sources, DefaultLoc.getLocWithOffset(10), "bb",
1114                    /*InsertAfter=*/false);
1115  ASSERT_TRUE(!Err);
1116  Change.addHeader("a.h");
1117  Change.removeHeader("b.h");
1118  std::string YAMLString = Change.toYAMLString();
1119
1120  // NOTE: If this test starts to fail for no obvious reason, check whitespace.
1121  ASSERT_STREQ("---\n"
1122               "Key:             'input.cpp:20'\n"
1123               "FilePath:        input.cpp\n"
1124               "Error:           ''\n"
1125               "InsertedHeaders: \n" // Extra whitespace here!
1126               "  - a.h\n"
1127               "RemovedHeaders:  \n" // Extra whitespace here!
1128               "  - b.h\n"
1129               "Replacements:    \n" // Extra whitespace here!
1130               "  - FilePath:        input.cpp\n"
1131               "    Offset:          20\n"
1132               "    Length:          0\n"
1133               "    ReplacementText: aa\n"
1134               "  - FilePath:        input.cpp\n"
1135               "    Offset:          30\n"
1136               "    Length:          0\n"
1137               "    ReplacementText: bb\n"
1138               "...\n",
1139               YAMLString.c_str());
1140}
1141
1142TEST_F(AtomicChangeTest, YAMLToAtomicChange) {
1143  std::string YamlContent = "---\n"
1144                            "Key:             'input.cpp:20'\n"
1145                            "FilePath:        input.cpp\n"
1146                            "Error:           'ok'\n"
1147                            "InsertedHeaders: \n" // Extra whitespace here!
1148                            "  - a.h\n"
1149                            "RemovedHeaders:  \n" // Extra whitespace here!
1150                            "  - b.h\n"
1151                            "Replacements:    \n" // Extra whitespace here!
1152                            "  - FilePath:        input.cpp\n"
1153                            "    Offset:          20\n"
1154                            "    Length:          0\n"
1155                            "    ReplacementText: aa\n"
1156                            "  - FilePath:        input.cpp\n"
1157                            "    Offset:          30\n"
1158                            "    Length:          0\n"
1159                            "    ReplacementText: bb\n"
1160                            "...\n";
1161  AtomicChange ExpectedChange(Context.Sources, DefaultLoc);
1162  llvm::Error Err = ExpectedChange.insert(Context.Sources, DefaultLoc, "aa",
1163                                        /*InsertAfter=*/false);
1164  ASSERT_TRUE(!Err);
1165  Err = ExpectedChange.insert(Context.Sources, DefaultLoc.getLocWithOffset(10),
1166                            "bb", /*InsertAfter=*/false);
1167  ASSERT_TRUE(!Err);
1168
1169  ExpectedChange.addHeader("a.h");
1170  ExpectedChange.removeHeader("b.h");
1171  ExpectedChange.setError("ok");
1172
1173  AtomicChange ActualChange = AtomicChange::convertFromYAML(YamlContent);
1174  EXPECT_EQ(ExpectedChange.getKey(), ActualChange.getKey());
1175  EXPECT_EQ(ExpectedChange.getFilePath(), ActualChange.getFilePath());
1176  EXPECT_EQ(ExpectedChange.getError(), ActualChange.getError());
1177  EXPECT_EQ(ExpectedChange.getInsertedHeaders(),
1178            ActualChange.getInsertedHeaders());
1179  EXPECT_EQ(ExpectedChange.getRemovedHeaders(),
1180            ActualChange.getRemovedHeaders());
1181  EXPECT_EQ(ExpectedChange.getReplacements().size(),
1182            ActualChange.getReplacements().size());
1183  EXPECT_EQ(2u, ActualChange.getReplacements().size());
1184  EXPECT_EQ(*ExpectedChange.getReplacements().begin(),
1185            *ActualChange.getReplacements().begin());
1186  EXPECT_EQ(*(++ExpectedChange.getReplacements().begin()),
1187            *(++ActualChange.getReplacements().begin()));
1188}
1189
1190TEST_F(AtomicChangeTest, CheckKeyAndKeyFile) {
1191  AtomicChange Change(Context.Sources, DefaultLoc);
1192  EXPECT_EQ("input.cpp:20", Change.getKey());
1193  EXPECT_EQ("input.cpp", Change.getFilePath());
1194}
1195
1196TEST_F(AtomicChangeTest, Replace) {
1197  AtomicChange Change(Context.Sources, DefaultLoc);
1198  llvm::Error Err = Change.replace(Context.Sources, DefaultLoc, 2, "aa");
1199  ASSERT_TRUE(!Err);
1200  EXPECT_EQ(Change.getReplacements().size(), 1u);
1201  EXPECT_EQ(*Change.getReplacements().begin(),
1202            Replacement(Context.Sources, DefaultLoc, 2, "aa"));
1203
1204  // Add a new replacement that conflicts with the existing one.
1205  Err = Change.replace(Context.Sources, DefaultLoc, 3, "ab");
1206  EXPECT_TRUE((bool)Err);
1207  llvm::consumeError(std::move(Err));
1208  EXPECT_EQ(Change.getReplacements().size(), 1u);
1209}
1210
1211TEST_F(AtomicChangeTest, ReplaceWithRange) {
1212  AtomicChange Change(Context.Sources, DefaultLoc);
1213  SourceLocation End = DefaultLoc.getLocWithOffset(20);
1214  llvm::Error Err = Change.replace(
1215      Context.Sources, CharSourceRange::getCharRange(DefaultLoc, End), "aa");
1216  ASSERT_TRUE(!Err);
1217  EXPECT_EQ(Change.getReplacements().size(), 1u);
1218  EXPECT_EQ(*Change.getReplacements().begin(),
1219            Replacement(Context.Sources, DefaultLoc, 20, "aa"));
1220}
1221
1222TEST_F(AtomicChangeTest, InsertBefore) {
1223  AtomicChange Change(Context.Sources, DefaultLoc);
1224  llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
1225  ASSERT_TRUE(!Err);
1226  EXPECT_EQ(Change.getReplacements().size(), 1u);
1227  EXPECT_EQ(*Change.getReplacements().begin(),
1228            Replacement(Context.Sources, DefaultLoc, 0, "aa"));
1229  Err = Change.insert(Context.Sources, DefaultLoc, "b", /*InsertAfter=*/false);
1230  ASSERT_TRUE(!Err);
1231  EXPECT_EQ(Change.getReplacements().size(), 1u);
1232  EXPECT_EQ(*Change.getReplacements().begin(),
1233            Replacement(Context.Sources, DefaultLoc, 0, "baa"));
1234}
1235
1236TEST_F(AtomicChangeTest, InsertAfter) {
1237  AtomicChange Change(Context.Sources, DefaultLoc);
1238  llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "aa");
1239  ASSERT_TRUE(!Err);
1240  EXPECT_EQ(Change.getReplacements().size(), 1u);
1241  EXPECT_EQ(*Change.getReplacements().begin(),
1242            Replacement(Context.Sources, DefaultLoc, 0, "aa"));
1243  Err = Change.insert(Context.Sources, DefaultLoc, "b");
1244  ASSERT_TRUE(!Err);
1245  EXPECT_EQ(Change.getReplacements().size(), 1u);
1246  EXPECT_EQ(*Change.getReplacements().begin(),
1247            Replacement(Context.Sources, DefaultLoc, 0, "aab"));
1248}
1249
1250TEST_F(AtomicChangeTest, InsertBeforeWithInvalidLocation) {
1251  AtomicChange Change(Context.Sources, DefaultLoc);
1252  llvm::Error Err =
1253      Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false);
1254  ASSERT_TRUE(!Err);
1255
1256  // Invalid location.
1257  Err = Change.insert(Context.Sources, SourceLocation(), "a",
1258                    /*InsertAfter=*/false);
1259  ASSERT_TRUE((bool)Err);
1260  EXPECT_TRUE(checkReplacementError(
1261      std::move(Err), replacement_error::wrong_file_path,
1262      Replacement(Context.Sources, DefaultLoc, 0, "a"),
1263      Replacement(Context.Sources, SourceLocation(), 0, "a")));
1264}
1265
1266TEST_F(AtomicChangeTest, InsertBeforeToWrongFile) {
1267  AtomicChange Change(Context.Sources, DefaultLoc);
1268  llvm::Error Err =
1269      Change.insert(Context.Sources, DefaultLoc, "a", /*InsertAfter=*/false);
1270  ASSERT_TRUE(!Err);
1271
1272  // Inserting at a different file.
1273  FileID NewID = Context.createInMemoryFile("extra.cpp", DefaultCode);
1274  SourceLocation NewLoc = Context.Sources.getLocForStartOfFile(NewID);
1275  Err = Change.insert(Context.Sources, NewLoc, "b", /*InsertAfter=*/false);
1276  ASSERT_TRUE((bool)Err);
1277  EXPECT_TRUE(
1278      checkReplacementError(std::move(Err), replacement_error::wrong_file_path,
1279                            Replacement(Context.Sources, DefaultLoc, 0, "a"),
1280                            Replacement(Context.Sources, NewLoc, 0, "b")));
1281}
1282
1283TEST_F(AtomicChangeTest, InsertAfterWithInvalidLocation) {
1284  AtomicChange Change(Context.Sources, DefaultLoc);
1285  llvm::Error Err = Change.insert(Context.Sources, DefaultLoc, "a");
1286  ASSERT_TRUE(!Err);
1287
1288  // Invalid location.
1289  Err = Change.insert(Context.Sources, SourceLocation(), "b");
1290  ASSERT_TRUE((bool)Err);
1291  EXPECT_TRUE(checkReplacementError(
1292      std::move(Err), replacement_error::wrong_file_path,
1293      Replacement(Context.Sources, DefaultLoc, 0, "a"),
1294      Replacement(Context.Sources, SourceLocation(), 0, "b")));
1295}
1296
1297class ApplyAtomicChangesTest : public ::testing::Test {
1298protected:
1299  ApplyAtomicChangesTest() : FilePath("file.cc") {
1300    Spec.Cleanup = true;
1301    Spec.Format = ApplyChangesSpec::kAll;
1302    Spec.Style = format::getLLVMStyle();
1303  }
1304
1305  ~ApplyAtomicChangesTest() override {}
1306
1307  void setInput(llvm::StringRef Input) {
1308    Code = Input;
1309    FID = Context.createInMemoryFile(FilePath, Code);
1310  }
1311
1312  SourceLocation getLoc(unsigned Offset) const {
1313    return Context.Sources.getLocForStartOfFile(FID).getLocWithOffset(Offset);
1314  }
1315
1316  AtomicChange replacementToAtomicChange(llvm::StringRef Key, unsigned Offset,
1317                                         unsigned Length,
1318                                         llvm::StringRef Text) {
1319    AtomicChange Change(FilePath, Key);
1320    llvm::Error Err =
1321        Change.replace(Context.Sources, getLoc(Offset), Length, Text);
1322    EXPECT_FALSE(Err);
1323    return Change;
1324  }
1325
1326  std::string rewrite(bool FailureExpected = false) {
1327    llvm::Expected<std::string> ChangedCode =
1328        applyAtomicChanges(FilePath, Code, Changes, Spec);
1329    EXPECT_EQ(FailureExpected, !ChangedCode);
1330    if (!ChangedCode) {
1331      llvm::errs() << "Failed to apply changes: "
1332                   << llvm::toString(ChangedCode.takeError()) << "\n";
1333      return "";
1334    }
1335    return *ChangedCode;
1336  }
1337
1338  RewriterTestContext Context;
1339  FileID FID;
1340  ApplyChangesSpec Spec;
1341  std::string Code;
1342  std::string FilePath;
1343  llvm::SmallVector<AtomicChange, 8> Changes;
1344};
1345
1346TEST_F(ApplyAtomicChangesTest, BasicRefactoring) {
1347  setInput("int a;");
1348  AtomicChange Change(FilePath, "key1");
1349  Changes.push_back(replacementToAtomicChange("key1", 4, 1, "b"));
1350  EXPECT_EQ("int b;", rewrite());
1351}
1352
1353TEST_F(ApplyAtomicChangesTest, SeveralRefactorings) {
1354  setInput("int a;\n"
1355           "int b;");
1356  Changes.push_back(replacementToAtomicChange("key1", 0, 3, "float"));
1357  Changes.push_back(replacementToAtomicChange("key2", 4, 1, "f"));
1358  Changes.push_back(replacementToAtomicChange("key3", 11, 1, "g"));
1359  Changes.push_back(replacementToAtomicChange("key4", 7, 3, "float"));
1360  EXPECT_EQ("float f;\n"
1361            "float g;",
1362            rewrite());
1363}
1364
1365TEST_F(ApplyAtomicChangesTest, IgnorePathsInRefactorings) {
1366  setInput("int a;\n"
1367           "int b;");
1368  Changes.push_back(replacementToAtomicChange("key1", 4, 1, "aa"));
1369
1370  FileID ID = Context.createInMemoryFile("AnotherFile", "12345678912345");
1371  Changes.emplace_back("AnotherFile", "key2");
1372  auto Err = Changes.back().replace(
1373      Context.Sources,
1374      Context.Sources.getLocForStartOfFile(ID).getLocWithOffset(11), 1, "bb");
1375  ASSERT_TRUE(!Err);
1376  EXPECT_EQ("int aa;\n"
1377            "int bb;",
1378            rewrite());
1379}
1380
1381TEST_F(ApplyAtomicChangesTest, AppliesDuplicateInsertions) {
1382  setInput("int a;");
1383  Changes.push_back(replacementToAtomicChange("key1", 5, 0, "b"));
1384  Changes.push_back(replacementToAtomicChange("key2", 5, 0, "b"));
1385  EXPECT_EQ("int abb;", rewrite());
1386}
1387
1388TEST_F(ApplyAtomicChangesTest, BailsOnOverlappingRefactorings) {
1389  setInput("int a;");
1390  Changes.push_back(replacementToAtomicChange("key1", 0, 5, "float f"));
1391  Changes.push_back(replacementToAtomicChange("key2", 4, 1, "b"));
1392  EXPECT_EQ("", rewrite(/*FailureExpected=*/true));
1393}
1394
1395TEST_F(ApplyAtomicChangesTest, BasicReformatting) {
1396  setInput("int  a;");
1397  Changes.push_back(replacementToAtomicChange("key1", 5, 1, "b"));
1398  EXPECT_EQ("int b;", rewrite());
1399}
1400
1401TEST_F(ApplyAtomicChangesTest, OnlyFormatWhenViolateColumnLimits) {
1402  Spec.Format = ApplyChangesSpec::kViolations;
1403  Spec.Style.ColumnLimit = 8;
1404  setInput("int  a;\n"
1405           "int    a;\n"
1406           "int  aaaaaaaa;\n");
1407  Changes.push_back(replacementToAtomicChange("key1", 5, 1, "x"));
1408  Changes.push_back(replacementToAtomicChange("key2", 15, 1, "x"));
1409  Changes.push_back(replacementToAtomicChange("key3", 23, 8, "xx"));
1410  EXPECT_EQ("int  x;\n"
1411            "int x;\n"
1412            "int  xx;\n",
1413            rewrite());
1414}
1415
1416TEST_F(ApplyAtomicChangesTest, LastLineViolateColumnLimits) {
1417  Spec.Format = ApplyChangesSpec::kViolations;
1418  Spec.Style.ColumnLimit = 8;
1419  setInput("int  a;\n"
1420           "int    a;");
1421  Changes.push_back(replacementToAtomicChange("key1", 0, 1, "i"));
1422  Changes.push_back(replacementToAtomicChange("key2", 15, 2, "y;"));
1423  EXPECT_EQ("int  a;\n"
1424            "int y;",
1425            rewrite());
1426}
1427
1428TEST_F(ApplyAtomicChangesTest, LastLineWithNewlineViolateColumnLimits) {
1429  Spec.Format = ApplyChangesSpec::kViolations;
1430  Spec.Style.ColumnLimit = 8;
1431  setInput("int  a;\n"
1432           "int   a;\n");
1433  Changes.push_back(replacementToAtomicChange("key1", 0, 1, "i"));
1434  Changes.push_back(replacementToAtomicChange("key2", 14, 3, "y;\n"));
1435  EXPECT_EQ("int  a;\n"
1436            "int   y;\n",
1437            rewrite());
1438}
1439
1440TEST_F(ApplyAtomicChangesTest, Longer) {
1441  setInput("int  a;");
1442  Changes.push_back(replacementToAtomicChange("key1", 5, 1, "bbb"));
1443  EXPECT_EQ("int bbb;", rewrite());
1444}
1445
1446TEST_F(ApplyAtomicChangesTest, Shorter) {
1447  setInput("int  aaa;");
1448  Changes.push_back(replacementToAtomicChange("key1", 5, 3, "b"));
1449  EXPECT_EQ("int b;", rewrite());
1450}
1451
1452TEST_F(ApplyAtomicChangesTest, OnlyFormatChangedLines) {
1453  setInput("int  aaa;\n"
1454           "int a = b;\n"
1455           "int  bbb;");
1456  Changes.push_back(replacementToAtomicChange("key1", 14, 1, "b"));
1457  EXPECT_EQ("int  aaa;\n"
1458            "int b = b;\n"
1459            "int  bbb;",
1460            rewrite());
1461}
1462
1463TEST_F(ApplyAtomicChangesTest, DisableFormatting) {
1464  Spec.Format = ApplyChangesSpec::kNone;
1465  setInput("int  aaa;\n"
1466           "int a   = b;\n"
1467           "int  bbb;");
1468  Changes.push_back(replacementToAtomicChange("key1", 14, 1, "b"));
1469  EXPECT_EQ("int  aaa;\n"
1470            "int b   = b;\n"
1471            "int  bbb;",
1472            rewrite());
1473}
1474
1475TEST_F(ApplyAtomicChangesTest, AdaptsToLocalPointerStyle) {
1476  setInput("int *aaa;\n"
1477           "int *bbb;");
1478  Changes.push_back(replacementToAtomicChange("key1", 0, 0, "int* ccc;\n"));
1479  EXPECT_EQ("int *ccc;\n"
1480            "int *aaa;\n"
1481            "int *bbb;",
1482            rewrite());
1483}
1484
1485TEST_F(ApplyAtomicChangesTest, AcceptsSurroundingFormatting) {
1486  setInput("   int  aaa;\n"
1487           "   int a = b;\n"
1488           "   int  bbb;");
1489  Changes.push_back(replacementToAtomicChange("key1", 20, 1, "b"));
1490  EXPECT_EQ("   int  aaa;\n"
1491            "   int b = b;\n"
1492            "   int  bbb;",
1493            rewrite());
1494}
1495
1496TEST_F(ApplyAtomicChangesTest, BailsOutOnConflictingChanges) {
1497  setInput("int c;\n"
1498           "int f;");
1499  // Insertions at the same offset are only allowed in the same AtomicChange.
1500  Changes.push_back(replacementToAtomicChange("key1", 0, 0, "int a;\n"));
1501  Changes.push_back(replacementToAtomicChange("key2", 0, 0, "int b;\n"));
1502  EXPECT_EQ("", rewrite(/*FailureExpected=*/true));
1503}
1504
1505TEST_F(ApplyAtomicChangesTest, InsertsNewIncludesInRightOrder) {
1506  setInput("int a;");
1507  Changes.emplace_back(FilePath, "key1");
1508  Changes.back().addHeader("b");
1509  Changes.back().addHeader("c");
1510  Changes.emplace_back(FilePath, "key2");
1511  Changes.back().addHeader("a");
1512  EXPECT_EQ("#include \"a\"\n"
1513            "#include \"b\"\n"
1514            "#include \"c\"\n"
1515            "int a;",
1516            rewrite());
1517}
1518
1519TEST_F(ApplyAtomicChangesTest, RemoveAndSortIncludes) {
1520  setInput("#include \"a\"\n"
1521           "#include \"b\"\n"
1522           "#include \"c\"\n"
1523           "\n"
1524           "int a;");
1525  Changes.emplace_back(FilePath, "key1");
1526  Changes.back().removeHeader("b");
1527  EXPECT_EQ("#include \"a\"\n"
1528            "#include \"c\"\n"
1529            "\n"
1530            "int a;",
1531            rewrite());
1532}
1533TEST_F(ApplyAtomicChangesTest, InsertsSystemIncludes) {
1534  setInput("#include <asys>\n"
1535           "#include <csys>\n"
1536           "\n"
1537           "#include \"a\"\n"
1538           "#include \"c\"\n");
1539  Changes.emplace_back(FilePath, "key1");
1540  Changes.back().addHeader("<asys>"); // Already exists.
1541  Changes.back().addHeader("<b>");
1542  Changes.back().addHeader("<d>");
1543  Changes.back().addHeader("\"b-already-escaped\"");
1544  EXPECT_EQ("#include <asys>\n"
1545            "#include <b>\n"
1546            "#include <csys>\n"
1547            "#include <d>\n"
1548            "\n"
1549            "#include \"a\"\n"
1550            "#include \"b-already-escaped\"\n"
1551            "#include \"c\"\n",
1552            rewrite());
1553}
1554
1555TEST_F(ApplyAtomicChangesTest, RemoveSystemIncludes) {
1556  setInput("#include <a>\n"
1557           "#include <b>\n"
1558           "\n"
1559           "#include \"c\""
1560           "\n"
1561           "int a;");
1562  Changes.emplace_back(FilePath, "key1");
1563  Changes.back().removeHeader("<a>");
1564  EXPECT_EQ("#include <b>\n"
1565            "\n"
1566            "#include \"c\""
1567            "\n"
1568            "int a;",
1569            rewrite());
1570}
1571
1572TEST_F(ApplyAtomicChangesTest,
1573       DoNotFormatFollowingLinesIfSeparatedWithNewline) {
1574  setInput("#ifndef __H__\n"
1575           "#define __H__\n"
1576           "#include \"b\"\n"
1577           "\n"
1578           "int  a;\n"
1579           "int  a;\n"
1580           "int  a;\n"
1581           "#endif // __H__\n");
1582  Changes.push_back(replacementToAtomicChange("key1",
1583                                              llvm::StringRef("#ifndef __H__\n"
1584                                                              "#define __H__\n"
1585                                                              "\n"
1586                                                              "#include \"b\"\n"
1587                                                              "int  a;\n"
1588                                                              "int  ")
1589                                                  .size(),
1590                                              1, "b"));
1591  Changes.back().addHeader("a");
1592  EXPECT_EQ("#ifndef __H__\n"
1593            "#define __H__\n"
1594            "#include \"a\"\n"
1595            "#include \"b\"\n"
1596            "\n"
1597            "int  a;\n"
1598            "int b;\n"
1599            "int  a;\n"
1600            "#endif // __H__\n",
1601            rewrite());
1602}
1603
1604TEST_F(ApplyAtomicChangesTest, FormatsCorrectLineWhenHeaderIsRemoved) {
1605  setInput("#include \"a\"\n"
1606           "\n"
1607           "int  a;\n"
1608           "int  a;\n"
1609           "int  a;");
1610  Changes.push_back(replacementToAtomicChange("key1", 27, 1, "b"));
1611  Changes.back().removeHeader("a");
1612  EXPECT_EQ("\n"
1613            "int  a;\n"
1614            "int b;\n"
1615            "int  a;",
1616            rewrite());
1617}
1618
1619TEST_F(ApplyAtomicChangesTest, CleansUpCtorInitializers) {
1620  setInput("A::A() : a(), b() {}\n"
1621           "A::A() : a(), b() {}\n"
1622           "A::A() : a(), b() {}\n"
1623           "A::A() : a()/**/, b() {}\n"
1624           "A::A() : a()  ,// \n"
1625           "   /**/    b()    {}");
1626  Changes.emplace_back(FilePath, "key1");
1627  auto Err = Changes.back().replace(Context.Sources, getLoc(9), 3, "");
1628  ASSERT_TRUE(!Err);
1629  Err = Changes.back().replace(Context.Sources, getLoc(35), 3, "");
1630  ASSERT_TRUE(!Err);
1631  Err = Changes.back().replace(Context.Sources, getLoc(51), 3, "");
1632  ASSERT_TRUE(!Err);
1633  Err = Changes.back().replace(Context.Sources, getLoc(56), 3, "");
1634  ASSERT_TRUE(!Err);
1635  Err = Changes.back().replace(Context.Sources, getLoc(72), 3, "");
1636  ASSERT_TRUE(!Err);
1637  Err = Changes.back().replace(Context.Sources, getLoc(97), 3, "");
1638  ASSERT_TRUE(!Err);
1639  Err = Changes.back().replace(Context.Sources, getLoc(118), 3, "");
1640  ASSERT_TRUE(!Err);
1641  EXPECT_EQ("A::A() : b() {}\n"
1642            "A::A() : a() {}\n"
1643            "A::A() {}\n"
1644            "A::A() : b() {}\n"
1645            "A::A() {}",
1646            rewrite());
1647}
1648
1649TEST_F(ApplyAtomicChangesTest, CleansUpParameterLists) {
1650  setInput("void f(int i, float f, string s);\n"
1651           "f(1, 2.0f, \"a\");\n"
1652           "g(1, 1);");
1653  Changes.emplace_back(FilePath, "key1");
1654  auto Err = Changes.back().replace(Context.Sources, getLoc(7), 5, "");
1655  ASSERT_TRUE(!Err);
1656  Err = Changes.back().replace(Context.Sources, getLoc(23), 8, "");
1657  ASSERT_TRUE(!Err);
1658  Err = Changes.back().replace(Context.Sources, getLoc(36), 1, "");
1659  ASSERT_TRUE(!Err);
1660  Err = Changes.back().replace(Context.Sources, getLoc(45), 3, "");
1661  ASSERT_TRUE(!Err);
1662  Err = Changes.back().replace(Context.Sources, getLoc(53), 1, "");
1663  ASSERT_TRUE(!Err);
1664  Err = Changes.back().replace(Context.Sources, getLoc(56), 1, "");
1665  ASSERT_TRUE(!Err);
1666  EXPECT_EQ("void f(float f);\n"
1667            "f(2.0f);\n"
1668            "g();",
1669            rewrite());
1670}
1671
1672TEST_F(ApplyAtomicChangesTest, DisableCleanup) {
1673  Spec.Cleanup = false;
1674  setInput("void f(int i, float f, string s);\n"
1675           "f(1, 2.0f, \"a\");\n"
1676           "g(1, 1);");
1677  Changes.emplace_back(FilePath, "key1");
1678  auto Err = Changes.back().replace(Context.Sources, getLoc(7), 5, "");
1679  ASSERT_TRUE(!Err);
1680  Err = Changes.back().replace(Context.Sources, getLoc(23), 8, "");
1681  ASSERT_TRUE(!Err);
1682  Err = Changes.back().replace(Context.Sources, getLoc(36), 1, "");
1683  ASSERT_TRUE(!Err);
1684  Err = Changes.back().replace(Context.Sources, getLoc(45), 3, "");
1685  ASSERT_TRUE(!Err);
1686  Err = Changes.back().replace(Context.Sources, getLoc(53), 1, "");
1687  ASSERT_TRUE(!Err);
1688  Err = Changes.back().replace(Context.Sources, getLoc(56), 1, "");
1689  ASSERT_TRUE(!Err);
1690  EXPECT_EQ("void f(, float f, );\n"
1691            "f(, 2.0f, );\n"
1692            "g(, );",
1693            rewrite());
1694}
1695
1696TEST_F(ApplyAtomicChangesTest, EverythingDeleted) {
1697  setInput("int a;");
1698  Changes.push_back(replacementToAtomicChange("key1", 0, 6, ""));
1699  EXPECT_EQ("", rewrite());
1700}
1701
1702TEST_F(ApplyAtomicChangesTest, DoesNotDeleteInserts) {
1703  setInput("int a;\n"
1704           "int b;");
1705  Changes.emplace_back(FilePath, "key1");
1706  auto Err = Changes.back().replace(Context.Sources, getLoc(4), 1, "");
1707  ASSERT_TRUE(!Err);
1708  Err = Changes.back().replace(Context.Sources, getLoc(4), 0, "b");
1709  ASSERT_TRUE(!Err);
1710  Err = Changes.back().replace(Context.Sources, getLoc(11), 0, "a");
1711  ASSERT_TRUE(!Err);
1712  Err = Changes.back().replace(Context.Sources, getLoc(11), 1, "");
1713  ASSERT_TRUE(!Err);
1714  EXPECT_EQ("int b;\n"
1715            "int a;",
1716            rewrite());
1717}
1718
1719} // end namespace tooling
1720} // end namespace clang
1721