blob: cb1c742fecb936c04dead5b03034d6fd99d77f47 [file] [log] [blame]
Eric Liu4cfb88a2016-04-25 15:09:22 +00001//===- 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
Eric Liu40ef2fb2016-08-01 10:16:37 +000012#include "../Tooling/ReplacementTest.h"
Eric Liu1ef68452016-05-27 08:20:02 +000013#include "../Tooling/RewriterTestContext.h"
Eric Liu4cfb88a2016-04-25 15:09:22 +000014#include "clang/Tooling/Core/Replacement.h"
15
16#include "gtest/gtest.h"
17
Eric Liu40ef2fb2016-08-01 10:16:37 +000018using clang::tooling::ReplacementTest;
19using clang::tooling::toReplacements;
20
Eric Liu4cfb88a2016-04-25 15:09:22 +000021namespace clang {
22namespace format {
23namespace {
24
25class CleanupTest : public ::testing::Test {
26protected:
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
Eric Liu4f8d9942016-07-11 13:53:12 +000032 auto Result = applyAllReplacements(Code, Replaces);
33 EXPECT_TRUE(static_cast<bool>(Result));
34 return *Result;
Eric Liu4cfb88a2016-04-25 15:09:22 +000035 }
36};
37
38TEST_F(CleanupTest, DeleteEmptyNamespaces) {
39 std::string Code = "namespace A {\n"
40 "namespace B {\n"
41 "} // namespace B\n"
42 "} // namespace A\n\n"
43 "namespace C {\n"
44 "namespace D { int i; }\n"
45 "inline namespace E { namespace { } }\n"
46 "}";
47 std::string Expected = "\n\n\n\n\nnamespace C {\n"
48 "namespace D { int i; }\n \n"
49 "}";
50 std::vector<tooling::Range> Ranges;
51 Ranges.push_back(tooling::Range(28, 0));
52 Ranges.push_back(tooling::Range(91, 6));
53 Ranges.push_back(tooling::Range(132, 0));
54 std::string Result = cleanup(Code, Ranges);
55 EXPECT_EQ(Expected, Result);
56}
57
58TEST_F(CleanupTest, NamespaceWithSyntaxError) {
59 std::string Code = "namespace A {\n"
60 "namespace B {\n" // missing r_brace
61 "} // namespace A\n\n"
62 "namespace C {\n"
63 "namespace D int i; }\n"
64 "inline namespace E { namespace { } }\n"
65 "}";
66 std::string Expected = "namespace A {\n"
67 "\n\n\nnamespace C {\n"
68 "namespace D int i; }\n \n"
69 "}";
70 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
71 std::string Result = cleanup(Code, Ranges);
72 EXPECT_EQ(Expected, Result);
73}
74
75TEST_F(CleanupTest, EmptyNamespaceNotAffected) {
76 std::string Code = "namespace A {\n\n"
77 "namespace {\n\n}}";
78 // Even though the namespaces are empty, but the inner most empty namespace
79 // block is not affected by the changed ranges.
80 std::string Expected = "namespace A {\n\n"
81 "namespace {\n\n}}";
82 // Set the changed range to be the second "\n".
83 std::vector<tooling::Range> Ranges(1, tooling::Range(14, 0));
84 std::string Result = cleanup(Code, Ranges);
85 EXPECT_EQ(Expected, Result);
86}
87
88TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) {
89 std::string Code = "namespace A {\n"
90 "namespace B {\n"
91 "// Yo\n"
92 "} // namespace B\n"
93 "} // namespace A\n"
94 "namespace C { // Yo\n"
95 "}";
96 std::string Expected = "\n\n\n\n\n\n";
97 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
98 std::string Result = cleanup(Code, Ranges);
99 EXPECT_EQ(Expected, Result);
100}
101
102TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) {
103 std::string Code = "namespace A\n"
104 "/* Yo */ {\n"
105 "namespace B\n"
106 "{\n"
107 "// Yo\n"
108 "} // namespace B\n"
109 "} // namespace A\n"
110 "namespace C\n"
111 "{ // Yo\n"
112 "}\n";
113 std::string Expected = "\n\n\n\n\n\n\n\n\n\n";
114 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
115 FormatStyle Style = getLLVMStyle();
116 Style.BraceWrapping.AfterNamespace = true;
117 std::string Result = cleanup(Code, Ranges, Style);
118 EXPECT_EQ(Expected, Result);
119}
120
Eric Liuce5e4bc2016-05-18 08:02:56 +0000121TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) {
122 std::string Code = "class A {\nA() : , {} };";
123 std::string Expected = "class A {\nA() {} };";
124 std::vector<tooling::Range> Ranges;
125 Ranges.push_back(tooling::Range(17, 0));
126 Ranges.push_back(tooling::Range(19, 0));
127 std::string Result = cleanup(Code, Ranges);
128 EXPECT_EQ(Expected, Result);
129
130 Code = "class A {\nA() : x(1), {} };";
131 Expected = "class A {\nA() : x(1) {} };";
132 Ranges.clear();
133 Ranges.push_back(tooling::Range(23, 0));
134 Result = cleanup(Code, Ranges);
135 EXPECT_EQ(Expected, Result);
136
137 Code = "class A {\nA() :,,,,{} };";
138 Expected = "class A {\nA() {} };";
139 Ranges.clear();
140 Ranges.push_back(tooling::Range(15, 0));
141 Result = cleanup(Code, Ranges);
142 EXPECT_EQ(Expected, Result);
143}
144
145TEST_F(CleanupTest, ListSimpleRedundantComma) {
146 std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }";
147 std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }";
148 std::vector<tooling::Range> Ranges;
149 Ranges.push_back(tooling::Range(40, 0));
150 std::string Result = cleanup(Code, Ranges);
151 EXPECT_EQ(Expected, Result);
152
153 Code = "int main() { f(1,,2,3,,4);}";
154 Expected = "int main() { f(1,2,3,4);}";
155 Ranges.clear();
156 Ranges.push_back(tooling::Range(17, 0));
157 Ranges.push_back(tooling::Range(22, 0));
158 Result = cleanup(Code, Ranges);
159 EXPECT_EQ(Expected, Result);
160}
161
162TEST_F(CleanupTest, CtorInitializationBracesInParens) {
163 std::string Code = "class A {\nA() : x({1}),, {} };";
164 std::string Expected = "class A {\nA() : x({1}) {} };";
165 std::vector<tooling::Range> Ranges;
166 Ranges.push_back(tooling::Range(24, 0));
167 Ranges.push_back(tooling::Range(26, 0));
168 std::string Result = cleanup(Code, Ranges);
169 EXPECT_EQ(Expected, Result);
170}
171
172TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
173 std::string Code =
174 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
175 std::string Expected =
176 "class A {\nA() : x({1}), /* comment */, { int x = 0; } };";
177 // Set the affected range to be "int x = 0", which does not intercept the
178 // constructor initialization list.
179 std::vector<tooling::Range> Ranges(1, tooling::Range(42, 9));
180 std::string Result = cleanup(Code, Ranges);
181 EXPECT_EQ(Expected, Result);
182
183 Code = "class A {\nA() : x(1), {} };";
184 Expected = "class A {\nA() : x(1), {} };";
185 // No range. Fixer should do nothing.
186 Ranges.clear();
187 Result = cleanup(Code, Ranges);
188 EXPECT_EQ(Expected, Result);
189}
190
191// FIXME: delete comments too.
192TEST_F(CleanupTest, CtorInitializationCommentAroundCommas) {
193 // Remove redundant commas around comment.
194 std::string Code = "class A {\nA() : x({1}), /* comment */, {} };";
195 std::string Expected = "class A {\nA() : x({1}) /* comment */ {} };";
196 std::vector<tooling::Range> Ranges;
197 Ranges.push_back(tooling::Range(25, 0));
198 Ranges.push_back(tooling::Range(40, 0));
199 std::string Result = cleanup(Code, Ranges);
200 EXPECT_EQ(Expected, Result);
201
202 // Remove trailing comma and ignore comment.
203 Code = "class A {\nA() : x({1}), // comment\n{} };";
204 Expected = "class A {\nA() : x({1}) // comment\n{} };";
205 Ranges = std::vector<tooling::Range>(1, tooling::Range(25, 0));
206 Result = cleanup(Code, Ranges);
207 EXPECT_EQ(Expected, Result);
208
209 // Remove trailing comma and ignore comment.
210 Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };";
211 Expected = "class A {\nA() : x({1}), // comment\n y(1){} };";
212 Ranges = std::vector<tooling::Range>(1, tooling::Range(38, 0));
213 Result = cleanup(Code, Ranges);
214 EXPECT_EQ(Expected, Result);
215
216 // Remove trailing comma and ignore comment.
217 Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };";
218 Expected = "class A {\nA() : x({1}), \n/* comment */ y(1){} };";
219 Ranges = std::vector<tooling::Range>(1, tooling::Range(40, 0));
220 Result = cleanup(Code, Ranges);
221 EXPECT_EQ(Expected, Result);
222
223 // Remove trailing comma and ignore comment.
224 Code = "class A {\nA() : , // comment\n y(1),{} };";
225 Expected = "class A {\nA() : // comment\n y(1){} };";
226 Ranges = std::vector<tooling::Range>(1, tooling::Range(17, 0));
227 Result = cleanup(Code, Ranges);
228 EXPECT_EQ(Expected, Result);
229}
230
231TEST_F(CleanupTest, CtorInitializerInNamespace) {
232 std::string Code = "namespace A {\n"
233 "namespace B {\n" // missing r_brace
234 "} // namespace A\n\n"
235 "namespace C {\n"
236 "class A { A() : x(0),, {} };\n"
237 "inline namespace E { namespace { } }\n"
238 "}";
239 std::string Expected = "namespace A {\n"
240 "\n\n\nnamespace C {\n"
241 "class A { A() : x(0) {} };\n \n"
242 "}";
243 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
244 std::string Result = cleanup(Code, Ranges);
245 EXPECT_EQ(Expected, Result);
246}
247
Eric Liu40ef2fb2016-08-01 10:16:37 +0000248class CleanUpReplacementsTest : public ReplacementTest {
Eric Liu1ef68452016-05-27 08:20:02 +0000249protected:
Eric Liu659afd52016-05-31 13:34:20 +0000250 tooling::Replacement createReplacement(unsigned Offset, unsigned Length,
251 StringRef Text) {
252 return tooling::Replacement(FileName, Offset, Length, Text);
Eric Liu1ef68452016-05-27 08:20:02 +0000253 }
254
Eric Liu659afd52016-05-31 13:34:20 +0000255 tooling::Replacement createInsertion(StringRef HeaderName) {
256 return createReplacement(UINT_MAX, 0, HeaderName);
257 }
258
259 inline std::string apply(StringRef Code,
260 const tooling::Replacements Replaces) {
Eric Liu4f8d9942016-07-11 13:53:12 +0000261 auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
262 EXPECT_TRUE(static_cast<bool>(CleanReplaces))
263 << llvm::toString(CleanReplaces.takeError()) << "\n";
264 auto Result = applyAllReplacements(Code, *CleanReplaces);
265 EXPECT_TRUE(static_cast<bool>(Result));
266 return *Result;
Eric Liu659afd52016-05-31 13:34:20 +0000267 }
268
269 inline std::string formatAndApply(StringRef Code,
270 const tooling::Replacements Replaces) {
Eric Liu4f8d9942016-07-11 13:53:12 +0000271
272 auto CleanReplaces = cleanupAroundReplacements(Code, Replaces, Style);
273 EXPECT_TRUE(static_cast<bool>(CleanReplaces))
274 << llvm::toString(CleanReplaces.takeError()) << "\n";
275 auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style);
276 EXPECT_TRUE(static_cast<bool>(FormattedReplaces))
277 << llvm::toString(FormattedReplaces.takeError()) << "\n";
278 auto Result = applyAllReplacements(Code, *FormattedReplaces);
279 EXPECT_TRUE(static_cast<bool>(Result));
280 return *Result;
Eric Liu659afd52016-05-31 13:34:20 +0000281 }
282
283 int getOffset(StringRef Code, int Line, int Column) {
284 RewriterTestContext Context;
285 FileID ID = Context.createInMemoryFile(FileName, Code);
286 auto DecomposedLocation =
287 Context.Sources.getDecomposedLoc(Context.getLocation(ID, Line, Column));
288 return DecomposedLocation.second;
289 }
290
291 const std::string FileName = "fix.cpp";
292 FormatStyle Style = getLLVMStyle();
Eric Liu1ef68452016-05-27 08:20:02 +0000293};
294
295TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
296 std::string Code = "namespace A {\n"
297 "namespace B {\n"
298 " int x;\n"
299 "} // namespace B\n"
300 "} // namespace A\n"
301 "\n"
302 "namespace C {\n"
303 "namespace D { int i; }\n"
304 "inline namespace E { namespace { int y; } }\n"
305 "int x= 0;"
306 "}";
307 std::string Expected = "\n\nnamespace C {\n"
308 "namespace D { int i; }\n\n"
309 "int x= 0;"
310 "}";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000311 tooling::Replacements Replaces =
312 toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
313 createReplacement(getOffset(Code, 9, 34), 6, "")});
Eric Liu1ef68452016-05-27 08:20:02 +0000314
Eric Liu659afd52016-05-31 13:34:20 +0000315 EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
316}
317
318TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
319 std::string Code = "int main() {}";
320 std::string Expected = "#include \"a.h\"\n"
321 "int main() {}";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000322 tooling::Replacements Replaces =
323 toReplacements({createInsertion("#include \"a.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000324 EXPECT_EQ(Expected, apply(Code, Replaces));
325}
326
327TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
328 std::string Code = "#ifndef A_H\n"
329 "#define A_H\n"
330 "class A {};\n"
331 "#define MMM 123\n"
332 "#endif";
333 std::string Expected = "#ifndef A_H\n"
334 "#define A_H\n"
335 "#include \"b.h\"\n"
336 "class A {};\n"
337 "#define MMM 123\n"
338 "#endif";
339
Eric Liu40ef2fb2016-08-01 10:16:37 +0000340 tooling::Replacements Replaces =
341 toReplacements({createInsertion("#include \"b.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000342 EXPECT_EQ(Expected, apply(Code, Replaces));
343}
344
345TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
346 std::string Code = "#ifndef A_H\n"
347 "#define A_H\n"
348 "\n"
349 "\n"
350 "\n"
351 "#include <vector>\n"
352 "class A {};\n"
353 "#define MMM 123\n"
354 "#endif";
355 std::string Expected = "#ifndef A_H\n"
356 "#define A_H\n"
357 "\n"
358 "\n"
359 "\n"
360 "#include \"a.h\"\n"
361 "#include <vector>\n"
362 "class A {};\n"
363 "#define MMM 123\n"
364 "#endif";
365
Eric Liu40ef2fb2016-08-01 10:16:37 +0000366 tooling::Replacements Replaces =
367 toReplacements({createInsertion("#include \"a.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000368 EXPECT_EQ(Expected, apply(Code, Replaces));
369}
370
371TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
372 std::string Code = "#include \"fix.h\"\n"
373 "\n"
374 "int main() {}";
375 std::string Expected = "#include \"fix.h\"\n"
376 "#include <a>\n"
377 "\n"
378 "int main() {}";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000379 tooling::Replacements Replaces =
380 toReplacements({createInsertion("#include <a>")});
Eric Liu659afd52016-05-31 13:34:20 +0000381 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
382 EXPECT_EQ(Expected, apply(Code, Replaces));
383}
384
385TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
386 std::string Code = "#include <memory>\n"
387 "\n"
388 "int main() {}";
389 std::string Expected = "#include \"z.h\"\n"
390 "#include <memory>\n"
391 "\n"
392 "int main() {}";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000393 tooling::Replacements Replaces =
394 toReplacements({createInsertion("#include \"z.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000395 EXPECT_EQ(Expected, apply(Code, Replaces));
396}
397
398TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
399 std::string Code = "#include <memory>\n"
400 "\n"
401 "int main() {}";
402 std::string Expected = "#include <memory>\n"
403 "#include \"z.h\"\n"
404 "\n"
405 "int main() {}";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000406 tooling::Replacements Replaces =
407 toReplacements({createInsertion("#include \"z.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000408 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
409 EXPECT_EQ(Expected, apply(Code, Replaces));
410}
411
412TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
413 std::string Code = "#include \"x/fix.h\"\n"
414 "#include \"a.h\"\n"
415 "#include \"b.h\"\n"
416 "#include \"clang/Format/Format.h\"\n"
417 "#include <memory>\n";
418 std::string Expected = "#include \"x/fix.h\"\n"
419 "#include \"a.h\"\n"
420 "#include \"b.h\"\n"
421 "#include \"d.h\"\n"
422 "#include \"clang/Format/Format.h\"\n"
423 "#include \"llvm/x/y.h\"\n"
424 "#include <memory>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000425 tooling::Replacements Replaces =
426 toReplacements({createInsertion("#include \"d.h\""),
427 createInsertion("#include \"llvm/x/y.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000428 EXPECT_EQ(Expected, apply(Code, Replaces));
429}
430
431TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
432 std::string Code = "#include \"x/fix.h\"\n"
433 "#include \"a.h\"\n"
434 "#include \"b.h\"\n"
435 "#include \"clang/Format/Format.h\"\n"
436 "#include <memory>\n";
437 std::string Expected = "#include \"x/fix.h\"\n"
438 "#include \"a.h\"\n"
439 "#include \"b.h\"\n"
440 "#include \"new/new.h\"\n"
441 "#include \"clang/Format/Format.h\"\n"
442 "#include <memory>\n"
443 "#include <list>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000444 tooling::Replacements Replaces =
445 toReplacements({createInsertion("#include <list>"),
446 createInsertion("#include \"new/new.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000447 EXPECT_EQ(Expected, apply(Code, Replaces));
448}
449
450TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
451 std::string Code = "#include \"x/fix.h\"\n"
452 "\n"
453 "#include \"y/a.h\"\n"
454 "#include \"z/b.h\"\n";
455 // FIXME: inserting after the empty line following the main header might be
456 // prefered.
457 std::string Expected = "#include \"x/fix.h\"\n"
458 "#include <vector>\n"
459 "\n"
460 "#include \"y/a.h\"\n"
461 "#include \"z/b.h\"\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000462 tooling::Replacements Replaces =
463 toReplacements({createInsertion("#include <vector>")});
Eric Liu659afd52016-05-31 13:34:20 +0000464 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
465 EXPECT_EQ(Expected, apply(Code, Replaces));
466}
467
468TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
469 std::string Code = "#include \"x/fix.h\"\n"
470 "\n"
471 "#include <vector>\n"
472 "\n"
473 "#include \"y/a.h\"\n"
474 "#include \"z/b.h\"\n";
475 std::string Expected = "#include \"x/fix.h\"\n"
476 "\n"
477 "#include <vector>\n"
478 "#include <list>\n"
479 "\n"
480 "#include \"y/a.h\"\n"
481 "#include \"z/b.h\"\n"
482 "#include \"x/x.h\"\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000483 tooling::Replacements Replaces =
484 toReplacements({createInsertion("#include <list>"),
485 createInsertion("#include \"x/x.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000486 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
487 EXPECT_EQ(Expected, apply(Code, Replaces));
488}
489
490TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) {
491 std::string Code = "\nint x;";
Eric Liu303baf52016-06-03 12:52:59 +0000492 std::string Expected = "\n#include \"fix.h\"\n"
Eric Liu659afd52016-05-31 13:34:20 +0000493 "#include \"a.h\"\n"
494 "#include \"b.h\"\n"
495 "#include \"c.h\"\n"
496 "#include <list>\n"
497 "#include <vector>\n"
Eric Liu303baf52016-06-03 12:52:59 +0000498 "int x;";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000499 tooling::Replacements Replaces = toReplacements(
500 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
501 createInsertion("#include \"b.h\""),
502 createInsertion("#include <vector>"), createInsertion("#include <list>"),
503 createInsertion("#include \"fix.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000504 EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
505}
506
507TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
508 std::string Code = "\nint x;";
Eric Liu303baf52016-06-03 12:52:59 +0000509 std::string Expected = "\n#include \"fix.h\"\n"
Eric Liu659afd52016-05-31 13:34:20 +0000510 "#include <list>\n"
511 "#include <vector>\n"
512 "#include \"a.h\"\n"
513 "#include \"b.h\"\n"
514 "#include \"c.h\"\n"
Eric Liu303baf52016-06-03 12:52:59 +0000515 "int x;";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000516 tooling::Replacements Replaces = toReplacements(
517 {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
518 createInsertion("#include \"b.h\""),
519 createInsertion("#include <vector>"), createInsertion("#include <list>"),
520 createInsertion("#include \"fix.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000521 Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
522 EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
523}
524
525TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
526 std::string Code = "\n"
Eric Liu303baf52016-06-03 12:52:59 +0000527 "int x;\n"
Eric Liu659afd52016-05-31 13:34:20 +0000528 "int a;\n"
529 "int a;\n"
530 "int a;";
531
Eric Liu303baf52016-06-03 12:52:59 +0000532 std::string Expected = "\n#include \"x.h\"\n"
Eric Liu659afd52016-05-31 13:34:20 +0000533 "#include \"y.h\"\n"
534 "#include \"clang/x/x.h\"\n"
535 "#include <list>\n"
536 "#include <vector>\n"
Eric Liu303baf52016-06-03 12:52:59 +0000537 "int x;\n"
Eric Liu659afd52016-05-31 13:34:20 +0000538 "int a;\n"
539 "int b;\n"
540 "int a;";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000541 tooling::Replacements Replaces = toReplacements(
542 {createReplacement(getOffset(Code, 4, 8), 1, "b"),
543 createInsertion("#include <vector>"), createInsertion("#include <list>"),
544 createInsertion("#include \"clang/x/x.h\""),
545 createInsertion("#include \"y.h\""),
546 createInsertion("#include \"x.h\"")});
Eric Liu659afd52016-05-31 13:34:20 +0000547 EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
548}
549
550TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
551 std::string Code = "void f() {}\n"
552 "#define A \\\n"
553 " int i;";
554 std::string Expected = "#include <vector>\n"
555 "void f() {}\n"
556 "#define A \\\n"
557 " int i;";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000558 tooling::Replacements Replaces =
559 toReplacements({createInsertion("#include <vector>")});
Eric Liu659afd52016-05-31 13:34:20 +0000560 EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
Eric Liu1ef68452016-05-27 08:20:02 +0000561}
562
Eric Liu303baf52016-06-03 12:52:59 +0000563TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
564 std::string Code = "// comment\n"
565 "\n"
566 " // comment\n";
567 std::string Expected = "// comment\n"
568 "\n"
569 " // comment\n"
570 "#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000571 tooling::Replacements Replaces =
572 toReplacements({createInsertion("#include <vector>")});
Eric Liu303baf52016-06-03 12:52:59 +0000573 EXPECT_EQ(Expected, apply(Code, Replaces));
574}
575
576TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
577 std::string Code = "// comment\n"
578 "// comment \\\n"
579 " comment continued\n"
580 "/*\n"
581 "* comment\n"
582 "*/\n";
583 std::string Expected = "// comment\n"
584 "// comment \\\n"
585 " comment continued\n"
586 "/*\n"
587 "* comment\n"
588 "*/\n"
589 "#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000590 tooling::Replacements Replaces =
591 toReplacements({createInsertion("#include <vector>")});
Eric Liu303baf52016-06-03 12:52:59 +0000592 EXPECT_EQ(Expected, apply(Code, Replaces));
593}
594
595TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
596 std::string Code = "/*\n"
597 "* comment\n"
598 "*/ /* comment\n"
599 "*/\n"
600 "\n\n"
601 "/* c1 */ /*c2 */\n";
602 std::string Expected = "/*\n"
603 "* comment\n"
604 "*/ /* comment\n"
605 "*/\n"
606 "\n\n"
607 "/* c1 */ /*c2 */\n"
608 "#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000609 tooling::Replacements Replaces =
610 toReplacements({createInsertion("#include <vector>")});
Eric Liu303baf52016-06-03 12:52:59 +0000611 EXPECT_EQ(Expected, apply(Code, Replaces));
612}
613
614TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
615 std::string Code = "/*\n"
616 "* comment\n"
617 "*/ /* comment\n"
618 "*/\n"
619 "\n\n"
620 "/* c1 */ /*c2 */\n"
621 "\n"
622 "int x;\n";
623 std::string Expected = "/*\n"
624 "* comment\n"
625 "*/ /* comment\n"
626 "*/\n"
627 "\n\n"
628 "/* c1 */ /*c2 */\n"
629 "\n"
630 "#include <vector>\n"
631 "int x;\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000632 tooling::Replacements Replaces =
633 toReplacements({createInsertion("#include <vector>")});
Eric Liu303baf52016-06-03 12:52:59 +0000634 EXPECT_EQ(Expected, apply(Code, Replaces));
635}
636
Eric Liu35288322016-06-06 11:00:13 +0000637TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
638 std::string Code = "// comment \n"
639 "#ifdef X\n"
640 "#define X\n";
641 std::string Expected = "// comment \n"
642 "#include <vector>\n"
643 "#ifdef X\n"
644 "#define X\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000645 tooling::Replacements Replaces =
646 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000647 EXPECT_EQ(Expected, apply(Code, Replaces));
648}
649
650TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
651 std::string Code = "// comment \n"
652 "#ifndef X\n"
653 "#define X\n"
654 "int x;\n"
655 "#define Y 1\n";
656 std::string Expected = "// comment \n"
657 "#ifndef X\n"
658 "#define X\n"
659 "#include <vector>\n"
660 "int x;\n"
661 "#define Y 1\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000662 tooling::Replacements Replaces =
663 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000664 EXPECT_EQ(Expected, apply(Code, Replaces));
665}
666
667TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
668 std::string Code = "// comment \n"
669 "#ifndef X\n"
670 "int x;\n"
671 "#define Y 1\n";
672 std::string Expected = "// comment \n"
673 "#include <vector>\n"
674 "#ifndef X\n"
675 "int x;\n"
676 "#define Y 1\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000677 tooling::Replacements Replaces =
678 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000679 EXPECT_EQ(Expected, apply(Code, Replaces));
680}
681
682TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
683 std::string Code = "// comment \n"
684 "#ifndef X // comment\n"
685 "// comment\n"
686 "/* comment\n"
687 "*/\n"
688 "/* comment */ #define X\n"
689 "int x;\n"
690 "#define Y 1\n";
691 std::string Expected = "// comment \n"
692 "#ifndef X // comment\n"
693 "// comment\n"
694 "/* comment\n"
695 "*/\n"
696 "/* comment */ #define X\n"
697 "#include <vector>\n"
698 "int x;\n"
699 "#define Y 1\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000700 tooling::Replacements Replaces =
701 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000702 EXPECT_EQ(Expected, apply(Code, Replaces));
703}
704
705TEST_F(CleanUpReplacementsTest, EmptyCode) {
706 std::string Code = "";
707 std::string Expected = "#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000708 tooling::Replacements Replaces =
709 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000710 EXPECT_EQ(Expected, apply(Code, Replaces));
711}
712
713// FIXME: although this case does not crash, the insertion is wrong. A '\n'
714// should be inserted between the two #includes.
715TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
716 std::string Code = "#include <map>";
717 std::string Expected = "#include <map>#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000718 tooling::Replacements Replaces =
719 toReplacements({createInsertion("#include <vector>")});
Eric Liu35288322016-06-06 11:00:13 +0000720 EXPECT_EQ(Expected, apply(Code, Replaces));
721}
722
Eric Liu3753f912016-06-14 14:09:21 +0000723TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
724 std::string Code = "#include \"a.h\"\n"
725 "#include <vector>\n";
726 std::string Expected = "#include \"a.h\"\n"
727 "#include <vector>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000728 tooling::Replacements Replaces =
729 toReplacements({createInsertion("#include <vector>"),
730 createInsertion("#include \"a.h\"")});
Eric Liu3753f912016-06-14 14:09:21 +0000731 EXPECT_EQ(Expected, apply(Code, Replaces));
732}
733
734TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
735 std::string Code = "#include \"a.h\"\n"
736 "#include <vector>\n";
737 // FIXME: this might not be the best behavior.
738 std::string Expected = "#include \"a.h\"\n"
739 "#include \"vector\"\n"
740 "#include <vector>\n"
741 "#include <a.h>\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000742 tooling::Replacements Replaces =
743 toReplacements({createInsertion("#include \"vector\""),
744 createInsertion("#include <a.h>")});
Eric Liu3753f912016-06-14 14:09:21 +0000745 EXPECT_EQ(Expected, apply(Code, Replaces));
746}
747
Eric Liu4cfb88a2016-04-25 15:09:22 +0000748} // end namespace
749} // end namespace format
750} // end namespace clang