xref: /llvm-project/clang/unittests/Format/CleanupTest.cpp (revision 531dbc7c17f58ed0df9366aff9615a80559eeaf2)
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, EmptyNamespaceAroundConditionalCompilation) {
123   std::string Code = "#ifdef A\n"
124                      "int a;\n"
125                      "int b;\n"
126                      "#else\n"
127                      "#endif\n"
128                      "namespace {}";
129   std::string Expected = "#ifdef A\n"
130                          "int a;\n"
131                          "int b;\n"
132                          "#else\n"
133                          "#endif\n";
134   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
135   FormatStyle Style = getLLVMStyle();
136   std::string Result = cleanup(Code, Ranges, Style);
137   EXPECT_EQ(Expected, Result);
138 }
139 
140 TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) {
141   std::string Code = "class A {\nA() : , {} };";
142   std::string Expected = "class A {\nA()  {} };";
143   EXPECT_EQ(Expected, cleanupAroundOffsets({17, 19}, Code));
144 
145   Code = "class A {\nA() : x(1), {} };";
146   Expected = "class A {\nA() : x(1) {} };";
147   EXPECT_EQ(Expected, cleanupAroundOffsets({23}, Code));
148 
149   Code = "class A {\nA() :,,,,{} };";
150   Expected = "class A {\nA() {} };";
151   EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
152 }
153 
154 TEST_F(CleanupTest, CtorInitializationSimpleRedundantColon) {
155   std::string Code = "class A {\nA() : =default; };";
156   std::string Expected = "class A {\nA()  =default; };";
157   EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
158 
159   Code = "class A {\nA() : , =default; };";
160   Expected = "class A {\nA()  =default; };";
161   EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
162 }
163 
164 TEST_F(CleanupTest, ListRedundantComma) {
165   std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }";
166   std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }";
167   EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
168 
169   Code = "int main() { f(1,,2,3,,4);}";
170   Expected = "int main() { f(1,2,3,4);}";
171   EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code));
172 }
173 
174 TEST_F(CleanupTest, TrailingCommaInParens) {
175   std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}";
176   std::string Expected = "int main() { f(1,2,3,f(1,2),4);}";
177   EXPECT_EQ(Expected, cleanupAroundOffsets({15, 18, 29, 33}, Code));
178 }
179 
180 TEST_F(CleanupTest, TrailingCommaInBraces) {
181   // Trainling comma is allowed in brace list.
182   // If there was trailing comma in the original code, then trailing comma is
183   // preserved. In this example, element between the last two commas is deleted
184   // causing the second-last comma to be redundant.
185   std::string Code = "void f() { std::vector<int> v = {1,2,3,,}; }";
186   std::string Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
187   EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
188 
189   // If there was no trailing comma in the original code, then trainling comma
190   // introduced by replacements should be cleaned up. In this example, the
191   // element after the last comma is deleted causing the last comma to be
192   // redundant.
193   Code = "void f() { std::vector<int> v = {1,2,3,}; }";
194   // FIXME: redundant trailing comma should be removed.
195   Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
196   EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
197 
198   // Still no trailing comma in the original code, but two elements are deleted,
199   // which makes it seems like there was trailing comma.
200   Code = "void f() { std::vector<int> v = {1, 2, 3, , }; }";
201   // FIXME: redundant trailing comma should also be removed.
202   Expected = "void f() { std::vector<int> v = {1, 2, 3,  }; }";
203   EXPECT_EQ(Expected, cleanupAroundOffsets({42, 44}, Code));
204 }
205 
206 TEST_F(CleanupTest, CtorInitializationBracesInParens) {
207   std::string Code = "class A {\nA() : x({1}),, {} };";
208   std::string Expected = "class A {\nA() : x({1}) {} };";
209   EXPECT_EQ(Expected, cleanupAroundOffsets({24, 26}, Code));
210 }
211 
212 TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
213   std::string Code =
214       "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
215   std::string Expected =
216       "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
217   // Set the affected range to be "int x = 0", which does not intercept the
218   // constructor initialization list.
219   std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9));
220   std::string Result = cleanup(Code, Ranges);
221   EXPECT_EQ(Expected, Result);
222 
223   Code = "class A {\nA() : x(1), {} };";
224   Expected = "class A {\nA() : x(1), {} };";
225   // No range. Fixer should do nothing.
226   Ranges.clear();
227   Result = cleanup(Code, Ranges);
228   EXPECT_EQ(Expected, Result);
229 }
230 
231 TEST_F(CleanupTest, RemoveCommentsAroundDeleteCode) {
232   std::string Code =
233       "class A {\nA() : x({1}), /* comment */, /* comment */ {} };";
234   std::string Expected = "class A {\nA() : x({1}) {} };";
235   EXPECT_EQ(Expected, cleanupAroundOffsets({25, 40}, Code));
236 
237   Code = "class A {\nA() : x({1}), // comment\n {} };";
238   Expected = "class A {\nA() : x({1})\n {} };";
239   EXPECT_EQ(Expected, cleanupAroundOffsets({25}, Code));
240 
241   Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };";
242   Expected = "class A {\nA() : x({1}),  y(1){} };";
243   EXPECT_EQ(Expected, cleanupAroundOffsets({38}, Code));
244 
245   Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };";
246   Expected = "class A {\nA() : x({1}), \n y(1){} };";
247   EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
248 
249   Code = "class A {\nA() : , // comment\n y(1),{} };";
250   Expected = "class A {\nA() :  // comment\n y(1){} };";
251   EXPECT_EQ(Expected, cleanupAroundOffsets({17}, Code));
252 
253   Code = "class A {\nA() // comment\n : ,,{} };";
254   Expected = "class A {\nA() // comment\n {} };";
255   EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code));
256 
257   Code = "class A {\nA() // comment\n : ,,=default; };";
258   Expected = "class A {\nA() // comment\n =default; };";
259   EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code));
260 }
261 
262 TEST_F(CleanupTest, CtorInitializerInNamespace) {
263   std::string Code = "namespace A {\n"
264                      "namespace B {\n" // missing r_brace
265                      "} // namespace A\n\n"
266                      "namespace C {\n"
267                      "class A { A() : x(0),, {} };\n"
268                      "inline namespace E { namespace { } }\n"
269                      "}";
270   std::string Expected = "namespace A {\n"
271                          "\n\n\nnamespace C {\n"
272                          "class A { A() : x(0) {} };\n   \n"
273                          "}";
274   std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
275   std::string Result = cleanup(Code, Ranges);
276   EXPECT_EQ(Expected, Result);
277 }
278 
279 class CleanUpReplacementsTest : public ReplacementTest {
280 protected:
281   tooling::Replacement createReplacement(unsigned Offset, unsigned Length,
282                                          StringRef Text) {
283     return tooling::Replacement(FileName, Offset, Length, Text);
284   }
285 
286   tooling::Replacement createInsertion(StringRef IncludeDirective) {
287     return createReplacement(UINT_MAX, 0, IncludeDirective);
288   }
289 
290   tooling::Replacement createDeletion(StringRef HeaderName) {
291     return createReplacement(UINT_MAX, 1, HeaderName);
292   }
293 
294   inline std::string apply(StringRef Code,
295                            const tooling::Replacements &Replaces) {
296     auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
297     EXPECT_TRUE(static_cast<bool>(CleanReplaces))
298         << llvm::toString(CleanReplaces.takeError()) << "\n";
299     auto Result = applyAllReplacements(Code, *CleanReplaces);
300     EXPECT_TRUE(static_cast<bool>(Result));
301     return *Result;
302   }
303 
304   inline std::string formatAndApply(StringRef Code,
305                                     const tooling::Replacements &Replaces) {
306     auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
307     EXPECT_TRUE(static_cast<bool>(CleanReplaces))
308         << llvm::toString(CleanReplaces.takeError()) << "\n";
309     auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style);
310     EXPECT_TRUE(static_cast<bool>(FormattedReplaces))
311         << llvm::toString(FormattedReplaces.takeError()) << "\n";
312     auto Result = applyAllReplacements(Code, *FormattedReplaces);
313     EXPECT_TRUE(static_cast<bool>(Result));
314     return *Result;
315   }
316 
317   int getOffset(StringRef Code, int Line, int Column) {
318     RewriterTestContext Context;
319     FileID ID = Context.createInMemoryFile(FileName, Code);
320     auto DecomposedLocation =
321         Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column));
322     return DecomposedLocation.second;
323   }
324 
325   const std::string FileName = "fix.cpp";
326   FormatStyle Style = getLLVMStyle();
327 };
328 
329 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
330   std::string Code = "namespace A {\n"
331                      "namespace B {\n"
332                      "  int x;\n"
333                      "} // namespace B\n"
334                      "} // namespace A\n"
335                      "\n"
336                      "namespace C {\n"
337                      "namespace D { int i; }\n"
338                      "inline namespace E { namespace { int y; } }\n"
339                      "int x=     0;"
340                      "}";
341   std::string Expected = "\n\nnamespace C {\n"
342                          "namespace D { int i; }\n\n"
343                          "int x=     0;"
344                          "}";
345   tooling::Replacements Replaces =
346       toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
347                       createReplacement(getOffset(Code, 9, 34), 6, "")});
348 
349   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
350 }
351 
352 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
353   std::string Code = "int main() {}";
354   std::string Expected = "#include \"a.h\"\n"
355                          "int main() {}";
356   tooling::Replacements Replaces =
357       toReplacements({createInsertion("#include \"a.h\"")});
358   EXPECT_EQ(Expected, apply(Code, Replaces));
359 }
360 
361 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
362   std::string Code = "#ifndef A_H\n"
363                      "#define A_H\n"
364                      "class A {};\n"
365                      "#define MMM 123\n"
366                      "#endif";
367   std::string Expected = "#ifndef A_H\n"
368                          "#define A_H\n"
369                          "#include \"b.h\"\n"
370                          "class A {};\n"
371                          "#define MMM 123\n"
372                          "#endif";
373 
374   tooling::Replacements Replaces =
375       toReplacements({createInsertion("#include \"b.h\"")});
376   EXPECT_EQ(Expected, apply(Code, Replaces));
377 }
378 
379 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
380   std::string Code = "#ifndef A_H\n"
381                      "#define A_H\n"
382                      "\n"
383                      "\n"
384                      "\n"
385                      "#include <vector>\n"
386                      "class A {};\n"
387                      "#define MMM 123\n"
388                      "#endif";
389   std::string Expected = "#ifndef A_H\n"
390                          "#define A_H\n"
391                          "\n"
392                          "\n"
393                          "\n"
394                          "#include \"a.h\"\n"
395                          "#include <vector>\n"
396                          "class A {};\n"
397                          "#define MMM 123\n"
398                          "#endif";
399 
400   tooling::Replacements Replaces =
401       toReplacements({createInsertion("#include \"a.h\"")});
402   EXPECT_EQ(Expected, apply(Code, Replaces));
403 }
404 
405 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
406   std::string Code = "#include \"fix.h\"\n"
407                      "\n"
408                      "int main() {}";
409   std::string Expected = "#include \"fix.h\"\n"
410                          "#include <a>\n"
411                          "\n"
412                          "int main() {}";
413   tooling::Replacements Replaces =
414       toReplacements({createInsertion("#include <a>")});
415   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
416   EXPECT_EQ(Expected, apply(Code, Replaces));
417 }
418 
419 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
420   std::string Code = "#include <memory>\n"
421                      "\n"
422                      "int main() {}";
423   std::string Expected = "#include \"z.h\"\n"
424                          "#include <memory>\n"
425                          "\n"
426                          "int main() {}";
427   tooling::Replacements Replaces =
428       toReplacements({createInsertion("#include \"z.h\"")});
429   EXPECT_EQ(Expected, apply(Code, Replaces));
430 }
431 
432 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
433   std::string Code = "#include <memory>\n"
434                      "\n"
435                      "int main() {}";
436   std::string Expected = "#include <memory>\n"
437                          "#include \"z.h\"\n"
438                          "\n"
439                          "int main() {}";
440   tooling::Replacements Replaces =
441       toReplacements({createInsertion("#include \"z.h\"")});
442   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
443   EXPECT_EQ(Expected, apply(Code, Replaces));
444 }
445 
446 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
447   std::string Code = "#include \"x/fix.h\"\n"
448                      "#include \"a.h\"\n"
449                      "#include \"b.h\"\n"
450                      "#include \"clang/Format/Format.h\"\n"
451                      "#include <memory>\n";
452   std::string Expected = "#include \"x/fix.h\"\n"
453                          "#include \"a.h\"\n"
454                          "#include \"b.h\"\n"
455                          "#include \"d.h\"\n"
456                          "#include \"clang/Format/Format.h\"\n"
457                          "#include \"llvm/x/y.h\"\n"
458                          "#include <memory>\n";
459   tooling::Replacements Replaces =
460       toReplacements({createInsertion("#include \"d.h\""),
461                       createInsertion("#include \"llvm/x/y.h\"")});
462   EXPECT_EQ(Expected, apply(Code, Replaces));
463 }
464 
465 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
466   std::string Code = "#include \"x/fix.h\"\n"
467                      "#include \"a.h\"\n"
468                      "#include \"b.h\"\n"
469                      "#include \"clang/Format/Format.h\"\n"
470                      "#include <memory>\n";
471   std::string Expected = "#include \"x/fix.h\"\n"
472                          "#include \"a.h\"\n"
473                          "#include \"b.h\"\n"
474                          "#include \"new/new.h\"\n"
475                          "#include \"clang/Format/Format.h\"\n"
476                          "#include <memory>\n"
477                          "#include <list>\n";
478   tooling::Replacements Replaces =
479       toReplacements({createInsertion("#include <list>"),
480                       createInsertion("#include \"new/new.h\"")});
481   EXPECT_EQ(Expected, apply(Code, Replaces));
482 }
483 
484 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
485   std::string Code = "#include \"x/fix.h\"\n"
486                      "\n"
487                      "#include \"y/a.h\"\n"
488                      "#include \"z/b.h\"\n";
489   // FIXME: inserting after the empty line following the main header might be
490   // prefered.
491   std::string Expected = "#include \"x/fix.h\"\n"
492                          "#include <vector>\n"
493                          "\n"
494                          "#include \"y/a.h\"\n"
495                          "#include \"z/b.h\"\n";
496   tooling::Replacements Replaces =
497       toReplacements({createInsertion("#include <vector>")});
498   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
499   EXPECT_EQ(Expected, apply(Code, Replaces));
500 }
501 
502 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
503   std::string Code = "#include \"x/fix.h\"\n"
504                      "\n"
505                      "#include <vector>\n"
506                      "\n"
507                      "#include \"y/a.h\"\n"
508                      "#include \"z/b.h\"\n";
509   std::string Expected = "#include \"x/fix.h\"\n"
510                          "\n"
511                          "#include <vector>\n"
512                          "#include <list>\n"
513                          "\n"
514                          "#include \"y/a.h\"\n"
515                          "#include \"z/b.h\"\n"
516                          "#include \"x/x.h\"\n";
517   tooling::Replacements Replaces =
518       toReplacements({createInsertion("#include <list>"),
519                       createInsertion("#include \"x/x.h\"")});
520   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
521   EXPECT_EQ(Expected, apply(Code, Replaces));
522 }
523 
524 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) {
525   std::string Code = "\nint x;";
526   std::string Expected = "\n#include \"fix.h\"\n"
527                          "#include \"a.h\"\n"
528                          "#include \"b.h\"\n"
529                          "#include \"c.h\"\n"
530                          "#include <list>\n"
531                          "#include <vector>\n"
532                          "int x;";
533   tooling::Replacements Replaces = toReplacements(
534       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
535        createInsertion("#include \"b.h\""),
536        createInsertion("#include <vector>"), createInsertion("#include <list>"),
537        createInsertion("#include \"fix.h\"")});
538   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
539 }
540 
541 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
542   std::string Code = "\nint x;";
543   std::string Expected = "\n#include \"fix.h\"\n"
544                          "#include <list>\n"
545                          "#include <vector>\n"
546                          "#include \"a.h\"\n"
547                          "#include \"b.h\"\n"
548                          "#include \"c.h\"\n"
549                          "int x;";
550   tooling::Replacements Replaces = toReplacements(
551       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
552        createInsertion("#include \"b.h\""),
553        createInsertion("#include <vector>"), createInsertion("#include <list>"),
554        createInsertion("#include \"fix.h\"")});
555   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
556   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
557 }
558 
559 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
560   std::string Code = "\n"
561                      "int x;\n"
562                      "int    a;\n"
563                      "int    a;\n"
564                      "int    a;";
565 
566   std::string Expected = "\n#include \"x.h\"\n"
567                          "#include \"y.h\"\n"
568                          "#include \"clang/x/x.h\"\n"
569                          "#include <list>\n"
570                          "#include <vector>\n"
571                          "int x;\n"
572                          "int    a;\n"
573                          "int b;\n"
574                          "int    a;";
575   tooling::Replacements Replaces = toReplacements(
576       {createReplacement(getOffset(Code, 4, 8), 1, "b"),
577        createInsertion("#include <vector>"), createInsertion("#include <list>"),
578        createInsertion("#include \"clang/x/x.h\""),
579        createInsertion("#include \"y.h\""),
580        createInsertion("#include \"x.h\"")});
581   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
582 }
583 
584 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
585   std::string Code = "void f() {}\n"
586                      "#define A \\\n"
587                      "  int i;";
588   std::string Expected = "#include <vector>\n"
589                          "void f() {}\n"
590                          "#define A \\\n"
591                          "  int i;";
592   tooling::Replacements Replaces =
593       toReplacements({createInsertion("#include <vector>")});
594   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
595 }
596 
597 TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
598   std::string Code = "// comment\n"
599                      "\n"
600                      "   // comment\n";
601   std::string Expected = "// comment\n"
602                          "\n"
603                          "   // comment\n"
604                          "#include <vector>\n";
605   tooling::Replacements Replaces =
606       toReplacements({createInsertion("#include <vector>")});
607   EXPECT_EQ(Expected, apply(Code, Replaces));
608 }
609 
610 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
611   std::string Code = "// comment\n"
612                      "// comment \\\n"
613                      " comment continued\n"
614                      "/*\n"
615                      "* comment\n"
616                      "*/\n";
617   std::string Expected = "// comment\n"
618                          "// comment \\\n"
619                          " comment continued\n"
620                          "/*\n"
621                          "* comment\n"
622                          "*/\n"
623                          "#include <vector>\n";
624   tooling::Replacements Replaces =
625       toReplacements({createInsertion("#include <vector>")});
626   EXPECT_EQ(Expected, apply(Code, Replaces));
627 }
628 
629 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
630   std::string Code = "/*\n"
631                      "* comment\n"
632                      "*/ /* comment\n"
633                      "*/\n"
634                      "\n\n"
635                      "/* c1 */ /*c2 */\n";
636   std::string Expected = "/*\n"
637                          "* comment\n"
638                          "*/ /* comment\n"
639                          "*/\n"
640                          "\n\n"
641                          "/* c1 */ /*c2 */\n"
642                          "#include <vector>\n";
643   tooling::Replacements Replaces =
644       toReplacements({createInsertion("#include <vector>")});
645   EXPECT_EQ(Expected, apply(Code, Replaces));
646 }
647 
648 TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
649   std::string Code = "/*\n"
650                      "* comment\n"
651                      "*/ /* comment\n"
652                      "*/\n"
653                      "\n\n"
654                      "/* c1 */ /*c2 */\n"
655                      "\n"
656                      "int x;\n";
657   std::string Expected = "/*\n"
658                          "* comment\n"
659                          "*/ /* comment\n"
660                          "*/\n"
661                          "\n\n"
662                          "/* c1 */ /*c2 */\n"
663                          "\n"
664                          "#include <vector>\n"
665                          "int x;\n";
666   tooling::Replacements Replaces =
667       toReplacements({createInsertion("#include <vector>")});
668   EXPECT_EQ(Expected, apply(Code, Replaces));
669 }
670 
671 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
672   std::string Code = "// comment \n"
673                      "#ifdef X\n"
674                      "#define X\n";
675   std::string Expected = "// comment \n"
676                          "#include <vector>\n"
677                          "#ifdef X\n"
678                          "#define X\n";
679   tooling::Replacements Replaces =
680       toReplacements({createInsertion("#include <vector>")});
681   EXPECT_EQ(Expected, apply(Code, Replaces));
682 }
683 
684 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
685   std::string Code = "// comment \n"
686                      "#ifndef X\n"
687                      "#define X\n"
688                      "int x;\n"
689                      "#define Y 1\n";
690   std::string Expected = "// comment \n"
691                          "#ifndef X\n"
692                          "#define X\n"
693                          "#include <vector>\n"
694                          "int x;\n"
695                          "#define Y 1\n";
696   tooling::Replacements Replaces =
697       toReplacements({createInsertion("#include <vector>")});
698   EXPECT_EQ(Expected, apply(Code, Replaces));
699 }
700 
701 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
702   std::string Code = "// comment \n"
703                      "#ifndef X\n"
704                      "int x;\n"
705                      "#define Y 1\n";
706   std::string Expected = "// comment \n"
707                          "#include <vector>\n"
708                          "#ifndef X\n"
709                          "int x;\n"
710                          "#define Y 1\n";
711   tooling::Replacements Replaces =
712       toReplacements({createInsertion("#include <vector>")});
713   EXPECT_EQ(Expected, apply(Code, Replaces));
714 }
715 
716 TEST_F(CleanUpReplacementsTest, FakeHeaderGuard) {
717   std::string Code = "// comment \n"
718                      "#ifndef X\n"
719                      "#define 1\n";
720   std::string Expected = "// comment \n"
721                          "#include <vector>\n"
722                          "#ifndef X\n"
723                          "#define 1\n";
724   tooling::Replacements Replaces =
725       toReplacements({createInsertion("#include <vector>")});
726   EXPECT_EQ(Expected, apply(Code, Replaces));
727 }
728 
729 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
730   std::string Code = "// comment \n"
731                      "#ifndef X // comment\n"
732                      "// comment\n"
733                      "/* comment\n"
734                      "*/\n"
735                      "/* comment */ #define X\n"
736                      "int x;\n"
737                      "#define Y 1\n";
738   std::string Expected = "// comment \n"
739                          "#ifndef X // comment\n"
740                          "// comment\n"
741                          "/* comment\n"
742                          "*/\n"
743                          "/* comment */ #define X\n"
744                          "#include <vector>\n"
745                          "int x;\n"
746                          "#define Y 1\n";
747   tooling::Replacements Replaces =
748       toReplacements({createInsertion("#include <vector>")});
749   EXPECT_EQ(Expected, apply(Code, Replaces));
750 }
751 
752 TEST_F(CleanUpReplacementsTest, EmptyCode) {
753   std::string Code = "";
754   std::string Expected = "#include <vector>\n";
755   tooling::Replacements Replaces =
756       toReplacements({createInsertion("#include <vector>")});
757   EXPECT_EQ(Expected, apply(Code, Replaces));
758 }
759 
760 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
761   std::string Code = "#include <map>";
762   std::string Expected = "#include <map>\n#include <vector>\n";
763   tooling::Replacements Replaces =
764       toReplacements({createInsertion("#include <vector>")});
765   EXPECT_EQ(Expected, apply(Code, Replaces));
766 }
767 
768 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) {
769   std::string Code = "#include <map>";
770   std::string Expected =
771       "#include <map>\n#include <string>\n#include <vector>\n";
772   tooling::Replacements Replaces =
773       toReplacements({createInsertion("#include <string>"),
774                       createInsertion("#include <vector>")});
775   EXPECT_EQ(Expected, apply(Code, Replaces));
776 }
777 
778 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
779   std::string Code = "#include \"a.h\"\n"
780                      "#include <vector>\n";
781   std::string Expected = "#include \"a.h\"\n"
782                          "#include <vector>\n";
783   tooling::Replacements Replaces =
784       toReplacements({createInsertion("#include <vector>"),
785                       createInsertion("#include \"a.h\"")});
786   EXPECT_EQ(Expected, apply(Code, Replaces));
787 }
788 
789 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
790   std::string Code = "#include \"a.h\"\n"
791                      "#include <vector>\n";
792   // FIXME: this might not be the best behavior.
793   std::string Expected = "#include \"a.h\"\n"
794                          "#include \"vector\"\n"
795                          "#include <vector>\n"
796                          "#include <a.h>\n";
797   tooling::Replacements Replaces =
798       toReplacements({createInsertion("#include \"vector\""),
799                       createInsertion("#include <a.h>")});
800   EXPECT_EQ(Expected, apply(Code, Replaces));
801 }
802 
803 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) {
804   std::string Code = "#include \"abc.h\"\n"
805                      "#include \"xyz.h\" // comment\n"
806                      "#include \"xyz\"\n"
807                      "int x;\n";
808   std::string Expected = "#include \"xyz\"\n"
809                          "int x;\n";
810   tooling::Replacements Replaces =
811       toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")});
812   EXPECT_EQ(Expected, apply(Code, Replaces));
813 }
814 
815 TEST_F(CleanUpReplacementsTest, DeleteAllCode) {
816   std::string Code = "#include \"xyz.h\"\n"
817                      "#include <xyz.h>";
818   std::string Expected = "";
819   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
820   EXPECT_EQ(Expected, apply(Code, Replaces));
821 }
822 
823 TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) {
824   std::string Code = "#include \"xyz.h\"\n"
825                      "#include \"xyz\"\n"
826                      "#include <xyz.h>\n";
827   std::string Expected = "#include \"xyz\"\n";
828   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
829   EXPECT_EQ(Expected, apply(Code, Replaces));
830 }
831 
832 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) {
833   std::string Code = "#include \"xyz.h\"\n"
834                      "#include \"xyz\"\n"
835                      "#include <xyz.h>";
836   std::string Expected = "#include \"xyz.h\"\n"
837                          "#include \"xyz\"\n";
838   tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")});
839   EXPECT_EQ(Expected, apply(Code, Replaces));
840 }
841 
842 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) {
843   std::string Code = "#include \"a.h\"\n"
844                      "\n"
845                      "#include <vector>\n";
846   std::string Expected = "#include \"a.h\"\n"
847                          "\n"
848                          "#include <map>\n";
849   tooling::Replacements Replaces = toReplacements(
850       {createDeletion("<vector>"), createInsertion("#include <map>")});
851   EXPECT_EQ(Expected, apply(Code, Replaces));
852 }
853 
854 TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) {
855   std::string Code = "#include \"a.h\"\n"
856                      "void f() {}\n"
857                      "#include \"b.h\"\n";
858   std::string Expected = "#include \"a.h\"\n"
859                          "#include \"c.h\"\n"
860                          "void f() {}\n"
861                          "#include \"b.h\"\n";
862   tooling::Replacements Replaces = toReplacements(
863       {createInsertion("#include \"c.h\"")});
864   EXPECT_EQ(Expected, apply(Code, Replaces));
865 }
866 
867 TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) {
868   std::string Code = "#include \"a.h\"\n"
869                      "const char[] = R\"(\n"
870                      "#include \"b.h\"\n"
871                      ")\";\n";
872   std::string Expected = "#include \"a.h\"\n"
873                          "#include \"c.h\"\n"
874                          "const char[] = R\"(\n"
875                          "#include \"b.h\"\n"
876                          ")\";\n";
877   tooling::Replacements Replaces =
878       toReplacements({createInsertion("#include \"c.h\"")});
879   EXPECT_EQ(Expected, apply(Code, Replaces));
880 }
881 
882 TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) {
883   std::string Code = "#include \"a.h\"\n"
884                      "#ifdef X\n"
885                      "#include \"b.h\"\n"
886                      "#endif\n";
887   std::string Expected = "#include \"a.h\"\n"
888                          "#include \"c.h\"\n"
889                          "#ifdef X\n"
890                          "#include \"b.h\"\n"
891                          "#endif\n";
892   tooling::Replacements Replaces = toReplacements(
893       {createInsertion("#include \"c.h\"")});
894   EXPECT_EQ(Expected, apply(Code, Replaces));
895 }
896 
897 TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) {
898   std::string Code = "#include \"a.h\"\n"
899                      "// comment\n\n"
900                      "#include <a/b/c/d/e.h>\n";
901   std::string Expected = "#include \"a.h\"\n"
902                          "// comment\n\n"
903                          "#include <a/b/c/d/e.h>\n"
904                          "#include <x.h>\n";
905   tooling::Replacements Replaces =
906       toReplacements({createInsertion("#include <x.h>")});
907   EXPECT_EQ(Expected, apply(Code, Replaces));
908 }
909 
910 TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) {
911   std::string Code = "#include \"a.h\"\n"
912                      "// Comment\n"
913                      "\n"
914                      "/* Comment */\n"
915                      "// Comment\n"
916                      "\n"
917                      "#include \"b.h\"\n";
918   std::string Expected = "#include \"a.h\"\n"
919                          "// Comment\n"
920                          "\n"
921                          "/* Comment */\n"
922                          "// Comment\n"
923                          "\n"
924                          "#include \"b.h\"\n"
925                          "#include \"c.h\"\n";
926   tooling::Replacements Replaces =
927       toReplacements({createInsertion("#include \"c.h\"")});
928   EXPECT_EQ(Expected, apply(Code, Replaces));
929 }
930 
931 TEST_F(CleanUpReplacementsTest, LongCommentsInTheBeginningOfFile) {
932   std::string Code = "// Loooooooooooooooooooooooooong comment\n"
933                      "// Loooooooooooooooooooooooooong comment\n"
934                      "// Loooooooooooooooooooooooooong comment\n"
935                      "#include <string>\n"
936                      "#include <vector>\n"
937                      "\n"
938                      "#include \"a.h\"\n"
939                      "#include \"b.h\"\n";
940   std::string Expected = "// Loooooooooooooooooooooooooong comment\n"
941                          "// Loooooooooooooooooooooooooong comment\n"
942                          "// Loooooooooooooooooooooooooong comment\n"
943                          "#include <string>\n"
944                          "#include <vector>\n"
945                          "\n"
946                          "#include \"a.h\"\n"
947                          "#include \"b.h\"\n"
948                          "#include \"third.h\"\n";
949   tooling::Replacements Replaces =
950       toReplacements({createInsertion("#include \"third.h\"")});
951   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
952   EXPECT_EQ(Expected, apply(Code, Replaces));
953 }
954 
955 TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) {
956   std::string Code = "#include \"a.h\"\n"
957                      "void f() {}\n"
958                      "#include \"b.h\"\n";
959   std::string Expected = "#include \"a.h\"\n"
960                          "void f() {}\n";
961   tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")});
962   EXPECT_EQ(Expected, apply(Code, Replaces));
963 }
964 
965 } // end namespace
966 } // end namespace format
967 } // end namespace clang
968