CleanupTest.cpp 32 KB

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