xref: /llvm-project/clang/unittests/Format/CleanupTest.cpp (revision 11a4237b23eaeb718ac7b746dc91a6131054cf81)
1 //===- unittest/Format/CleanupTest.cpp - Code cleanup unit tests ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "clang/Format/Format.h"
11 
12 #include "../Tooling/ReplacementTest.h"
13 #include "../Tooling/RewriterTestContext.h"
14 #include "clang/Tooling/Core/Replacement.h"
15 
16 #include "gtest/gtest.h"
17 
18 using clang::tooling::ReplacementTest;
19 using clang::tooling::toReplacements;
20 
21 namespace clang {
22 namespace format {
23 namespace {
24 
25 class CleanupTest : public ::testing::Test {
26 protected:
27   std::string cleanup(llvm::StringRef Code,
28                       const std::vector<tooling::Range> &Ranges,
29                       const FormatStyle &Style = getLLVMStyle()) {
30     tooling::Replacements Replaces = format::cleanup(Style, Code, Ranges);
31 
32     auto Result = applyAllReplacements(Code, Replaces);
33     EXPECT_TRUE(static_cast<bool>(Result));
34     return *Result;
35   }
36 
37   // Returns code after cleanup around \p Offsets.
38   std::string cleanupAroundOffsets(llvm::ArrayRef<unsigned> Offsets,
39                                    llvm::StringRef Code) {
40     std::vector<tooling::Range> Ranges;
41     for (auto Offset : Offsets)
42       Ranges.push_back(tooling::Range(Offset, 0));
43     return cleanup(Code, Ranges);
44   }
45 };
46 
47 TEST_F(CleanupTest, DeleteEmptyNamespaces) {
48   std::string Code = "namespace A {\n"
49                      "namespace B {\n"
50                      "} // namespace B\n"
51                      "} // namespace A\n\n"
52                      "namespace C {\n"
53                      "namespace D { int i; }\n"
54                      "inline namespace E { namespace { } }\n"
55                      "}";
56   std::string Expected = "\n\n\n\n\nnamespace C {\n"
57                          "namespace D { int i; }\n   \n"
58                          "}";
59   EXPECT_EQ(Expected, cleanupAroundOffsets({28, 91, 132}, Code));
60 }
61 
62 TEST_F(CleanupTest, NamespaceWithSyntaxError) {
63   std::string Code = "namespace A {\n"
64                      "namespace B {\n" // missing r_brace
65                      "} // namespace A\n\n"
66                      "namespace C {\n"
67                      "namespace D int i; }\n"
68                      "inline namespace E { namespace { } }\n"
69                      "}";
70   std::string Expected = "namespace A {\n"
71                          "\n\n\nnamespace C {\n"
72                          "namespace D int i; }\n   \n"
73                          "}";
74   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
75   EXPECT_EQ(Expected, cleanup(Code, Ranges));
76 }
77 
78 TEST_F(CleanupTest, EmptyNamespaceNotAffected) {
79   std::string Code = "namespace A {\n\n"
80                      "namespace {\n\n}}";
81   // Even though the namespaces are empty, but the inner most empty namespace
82   // block is not affected by the changed ranges.
83   std::string Expected = "namespace A {\n\n"
84                          "namespace {\n\n}}";
85   // Set the changed range to be the second "\n".
86   EXPECT_EQ(Expected, cleanupAroundOffsets({14}, Code));
87 }
88 
89 TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) {
90   std::string Code = "namespace A {\n"
91                      "namespace B {\n"
92                      "// Yo\n"
93                      "} // namespace B\n"
94                      "} // namespace A\n"
95                      "namespace C { // Yo\n"
96                      "}";
97   std::string Expected = "\n\n\n\n\n\n";
98   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
99   std::string Result = cleanup(Code, Ranges);
100   EXPECT_EQ(Expected, Result);
101 }
102 
103 TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) {
104   std::string Code = "namespace A\n"
105                      "/* Yo */ {\n"
106                      "namespace B\n"
107                      "{\n"
108                      "// Yo\n"
109                      "} // namespace B\n"
110                      "} // namespace A\n"
111                      "namespace C\n"
112                      "{ // Yo\n"
113                      "}\n";
114   std::string Expected = "\n\n\n\n\n\n\n\n\n\n";
115   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
116   FormatStyle Style = getLLVMStyle();
117   Style.BraceWrapping.AfterNamespace = true;
118   std::string Result = cleanup(Code, Ranges, Style);
119   EXPECT_EQ(Expected, Result);
120 }
121 
122 TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) {
123   std::string Code = "class A {\nA() : , {} };";
124   std::string Expected = "class A {\nA()  {} };";
125   EXPECT_EQ(Expected, cleanupAroundOffsets({17, 19}, Code));
126 
127   Code = "class A {\nA() : x(1), {} };";
128   Expected = "class A {\nA() : x(1) {} };";
129   EXPECT_EQ(Expected, cleanupAroundOffsets({23}, Code));
130 
131   Code = "class A {\nA() :,,,,{} };";
132   Expected = "class A {\nA() {} };";
133   EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
134 }
135 
136 TEST_F(CleanupTest, ListRedundantComma) {
137   std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }";
138   std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }";
139   EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
140 
141   Code = "int main() { f(1,,2,3,,4);}";
142   Expected = "int main() { f(1,2,3,4);}";
143   EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code));
144 }
145 
146 TEST_F(CleanupTest, TrailingCommaInParens) {
147   std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}";
148   std::string Expected = "int main() { f(1,2,3,f(1,2),4);}";
149   EXPECT_EQ(Expected, cleanupAroundOffsets({15, 18, 29, 33}, Code));
150 }
151 
152 TEST_F(CleanupTest, TrailingCommaInBraces) {
153   // Trainling comma is allowed in brace list.
154   // If there was trailing comma in the original code, then trailing comma is
155   // preserved. In this example, element between the last two commas is deleted
156   // causing the second-last comma to be redundant.
157   std::string Code = "void f() { std::vector<int> v = {1,2,3,,}; }";
158   std::string Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
159   EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
160 
161   // If there was no trailing comma in the original code, then trainling comma
162   // introduced by replacements should be cleaned up. In this example, the
163   // element after the last comma is deleted causing the last comma to be
164   // redundant.
165   Code = "void f() { std::vector<int> v = {1,2,3,}; }";
166   // FIXME: redundant trailing comma should be removed.
167   Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
168   EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
169 
170   // Still no trailing comma in the original code, but two elements are deleted,
171   // which makes it seems like there was trailing comma.
172   Code = "void f() { std::vector<int> v = {1, 2, 3, , }; }";
173   // FIXME: redundant trailing comma should also be removed.
174   Expected = "void f() { std::vector<int> v = {1, 2, 3,  }; }";
175   EXPECT_EQ(Expected, cleanupAroundOffsets({42, 44}, Code));
176 }
177 
178 TEST_F(CleanupTest, CtorInitializationBracesInParens) {
179   std::string Code = "class A {\nA() : x({1}),, {} };";
180   std::string Expected = "class A {\nA() : x({1}) {} };";
181   EXPECT_EQ(Expected, cleanupAroundOffsets({24, 26}, Code));
182 }
183 
184 TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
185   std::string Code =
186       "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
187   std::string Expected =
188       "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
189   // Set the affected range to be "int x = 0", which does not intercept the
190   // constructor initialization list.
191   std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9));
192   std::string Result = cleanup(Code, Ranges);
193   EXPECT_EQ(Expected, Result);
194 
195   Code = "class A {\nA() : x(1), {} };";
196   Expected = "class A {\nA() : x(1), {} };";
197   // No range. Fixer should do nothing.
198   Ranges.clear();
199   Result = cleanup(Code, Ranges);
200   EXPECT_EQ(Expected, Result);
201 }
202 
203 TEST_F(CleanupTest, RemoveCommentsAroundDeleteCode) {
204   std::string Code =
205       "class A {\nA() : x({1}), /* comment */, /* comment */ {} };";
206   std::string Expected = "class A {\nA() : x({1}) {} };";
207   EXPECT_EQ(Expected, cleanupAroundOffsets({25, 40}, Code));
208 
209   Code = "class A {\nA() : x({1}), // comment\n {} };";
210   Expected = "class A {\nA() : x({1})\n {} };";
211   EXPECT_EQ(Expected, cleanupAroundOffsets({25}, Code));
212 
213   Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };";
214   Expected = "class A {\nA() : x({1}),  y(1){} };";
215   EXPECT_EQ(Expected, cleanupAroundOffsets({38}, Code));
216 
217   Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };";
218   Expected = "class A {\nA() : x({1}), \n y(1){} };";
219   EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
220 
221   Code = "class A {\nA() : , // comment\n y(1),{} };";
222   Expected = "class A {\nA() :  // comment\n y(1){} };";
223   EXPECT_EQ(Expected, cleanupAroundOffsets({17}, Code));
224 }
225 
226 TEST_F(CleanupTest, CtorInitializerInNamespace) {
227   std::string Code = "namespace A {\n"
228                      "namespace B {\n" // missing r_brace
229                      "} // namespace A\n\n"
230                      "namespace C {\n"
231                      "class A { A() : x(0),, {} };\n"
232                      "inline namespace E { namespace { } }\n"
233                      "}";
234   std::string Expected = "namespace A {\n"
235                          "\n\n\nnamespace C {\n"
236                          "class A { A() : x(0) {} };\n   \n"
237                          "}";
238   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
239   std::string Result = cleanup(Code, Ranges);
240   EXPECT_EQ(Expected, Result);
241 }
242 
243 class CleanUpReplacementsTest : public ReplacementTest {
244 protected:
245   tooling::Replacement createReplacement(unsigned Offset, unsigned Length,
246                                          StringRef Text) {
247     return tooling::Replacement(FileName, Offset, Length, Text);
248   }
249 
250   tooling::Replacement createInsertion(StringRef IncludeDirective) {
251     return createReplacement(UINT_MAX, 0, IncludeDirective);
252   }
253 
254   tooling::Replacement createDeletion(StringRef HeaderName) {
255     return createReplacement(UINT_MAX, 1, HeaderName);
256   }
257 
258   inline std::string apply(StringRef Code,
259                            const tooling::Replacements Replaces) {
260     auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
261     EXPECT_TRUE(static_cast<bool>(CleanReplaces))
262         << llvm::toString(CleanReplaces.takeError()) << "\n";
263     auto Result = applyAllReplacements(Code, *CleanReplaces);
264     EXPECT_TRUE(static_cast<bool>(Result));
265     return *Result;
266   }
267 
268   inline std::string formatAndApply(StringRef Code,
269                                     const tooling::Replacements Replaces) {
270 
271     auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
272     EXPECT_TRUE(static_cast<bool>(CleanReplaces))
273         << llvm::toString(CleanReplaces.takeError()) << "\n";
274     auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style);
275     EXPECT_TRUE(static_cast<bool>(FormattedReplaces))
276         << llvm::toString(FormattedReplaces.takeError()) << "\n";
277     auto Result = applyAllReplacements(Code, *FormattedReplaces);
278     EXPECT_TRUE(static_cast<bool>(Result));
279     return *Result;
280   }
281 
282   int getOffset(StringRef Code, int Line, int Column) {
283     RewriterTestContext Context;
284     FileID ID = Context.createInMemoryFile(FileName, Code);
285     auto DecomposedLocation =
286         Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column));
287     return DecomposedLocation.second;
288   }
289 
290   const std::string FileName = "fix.cpp";
291   FormatStyle Style = getLLVMStyle();
292 };
293 
294 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
295   std::string Code = "namespace A {\n"
296                      "namespace B {\n"
297                      "  int x;\n"
298                      "} // namespace B\n"
299                      "} // namespace A\n"
300                      "\n"
301                      "namespace C {\n"
302                      "namespace D { int i; }\n"
303                      "inline namespace E { namespace { int y; } }\n"
304                      "int x=     0;"
305                      "}";
306   std::string Expected = "\n\nnamespace C {\n"
307                          "namespace D { int i; }\n\n"
308                          "int x=     0;"
309                          "}";
310   tooling::Replacements Replaces =
311       toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
312                       createReplacement(getOffset(Code, 9, 34), 6, "")});
313 
314   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
315 }
316 
317 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
318   std::string Code = "int main() {}";
319   std::string Expected = "#include \"a.h\"\n"
320                          "int main() {}";
321   tooling::Replacements Replaces =
322       toReplacements({createInsertion("#include \"a.h\"")});
323   EXPECT_EQ(Expected, apply(Code, Replaces));
324 }
325 
326 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
327   std::string Code = "#ifndef A_H\n"
328                      "#define A_H\n"
329                      "class A {};\n"
330                      "#define MMM 123\n"
331                      "#endif";
332   std::string Expected = "#ifndef A_H\n"
333                          "#define A_H\n"
334                          "#include \"b.h\"\n"
335                          "class A {};\n"
336                          "#define MMM 123\n"
337                          "#endif";
338 
339   tooling::Replacements Replaces =
340       toReplacements({createInsertion("#include \"b.h\"")});
341   EXPECT_EQ(Expected, apply(Code, Replaces));
342 }
343 
344 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
345   std::string Code = "#ifndef A_H\n"
346                      "#define A_H\n"
347                      "\n"
348                      "\n"
349                      "\n"
350                      "#include <vector>\n"
351                      "class A {};\n"
352                      "#define MMM 123\n"
353                      "#endif";
354   std::string Expected = "#ifndef A_H\n"
355                          "#define A_H\n"
356                          "\n"
357                          "\n"
358                          "\n"
359                          "#include \"a.h\"\n"
360                          "#include <vector>\n"
361                          "class A {};\n"
362                          "#define MMM 123\n"
363                          "#endif";
364 
365   tooling::Replacements Replaces =
366       toReplacements({createInsertion("#include \"a.h\"")});
367   EXPECT_EQ(Expected, apply(Code, Replaces));
368 }
369 
370 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
371   std::string Code = "#include \"fix.h\"\n"
372                      "\n"
373                      "int main() {}";
374   std::string Expected = "#include \"fix.h\"\n"
375                          "#include <a>\n"
376                          "\n"
377                          "int main() {}";
378   tooling::Replacements Replaces =
379       toReplacements({createInsertion("#include <a>")});
380   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
381   EXPECT_EQ(Expected, apply(Code, Replaces));
382 }
383 
384 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
385   std::string Code = "#include <memory>\n"
386                      "\n"
387                      "int main() {}";
388   std::string Expected = "#include \"z.h\"\n"
389                          "#include <memory>\n"
390                          "\n"
391                          "int main() {}";
392   tooling::Replacements Replaces =
393       toReplacements({createInsertion("#include \"z.h\"")});
394   EXPECT_EQ(Expected, apply(Code, Replaces));
395 }
396 
397 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
398   std::string Code = "#include <memory>\n"
399                      "\n"
400                      "int main() {}";
401   std::string Expected = "#include <memory>\n"
402                          "#include \"z.h\"\n"
403                          "\n"
404                          "int main() {}";
405   tooling::Replacements Replaces =
406       toReplacements({createInsertion("#include \"z.h\"")});
407   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
408   EXPECT_EQ(Expected, apply(Code, Replaces));
409 }
410 
411 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
412   std::string Code = "#include \"x/fix.h\"\n"
413                      "#include \"a.h\"\n"
414                      "#include \"b.h\"\n"
415                      "#include \"clang/Format/Format.h\"\n"
416                      "#include <memory>\n";
417   std::string Expected = "#include \"x/fix.h\"\n"
418                          "#include \"a.h\"\n"
419                          "#include \"b.h\"\n"
420                          "#include \"d.h\"\n"
421                          "#include \"clang/Format/Format.h\"\n"
422                          "#include \"llvm/x/y.h\"\n"
423                          "#include <memory>\n";
424   tooling::Replacements Replaces =
425       toReplacements({createInsertion("#include \"d.h\""),
426                       createInsertion("#include \"llvm/x/y.h\"")});
427   EXPECT_EQ(Expected, apply(Code, Replaces));
428 }
429 
430 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
431   std::string Code = "#include \"x/fix.h\"\n"
432                      "#include \"a.h\"\n"
433                      "#include \"b.h\"\n"
434                      "#include \"clang/Format/Format.h\"\n"
435                      "#include <memory>\n";
436   std::string Expected = "#include \"x/fix.h\"\n"
437                          "#include \"a.h\"\n"
438                          "#include \"b.h\"\n"
439                          "#include \"new/new.h\"\n"
440                          "#include \"clang/Format/Format.h\"\n"
441                          "#include <memory>\n"
442                          "#include <list>\n";
443   tooling::Replacements Replaces =
444       toReplacements({createInsertion("#include <list>"),
445                       createInsertion("#include \"new/new.h\"")});
446   EXPECT_EQ(Expected, apply(Code, Replaces));
447 }
448 
449 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
450   std::string Code = "#include \"x/fix.h\"\n"
451                      "\n"
452                      "#include \"y/a.h\"\n"
453                      "#include \"z/b.h\"\n";
454   // FIXME: inserting after the empty line following the main header might be
455   // prefered.
456   std::string Expected = "#include \"x/fix.h\"\n"
457                          "#include <vector>\n"
458                          "\n"
459                          "#include \"y/a.h\"\n"
460                          "#include \"z/b.h\"\n";
461   tooling::Replacements Replaces =
462       toReplacements({createInsertion("#include <vector>")});
463   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
464   EXPECT_EQ(Expected, apply(Code, Replaces));
465 }
466 
467 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
468   std::string Code = "#include \"x/fix.h\"\n"
469                      "\n"
470                      "#include <vector>\n"
471                      "\n"
472                      "#include \"y/a.h\"\n"
473                      "#include \"z/b.h\"\n";
474   std::string Expected = "#include \"x/fix.h\"\n"
475                          "\n"
476                          "#include <vector>\n"
477                          "#include <list>\n"
478                          "\n"
479                          "#include \"y/a.h\"\n"
480                          "#include \"z/b.h\"\n"
481                          "#include \"x/x.h\"\n";
482   tooling::Replacements Replaces =
483       toReplacements({createInsertion("#include <list>"),
484                       createInsertion("#include \"x/x.h\"")});
485   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
486   EXPECT_EQ(Expected, apply(Code, Replaces));
487 }
488 
489 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) {
490   std::string Code = "\nint x;";
491   std::string Expected = "\n#include \"fix.h\"\n"
492                          "#include \"a.h\"\n"
493                          "#include \"b.h\"\n"
494                          "#include \"c.h\"\n"
495                          "#include <list>\n"
496                          "#include <vector>\n"
497                          "int x;";
498   tooling::Replacements Replaces = toReplacements(
499       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
500        createInsertion("#include \"b.h\""),
501        createInsertion("#include <vector>"), createInsertion("#include <list>"),
502        createInsertion("#include \"fix.h\"")});
503   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
504 }
505 
506 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
507   std::string Code = "\nint x;";
508   std::string Expected = "\n#include \"fix.h\"\n"
509                          "#include <list>\n"
510                          "#include <vector>\n"
511                          "#include \"a.h\"\n"
512                          "#include \"b.h\"\n"
513                          "#include \"c.h\"\n"
514                          "int x;";
515   tooling::Replacements Replaces = toReplacements(
516       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
517        createInsertion("#include \"b.h\""),
518        createInsertion("#include <vector>"), createInsertion("#include <list>"),
519        createInsertion("#include \"fix.h\"")});
520   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
521   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
522 }
523 
524 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
525   std::string Code = "\n"
526                      "int x;\n"
527                      "int    a;\n"
528                      "int    a;\n"
529                      "int    a;";
530 
531   std::string Expected = "\n#include \"x.h\"\n"
532                          "#include \"y.h\"\n"
533                          "#include \"clang/x/x.h\"\n"
534                          "#include <list>\n"
535                          "#include <vector>\n"
536                          "int x;\n"
537                          "int    a;\n"
538                          "int b;\n"
539                          "int    a;";
540   tooling::Replacements Replaces = toReplacements(
541       {createReplacement(getOffset(Code, 4, 8), 1, "b"),
542        createInsertion("#include <vector>"), createInsertion("#include <list>"),
543        createInsertion("#include \"clang/x/x.h\""),
544        createInsertion("#include \"y.h\""),
545        createInsertion("#include \"x.h\"")});
546   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
547 }
548 
549 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
550   std::string Code = "void f() {}\n"
551                      "#define A \\\n"
552                      "  int i;";
553   std::string Expected = "#include <vector>\n"
554                          "void f() {}\n"
555                          "#define A \\\n"
556                          "  int i;";
557   tooling::Replacements Replaces =
558       toReplacements({createInsertion("#include <vector>")});
559   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
560 }
561 
562 TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
563   std::string Code = "// comment\n"
564                      "\n"
565                      "   // comment\n";
566   std::string Expected = "// comment\n"
567                          "\n"
568                          "   // comment\n"
569                          "#include <vector>\n";
570   tooling::Replacements Replaces =
571       toReplacements({createInsertion("#include <vector>")});
572   EXPECT_EQ(Expected, apply(Code, Replaces));
573 }
574 
575 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
576   std::string Code = "// comment\n"
577                      "// comment \\\n"
578                      " comment continued\n"
579                      "/*\n"
580                      "* comment\n"
581                      "*/\n";
582   std::string Expected = "// comment\n"
583                          "// comment \\\n"
584                          " comment continued\n"
585                          "/*\n"
586                          "* comment\n"
587                          "*/\n"
588                          "#include <vector>\n";
589   tooling::Replacements Replaces =
590       toReplacements({createInsertion("#include <vector>")});
591   EXPECT_EQ(Expected, apply(Code, Replaces));
592 }
593 
594 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
595   std::string Code = "/*\n"
596                      "* comment\n"
597                      "*/ /* comment\n"
598                      "*/\n"
599                      "\n\n"
600                      "/* c1 */ /*c2 */\n";
601   std::string Expected = "/*\n"
602                          "* comment\n"
603                          "*/ /* comment\n"
604                          "*/\n"
605                          "\n\n"
606                          "/* c1 */ /*c2 */\n"
607                          "#include <vector>\n";
608   tooling::Replacements Replaces =
609       toReplacements({createInsertion("#include <vector>")});
610   EXPECT_EQ(Expected, apply(Code, Replaces));
611 }
612 
613 TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
614   std::string Code = "/*\n"
615                      "* comment\n"
616                      "*/ /* comment\n"
617                      "*/\n"
618                      "\n\n"
619                      "/* c1 */ /*c2 */\n"
620                      "\n"
621                      "int x;\n";
622   std::string Expected = "/*\n"
623                          "* comment\n"
624                          "*/ /* comment\n"
625                          "*/\n"
626                          "\n\n"
627                          "/* c1 */ /*c2 */\n"
628                          "\n"
629                          "#include <vector>\n"
630                          "int x;\n";
631   tooling::Replacements Replaces =
632       toReplacements({createInsertion("#include <vector>")});
633   EXPECT_EQ(Expected, apply(Code, Replaces));
634 }
635 
636 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
637   std::string Code = "// comment \n"
638                      "#ifdef X\n"
639                      "#define X\n";
640   std::string Expected = "// comment \n"
641                          "#include <vector>\n"
642                          "#ifdef X\n"
643                          "#define X\n";
644   tooling::Replacements Replaces =
645       toReplacements({createInsertion("#include <vector>")});
646   EXPECT_EQ(Expected, apply(Code, Replaces));
647 }
648 
649 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
650   std::string Code = "// comment \n"
651                      "#ifndef X\n"
652                      "#define X\n"
653                      "int x;\n"
654                      "#define Y 1\n";
655   std::string Expected = "// comment \n"
656                          "#ifndef X\n"
657                          "#define X\n"
658                          "#include <vector>\n"
659                          "int x;\n"
660                          "#define Y 1\n";
661   tooling::Replacements Replaces =
662       toReplacements({createInsertion("#include <vector>")});
663   EXPECT_EQ(Expected, apply(Code, Replaces));
664 }
665 
666 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
667   std::string Code = "// comment \n"
668                      "#ifndef X\n"
669                      "int x;\n"
670                      "#define Y 1\n";
671   std::string Expected = "// comment \n"
672                          "#include <vector>\n"
673                          "#ifndef X\n"
674                          "int x;\n"
675                          "#define Y 1\n";
676   tooling::Replacements Replaces =
677       toReplacements({createInsertion("#include <vector>")});
678   EXPECT_EQ(Expected, apply(Code, Replaces));
679 }
680 
681 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
682   std::string Code = "// comment \n"
683                      "#ifndef X // comment\n"
684                      "// comment\n"
685                      "/* comment\n"
686                      "*/\n"
687                      "/* comment */ #define X\n"
688                      "int x;\n"
689                      "#define Y 1\n";
690   std::string Expected = "// comment \n"
691                          "#ifndef X // comment\n"
692                          "// comment\n"
693                          "/* comment\n"
694                          "*/\n"
695                          "/* comment */ #define X\n"
696                          "#include <vector>\n"
697                          "int x;\n"
698                          "#define Y 1\n";
699   tooling::Replacements Replaces =
700       toReplacements({createInsertion("#include <vector>")});
701   EXPECT_EQ(Expected, apply(Code, Replaces));
702 }
703 
704 TEST_F(CleanUpReplacementsTest, EmptyCode) {
705   std::string Code = "";
706   std::string Expected = "#include <vector>\n";
707   tooling::Replacements Replaces =
708       toReplacements({createInsertion("#include <vector>")});
709   EXPECT_EQ(Expected, apply(Code, Replaces));
710 }
711 
712 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
713   std::string Code = "#include <map>";
714   std::string Expected = "#include <map>\n#include <vector>\n";
715   tooling::Replacements Replaces =
716       toReplacements({createInsertion("#include <vector>")});
717   EXPECT_EQ(Expected, apply(Code, Replaces));
718 }
719 
720 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) {
721   std::string Code = "#include <map>";
722   std::string Expected =
723       "#include <map>\n#include <string>\n#include <vector>\n";
724   tooling::Replacements Replaces =
725       toReplacements({createInsertion("#include <string>"),
726                       createInsertion("#include <vector>")});
727   EXPECT_EQ(Expected, apply(Code, Replaces));
728 }
729 
730 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
731   std::string Code = "#include \"a.h\"\n"
732                      "#include <vector>\n";
733   std::string Expected = "#include \"a.h\"\n"
734                          "#include <vector>\n";
735   tooling::Replacements Replaces =
736       toReplacements({createInsertion("#include <vector>"),
737                       createInsertion("#include \"a.h\"")});
738   EXPECT_EQ(Expected, apply(Code, Replaces));
739 }
740 
741 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
742   std::string Code = "#include \"a.h\"\n"
743                      "#include <vector>\n";
744   // FIXME: this might not be the best behavior.
745   std::string Expected = "#include \"a.h\"\n"
746                          "#include \"vector\"\n"
747                          "#include <vector>\n"
748                          "#include <a.h>\n";
749   tooling::Replacements Replaces =
750       toReplacements({createInsertion("#include \"vector\""),
751                       createInsertion("#include <a.h>")});
752   EXPECT_EQ(Expected, apply(Code, Replaces));
753 }
754 
755 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) {
756   std::string Code = "#include \"abc.h\"\n"
757                      "#include \"xyz.h\" // comment\n"
758                      "#include \"xyz\"\n"
759                      "int x;\n";
760   std::string Expected = "#include \"xyz\"\n"
761                          "int x;\n";
762   tooling::Replacements Replaces =
763       toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")});
764   EXPECT_EQ(Expected, apply(Code, Replaces));
765 }
766 
767 TEST_F(CleanUpReplacementsTest, DeleteAllCode) {
768   std::string Code = "#include \"xyz.h\"\n"
769                      "#include <xyz.h>";
770   std::string Expected = "";
771   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
772   EXPECT_EQ(Expected, apply(Code, Replaces));
773 }
774 
775 TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) {
776   std::string Code = "#include \"xyz.h\"\n"
777                      "#include \"xyz\"\n"
778                      "#include <xyz.h>\n";
779   std::string Expected = "#include \"xyz\"\n";
780   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
781   EXPECT_EQ(Expected, apply(Code, Replaces));
782 }
783 
784 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) {
785   std::string Code = "#include \"xyz.h\"\n"
786                      "#include \"xyz\"\n"
787                      "#include <xyz.h>";
788   std::string Expected = "#include \"xyz.h\"\n"
789                          "#include \"xyz\"\n";
790   tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")});
791   EXPECT_EQ(Expected, apply(Code, Replaces));
792 }
793 
794 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) {
795   std::string Code = "#include \"a.h\"\n"
796                      "\n"
797                      "#include <vector>\n";
798   std::string Expected = "#include \"a.h\"\n"
799                          "\n"
800                          "#include <map>\n";
801   tooling::Replacements Replaces = toReplacements(
802       {createDeletion("<vector>"), createInsertion("#include <map>")});
803   EXPECT_EQ(Expected, apply(Code, Replaces));
804 }
805 
806 } // end namespace
807 } // end namespace format
808 } // end namespace clang
809