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