CleanupTest.cpp 38 KB

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