xref: /llvm-project/clang/unittests/Format/CleanupTest.cpp (revision 964782adbb1dc17413707e173f323a19ff479c7d)
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 
307     auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
308     EXPECT_TRUE(static_cast<bool>(CleanReplaces))
309         << llvm::toString(CleanReplaces.takeError()) << "\n";
310     auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style);
311     EXPECT_TRUE(static_cast<bool>(FormattedReplaces))
312         << llvm::toString(FormattedReplaces.takeError()) << "\n";
313     auto Result = applyAllReplacements(Code, *FormattedReplaces);
314     EXPECT_TRUE(static_cast<bool>(Result));
315     return *Result;
316   }
317 
318   int getOffset(StringRef Code, int Line, int Column) {
319     RewriterTestContext Context;
320     FileID ID = Context.createInMemoryFile(FileName, Code);
321     auto DecomposedLocation =
322         Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column));
323     return DecomposedLocation.second;
324   }
325 
326   const std::string FileName = "fix.cpp";
327   FormatStyle Style = getLLVMStyle();
328 };
329 
330 TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
331   std::string Code = "namespace A {\n"
332                      "namespace B {\n"
333                      "  int x;\n"
334                      "} // namespace B\n"
335                      "} // namespace A\n"
336                      "\n"
337                      "namespace C {\n"
338                      "namespace D { int i; }\n"
339                      "inline namespace E { namespace { int y; } }\n"
340                      "int x=     0;"
341                      "}";
342   std::string Expected = "\n\nnamespace C {\n"
343                          "namespace D { int i; }\n\n"
344                          "int x=     0;"
345                          "}";
346   tooling::Replacements Replaces =
347       toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
348                       createReplacement(getOffset(Code, 9, 34), 6, "")});
349 
350   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
351 }
352 
353 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
354   std::string Code = "int main() {}";
355   std::string Expected = "#include \"a.h\"\n"
356                          "int main() {}";
357   tooling::Replacements Replaces =
358       toReplacements({createInsertion("#include \"a.h\"")});
359   EXPECT_EQ(Expected, apply(Code, Replaces));
360 }
361 
362 TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
363   std::string Code = "#ifndef A_H\n"
364                      "#define A_H\n"
365                      "class A {};\n"
366                      "#define MMM 123\n"
367                      "#endif";
368   std::string Expected = "#ifndef A_H\n"
369                          "#define A_H\n"
370                          "#include \"b.h\"\n"
371                          "class A {};\n"
372                          "#define MMM 123\n"
373                          "#endif";
374 
375   tooling::Replacements Replaces =
376       toReplacements({createInsertion("#include \"b.h\"")});
377   EXPECT_EQ(Expected, apply(Code, Replaces));
378 }
379 
380 TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
381   std::string Code = "#ifndef A_H\n"
382                      "#define A_H\n"
383                      "\n"
384                      "\n"
385                      "\n"
386                      "#include <vector>\n"
387                      "class A {};\n"
388                      "#define MMM 123\n"
389                      "#endif";
390   std::string Expected = "#ifndef A_H\n"
391                          "#define A_H\n"
392                          "\n"
393                          "\n"
394                          "\n"
395                          "#include \"a.h\"\n"
396                          "#include <vector>\n"
397                          "class A {};\n"
398                          "#define MMM 123\n"
399                          "#endif";
400 
401   tooling::Replacements Replaces =
402       toReplacements({createInsertion("#include \"a.h\"")});
403   EXPECT_EQ(Expected, apply(Code, Replaces));
404 }
405 
406 TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
407   std::string Code = "#include \"fix.h\"\n"
408                      "\n"
409                      "int main() {}";
410   std::string Expected = "#include \"fix.h\"\n"
411                          "#include <a>\n"
412                          "\n"
413                          "int main() {}";
414   tooling::Replacements Replaces =
415       toReplacements({createInsertion("#include <a>")});
416   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
417   EXPECT_EQ(Expected, apply(Code, Replaces));
418 }
419 
420 TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
421   std::string Code = "#include <memory>\n"
422                      "\n"
423                      "int main() {}";
424   std::string Expected = "#include \"z.h\"\n"
425                          "#include <memory>\n"
426                          "\n"
427                          "int main() {}";
428   tooling::Replacements Replaces =
429       toReplacements({createInsertion("#include \"z.h\"")});
430   EXPECT_EQ(Expected, apply(Code, Replaces));
431 }
432 
433 TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
434   std::string Code = "#include <memory>\n"
435                      "\n"
436                      "int main() {}";
437   std::string Expected = "#include <memory>\n"
438                          "#include \"z.h\"\n"
439                          "\n"
440                          "int main() {}";
441   tooling::Replacements Replaces =
442       toReplacements({createInsertion("#include \"z.h\"")});
443   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
444   EXPECT_EQ(Expected, apply(Code, Replaces));
445 }
446 
447 TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
448   std::string Code = "#include \"x/fix.h\"\n"
449                      "#include \"a.h\"\n"
450                      "#include \"b.h\"\n"
451                      "#include \"clang/Format/Format.h\"\n"
452                      "#include <memory>\n";
453   std::string Expected = "#include \"x/fix.h\"\n"
454                          "#include \"a.h\"\n"
455                          "#include \"b.h\"\n"
456                          "#include \"d.h\"\n"
457                          "#include \"clang/Format/Format.h\"\n"
458                          "#include \"llvm/x/y.h\"\n"
459                          "#include <memory>\n";
460   tooling::Replacements Replaces =
461       toReplacements({createInsertion("#include \"d.h\""),
462                       createInsertion("#include \"llvm/x/y.h\"")});
463   EXPECT_EQ(Expected, apply(Code, Replaces));
464 }
465 
466 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
467   std::string Code = "#include \"x/fix.h\"\n"
468                      "#include \"a.h\"\n"
469                      "#include \"b.h\"\n"
470                      "#include \"clang/Format/Format.h\"\n"
471                      "#include <memory>\n";
472   std::string Expected = "#include \"x/fix.h\"\n"
473                          "#include \"a.h\"\n"
474                          "#include \"b.h\"\n"
475                          "#include \"new/new.h\"\n"
476                          "#include \"clang/Format/Format.h\"\n"
477                          "#include <memory>\n"
478                          "#include <list>\n";
479   tooling::Replacements Replaces =
480       toReplacements({createInsertion("#include <list>"),
481                       createInsertion("#include \"new/new.h\"")});
482   EXPECT_EQ(Expected, apply(Code, Replaces));
483 }
484 
485 TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
486   std::string Code = "#include \"x/fix.h\"\n"
487                      "\n"
488                      "#include \"y/a.h\"\n"
489                      "#include \"z/b.h\"\n";
490   // FIXME: inserting after the empty line following the main header might be
491   // prefered.
492   std::string Expected = "#include \"x/fix.h\"\n"
493                          "#include <vector>\n"
494                          "\n"
495                          "#include \"y/a.h\"\n"
496                          "#include \"z/b.h\"\n";
497   tooling::Replacements Replaces =
498       toReplacements({createInsertion("#include <vector>")});
499   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
500   EXPECT_EQ(Expected, apply(Code, Replaces));
501 }
502 
503 TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
504   std::string Code = "#include \"x/fix.h\"\n"
505                      "\n"
506                      "#include <vector>\n"
507                      "\n"
508                      "#include \"y/a.h\"\n"
509                      "#include \"z/b.h\"\n";
510   std::string Expected = "#include \"x/fix.h\"\n"
511                          "\n"
512                          "#include <vector>\n"
513                          "#include <list>\n"
514                          "\n"
515                          "#include \"y/a.h\"\n"
516                          "#include \"z/b.h\"\n"
517                          "#include \"x/x.h\"\n";
518   tooling::Replacements Replaces =
519       toReplacements({createInsertion("#include <list>"),
520                       createInsertion("#include \"x/x.h\"")});
521   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
522   EXPECT_EQ(Expected, apply(Code, Replaces));
523 }
524 
525 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) {
526   std::string Code = "\nint x;";
527   std::string Expected = "\n#include \"fix.h\"\n"
528                          "#include \"a.h\"\n"
529                          "#include \"b.h\"\n"
530                          "#include \"c.h\"\n"
531                          "#include <list>\n"
532                          "#include <vector>\n"
533                          "int x;";
534   tooling::Replacements Replaces = toReplacements(
535       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
536        createInsertion("#include \"b.h\""),
537        createInsertion("#include <vector>"), createInsertion("#include <list>"),
538        createInsertion("#include \"fix.h\"")});
539   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
540 }
541 
542 TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
543   std::string Code = "\nint x;";
544   std::string Expected = "\n#include \"fix.h\"\n"
545                          "#include <list>\n"
546                          "#include <vector>\n"
547                          "#include \"a.h\"\n"
548                          "#include \"b.h\"\n"
549                          "#include \"c.h\"\n"
550                          "int x;";
551   tooling::Replacements Replaces = toReplacements(
552       {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
553        createInsertion("#include \"b.h\""),
554        createInsertion("#include <vector>"), createInsertion("#include <list>"),
555        createInsertion("#include \"fix.h\"")});
556   Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
557   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
558 }
559 
560 TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
561   std::string Code = "\n"
562                      "int x;\n"
563                      "int    a;\n"
564                      "int    a;\n"
565                      "int    a;";
566 
567   std::string Expected = "\n#include \"x.h\"\n"
568                          "#include \"y.h\"\n"
569                          "#include \"clang/x/x.h\"\n"
570                          "#include <list>\n"
571                          "#include <vector>\n"
572                          "int x;\n"
573                          "int    a;\n"
574                          "int b;\n"
575                          "int    a;";
576   tooling::Replacements Replaces = toReplacements(
577       {createReplacement(getOffset(Code, 4, 8), 1, "b"),
578        createInsertion("#include <vector>"), createInsertion("#include <list>"),
579        createInsertion("#include \"clang/x/x.h\""),
580        createInsertion("#include \"y.h\""),
581        createInsertion("#include \"x.h\"")});
582   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
583 }
584 
585 TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
586   std::string Code = "void f() {}\n"
587                      "#define A \\\n"
588                      "  int i;";
589   std::string Expected = "#include <vector>\n"
590                          "void f() {}\n"
591                          "#define A \\\n"
592                          "  int i;";
593   tooling::Replacements Replaces =
594       toReplacements({createInsertion("#include <vector>")});
595   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
596 }
597 
598 TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
599   std::string Code = "// comment\n"
600                      "\n"
601                      "   // comment\n";
602   std::string Expected = "// comment\n"
603                          "\n"
604                          "   // comment\n"
605                          "#include <vector>\n";
606   tooling::Replacements Replaces =
607       toReplacements({createInsertion("#include <vector>")});
608   EXPECT_EQ(Expected, apply(Code, Replaces));
609 }
610 
611 TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
612   std::string Code = "// comment\n"
613                      "// comment \\\n"
614                      " comment continued\n"
615                      "/*\n"
616                      "* comment\n"
617                      "*/\n";
618   std::string Expected = "// comment\n"
619                          "// comment \\\n"
620                          " comment continued\n"
621                          "/*\n"
622                          "* comment\n"
623                          "*/\n"
624                          "#include <vector>\n";
625   tooling::Replacements Replaces =
626       toReplacements({createInsertion("#include <vector>")});
627   EXPECT_EQ(Expected, apply(Code, Replaces));
628 }
629 
630 TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
631   std::string Code = "/*\n"
632                      "* comment\n"
633                      "*/ /* comment\n"
634                      "*/\n"
635                      "\n\n"
636                      "/* c1 */ /*c2 */\n";
637   std::string Expected = "/*\n"
638                          "* comment\n"
639                          "*/ /* comment\n"
640                          "*/\n"
641                          "\n\n"
642                          "/* c1 */ /*c2 */\n"
643                          "#include <vector>\n";
644   tooling::Replacements Replaces =
645       toReplacements({createInsertion("#include <vector>")});
646   EXPECT_EQ(Expected, apply(Code, Replaces));
647 }
648 
649 TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
650   std::string Code = "/*\n"
651                      "* comment\n"
652                      "*/ /* comment\n"
653                      "*/\n"
654                      "\n\n"
655                      "/* c1 */ /*c2 */\n"
656                      "\n"
657                      "int x;\n";
658   std::string Expected = "/*\n"
659                          "* comment\n"
660                          "*/ /* comment\n"
661                          "*/\n"
662                          "\n\n"
663                          "/* c1 */ /*c2 */\n"
664                          "\n"
665                          "#include <vector>\n"
666                          "int x;\n";
667   tooling::Replacements Replaces =
668       toReplacements({createInsertion("#include <vector>")});
669   EXPECT_EQ(Expected, apply(Code, Replaces));
670 }
671 
672 TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
673   std::string Code = "// comment \n"
674                      "#ifdef X\n"
675                      "#define X\n";
676   std::string Expected = "// comment \n"
677                          "#include <vector>\n"
678                          "#ifdef X\n"
679                          "#define X\n";
680   tooling::Replacements Replaces =
681       toReplacements({createInsertion("#include <vector>")});
682   EXPECT_EQ(Expected, apply(Code, Replaces));
683 }
684 
685 TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
686   std::string Code = "// comment \n"
687                      "#ifndef X\n"
688                      "#define X\n"
689                      "int x;\n"
690                      "#define Y 1\n";
691   std::string Expected = "// comment \n"
692                          "#ifndef X\n"
693                          "#define X\n"
694                          "#include <vector>\n"
695                          "int x;\n"
696                          "#define Y 1\n";
697   tooling::Replacements Replaces =
698       toReplacements({createInsertion("#include <vector>")});
699   EXPECT_EQ(Expected, apply(Code, Replaces));
700 }
701 
702 TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
703   std::string Code = "// comment \n"
704                      "#ifndef X\n"
705                      "int x;\n"
706                      "#define Y 1\n";
707   std::string Expected = "// comment \n"
708                          "#include <vector>\n"
709                          "#ifndef X\n"
710                          "int x;\n"
711                          "#define Y 1\n";
712   tooling::Replacements Replaces =
713       toReplacements({createInsertion("#include <vector>")});
714   EXPECT_EQ(Expected, apply(Code, Replaces));
715 }
716 
717 TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
718   std::string Code = "// comment \n"
719                      "#ifndef X // comment\n"
720                      "// comment\n"
721                      "/* comment\n"
722                      "*/\n"
723                      "/* comment */ #define X\n"
724                      "int x;\n"
725                      "#define Y 1\n";
726   std::string Expected = "// comment \n"
727                          "#ifndef X // comment\n"
728                          "// comment\n"
729                          "/* comment\n"
730                          "*/\n"
731                          "/* comment */ #define X\n"
732                          "#include <vector>\n"
733                          "int x;\n"
734                          "#define Y 1\n";
735   tooling::Replacements Replaces =
736       toReplacements({createInsertion("#include <vector>")});
737   EXPECT_EQ(Expected, apply(Code, Replaces));
738 }
739 
740 TEST_F(CleanUpReplacementsTest, EmptyCode) {
741   std::string Code = "";
742   std::string Expected = "#include <vector>\n";
743   tooling::Replacements Replaces =
744       toReplacements({createInsertion("#include <vector>")});
745   EXPECT_EQ(Expected, apply(Code, Replaces));
746 }
747 
748 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
749   std::string Code = "#include <map>";
750   std::string Expected = "#include <map>\n#include <vector>\n";
751   tooling::Replacements Replaces =
752       toReplacements({createInsertion("#include <vector>")});
753   EXPECT_EQ(Expected, apply(Code, Replaces));
754 }
755 
756 TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCodeMultipleInsertions) {
757   std::string Code = "#include <map>";
758   std::string Expected =
759       "#include <map>\n#include <string>\n#include <vector>\n";
760   tooling::Replacements Replaces =
761       toReplacements({createInsertion("#include <string>"),
762                       createInsertion("#include <vector>")});
763   EXPECT_EQ(Expected, apply(Code, Replaces));
764 }
765 
766 TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
767   std::string Code = "#include \"a.h\"\n"
768                      "#include <vector>\n";
769   std::string Expected = "#include \"a.h\"\n"
770                          "#include <vector>\n";
771   tooling::Replacements Replaces =
772       toReplacements({createInsertion("#include <vector>"),
773                       createInsertion("#include \"a.h\"")});
774   EXPECT_EQ(Expected, apply(Code, Replaces));
775 }
776 
777 TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
778   std::string Code = "#include \"a.h\"\n"
779                      "#include <vector>\n";
780   // FIXME: this might not be the best behavior.
781   std::string Expected = "#include \"a.h\"\n"
782                          "#include \"vector\"\n"
783                          "#include <vector>\n"
784                          "#include <a.h>\n";
785   tooling::Replacements Replaces =
786       toReplacements({createInsertion("#include \"vector\""),
787                       createInsertion("#include <a.h>")});
788   EXPECT_EQ(Expected, apply(Code, Replaces));
789 }
790 
791 TEST_F(CleanUpReplacementsTest, SimpleDeleteIncludes) {
792   std::string Code = "#include \"abc.h\"\n"
793                      "#include \"xyz.h\" // comment\n"
794                      "#include \"xyz\"\n"
795                      "int x;\n";
796   std::string Expected = "#include \"xyz\"\n"
797                          "int x;\n";
798   tooling::Replacements Replaces =
799       toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")});
800   EXPECT_EQ(Expected, apply(Code, Replaces));
801 }
802 
803 TEST_F(CleanUpReplacementsTest, DeleteAllCode) {
804   std::string Code = "#include \"xyz.h\"\n"
805                      "#include <xyz.h>";
806   std::string Expected = "";
807   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
808   EXPECT_EQ(Expected, apply(Code, Replaces));
809 }
810 
811 TEST_F(CleanUpReplacementsTest, DeleteAllIncludesWithSameNameIfNoType) {
812   std::string Code = "#include \"xyz.h\"\n"
813                      "#include \"xyz\"\n"
814                      "#include <xyz.h>\n";
815   std::string Expected = "#include \"xyz\"\n";
816   tooling::Replacements Replaces = toReplacements({createDeletion("xyz.h")});
817   EXPECT_EQ(Expected, apply(Code, Replaces));
818 }
819 
820 TEST_F(CleanUpReplacementsTest, OnlyDeleteHeaderWithType) {
821   std::string Code = "#include \"xyz.h\"\n"
822                      "#include \"xyz\"\n"
823                      "#include <xyz.h>";
824   std::string Expected = "#include \"xyz.h\"\n"
825                          "#include \"xyz\"\n";
826   tooling::Replacements Replaces = toReplacements({createDeletion("<xyz.h>")});
827   EXPECT_EQ(Expected, apply(Code, Replaces));
828 }
829 
830 TEST_F(CleanUpReplacementsTest, InsertionAndDeleteHeader) {
831   std::string Code = "#include \"a.h\"\n"
832                      "\n"
833                      "#include <vector>\n";
834   std::string Expected = "#include \"a.h\"\n"
835                          "\n"
836                          "#include <map>\n";
837   tooling::Replacements Replaces = toReplacements(
838       {createDeletion("<vector>"), createInsertion("#include <map>")});
839   EXPECT_EQ(Expected, apply(Code, Replaces));
840 }
841 
842 TEST_F(CleanUpReplacementsTest, NoInsertionAfterCode) {
843   std::string Code = "#include \"a.h\"\n"
844                      "void f() {}\n"
845                      "#include \"b.h\"\n";
846   std::string Expected = "#include \"a.h\"\n"
847                          "#include \"c.h\"\n"
848                          "void f() {}\n"
849                          "#include \"b.h\"\n";
850   tooling::Replacements Replaces = toReplacements(
851       {createInsertion("#include \"c.h\"")});
852   EXPECT_EQ(Expected, apply(Code, Replaces));
853 }
854 
855 TEST_F(CleanUpReplacementsTest, NoInsertionInStringLiteral) {
856   std::string Code = "#include \"a.h\"\n"
857                      "const char[] = R\"(\n"
858                      "#include \"b.h\"\n"
859                      ")\";\n";
860   std::string Expected = "#include \"a.h\"\n"
861                          "#include \"c.h\"\n"
862                          "const char[] = R\"(\n"
863                          "#include \"b.h\"\n"
864                          ")\";\n";
865   tooling::Replacements Replaces =
866       toReplacements({createInsertion("#include \"c.h\"")});
867   EXPECT_EQ(Expected, apply(Code, Replaces));
868 }
869 
870 TEST_F(CleanUpReplacementsTest, NoInsertionAfterOtherDirective) {
871   std::string Code = "#include \"a.h\"\n"
872                      "#ifdef X\n"
873                      "#include \"b.h\"\n"
874                      "#endif\n";
875   std::string Expected = "#include \"a.h\"\n"
876                          "#include \"c.h\"\n"
877                          "#ifdef X\n"
878                          "#include \"b.h\"\n"
879                          "#endif\n";
880   tooling::Replacements Replaces = toReplacements(
881       {createInsertion("#include \"c.h\"")});
882   EXPECT_EQ(Expected, apply(Code, Replaces));
883 }
884 
885 TEST_F(CleanUpReplacementsTest, CanInsertAfterLongSystemInclude) {
886   std::string Code = "#include \"a.h\"\n"
887                      "// comment\n\n"
888                      "#include <a/b/c/d/e.h>\n";
889   std::string Expected = "#include \"a.h\"\n"
890                          "// comment\n\n"
891                          "#include <a/b/c/d/e.h>\n"
892                          "#include <x.h>\n";
893   tooling::Replacements Replaces =
894       toReplacements({createInsertion("#include <x.h>")});
895   EXPECT_EQ(Expected, apply(Code, Replaces));
896 }
897 
898 TEST_F(CleanUpReplacementsTest, CanInsertAfterComment) {
899   std::string Code = "#include \"a.h\"\n"
900                      "// Comment\n"
901                      "\n"
902                      "/* Comment */\n"
903                      "// Comment\n"
904                      "\n"
905                      "#include \"b.h\"\n";
906   std::string Expected = "#include \"a.h\"\n"
907                          "// Comment\n"
908                          "\n"
909                          "/* Comment */\n"
910                          "// Comment\n"
911                          "\n"
912                          "#include \"b.h\"\n"
913                          "#include \"c.h\"\n";
914   tooling::Replacements Replaces =
915       toReplacements({createInsertion("#include \"c.h\"")});
916   EXPECT_EQ(Expected, apply(Code, Replaces));
917 }
918 
919 TEST_F(CleanUpReplacementsTest, CanDeleteAfterCode) {
920   std::string Code = "#include \"a.h\"\n"
921                      "void f() {}\n"
922                      "#include \"b.h\"\n";
923   std::string Expected = "#include \"a.h\"\n"
924                          "void f() {}\n";
925   tooling::Replacements Replaces = toReplacements({createDeletion("\"b.h\"")});
926   EXPECT_EQ(Expected, apply(Code, Replaces));
927 }
928 
929 } // end namespace
930 } // end namespace format
931 } // end namespace clang
932