RefactoringTest.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. //===- unittest/Tooling/RefactoringTest.cpp - Refactoring 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 "ReplacementTest.h"
  10. #include "RewriterTestContext.h"
  11. #include "clang/AST/ASTConsumer.h"
  12. #include "clang/AST/ASTContext.h"
  13. #include "clang/AST/DeclCXX.h"
  14. #include "clang/AST/DeclGroup.h"
  15. #include "clang/AST/RecursiveASTVisitor.h"
  16. #include "clang/Basic/Diagnostic.h"
  17. #include "clang/Basic/DiagnosticOptions.h"
  18. #include "clang/Basic/FileManager.h"
  19. #include "clang/Basic/LangOptions.h"
  20. #include "clang/Basic/SourceManager.h"
  21. #include "clang/Format/Format.h"
  22. #include "clang/Frontend/CompilerInstance.h"
  23. #include "clang/Frontend/FrontendAction.h"
  24. #include "clang/Frontend/TextDiagnosticPrinter.h"
  25. #include "clang/Rewrite/Core/Rewriter.h"
  26. #include "clang/Tooling/Refactoring.h"
  27. #include "clang/Tooling/Tooling.h"
  28. #include "llvm/ADT/SmallString.h"
  29. #include "gtest/gtest.h"
  30. namespace clang {
  31. namespace tooling {
  32. TEST_F(ReplacementTest, CanDeleteAllText) {
  33. FileID ID = Context.createInMemoryFile("input.cpp", "text");
  34. SourceLocation Location = Context.getLocation(ID, 1, 1);
  35. Replacement Replace(createReplacement(Location, 4, ""));
  36. EXPECT_TRUE(Replace.apply(Context.Rewrite));
  37. EXPECT_EQ("", Context.getRewrittenText(ID));
  38. }
  39. TEST_F(ReplacementTest, CanDeleteAllTextInTextWithNewlines) {
  40. FileID ID = Context.createInMemoryFile("input.cpp", "line1\nline2\nline3");
  41. SourceLocation Location = Context.getLocation(ID, 1, 1);
  42. Replacement Replace(createReplacement(Location, 17, ""));
  43. EXPECT_TRUE(Replace.apply(Context.Rewrite));
  44. EXPECT_EQ("", Context.getRewrittenText(ID));
  45. }
  46. TEST_F(ReplacementTest, CanAddText) {
  47. FileID ID = Context.createInMemoryFile("input.cpp", "");
  48. SourceLocation Location = Context.getLocation(ID, 1, 1);
  49. Replacement Replace(createReplacement(Location, 0, "result"));
  50. EXPECT_TRUE(Replace.apply(Context.Rewrite));
  51. EXPECT_EQ("result", Context.getRewrittenText(ID));
  52. }
  53. TEST_F(ReplacementTest, CanReplaceTextAtPosition) {
  54. FileID ID = Context.createInMemoryFile("input.cpp",
  55. "line1\nline2\nline3\nline4");
  56. SourceLocation Location = Context.getLocation(ID, 2, 3);
  57. Replacement Replace(createReplacement(Location, 12, "x"));
  58. EXPECT_TRUE(Replace.apply(Context.Rewrite));
  59. EXPECT_EQ("line1\nlixne4", Context.getRewrittenText(ID));
  60. }
  61. TEST_F(ReplacementTest, CanReplaceTextAtPositionMultipleTimes) {
  62. FileID ID = Context.createInMemoryFile("input.cpp",
  63. "line1\nline2\nline3\nline4");
  64. SourceLocation Location1 = Context.getLocation(ID, 2, 3);
  65. Replacement Replace1(createReplacement(Location1, 12, "x\ny\n"));
  66. EXPECT_TRUE(Replace1.apply(Context.Rewrite));
  67. EXPECT_EQ("line1\nlix\ny\nne4", Context.getRewrittenText(ID));
  68. // Since the original source has not been modified, the (4, 4) points to the
  69. // 'e' in the original content.
  70. SourceLocation Location2 = Context.getLocation(ID, 4, 4);
  71. Replacement Replace2(createReplacement(Location2, 1, "f"));
  72. EXPECT_TRUE(Replace2.apply(Context.Rewrite));
  73. EXPECT_EQ("line1\nlix\ny\nnf4", Context.getRewrittenText(ID));
  74. }
  75. TEST_F(ReplacementTest, ApplyFailsForNonExistentLocation) {
  76. Replacement Replace("nonexistent-file.cpp", 0, 1, "");
  77. EXPECT_FALSE(Replace.apply(Context.Rewrite));
  78. }
  79. TEST_F(ReplacementTest, CanRetrivePath) {
  80. Replacement Replace("/path/to/file.cpp", 0, 1, "");
  81. EXPECT_EQ("/path/to/file.cpp", Replace.getFilePath());
  82. }
  83. TEST_F(ReplacementTest, ReturnsInvalidPath) {
  84. Replacement Replace1(Context.Sources, SourceLocation(), 0, "");
  85. EXPECT_TRUE(Replace1.getFilePath().empty());
  86. Replacement Replace2;
  87. EXPECT_TRUE(Replace2.getFilePath().empty());
  88. }
  89. TEST_F(ReplacementTest, FailAddReplacements) {
  90. Replacements Replaces;
  91. Replacement Deletion("x.cc", 0, 10, "3");
  92. auto Err = Replaces.add(Deletion);
  93. EXPECT_TRUE(!Err);
  94. llvm::consumeError(std::move(Err));
  95. Err = Replaces.add(Replacement("x.cc", 0, 2, "a"));
  96. EXPECT_TRUE((bool)Err);
  97. llvm::consumeError(std::move(Err));
  98. Err = Replaces.add(Replacement("x.cc", 2, 2, "a"));
  99. EXPECT_TRUE((bool)Err);
  100. llvm::consumeError(std::move(Err));
  101. Err = Replaces.add(Replacement("y.cc", 20, 2, ""));
  102. EXPECT_TRUE((bool)Err);
  103. llvm::consumeError(std::move(Err));
  104. EXPECT_EQ(1u, Replaces.size());
  105. EXPECT_EQ(Deletion, *Replaces.begin());
  106. }
  107. TEST_F(ReplacementTest, DeletionInReplacements) {
  108. Replacements Replaces;
  109. Replacement R("x.cc", 0, 10, "3");
  110. auto Err = Replaces.add(R);
  111. EXPECT_TRUE(!Err);
  112. llvm::consumeError(std::move(Err));
  113. Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
  114. EXPECT_TRUE(!Err);
  115. llvm::consumeError(std::move(Err));
  116. Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
  117. EXPECT_TRUE(!Err);
  118. llvm::consumeError(std::move(Err));
  119. EXPECT_EQ(1u, Replaces.size());
  120. EXPECT_EQ(R, *Replaces.begin());
  121. }
  122. TEST_F(ReplacementTest, OverlappingReplacements) {
  123. Replacements Replaces;
  124. auto Err = Replaces.add(Replacement("x.cc", 0, 3, "345"));
  125. EXPECT_TRUE(!Err);
  126. llvm::consumeError(std::move(Err));
  127. Err = Replaces.add(Replacement("x.cc", 2, 3, "543"));
  128. EXPECT_TRUE(!Err);
  129. llvm::consumeError(std::move(Err));
  130. EXPECT_EQ(1u, Replaces.size());
  131. EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
  132. Err = Replaces.add(Replacement("x.cc", 2, 1, "5"));
  133. EXPECT_TRUE(!Err);
  134. llvm::consumeError(std::move(Err));
  135. EXPECT_EQ(1u, Replaces.size());
  136. EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
  137. }
  138. TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {
  139. Replacements Replaces;
  140. // Test adding an insertion at the offset of an existing replacement.
  141. auto Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
  142. EXPECT_TRUE(!Err);
  143. llvm::consumeError(std::move(Err));
  144. Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
  145. EXPECT_TRUE(!Err);
  146. llvm::consumeError(std::move(Err));
  147. EXPECT_EQ(Replaces.size(), 2u);
  148. Replaces.clear();
  149. // Test overlap with an existing insertion.
  150. Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
  151. EXPECT_TRUE(!Err);
  152. llvm::consumeError(std::move(Err));
  153. Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
  154. EXPECT_TRUE(!Err);
  155. llvm::consumeError(std::move(Err));
  156. EXPECT_EQ(Replaces.size(), 2u);
  157. }
  158. TEST_F(ReplacementTest, MergeNewDeletions) {
  159. Replacements Replaces;
  160. Replacement ContainingReplacement("x.cc", 0, 10, "");
  161. auto Err = Replaces.add(ContainingReplacement);
  162. EXPECT_TRUE(!Err);
  163. llvm::consumeError(std::move(Err));
  164. Err = Replaces.add(Replacement("x.cc", 5, 3, ""));
  165. EXPECT_TRUE(!Err);
  166. llvm::consumeError(std::move(Err));
  167. Err = Replaces.add(Replacement("x.cc", 0, 10, ""));
  168. EXPECT_TRUE(!Err);
  169. llvm::consumeError(std::move(Err));
  170. Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
  171. EXPECT_TRUE(!Err);
  172. llvm::consumeError(std::move(Err));
  173. EXPECT_EQ(1u, Replaces.size());
  174. EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
  175. }
  176. TEST_F(ReplacementTest, MergeOverlappingButNotAdjacentReplacement) {
  177. Replacements Replaces;
  178. auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
  179. EXPECT_TRUE(!Err);
  180. llvm::consumeError(std::move(Err));
  181. Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
  182. EXPECT_TRUE(!Err);
  183. llvm::consumeError(std::move(Err));
  184. Replacement After = Replacement("x.cc", 10, 5, "");
  185. Err = Replaces.add(After);
  186. EXPECT_TRUE(!Err);
  187. llvm::consumeError(std::move(Err));
  188. Replacement ContainingReplacement("x.cc", 0, 10, "");
  189. Err = Replaces.add(ContainingReplacement);
  190. EXPECT_TRUE(!Err);
  191. llvm::consumeError(std::move(Err));
  192. EXPECT_EQ(2u, Replaces.size());
  193. EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
  194. EXPECT_EQ(*(++Replaces.begin()), After);
  195. }
  196. TEST_F(ReplacementTest, InsertionBeforeMergedDeletions) {
  197. Replacements Replaces;
  198. Replacement Insertion("x.cc", 0, 0, "123");
  199. auto Err = Replaces.add(Insertion);
  200. EXPECT_TRUE(!Err);
  201. llvm::consumeError(std::move(Err));
  202. Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
  203. EXPECT_TRUE(!Err);
  204. llvm::consumeError(std::move(Err));
  205. Replacement Deletion("x.cc", 0, 10, "");
  206. Err = Replaces.add(Deletion);
  207. EXPECT_TRUE(!Err);
  208. llvm::consumeError(std::move(Err));
  209. EXPECT_EQ(2u, Replaces.size());
  210. EXPECT_EQ(*Replaces.begin(), Insertion);
  211. EXPECT_EQ(*(++Replaces.begin()), Deletion);
  212. }
  213. TEST_F(ReplacementTest, MergeOverlappingDeletions) {
  214. Replacements Replaces;
  215. auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
  216. EXPECT_TRUE(!Err);
  217. llvm::consumeError(std::move(Err));
  218. Err = Replaces.add(Replacement("x.cc", 0, 5, ""));
  219. EXPECT_TRUE(!Err);
  220. llvm::consumeError(std::move(Err));
  221. EXPECT_EQ(1u, Replaces.size());
  222. EXPECT_EQ(Replacement("x.cc", 0, 5, ""), *Replaces.begin());
  223. Err = Replaces.add(Replacement("x.cc", 1, 5, ""));
  224. EXPECT_TRUE(!Err);
  225. llvm::consumeError(std::move(Err));
  226. EXPECT_EQ(1u, Replaces.size());
  227. EXPECT_EQ(Replacement("x.cc", 0, 6, ""), *Replaces.begin());
  228. }
  229. TEST_F(ReplacementTest, FailedMergeExistingDeletions) {
  230. Replacements Replaces;
  231. Replacement First("x.cc", 0, 2, "");
  232. auto Err = Replaces.add(First);
  233. EXPECT_TRUE(!Err);
  234. llvm::consumeError(std::move(Err));
  235. Replacement Second("x.cc", 5, 5, "");
  236. Err = Replaces.add(Second);
  237. EXPECT_TRUE(!Err);
  238. llvm::consumeError(std::move(Err));
  239. Err = Replaces.add(Replacement("x.cc", 1, 10, ""));
  240. EXPECT_TRUE(!Err);
  241. llvm::consumeError(std::move(Err));
  242. EXPECT_EQ(1u, Replaces.size());
  243. EXPECT_EQ(Replacement("x.cc", 0, 11, ""), *Replaces.begin());
  244. }
  245. TEST_F(ReplacementTest, FailAddRegression) {
  246. Replacements Replaces;
  247. // Create two replacements, where the second one is an insertion of the empty
  248. // string exactly at the end of the first one.
  249. auto Err = Replaces.add(Replacement("x.cc", 0, 10, "1"));
  250. EXPECT_TRUE(!Err);
  251. llvm::consumeError(std::move(Err));
  252. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  253. EXPECT_TRUE(!Err);
  254. llvm::consumeError(std::move(Err));
  255. // Make sure we find the overlap with the first entry when inserting a
  256. // replacement that ends exactly at the seam of the existing replacements.
  257. Err = Replaces.add(Replacement("x.cc", 5, 5, "fail"));
  258. EXPECT_TRUE((bool)Err);
  259. llvm::consumeError(std::move(Err));
  260. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  261. EXPECT_TRUE(!Err);
  262. llvm::consumeError(std::move(Err));
  263. }
  264. TEST_F(ReplacementTest, InsertAtOffsetOfReplacement) {
  265. Replacements Replaces;
  266. auto Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
  267. EXPECT_TRUE(!Err);
  268. llvm::consumeError(std::move(Err));
  269. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  270. EXPECT_TRUE(!Err);
  271. llvm::consumeError(std::move(Err));
  272. EXPECT_EQ(Replaces.size(), 2u);
  273. Replaces.clear();
  274. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  275. EXPECT_TRUE(!Err);
  276. llvm::consumeError(std::move(Err));
  277. Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
  278. EXPECT_TRUE(!Err);
  279. llvm::consumeError(std::move(Err));
  280. EXPECT_EQ(Replaces.size(), 2u);
  281. }
  282. TEST_F(ReplacementTest, AddInsertAtOtherInsertWhenOderIndependent) {
  283. Replacements Replaces;
  284. auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
  285. EXPECT_TRUE(!Err);
  286. llvm::consumeError(std::move(Err));
  287. Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
  288. EXPECT_TRUE((bool)Err);
  289. llvm::consumeError(std::move(Err));
  290. Replaces.clear();
  291. Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
  292. EXPECT_TRUE(!Err);
  293. llvm::consumeError(std::move(Err));
  294. Err = Replaces.add(Replacement("x.cc", 10, 0, "aa"));
  295. EXPECT_TRUE(!Err);
  296. llvm::consumeError(std::move(Err));
  297. EXPECT_EQ(1u, Replaces.size());
  298. EXPECT_EQ(Replacement("x.cc", 10, 0, "aaa"), *Replaces.begin());
  299. Replaces.clear();
  300. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  301. EXPECT_TRUE(!Err);
  302. llvm::consumeError(std::move(Err));
  303. Err = Replaces.add(Replacement("x.cc", 10, 3, ""));
  304. EXPECT_TRUE(!Err);
  305. llvm::consumeError(std::move(Err));
  306. Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
  307. EXPECT_TRUE(!Err);
  308. llvm::consumeError(std::move(Err));
  309. EXPECT_EQ(2u, Replaces.size());
  310. EXPECT_EQ(Replacement("x.cc", 10, 0, ""), *Replaces.begin());
  311. EXPECT_EQ(Replacement("x.cc", 10, 3, ""), *std::next(Replaces.begin()));
  312. }
  313. TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {
  314. Replacements Replaces;
  315. auto Err = Replaces.add(Replacement("x.cc", 10, 5, "a"));
  316. EXPECT_TRUE(!Err);
  317. llvm::consumeError(std::move(Err));
  318. Err = Replaces.add(Replacement("x.cc", 8, 2, "a"));
  319. EXPECT_TRUE(!Err);
  320. llvm::consumeError(std::move(Err));
  321. Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
  322. EXPECT_TRUE(!Err);
  323. llvm::consumeError(std::move(Err));
  324. }
  325. TEST_F(ReplacementTest, CanApplyReplacements) {
  326. FileID ID = Context.createInMemoryFile("input.cpp",
  327. "line1\nline2\nline3\nline4");
  328. Replacements Replaces =
  329. toReplacements({Replacement(Context.Sources,
  330. Context.getLocation(ID, 2, 1), 5, "replaced"),
  331. Replacement(Context.Sources,
  332. Context.getLocation(ID, 3, 1), 5, "other")});
  333. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  334. EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
  335. }
  336. // Verifies that replacement/deletion is applied before insertion at the same
  337. // offset.
  338. TEST_F(ReplacementTest, InsertAndDelete) {
  339. FileID ID = Context.createInMemoryFile("input.cpp",
  340. "line1\nline2\nline3\nline4");
  341. Replacements Replaces = toReplacements(
  342. {Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 6, ""),
  343. Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 0,
  344. "other\n")});
  345. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  346. EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
  347. }
  348. TEST_F(ReplacementTest, AdjacentReplacements) {
  349. FileID ID = Context.createInMemoryFile("input.cpp",
  350. "ab");
  351. Replacements Replaces = toReplacements(
  352. {Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 1, "x"),
  353. Replacement(Context.Sources, Context.getLocation(ID, 1, 2), 1, "y")});
  354. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  355. EXPECT_EQ("xy", Context.getRewrittenText(ID));
  356. }
  357. TEST_F(ReplacementTest, AddDuplicateReplacements) {
  358. FileID ID = Context.createInMemoryFile("input.cpp",
  359. "line1\nline2\nline3\nline4");
  360. auto Replaces = toReplacements({Replacement(
  361. Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
  362. auto Err = Replaces.add(Replacement(
  363. Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));
  364. EXPECT_TRUE(!Err);
  365. llvm::consumeError(std::move(Err));
  366. Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
  367. 5, "replaced"));
  368. EXPECT_TRUE(!Err);
  369. llvm::consumeError(std::move(Err));
  370. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  371. EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
  372. }
  373. TEST_F(ReplacementTest, FailOrderDependentReplacements) {
  374. FileID ID = Context.createInMemoryFile("input.cpp",
  375. "line1\nline2\nline3\nline4");
  376. auto Replaces = toReplacements({Replacement(
  377. Context.Sources, Context.getLocation(ID, 2, 1), 5, "other")});
  378. auto Err = Replaces.add(Replacement(
  379. Context.Sources, Context.getLocation(ID, 2, 1), 5, "rehto"));
  380. EXPECT_TRUE((bool)Err);
  381. llvm::consumeError(std::move(Err));
  382. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  383. EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
  384. }
  385. TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {
  386. Replacements Replaces =
  387. toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});
  388. EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
  389. }
  390. TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
  391. // Column limit is 20.
  392. std::string Code1 = "Long *a =\n"
  393. " new Long();\n"
  394. "long x = 1;";
  395. std::string Expected1 = "auto a = new Long();\n"
  396. "long x =\n"
  397. " 12345678901;";
  398. std::string Code2 = "int x = 123;\n"
  399. "int y = 0;";
  400. std::string Expected2 = "int x =\n"
  401. " 1234567890123;\n"
  402. "int y = 10;";
  403. StringRef File1 = "format_1.cpp";
  404. StringRef File2 = "format_2.cpp";
  405. FileID ID1 = Context.createInMemoryFile(File1, Code1);
  406. FileID ID2 = Context.createInMemoryFile(File2, Code2);
  407. // Scrambled the order of replacements.
  408. std::map<std::string, Replacements> FileToReplaces;
  409. FileToReplaces[File1] = toReplacements(
  410. {tooling::Replacement(Context.Sources, Context.getLocation(ID1, 1, 1), 6,
  411. "auto "),
  412. tooling::Replacement(Context.Sources, Context.getLocation(ID1, 3, 10), 1,
  413. "12345678901")});
  414. FileToReplaces[File2] = toReplacements(
  415. {tooling::Replacement(Context.Sources, Context.getLocation(ID2, 1, 12), 0,
  416. "4567890123"),
  417. tooling::Replacement(Context.Sources, Context.getLocation(ID2, 2, 9), 1,
  418. "10")});
  419. EXPECT_TRUE(
  420. formatAndApplyAllReplacements(FileToReplaces, Context.Rewrite,
  421. "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
  422. EXPECT_EQ(Expected1, Context.getRewrittenText(ID1));
  423. EXPECT_EQ(Expected2, Context.getRewrittenText(ID2));
  424. }
  425. TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
  426. Replacements Replaces =
  427. toReplacements({Replacement("", 0, 1, ""), Replacement("", 4, 3, " ")});
  428. // Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
  429. EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0)); // |int i;
  430. EXPECT_EQ(0u, Replaces.getShiftedCodePosition(1)); // |nt i;
  431. EXPECT_EQ(1u, Replaces.getShiftedCodePosition(2)); // i|t i;
  432. EXPECT_EQ(2u, Replaces.getShiftedCodePosition(3)); // in| i;
  433. EXPECT_EQ(3u, Replaces.getShiftedCodePosition(4)); // int| i;
  434. EXPECT_EQ(3u, Replaces.getShiftedCodePosition(5)); // int | i;
  435. EXPECT_EQ(3u, Replaces.getShiftedCodePosition(6)); // int |i;
  436. EXPECT_EQ(4u, Replaces.getShiftedCodePosition(7)); // int |;
  437. EXPECT_EQ(5u, Replaces.getShiftedCodePosition(8)); // int i|
  438. }
  439. TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
  440. Replacements Replaces = toReplacements({Replacement("", 4, 0, "\"\n\"")});
  441. // Assume '"12345678"' is turned into '"1234"\n"5678"'.
  442. EXPECT_EQ(3u, Replaces.getShiftedCodePosition(3)); // "123|5678"
  443. EXPECT_EQ(7u, Replaces.getShiftedCodePosition(4)); // "1234|678"
  444. EXPECT_EQ(8u, Replaces.getShiftedCodePosition(5)); // "12345|78"
  445. }
  446. TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
  447. // Replace the first four characters with "abcd".
  448. auto Replaces = toReplacements({Replacement("", 0, 4, "abcd")});
  449. for (unsigned i = 0; i < 3; ++i)
  450. EXPECT_EQ(i, Replaces.getShiftedCodePosition(i));
  451. }
  452. TEST(ShiftedCodePositionTest, NoReplacementText) {
  453. Replacements Replaces = toReplacements({Replacement("", 0, 42, "")});
  454. EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0));
  455. EXPECT_EQ(0u, Replaces.getShiftedCodePosition(39));
  456. EXPECT_EQ(3u, Replaces.getShiftedCodePosition(45));
  457. EXPECT_EQ(0u, Replaces.getShiftedCodePosition(42));
  458. }
  459. class FlushRewrittenFilesTest : public ::testing::Test {
  460. public:
  461. FlushRewrittenFilesTest() {}
  462. ~FlushRewrittenFilesTest() override {
  463. for (llvm::StringMap<std::string>::iterator I = TemporaryFiles.begin(),
  464. E = TemporaryFiles.end();
  465. I != E; ++I) {
  466. llvm::StringRef Name = I->second;
  467. std::error_code EC = llvm::sys::fs::remove(Name);
  468. (void)EC;
  469. assert(!EC);
  470. }
  471. }
  472. FileID createFile(llvm::StringRef Name, llvm::StringRef Content) {
  473. SmallString<1024> Path;
  474. int FD;
  475. std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
  476. assert(!EC);
  477. (void)EC;
  478. llvm::raw_fd_ostream OutStream(FD, true);
  479. OutStream << Content;
  480. OutStream.close();
  481. const FileEntry *File = Context.Files.getFile(Path);
  482. assert(File != nullptr);
  483. StringRef Found =
  484. TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
  485. assert(Found == Path);
  486. (void)Found;
  487. return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
  488. }
  489. std::string getFileContentFromDisk(llvm::StringRef Name) {
  490. std::string Path = TemporaryFiles.lookup(Name);
  491. assert(!Path.empty());
  492. // We need to read directly from the FileManager without relaying through
  493. // a FileEntry, as otherwise we'd read through an already opened file
  494. // descriptor, which might not see the changes made.
  495. // FIXME: Figure out whether there is a way to get the SourceManger to
  496. // reopen the file.
  497. auto FileBuffer = Context.Files.getBufferForFile(Path);
  498. return (*FileBuffer)->getBuffer();
  499. }
  500. llvm::StringMap<std::string> TemporaryFiles;
  501. RewriterTestContext Context;
  502. };
  503. TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
  504. FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
  505. Replacements Replaces = toReplacements({Replacement(
  506. Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
  507. EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
  508. EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
  509. EXPECT_EQ("line1\nreplaced\nline3\nline4",
  510. getFileContentFromDisk("input.cpp"));
  511. }
  512. namespace {
  513. template <typename T>
  514. class TestVisitor : public clang::RecursiveASTVisitor<T> {
  515. public:
  516. bool runOver(StringRef Code) {
  517. return runToolOnCode(new TestAction(this), Code);
  518. }
  519. protected:
  520. clang::SourceManager *SM;
  521. clang::ASTContext *Context;
  522. private:
  523. class FindConsumer : public clang::ASTConsumer {
  524. public:
  525. FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}
  526. void HandleTranslationUnit(clang::ASTContext &Context) override {
  527. Visitor->TraverseDecl(Context.getTranslationUnitDecl());
  528. }
  529. private:
  530. TestVisitor *Visitor;
  531. };
  532. class TestAction : public clang::ASTFrontendAction {
  533. public:
  534. TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}
  535. std::unique_ptr<clang::ASTConsumer>
  536. CreateASTConsumer(clang::CompilerInstance &compiler,
  537. llvm::StringRef dummy) override {
  538. Visitor->SM = &compiler.getSourceManager();
  539. Visitor->Context = &compiler.getASTContext();
  540. /// TestConsumer will be deleted by the framework calling us.
  541. return llvm::make_unique<FindConsumer>(Visitor);
  542. }
  543. private:
  544. TestVisitor *Visitor;
  545. };
  546. };
  547. } // end namespace
  548. void expectReplacementAt(const Replacement &Replace,
  549. StringRef File, unsigned Offset, unsigned Length) {
  550. ASSERT_TRUE(Replace.isApplicable());
  551. EXPECT_EQ(File, Replace.getFilePath());
  552. EXPECT_EQ(Offset, Replace.getOffset());
  553. EXPECT_EQ(Length, Replace.getLength());
  554. }
  555. class ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> {
  556. public:
  557. bool VisitCXXRecordDecl(CXXRecordDecl *Record) {
  558. if (Record->getName() == "X") {
  559. Replace = Replacement(*SM, Record, "");
  560. }
  561. return true;
  562. }
  563. Replacement Replace;
  564. };
  565. TEST(Replacement, CanBeConstructedFromNode) {
  566. ClassDeclXVisitor ClassDeclX;
  567. EXPECT_TRUE(ClassDeclX.runOver(" class X;"));
  568. expectReplacementAt(ClassDeclX.Replace, "input.cc", 5, 7);
  569. }
  570. TEST(Replacement, ReplacesAtSpellingLocation) {
  571. ClassDeclXVisitor ClassDeclX;
  572. EXPECT_TRUE(ClassDeclX.runOver("#define A(Y) Y\nA(class X);"));
  573. expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7);
  574. }
  575. class CallToFVisitor : public TestVisitor<CallToFVisitor> {
  576. public:
  577. bool VisitCallExpr(CallExpr *Call) {
  578. if (Call->getDirectCallee()->getName() == "F") {
  579. Replace = Replacement(*SM, Call, "");
  580. }
  581. return true;
  582. }
  583. Replacement Replace;
  584. };
  585. TEST(Replacement, FunctionCall) {
  586. CallToFVisitor CallToF;
  587. EXPECT_TRUE(CallToF.runOver("void F(); void G() { F(); }"));
  588. expectReplacementAt(CallToF.Replace, "input.cc", 21, 3);
  589. }
  590. TEST(Replacement, TemplatedFunctionCall) {
  591. CallToFVisitor CallToF;
  592. EXPECT_TRUE(CallToF.runOver(
  593. "template <typename T> void F(); void G() { F<int>(); }"));
  594. expectReplacementAt(CallToF.Replace, "input.cc", 43, 8);
  595. }
  596. class NestedNameSpecifierAVisitor
  597. : public TestVisitor<NestedNameSpecifierAVisitor> {
  598. public:
  599. bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) {
  600. if (NNSLoc.getNestedNameSpecifier()) {
  601. if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) {
  602. if (NS->getName() == "a") {
  603. Replace = Replacement(*SM, &NNSLoc, "", Context->getLangOpts());
  604. }
  605. }
  606. }
  607. return TestVisitor<NestedNameSpecifierAVisitor>::TraverseNestedNameSpecifierLoc(
  608. NNSLoc);
  609. }
  610. Replacement Replace;
  611. };
  612. TEST(Replacement, ColonColon) {
  613. NestedNameSpecifierAVisitor VisitNNSA;
  614. EXPECT_TRUE(VisitNNSA.runOver("namespace a { void f() { ::a::f(); } }"));
  615. expectReplacementAt(VisitNNSA.Replace, "input.cc", 25, 5);
  616. }
  617. TEST(Range, overlaps) {
  618. EXPECT_TRUE(Range(10, 10).overlapsWith(Range(0, 11)));
  619. EXPECT_TRUE(Range(0, 11).overlapsWith(Range(10, 10)));
  620. EXPECT_FALSE(Range(10, 10).overlapsWith(Range(0, 10)));
  621. EXPECT_FALSE(Range(0, 10).overlapsWith(Range(10, 10)));
  622. EXPECT_TRUE(Range(0, 10).overlapsWith(Range(2, 6)));
  623. EXPECT_TRUE(Range(2, 6).overlapsWith(Range(0, 10)));
  624. }
  625. TEST(Range, contains) {
  626. EXPECT_TRUE(Range(0, 10).contains(Range(0, 10)));
  627. EXPECT_TRUE(Range(0, 10).contains(Range(2, 6)));
  628. EXPECT_FALSE(Range(2, 6).contains(Range(0, 10)));
  629. EXPECT_FALSE(Range(0, 10).contains(Range(0, 11)));
  630. }
  631. TEST(Range, CalculateRangesOfReplacements) {
  632. // Before: aaaabbbbbbz
  633. // After : bbbbbbzzzzzzoooooooooooooooo
  634. Replacements Replaces = toReplacements(
  635. {Replacement("foo", 0, 4, ""), Replacement("foo", 10, 1, "zzzzzz"),
  636. Replacement("foo", 11, 0, "oooooooooooooooo")});
  637. std::vector<Range> Ranges = Replaces.getAffectedRanges();
  638. EXPECT_EQ(2ul, Ranges.size());
  639. EXPECT_TRUE(Ranges[0].getOffset() == 0);
  640. EXPECT_TRUE(Ranges[0].getLength() == 0);
  641. EXPECT_TRUE(Ranges[1].getOffset() == 6);
  642. EXPECT_TRUE(Ranges[1].getLength() == 22);
  643. }
  644. TEST(Range, CalculateRangesOfInsertionAroundReplacement) {
  645. Replacements Replaces = toReplacements(
  646. {Replacement("foo", 0, 2, ""), Replacement("foo", 0, 0, "ba")});
  647. std::vector<Range> Ranges = Replaces.getAffectedRanges();
  648. EXPECT_EQ(1ul, Ranges.size());
  649. EXPECT_EQ(0u, Ranges[0].getOffset());
  650. EXPECT_EQ(2u, Ranges[0].getLength());
  651. }
  652. TEST(Range, RangesAfterEmptyReplacements) {
  653. std::vector<Range> Ranges = {Range(5, 6), Range(10, 5)};
  654. Replacements Replaces;
  655. std::vector<Range> Expected = {Range(5, 10)};
  656. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  657. }
  658. TEST(Range, RangesAfterReplacements) {
  659. std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
  660. Replacements Replaces = toReplacements({Replacement("foo", 0, 2, "1234")});
  661. std::vector<Range> Expected = {Range(0, 4), Range(7, 2), Range(12, 5)};
  662. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  663. }
  664. TEST(Range, RangesBeforeReplacements) {
  665. std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
  666. Replacements Replaces = toReplacements({Replacement("foo", 20, 2, "1234")});
  667. std::vector<Range> Expected = {Range(5, 2), Range(10, 5), Range(20, 4)};
  668. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  669. }
  670. TEST(Range, NotAffectedByReplacements) {
  671. std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
  672. Replacements Replaces = toReplacements({Replacement("foo", 3, 2, "12"),
  673. Replacement("foo", 12, 2, "12"),
  674. Replacement("foo", 20, 5, "")});
  675. std::vector<Range> Expected = {Range(0, 2), Range(3, 4), Range(10, 5),
  676. Range(20, 0)};
  677. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  678. }
  679. TEST(Range, RangesWithNonOverlappingReplacements) {
  680. std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
  681. Replacements Replaces = toReplacements({Replacement("foo", 3, 1, ""),
  682. Replacement("foo", 6, 1, "123"),
  683. Replacement("foo", 20, 2, "12345")});
  684. std::vector<Range> Expected = {Range(0, 2), Range(3, 0), Range(4, 4),
  685. Range(11, 5), Range(21, 5)};
  686. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  687. }
  688. TEST(Range, RangesWithOverlappingReplacements) {
  689. std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5),
  690. Range(30, 5)};
  691. Replacements Replaces = toReplacements(
  692. {Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
  693. Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")});
  694. std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(12, 5),
  695. Range(22, 0)};
  696. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  697. }
  698. TEST(Range, MergeIntoOneRange) {
  699. std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
  700. Replacements Replaces =
  701. toReplacements({Replacement("foo", 1, 15, "1234567890")});
  702. std::vector<Range> Expected = {Range(0, 15)};
  703. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  704. }
  705. TEST(Range, ReplacementsStartingAtRangeOffsets) {
  706. std::vector<Range> Ranges = {Range(0, 2), Range(5, 5), Range(15, 5)};
  707. Replacements Replaces = toReplacements(
  708. {Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
  709. Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")});
  710. std::vector<Range> Expected = {Range(0, 2), Range(5, 9), Range(18, 2)};
  711. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  712. }
  713. TEST(Range, ReplacementsEndingAtRangeEnds) {
  714. std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
  715. Replacements Replaces = toReplacements(
  716. {Replacement("foo", 6, 1, "123"), Replacement("foo", 17, 3, "12")});
  717. std::vector<Range> Expected = {Range(0, 2), Range(5, 4), Range(17, 4)};
  718. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  719. }
  720. TEST(Range, AjacentReplacements) {
  721. std::vector<Range> Ranges = {Range(0, 0), Range(15, 5)};
  722. Replacements Replaces = toReplacements(
  723. {Replacement("foo", 1, 2, "123"), Replacement("foo", 12, 3, "1234")});
  724. std::vector<Range> Expected = {Range(0, 0), Range(1, 3), Range(13, 9)};
  725. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  726. }
  727. TEST(Range, MergeRangesAfterReplacements) {
  728. std::vector<Range> Ranges = {Range(8, 0), Range(5, 2), Range(9, 0), Range(0, 1)};
  729. Replacements Replaces = toReplacements({Replacement("foo", 1, 3, ""),
  730. Replacement("foo", 7, 0, "12"),
  731. Replacement("foo", 9, 2, "")});
  732. std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0),
  733. Range(8, 0)};
  734. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  735. }
  736. TEST(Range, ConflictingRangesBeforeReplacements) {
  737. std::vector<Range> Ranges = {Range(8, 3), Range(5, 4), Range(9, 1)};
  738. Replacements Replaces = toReplacements({Replacement("foo", 1, 3, "")});
  739. std::vector<Range> Expected = {Range(1, 0), Range(2, 6)};
  740. EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
  741. }
  742. class MergeReplacementsTest : public ::testing::Test {
  743. protected:
  744. void mergeAndTestRewrite(StringRef Code, StringRef Intermediate,
  745. StringRef Result, const Replacements &First,
  746. const Replacements &Second) {
  747. // These are mainly to verify the test itself and make it easier to read.
  748. auto AfterFirst = applyAllReplacements(Code, First);
  749. EXPECT_TRUE(static_cast<bool>(AfterFirst));
  750. auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
  751. EXPECT_TRUE(static_cast<bool>(InSequenceRewrite));
  752. EXPECT_EQ(Intermediate, *AfterFirst);
  753. EXPECT_EQ(Result, *InSequenceRewrite);
  754. tooling::Replacements Merged = First.merge(Second);
  755. auto MergedRewrite = applyAllReplacements(Code, Merged);
  756. EXPECT_TRUE(static_cast<bool>(MergedRewrite));
  757. EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
  758. if (*InSequenceRewrite != *MergedRewrite)
  759. for (tooling::Replacement M : Merged)
  760. llvm::errs() << M.getOffset() << " " << M.getLength() << " "
  761. << M.getReplacementText() << "\n";
  762. }
  763. void mergeAndTestRewrite(StringRef Code, const Replacements &First,
  764. const Replacements &Second) {
  765. auto AfterFirst = applyAllReplacements(Code, First);
  766. EXPECT_TRUE(static_cast<bool>(AfterFirst));
  767. auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
  768. tooling::Replacements Merged = First.merge(Second);
  769. auto MergedRewrite = applyAllReplacements(Code, Merged);
  770. EXPECT_TRUE(static_cast<bool>(MergedRewrite));
  771. EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
  772. if (*InSequenceRewrite != *MergedRewrite)
  773. for (tooling::Replacement M : Merged)
  774. llvm::errs() << M.getOffset() << " " << M.getLength() << " "
  775. << M.getReplacementText() << "\n";
  776. }
  777. };
  778. TEST_F(MergeReplacementsTest, Offsets) {
  779. mergeAndTestRewrite("aaa", "aabab", "cacabab",
  780. toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
  781. toReplacements({{"", 0, 0, "c"}, {"", 1, 0, "c"}}));
  782. mergeAndTestRewrite("aaa", "babaa", "babacac",
  783. toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "b"}}),
  784. toReplacements({{"", 4, 0, "c"}, {"", 5, 0, "c"}}));
  785. mergeAndTestRewrite("aaaa", "aaa", "aac", toReplacements({{"", 1, 1, ""}}),
  786. toReplacements({{"", 2, 1, "c"}}));
  787. mergeAndTestRewrite("aa", "bbabba", "bbabcba",
  788. toReplacements({{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}),
  789. toReplacements({{"", 4, 0, "c"}}));
  790. }
  791. TEST_F(MergeReplacementsTest, Concatenations) {
  792. // Basic concatenations. It is important to merge these into a single
  793. // replacement to ensure the correct order.
  794. {
  795. auto First = toReplacements({{"", 0, 0, "a"}});
  796. auto Second = toReplacements({{"", 1, 0, "b"}});
  797. EXPECT_EQ(toReplacements({{"", 0, 0, "ab"}}), First.merge(Second));
  798. }
  799. {
  800. auto First = toReplacements({{"", 0, 0, "a"}});
  801. auto Second = toReplacements({{"", 0, 0, "b"}});
  802. EXPECT_EQ(toReplacements({{"", 0, 0, "ba"}}), First.merge(Second));
  803. }
  804. mergeAndTestRewrite("", "a", "ab", toReplacements({{"", 0, 0, "a"}}),
  805. toReplacements({{"", 1, 0, "b"}}));
  806. mergeAndTestRewrite("", "a", "ba", toReplacements({{"", 0, 0, "a"}}),
  807. toReplacements({{"", 0, 0, "b"}}));
  808. }
  809. TEST_F(MergeReplacementsTest, NotChangingLengths) {
  810. mergeAndTestRewrite("aaaa", "abba", "acca",
  811. toReplacements({{"", 1, 2, "bb"}}),
  812. toReplacements({{"", 1, 2, "cc"}}));
  813. mergeAndTestRewrite("aaaa", "abba", "abcc",
  814. toReplacements({{"", 1, 2, "bb"}}),
  815. toReplacements({{"", 2, 2, "cc"}}));
  816. mergeAndTestRewrite("aaaa", "abba", "ccba",
  817. toReplacements({{"", 1, 2, "bb"}}),
  818. toReplacements({{"", 0, 2, "cc"}}));
  819. mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
  820. toReplacements({{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}),
  821. toReplacements({{"", 2, 2, "cc"}}));
  822. }
  823. TEST_F(MergeReplacementsTest, OverlappingRanges) {
  824. mergeAndTestRewrite("aaa", "bbd", "bcbcd",
  825. toReplacements({{"", 0, 1, "bb"}, {"", 1, 2, "d"}}),
  826. toReplacements({{"", 1, 0, "c"}, {"", 2, 0, "c"}}));
  827. mergeAndTestRewrite("aaaa", "aabbaa", "acccca",
  828. toReplacements({{"", 2, 0, "bb"}}),
  829. toReplacements({{"", 1, 4, "cccc"}}));
  830. mergeAndTestRewrite("aaaa", "aababa", "acccca",
  831. toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
  832. toReplacements({{"", 1, 4, "cccc"}}));
  833. mergeAndTestRewrite("aaaaaa", "abbbba", "abba",
  834. toReplacements({{"", 1, 4, "bbbb"}}),
  835. toReplacements({{"", 2, 2, ""}}));
  836. mergeAndTestRewrite("aaaa", "aa", "cc",
  837. toReplacements({{"", 1, 1, ""}, {"", 2, 1, ""}}),
  838. toReplacements({{"", 0, 2, "cc"}}));
  839. mergeAndTestRewrite("aa", "abbba", "abcbcba",
  840. toReplacements({{"", 1, 0, "bbb"}}),
  841. toReplacements({{"", 2, 0, "c"}, {"", 3, 0, "c"}}));
  842. mergeAndTestRewrite(
  843. "aaa", "abbab", "ccdd",
  844. toReplacements({{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}}),
  845. toReplacements({{"", 0, 2, "cc"}, {"", 2, 3, "dd"}}));
  846. mergeAndTestRewrite(
  847. "aa", "babbab", "ccdd",
  848. toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}}),
  849. toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
  850. }
  851. TEST(DeduplicateByFileTest, LeaveLeadingDotDot) {
  852. std::map<std::string, Replacements> FileToReplaces;
  853. #if !defined(LLVM_ON_WIN32)
  854. FileToReplaces["../../a/b/.././c.h"] = Replacements();
  855. FileToReplaces["../../a/c.h"] = Replacements();
  856. #else
  857. FileToReplaces["..\\..\\a\\b\\..\\.\\c.h"] = Replacements();
  858. FileToReplaces["..\\..\\a\\c.h"] = Replacements();
  859. #endif
  860. FileToReplaces = groupReplacementsByFile(FileToReplaces);
  861. EXPECT_EQ(1u, FileToReplaces.size());
  862. #if !defined(LLVM_ON_WIN32)
  863. EXPECT_EQ("../../a/c.h", FileToReplaces.begin()->first);
  864. #else
  865. EXPECT_EQ("..\\..\\a\\c.h", FileToReplaces.begin()->first);
  866. #endif
  867. }
  868. TEST(DeduplicateByFileTest, RemoveDotSlash) {
  869. std::map<std::string, Replacements> FileToReplaces;
  870. #if !defined(LLVM_ON_WIN32)
  871. FileToReplaces["./a/b/.././c.h"] = Replacements();
  872. FileToReplaces["a/c.h"] = Replacements();
  873. #else
  874. FileToReplaces[".\\a\\b\\..\\.\\c.h"] = Replacements();
  875. FileToReplaces["a\\c.h"] = Replacements();
  876. #endif
  877. FileToReplaces = groupReplacementsByFile(FileToReplaces);
  878. EXPECT_EQ(1u, FileToReplaces.size());
  879. #if !defined(LLVM_ON_WIN32)
  880. EXPECT_EQ("a/c.h", FileToReplaces.begin()->first);
  881. #else
  882. EXPECT_EQ("a\\c.h", FileToReplaces.begin()->first);
  883. #endif
  884. }
  885. } // end namespace tooling
  886. } // end namespace clang