blob: b4c269d1f142ccc65f9688c07df730b416434ba9 [file] [log] [blame]
Manuel Klimek3f001342012-05-23 16:29:20 +00001//===- 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
Eric Liu40ef2fb2016-08-01 10:16:37 +000010#include "ReplacementTest.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000011#include "RewriterTestContext.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000012#include "clang/AST/ASTConsumer.h"
Chandler Carruth320d9662012-12-04 09:45:34 +000013#include "clang/AST/ASTContext.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000014#include "clang/AST/DeclCXX.h"
15#include "clang/AST/DeclGroup.h"
16#include "clang/AST/RecursiveASTVisitor.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000017#include "clang/Basic/Diagnostic.h"
Douglas Gregor275e8832012-10-23 22:55:10 +000018#include "clang/Basic/DiagnosticOptions.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000019#include "clang/Basic/FileManager.h"
20#include "clang/Basic/LangOptions.h"
21#include "clang/Basic/SourceManager.h"
Eric Liu4c1ef97a2016-03-29 16:31:53 +000022#include "clang/Format/Format.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000023#include "clang/Frontend/CompilerInstance.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000024#include "clang/Frontend/FrontendAction.h"
25#include "clang/Frontend/TextDiagnosticPrinter.h"
Ted Kremenekcdf81492012-09-01 05:09:24 +000026#include "clang/Rewrite/Core/Rewriter.h"
Chandler Carruth320d9662012-12-04 09:45:34 +000027#include "clang/Tooling/Refactoring.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000028#include "clang/Tooling/Tooling.h"
29#include "llvm/ADT/SmallString.h"
Manuel Klimek3f001342012-05-23 16:29:20 +000030#include "gtest/gtest.h"
31
32namespace clang {
33namespace tooling {
34
Manuel Klimek3f001342012-05-23 16:29:20 +000035TEST_F(ReplacementTest, CanDeleteAllText) {
36 FileID ID = Context.createInMemoryFile("input.cpp", "text");
37 SourceLocation Location = Context.getLocation(ID, 1, 1);
38 Replacement Replace(createReplacement(Location, 4, ""));
39 EXPECT_TRUE(Replace.apply(Context.Rewrite));
40 EXPECT_EQ("", Context.getRewrittenText(ID));
41}
42
43TEST_F(ReplacementTest, CanDeleteAllTextInTextWithNewlines) {
44 FileID ID = Context.createInMemoryFile("input.cpp", "line1\nline2\nline3");
45 SourceLocation Location = Context.getLocation(ID, 1, 1);
46 Replacement Replace(createReplacement(Location, 17, ""));
47 EXPECT_TRUE(Replace.apply(Context.Rewrite));
48 EXPECT_EQ("", Context.getRewrittenText(ID));
49}
50
51TEST_F(ReplacementTest, CanAddText) {
52 FileID ID = Context.createInMemoryFile("input.cpp", "");
53 SourceLocation Location = Context.getLocation(ID, 1, 1);
54 Replacement Replace(createReplacement(Location, 0, "result"));
55 EXPECT_TRUE(Replace.apply(Context.Rewrite));
56 EXPECT_EQ("result", Context.getRewrittenText(ID));
57}
58
59TEST_F(ReplacementTest, CanReplaceTextAtPosition) {
60 FileID ID = Context.createInMemoryFile("input.cpp",
61 "line1\nline2\nline3\nline4");
62 SourceLocation Location = Context.getLocation(ID, 2, 3);
63 Replacement Replace(createReplacement(Location, 12, "x"));
64 EXPECT_TRUE(Replace.apply(Context.Rewrite));
65 EXPECT_EQ("line1\nlixne4", Context.getRewrittenText(ID));
66}
67
68TEST_F(ReplacementTest, CanReplaceTextAtPositionMultipleTimes) {
69 FileID ID = Context.createInMemoryFile("input.cpp",
70 "line1\nline2\nline3\nline4");
71 SourceLocation Location1 = Context.getLocation(ID, 2, 3);
72 Replacement Replace1(createReplacement(Location1, 12, "x\ny\n"));
73 EXPECT_TRUE(Replace1.apply(Context.Rewrite));
74 EXPECT_EQ("line1\nlix\ny\nne4", Context.getRewrittenText(ID));
75
76 // Since the original source has not been modified, the (4, 4) points to the
77 // 'e' in the original content.
78 SourceLocation Location2 = Context.getLocation(ID, 4, 4);
79 Replacement Replace2(createReplacement(Location2, 1, "f"));
80 EXPECT_TRUE(Replace2.apply(Context.Rewrite));
81 EXPECT_EQ("line1\nlix\ny\nnf4", Context.getRewrittenText(ID));
82}
83
84TEST_F(ReplacementTest, ApplyFailsForNonExistentLocation) {
85 Replacement Replace("nonexistent-file.cpp", 0, 1, "");
86 EXPECT_FALSE(Replace.apply(Context.Rewrite));
87}
88
89TEST_F(ReplacementTest, CanRetrivePath) {
90 Replacement Replace("/path/to/file.cpp", 0, 1, "");
91 EXPECT_EQ("/path/to/file.cpp", Replace.getFilePath());
92}
93
94TEST_F(ReplacementTest, ReturnsInvalidPath) {
95 Replacement Replace1(Context.Sources, SourceLocation(), 0, "");
96 EXPECT_TRUE(Replace1.getFilePath().empty());
97
98 Replacement Replace2;
99 EXPECT_TRUE(Replace2.getFilePath().empty());
100}
101
Eric Liu40ef2fb2016-08-01 10:16:37 +0000102TEST_F(ReplacementTest, FailAddReplacements) {
103 Replacements Replaces;
104 auto Err = Replaces.add(Replacement("x.cc", 0, 10, "3"));
105 EXPECT_TRUE(!Err);
106 llvm::consumeError(std::move(Err));
107 Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
108 EXPECT_TRUE((bool)Err);
109 llvm::consumeError(std::move(Err));
110 Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
111 EXPECT_TRUE((bool)Err);
112 llvm::consumeError(std::move(Err));
113 Err = Replaces.add(Replacement("y.cc", 20, 2, ""));
114 EXPECT_TRUE((bool)Err);
115 llvm::consumeError(std::move(Err));
116}
117
Eric Liu9df9b6f2016-09-19 08:40:42 +0000118TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {
Manuel Klimekdcb910b2016-08-03 14:12:17 +0000119 Replacements Replaces;
120 // Test adding an insertion at the offset of an existing replacement.
121 auto Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
122 EXPECT_TRUE(!Err);
123 llvm::consumeError(std::move(Err));
124 Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000125 EXPECT_TRUE(!Err);
Manuel Klimekdcb910b2016-08-03 14:12:17 +0000126 llvm::consumeError(std::move(Err));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000127 EXPECT_EQ(Replaces.size(), 2u);
Manuel Klimekdcb910b2016-08-03 14:12:17 +0000128
129 Replaces.clear();
130 // Test overlap with an existing insertion.
131 Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
132 EXPECT_TRUE(!Err);
133 llvm::consumeError(std::move(Err));
134 Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000135 EXPECT_TRUE(!Err);
Manuel Klimekdcb910b2016-08-03 14:12:17 +0000136 llvm::consumeError(std::move(Err));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000137 EXPECT_EQ(Replaces.size(), 2u);
Manuel Klimekdcb910b2016-08-03 14:12:17 +0000138}
139
140TEST_F(ReplacementTest, FailAddRegression) {
141 Replacements Replaces;
142 // Create two replacements, where the second one is an insertion of the empty
143 // string exactly at the end of the first one.
144 auto Err = Replaces.add(Replacement("x.cc", 0, 10, "1"));
145 EXPECT_TRUE(!Err);
146 llvm::consumeError(std::move(Err));
147 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
148 EXPECT_TRUE(!Err);
149 llvm::consumeError(std::move(Err));
150
151 // Make sure we find the overlap with the first entry when inserting a
152 // replacement that ends exactly at the seam of the existing replacements.
153 Err = Replaces.add(Replacement("x.cc", 5, 5, "fail"));
154 EXPECT_TRUE((bool)Err);
155 llvm::consumeError(std::move(Err));
156
157 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
158 EXPECT_TRUE((bool)Err);
159 llvm::consumeError(std::move(Err));
160}
161
Eric Liu9df9b6f2016-09-19 08:40:42 +0000162TEST_F(ReplacementTest, InsertAtOffsetOfReplacement) {
Manuel Klimek16c6d0a2016-08-03 15:12:00 +0000163 Replacements Replaces;
164 auto Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
165 EXPECT_TRUE(!Err);
166 llvm::consumeError(std::move(Err));
167 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000168 EXPECT_TRUE(!Err);
Manuel Klimek16c6d0a2016-08-03 15:12:00 +0000169 llvm::consumeError(std::move(Err));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000170 EXPECT_EQ(Replaces.size(), 2u);
171
172 Replaces.clear();
173 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
174 EXPECT_TRUE(!Err);
175 llvm::consumeError(std::move(Err));
176 Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
177 EXPECT_TRUE(!Err);
178 llvm::consumeError(std::move(Err));
179 EXPECT_EQ(Replaces.size(), 2u);
Manuel Klimek16c6d0a2016-08-03 15:12:00 +0000180}
181
182TEST_F(ReplacementTest, FailAddInsertAtOtherInsert) {
183 Replacements Replaces;
184 auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
185 EXPECT_TRUE(!Err);
186 llvm::consumeError(std::move(Err));
187 Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
188 EXPECT_TRUE((bool)Err);
189 llvm::consumeError(std::move(Err));
Eric Liu9df9b6f2016-09-19 08:40:42 +0000190
191 Replaces.clear();
192 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
193 EXPECT_TRUE(!Err);
194 llvm::consumeError(std::move(Err));
195 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
196 EXPECT_TRUE((bool)Err);
197 llvm::consumeError(std::move(Err));
198
199 Replaces.clear();
200 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
201 EXPECT_TRUE(!Err);
202 llvm::consumeError(std::move(Err));
203 Err = Replaces.add(Replacement("x.cc", 10, 3, ""));
204 EXPECT_TRUE(!Err);
205 llvm::consumeError(std::move(Err));
206 Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
207 EXPECT_TRUE((bool)Err);
208 llvm::consumeError(std::move(Err));
209}
210
211TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {
212 Replacements Replaces;
213 auto Err = Replaces.add(Replacement("x.cc", 10, 5, "a"));
214 EXPECT_TRUE(!Err);
215 llvm::consumeError(std::move(Err));
216 Err = Replaces.add(Replacement("x.cc", 8, 2, "a"));
217 EXPECT_TRUE(!Err);
218 llvm::consumeError(std::move(Err));
219 Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
220 EXPECT_TRUE(!Err);
221 llvm::consumeError(std::move(Err));
Manuel Klimek16c6d0a2016-08-03 15:12:00 +0000222}
223
Manuel Klimek3f001342012-05-23 16:29:20 +0000224TEST_F(ReplacementTest, CanApplyReplacements) {
225 FileID ID = Context.createInMemoryFile("input.cpp",
226 "line1\nline2\nline3\nline4");
Eric Liu40ef2fb2016-08-01 10:16:37 +0000227 Replacements Replaces =
228 toReplacements({Replacement(Context.Sources,
229 Context.getLocation(ID, 2, 1), 5, "replaced"),
230 Replacement(Context.Sources,
231 Context.getLocation(ID, 3, 1), 5, "other")});
Edwin Vane349e1c12013-08-13 17:38:19 +0000232 EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
233 EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
234}
235
Eric Liu9df9b6f2016-09-19 08:40:42 +0000236// Verifies that replacement/deletion is applied before insertion at the same
237// offset.
238TEST_F(ReplacementTest, InsertAndDelete) {
239 FileID ID = Context.createInMemoryFile("input.cpp",
240 "line1\nline2\nline3\nline4");
241 Replacements Replaces = toReplacements(
242 {Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 6, ""),
243 Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 0,
244 "other\n")});
245 EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
246 EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
247}
248
249TEST_F(ReplacementTest, AdjacentReplacements) {
250 FileID ID = Context.createInMemoryFile("input.cpp",
251 "ab");
252 Replacements Replaces = toReplacements(
253 {Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 1, "x"),
254 Replacement(Context.Sources, Context.getLocation(ID, 1, 2), 1, "y")});
255 EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
256 EXPECT_EQ("xy", Context.getRewrittenText(ID));
257}
258
Manuel Klimek3f001342012-05-23 16:29:20 +0000259TEST_F(ReplacementTest, SkipsDuplicateReplacements) {
260 FileID ID = Context.createInMemoryFile("input.cpp",
261 "line1\nline2\nline3\nline4");
Eric Liu40ef2fb2016-08-01 10:16:37 +0000262 auto Replaces = toReplacements({Replacement(
263 Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
264
265 auto Err = Replaces.add(Replacement(
266 Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));
267 EXPECT_TRUE((bool)Err);
268 llvm::consumeError(std::move(Err));
269
270 Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
271 5, "replaced"));
272 EXPECT_TRUE((bool)Err);
273 llvm::consumeError(std::move(Err));
274
Manuel Klimek3f001342012-05-23 16:29:20 +0000275 EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
276 EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
277}
278
Eric Liu40ef2fb2016-08-01 10:16:37 +0000279TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {
280 Replacements Replaces =
281 toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});
282
Manuel Klimek3f001342012-05-23 16:29:20 +0000283 EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
Manuel Klimek3f001342012-05-23 16:29:20 +0000284}
285
Eric Liu4c1ef97a2016-03-29 16:31:53 +0000286TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
287 // Column limit is 20.
288 std::string Code1 = "Long *a =\n"
289 " new Long();\n"
290 "long x = 1;";
291 std::string Expected1 = "auto a = new Long();\n"
292 "long x =\n"
293 " 12345678901;";
294 std::string Code2 = "int x = 123;\n"
295 "int y = 0;";
296 std::string Expected2 = "int x =\n"
297 " 1234567890123;\n"
298 "int y = 10;";
Eric Liu40ef2fb2016-08-01 10:16:37 +0000299 StringRef File1 = "format_1.cpp";
300 StringRef File2 = "format_2.cpp";
301 FileID ID1 = Context.createInMemoryFile(File1, Code1);
302 FileID ID2 = Context.createInMemoryFile(File2, Code2);
Eric Liu4c1ef97a2016-03-29 16:31:53 +0000303
Eric Liu4c1ef97a2016-03-29 16:31:53 +0000304 // Scrambled the order of replacements.
Eric Liu40ef2fb2016-08-01 10:16:37 +0000305 std::map<std::string, Replacements> FileToReplaces;
306 FileToReplaces[File1] = toReplacements(
307 {tooling::Replacement(Context.Sources, Context.getLocation(ID1, 1, 1), 6,
308 "auto "),
309 tooling::Replacement(Context.Sources, Context.getLocation(ID1, 3, 10), 1,
310 "12345678901")});
311 FileToReplaces[File2] = toReplacements(
312 {tooling::Replacement(Context.Sources, Context.getLocation(ID2, 1, 12), 0,
313 "4567890123"),
314 tooling::Replacement(Context.Sources, Context.getLocation(ID2, 2, 9), 1,
315 "10")});
316 EXPECT_TRUE(
317 formatAndApplyAllReplacements(FileToReplaces, Context.Rewrite,
318 "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
Eric Liu4c1ef97a2016-03-29 16:31:53 +0000319 EXPECT_EQ(Expected1, Context.getRewrittenText(ID1));
320 EXPECT_EQ(Expected2, Context.getRewrittenText(ID2));
321}
322
Daniel Jasper2a250b82013-05-21 12:21:39 +0000323TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
Eric Liu40ef2fb2016-08-01 10:16:37 +0000324 Replacements Replaces =
325 toReplacements({Replacement("", 0, 1, ""), Replacement("", 4, 3, " ")});
Daniel Jasper2a250b82013-05-21 12:21:39 +0000326 // Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
Eric Liu40ef2fb2016-08-01 10:16:37 +0000327 EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0)); // |int i;
328 EXPECT_EQ(0u, Replaces.getShiftedCodePosition(1)); // |nt i;
329 EXPECT_EQ(1u, Replaces.getShiftedCodePosition(2)); // i|t i;
330 EXPECT_EQ(2u, Replaces.getShiftedCodePosition(3)); // in| i;
331 EXPECT_EQ(3u, Replaces.getShiftedCodePosition(4)); // int| i;
332 EXPECT_EQ(3u, Replaces.getShiftedCodePosition(5)); // int | i;
333 EXPECT_EQ(3u, Replaces.getShiftedCodePosition(6)); // int |i;
334 EXPECT_EQ(4u, Replaces.getShiftedCodePosition(7)); // int |;
335 EXPECT_EQ(5u, Replaces.getShiftedCodePosition(8)); // int i|
Edwin Vane18e503c2013-08-27 15:44:26 +0000336}
337
Daniel Jasper2a250b82013-05-21 12:21:39 +0000338TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
Eric Liu40ef2fb2016-08-01 10:16:37 +0000339 Replacements Replaces = toReplacements({Replacement("", 4, 0, "\"\n\"")});
Daniel Jasper2a250b82013-05-21 12:21:39 +0000340 // Assume '"12345678"' is turned into '"1234"\n"5678"'.
Eric Liu40ef2fb2016-08-01 10:16:37 +0000341 EXPECT_EQ(3u, Replaces.getShiftedCodePosition(3)); // "123|5678"
342 EXPECT_EQ(7u, Replaces.getShiftedCodePosition(4)); // "1234|678"
343 EXPECT_EQ(8u, Replaces.getShiftedCodePosition(5)); // "12345|78"
Daniel Jasper3fed9452015-11-23 08:33:48 +0000344}
345
346TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
Daniel Jasper3fed9452015-11-23 08:33:48 +0000347 // Replace the first four characters with "abcd".
Eric Liu40ef2fb2016-08-01 10:16:37 +0000348 auto Replaces = toReplacements({Replacement("", 0, 4, "abcd")});
Daniel Jasper3fed9452015-11-23 08:33:48 +0000349 for (unsigned i = 0; i < 3; ++i)
Eric Liu40ef2fb2016-08-01 10:16:37 +0000350 EXPECT_EQ(i, Replaces.getShiftedCodePosition(i));
351}
352
353TEST(ShiftedCodePositionTest, NoReplacementText) {
354 Replacements Replaces = toReplacements({Replacement("", 0, 42, "")});
355 EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0));
356 EXPECT_EQ(0u, Replaces.getShiftedCodePosition(39));
357 EXPECT_EQ(3u, Replaces.getShiftedCodePosition(45));
358 EXPECT_EQ(0u, Replaces.getShiftedCodePosition(42));
Daniel Jasper2a250b82013-05-21 12:21:39 +0000359}
360
Manuel Klimek3f001342012-05-23 16:29:20 +0000361class FlushRewrittenFilesTest : public ::testing::Test {
Rafael Espindola641c6a12013-06-26 15:01:50 +0000362public:
363 FlushRewrittenFilesTest() {}
Manuel Klimek3f001342012-05-23 16:29:20 +0000364
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000365 ~FlushRewrittenFilesTest() override {
Rafael Espindola641c6a12013-06-26 15:01:50 +0000366 for (llvm::StringMap<std::string>::iterator I = TemporaryFiles.begin(),
367 E = TemporaryFiles.end();
368 I != E; ++I) {
369 llvm::StringRef Name = I->second;
Rafael Espindolac0809172014-06-12 14:02:15 +0000370 std::error_code EC = llvm::sys::fs::remove(Name);
Rafael Espindola641c6a12013-06-26 15:01:50 +0000371 (void)EC;
372 assert(!EC);
373 }
Manuel Klimek3f001342012-05-23 16:29:20 +0000374 }
375
376 FileID createFile(llvm::StringRef Name, llvm::StringRef Content) {
Rafael Espindola641c6a12013-06-26 15:01:50 +0000377 SmallString<1024> Path;
378 int FD;
Rafael Espindolac0809172014-06-12 14:02:15 +0000379 std::error_code EC = llvm::sys::fs::createTemporaryFile(Name, "", FD, Path);
Rafael Espindola641c6a12013-06-26 15:01:50 +0000380 assert(!EC);
381 (void)EC;
382
383 llvm::raw_fd_ostream OutStream(FD, true);
Manuel Klimek3f001342012-05-23 16:29:20 +0000384 OutStream << Content;
385 OutStream.close();
386 const FileEntry *File = Context.Files.getFile(Path);
Craig Topper416fa342014-06-08 08:38:12 +0000387 assert(File != nullptr);
Rafael Espindola641c6a12013-06-26 15:01:50 +0000388
David Blaikie13156b62014-11-19 03:06:06 +0000389 StringRef Found =
390 TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second;
Rafael Espindola641c6a12013-06-26 15:01:50 +0000391 assert(Found == Path);
392 (void)Found;
Manuel Klimek3f001342012-05-23 16:29:20 +0000393 return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User);
394 }
395
396 std::string getFileContentFromDisk(llvm::StringRef Name) {
Rafael Espindola641c6a12013-06-26 15:01:50 +0000397 std::string Path = TemporaryFiles.lookup(Name);
398 assert(!Path.empty());
Manuel Klimek3f001342012-05-23 16:29:20 +0000399 // We need to read directly from the FileManager without relaying through
400 // a FileEntry, as otherwise we'd read through an already opened file
401 // descriptor, which might not see the changes made.
402 // FIXME: Figure out whether there is a way to get the SourceManger to
403 // reopen the file.
Benjamin Kramera8857962014-10-26 22:44:13 +0000404 auto FileBuffer = Context.Files.getBufferForFile(Path);
405 return (*FileBuffer)->getBuffer();
Manuel Klimek3f001342012-05-23 16:29:20 +0000406 }
407
Rafael Espindola641c6a12013-06-26 15:01:50 +0000408 llvm::StringMap<std::string> TemporaryFiles;
Manuel Klimek3f001342012-05-23 16:29:20 +0000409 RewriterTestContext Context;
410};
411
412TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
413 FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
Eric Liu40ef2fb2016-08-01 10:16:37 +0000414 Replacements Replaces = toReplacements({Replacement(
415 Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
Manuel Klimek3f001342012-05-23 16:29:20 +0000416 EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
417 EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
418 EXPECT_EQ("line1\nreplaced\nline3\nline4",
419 getFileContentFromDisk("input.cpp"));
420}
421
422namespace {
423template <typename T>
424class TestVisitor : public clang::RecursiveASTVisitor<T> {
425public:
426 bool runOver(StringRef Code) {
427 return runToolOnCode(new TestAction(this), Code);
428 }
429
430protected:
431 clang::SourceManager *SM;
Manuel Klimek94a89232015-06-03 13:10:41 +0000432 clang::ASTContext *Context;
Manuel Klimek3f001342012-05-23 16:29:20 +0000433
434private:
435 class FindConsumer : public clang::ASTConsumer {
436 public:
437 FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {}
438
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000439 void HandleTranslationUnit(clang::ASTContext &Context) override {
Manuel Klimek3f001342012-05-23 16:29:20 +0000440 Visitor->TraverseDecl(Context.getTranslationUnitDecl());
441 }
442
443 private:
444 TestVisitor *Visitor;
445 };
446
447 class TestAction : public clang::ASTFrontendAction {
448 public:
449 TestAction(TestVisitor *Visitor) : Visitor(Visitor) {}
450
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000451 std::unique_ptr<clang::ASTConsumer>
David Blaikie6beb6aa2014-08-10 19:56:51 +0000452 CreateASTConsumer(clang::CompilerInstance &compiler,
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000453 llvm::StringRef dummy) override {
Manuel Klimek3f001342012-05-23 16:29:20 +0000454 Visitor->SM = &compiler.getSourceManager();
Manuel Klimek94a89232015-06-03 13:10:41 +0000455 Visitor->Context = &compiler.getASTContext();
Manuel Klimek3f001342012-05-23 16:29:20 +0000456 /// TestConsumer will be deleted by the framework calling us.
David Blaikie6beb6aa2014-08-10 19:56:51 +0000457 return llvm::make_unique<FindConsumer>(Visitor);
Manuel Klimek3f001342012-05-23 16:29:20 +0000458 }
459
460 private:
461 TestVisitor *Visitor;
462 };
463};
464} // end namespace
465
466void expectReplacementAt(const Replacement &Replace,
467 StringRef File, unsigned Offset, unsigned Length) {
468 ASSERT_TRUE(Replace.isApplicable());
469 EXPECT_EQ(File, Replace.getFilePath());
470 EXPECT_EQ(Offset, Replace.getOffset());
471 EXPECT_EQ(Length, Replace.getLength());
472}
473
474class ClassDeclXVisitor : public TestVisitor<ClassDeclXVisitor> {
475public:
476 bool VisitCXXRecordDecl(CXXRecordDecl *Record) {
477 if (Record->getName() == "X") {
478 Replace = Replacement(*SM, Record, "");
479 }
480 return true;
481 }
482 Replacement Replace;
483};
484
485TEST(Replacement, CanBeConstructedFromNode) {
486 ClassDeclXVisitor ClassDeclX;
487 EXPECT_TRUE(ClassDeclX.runOver(" class X;"));
488 expectReplacementAt(ClassDeclX.Replace, "input.cc", 5, 7);
489}
490
491TEST(Replacement, ReplacesAtSpellingLocation) {
492 ClassDeclXVisitor ClassDeclX;
493 EXPECT_TRUE(ClassDeclX.runOver("#define A(Y) Y\nA(class X);"));
494 expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7);
495}
496
497class CallToFVisitor : public TestVisitor<CallToFVisitor> {
498public:
499 bool VisitCallExpr(CallExpr *Call) {
500 if (Call->getDirectCallee()->getName() == "F") {
501 Replace = Replacement(*SM, Call, "");
502 }
503 return true;
504 }
505 Replacement Replace;
506};
507
508TEST(Replacement, FunctionCall) {
509 CallToFVisitor CallToF;
510 EXPECT_TRUE(CallToF.runOver("void F(); void G() { F(); }"));
511 expectReplacementAt(CallToF.Replace, "input.cc", 21, 3);
512}
513
514TEST(Replacement, TemplatedFunctionCall) {
515 CallToFVisitor CallToF;
516 EXPECT_TRUE(CallToF.runOver(
517 "template <typename T> void F(); void G() { F<int>(); }"));
518 expectReplacementAt(CallToF.Replace, "input.cc", 43, 8);
519}
520
Manuel Klimek94a89232015-06-03 13:10:41 +0000521class NestedNameSpecifierAVisitor
522 : public TestVisitor<NestedNameSpecifierAVisitor> {
523public:
524 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) {
525 if (NNSLoc.getNestedNameSpecifier()) {
526 if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) {
527 if (NS->getName() == "a") {
528 Replace = Replacement(*SM, &NNSLoc, "", Context->getLangOpts());
529 }
530 }
531 }
532 return TestVisitor<NestedNameSpecifierAVisitor>::TraverseNestedNameSpecifierLoc(
533 NNSLoc);
534 }
535 Replacement Replace;
536};
537
538TEST(Replacement, ColonColon) {
539 NestedNameSpecifierAVisitor VisitNNSA;
540 EXPECT_TRUE(VisitNNSA.runOver("namespace a { void f() { ::a::f(); } }"));
541 expectReplacementAt(VisitNNSA.Replace, "input.cc", 25, 5);
542}
543
Manuel Klimekdce23472013-07-19 12:12:36 +0000544TEST(Range, overlaps) {
545 EXPECT_TRUE(Range(10, 10).overlapsWith(Range(0, 11)));
546 EXPECT_TRUE(Range(0, 11).overlapsWith(Range(10, 10)));
547 EXPECT_FALSE(Range(10, 10).overlapsWith(Range(0, 10)));
548 EXPECT_FALSE(Range(0, 10).overlapsWith(Range(10, 10)));
549 EXPECT_TRUE(Range(0, 10).overlapsWith(Range(2, 6)));
Edwin Vanec5148482013-08-13 18:11:16 +0000550 EXPECT_TRUE(Range(2, 6).overlapsWith(Range(0, 10)));
Manuel Klimekdce23472013-07-19 12:12:36 +0000551}
552
553TEST(Range, contains) {
554 EXPECT_TRUE(Range(0, 10).contains(Range(0, 10)));
555 EXPECT_TRUE(Range(0, 10).contains(Range(2, 6)));
556 EXPECT_FALSE(Range(2, 6).contains(Range(0, 10)));
557 EXPECT_FALSE(Range(0, 10).contains(Range(0, 11)));
558}
559
Manuel Klimekb12e5a52016-03-01 12:37:30 +0000560TEST(Range, CalculateRangesOfReplacements) {
561 // Before: aaaabbbbbbz
562 // After : bbbbbbzzzzzzoooooooooooooooo
Eric Liu40ef2fb2016-08-01 10:16:37 +0000563 Replacements Replaces = toReplacements(
564 {Replacement("foo", 0, 4, ""), Replacement("foo", 10, 1, "zzzzzz"),
565 Replacement("foo", 11, 0, "oooooooooooooooo")});
Manuel Klimekb12e5a52016-03-01 12:37:30 +0000566
Eric Liu40ef2fb2016-08-01 10:16:37 +0000567 std::vector<Range> Ranges = Replaces.getAffectedRanges();
Manuel Klimekb12e5a52016-03-01 12:37:30 +0000568
Eric Liu8b636db2016-06-21 17:56:31 +0000569 EXPECT_EQ(2ul, Ranges.size());
Manuel Klimekb12e5a52016-03-01 12:37:30 +0000570 EXPECT_TRUE(Ranges[0].getOffset() == 0);
571 EXPECT_TRUE(Ranges[0].getLength() == 0);
572 EXPECT_TRUE(Ranges[1].getOffset() == 6);
Eric Liu8b636db2016-06-21 17:56:31 +0000573 EXPECT_TRUE(Ranges[1].getLength() == 22);
574}
575
Eric Liu9df9b6f2016-09-19 08:40:42 +0000576TEST(Range, CalculateRangesOfInsertionAroundReplacement) {
577 Replacements Replaces = toReplacements(
578 {Replacement("foo", 0, 2, ""), Replacement("foo", 0, 0, "ba")});
579
580 std::vector<Range> Ranges = Replaces.getAffectedRanges();
581
582 EXPECT_EQ(1ul, Ranges.size());
583 EXPECT_EQ(0u, Ranges[0].getOffset());
584 EXPECT_EQ(2u, Ranges[0].getLength());
585}
586
Eric Liu73337f32016-08-08 13:37:39 +0000587TEST(Range, RangesAfterEmptyReplacements) {
588 std::vector<Range> Ranges = {Range(5, 6), Range(10, 5)};
589 Replacements Replaces;
590 std::vector<Range> Expected = {Range(5, 10)};
591 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
592}
593
Eric Liu8b636db2016-06-21 17:56:31 +0000594TEST(Range, RangesAfterReplacements) {
595 std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000596 Replacements Replaces = toReplacements({Replacement("foo", 0, 2, "1234")});
Eric Liu8b636db2016-06-21 17:56:31 +0000597 std::vector<Range> Expected = {Range(0, 4), Range(7, 2), Range(12, 5)};
598 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
599}
600
601TEST(Range, RangesBeforeReplacements) {
602 std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000603 Replacements Replaces = toReplacements({Replacement("foo", 20, 2, "1234")});
Eric Liu8b636db2016-06-21 17:56:31 +0000604 std::vector<Range> Expected = {Range(5, 2), Range(10, 5), Range(20, 4)};
605 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
606}
607
608TEST(Range, NotAffectedByReplacements) {
609 std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000610 Replacements Replaces = toReplacements({Replacement("foo", 3, 2, "12"),
611 Replacement("foo", 12, 2, "12"),
612 Replacement("foo", 20, 5, "")});
Eric Liu8b636db2016-06-21 17:56:31 +0000613 std::vector<Range> Expected = {Range(0, 2), Range(3, 4), Range(10, 5),
614 Range(20, 0)};
615 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
616}
617
618TEST(Range, RangesWithNonOverlappingReplacements) {
619 std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000620 Replacements Replaces = toReplacements({Replacement("foo", 3, 1, ""),
621 Replacement("foo", 6, 1, "123"),
622 Replacement("foo", 20, 2, "12345")});
Eric Liu8b636db2016-06-21 17:56:31 +0000623 std::vector<Range> Expected = {Range(0, 2), Range(3, 0), Range(4, 4),
624 Range(11, 5), Range(21, 5)};
625 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
626}
627
628TEST(Range, RangesWithOverlappingReplacements) {
629 std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5),
630 Range(30, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000631 Replacements Replaces = toReplacements(
632 {Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
633 Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")});
Eric Liu8b636db2016-06-21 17:56:31 +0000634 std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(12, 5),
635 Range(22, 0)};
636 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
637}
638
639TEST(Range, MergeIntoOneRange) {
640 std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000641 Replacements Replaces =
642 toReplacements({Replacement("foo", 1, 15, "1234567890")});
Eric Liu8b636db2016-06-21 17:56:31 +0000643 std::vector<Range> Expected = {Range(0, 15)};
644 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
645}
646
647TEST(Range, ReplacementsStartingAtRangeOffsets) {
648 std::vector<Range> Ranges = {Range(0, 2), Range(5, 5), Range(15, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000649 Replacements Replaces = toReplacements(
650 {Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
651 Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")});
Eric Liu8b636db2016-06-21 17:56:31 +0000652 std::vector<Range> Expected = {Range(0, 2), Range(5, 9), Range(18, 2)};
653 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
654}
655
656TEST(Range, ReplacementsEndingAtRangeEnds) {
657 std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000658 Replacements Replaces = toReplacements(
659 {Replacement("foo", 6, 1, "123"), Replacement("foo", 17, 3, "12")});
Eric Liu8b636db2016-06-21 17:56:31 +0000660 std::vector<Range> Expected = {Range(0, 2), Range(5, 4), Range(17, 4)};
661 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
662}
663
664TEST(Range, AjacentReplacements) {
665 std::vector<Range> Ranges = {Range(0, 0), Range(15, 5)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000666 Replacements Replaces = toReplacements(
667 {Replacement("foo", 1, 2, "123"), Replacement("foo", 12, 3, "1234")});
Eric Liu8b636db2016-06-21 17:56:31 +0000668 std::vector<Range> Expected = {Range(0, 0), Range(1, 3), Range(13, 9)};
669 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
670}
671
672TEST(Range, MergeRangesAfterReplacements) {
673 std::vector<Range> Ranges = {Range(8, 0), Range(5, 2), Range(9, 0), Range(0, 1)};
Eric Liu40ef2fb2016-08-01 10:16:37 +0000674 Replacements Replaces = toReplacements({Replacement("foo", 1, 3, ""),
675 Replacement("foo", 7, 0, "12"),
676 Replacement("foo", 9, 2, "")});
677 std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0),
678 Range(8, 0)};
Eric Liu8b636db2016-06-21 17:56:31 +0000679 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
Manuel Klimekb12e5a52016-03-01 12:37:30 +0000680}
681
Eric Liu40ef2fb2016-08-01 10:16:37 +0000682TEST(Range, ConflictingRangesBeforeReplacements) {
683 std::vector<Range> Ranges = {Range(8, 3), Range(5, 4), Range(9, 1)};
684 Replacements Replaces = toReplacements({Replacement("foo", 1, 3, "")});
685 std::vector<Range> Expected = {Range(1, 0), Range(2, 6)};
686 EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
Edwin Vane938f6882013-08-08 13:31:14 +0000687}
688
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000689class MergeReplacementsTest : public ::testing::Test {
690protected:
691 void mergeAndTestRewrite(StringRef Code, StringRef Intermediate,
692 StringRef Result, const Replacements &First,
693 const Replacements &Second) {
694 // These are mainly to verify the test itself and make it easier to read.
Eric Liu4f8d9942016-07-11 13:53:12 +0000695 auto AfterFirst = applyAllReplacements(Code, First);
696 EXPECT_TRUE(static_cast<bool>(AfterFirst));
697 auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
698 EXPECT_TRUE(static_cast<bool>(InSequenceRewrite));
699 EXPECT_EQ(Intermediate, *AfterFirst);
700 EXPECT_EQ(Result, *InSequenceRewrite);
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000701
Eric Liu40ef2fb2016-08-01 10:16:37 +0000702 tooling::Replacements Merged = First.merge(Second);
Eric Liu4f8d9942016-07-11 13:53:12 +0000703 auto MergedRewrite = applyAllReplacements(Code, Merged);
704 EXPECT_TRUE(static_cast<bool>(MergedRewrite));
705 EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
706 if (*InSequenceRewrite != *MergedRewrite)
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000707 for (tooling::Replacement M : Merged)
708 llvm::errs() << M.getOffset() << " " << M.getLength() << " "
709 << M.getReplacementText() << "\n";
710 }
711 void mergeAndTestRewrite(StringRef Code, const Replacements &First,
712 const Replacements &Second) {
Eric Liu4f8d9942016-07-11 13:53:12 +0000713 auto AfterFirst = applyAllReplacements(Code, First);
714 EXPECT_TRUE(static_cast<bool>(AfterFirst));
715 auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
Eric Liu40ef2fb2016-08-01 10:16:37 +0000716 tooling::Replacements Merged = First.merge(Second);
Eric Liu4f8d9942016-07-11 13:53:12 +0000717 auto MergedRewrite = applyAllReplacements(Code, Merged);
718 EXPECT_TRUE(static_cast<bool>(MergedRewrite));
719 EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
720 if (*InSequenceRewrite != *MergedRewrite)
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000721 for (tooling::Replacement M : Merged)
722 llvm::errs() << M.getOffset() << " " << M.getLength() << " "
723 << M.getReplacementText() << "\n";
724 }
725};
726
727TEST_F(MergeReplacementsTest, Offsets) {
728 mergeAndTestRewrite("aaa", "aabab", "cacabab",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000729 toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
730 toReplacements({{"", 0, 0, "c"}, {"", 1, 0, "c"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000731 mergeAndTestRewrite("aaa", "babaa", "babacac",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000732 toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "b"}}),
733 toReplacements({{"", 4, 0, "c"}, {"", 5, 0, "c"}}));
734 mergeAndTestRewrite("aaaa", "aaa", "aac", toReplacements({{"", 1, 1, ""}}),
735 toReplacements({{"", 2, 1, "c"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000736
737 mergeAndTestRewrite("aa", "bbabba", "bbabcba",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000738 toReplacements({{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}),
739 toReplacements({{"", 4, 0, "c"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000740}
741
742TEST_F(MergeReplacementsTest, Concatenations) {
743 // Basic concatenations. It is important to merge these into a single
744 // replacement to ensure the correct order.
Eric Liu40ef2fb2016-08-01 10:16:37 +0000745 {
746 auto First = toReplacements({{"", 0, 0, "a"}});
747 auto Second = toReplacements({{"", 1, 0, "b"}});
748 EXPECT_EQ(toReplacements({{"", 0, 0, "ab"}}), First.merge(Second));
749 }
750 {
751 auto First = toReplacements({{"", 0, 0, "a"}});
752 auto Second = toReplacements({{"", 0, 0, "b"}});
753 EXPECT_EQ(toReplacements({{"", 0, 0, "ba"}}), First.merge(Second));
754 }
755 mergeAndTestRewrite("", "a", "ab", toReplacements({{"", 0, 0, "a"}}),
756 toReplacements({{"", 1, 0, "b"}}));
757 mergeAndTestRewrite("", "a", "ba", toReplacements({{"", 0, 0, "a"}}),
758 toReplacements({{"", 0, 0, "b"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000759}
760
761TEST_F(MergeReplacementsTest, NotChangingLengths) {
Eric Liu40ef2fb2016-08-01 10:16:37 +0000762 mergeAndTestRewrite("aaaa", "abba", "acca",
763 toReplacements({{"", 1, 2, "bb"}}),
764 toReplacements({{"", 1, 2, "cc"}}));
765 mergeAndTestRewrite("aaaa", "abba", "abcc",
766 toReplacements({{"", 1, 2, "bb"}}),
767 toReplacements({{"", 2, 2, "cc"}}));
768 mergeAndTestRewrite("aaaa", "abba", "ccba",
769 toReplacements({{"", 1, 2, "bb"}}),
770 toReplacements({{"", 0, 2, "cc"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000771 mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000772 toReplacements({{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}),
773 toReplacements({{"", 2, 2, "cc"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000774}
775
776TEST_F(MergeReplacementsTest, OverlappingRanges) {
777 mergeAndTestRewrite("aaa", "bbd", "bcbcd",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000778 toReplacements({{"", 0, 1, "bb"}, {"", 1, 2, "d"}}),
779 toReplacements({{"", 1, 0, "c"}, {"", 2, 0, "c"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000780
Eric Liu40ef2fb2016-08-01 10:16:37 +0000781 mergeAndTestRewrite("aaaa", "aabbaa", "acccca",
782 toReplacements({{"", 2, 0, "bb"}}),
783 toReplacements({{"", 1, 4, "cccc"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000784 mergeAndTestRewrite("aaaa", "aababa", "acccca",
Eric Liu40ef2fb2016-08-01 10:16:37 +0000785 toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
786 toReplacements({{"", 1, 4, "cccc"}}));
787 mergeAndTestRewrite("aaaaaa", "abbbba", "abba",
788 toReplacements({{"", 1, 4, "bbbb"}}),
789 toReplacements({{"", 2, 2, ""}}));
790 mergeAndTestRewrite("aaaa", "aa", "cc",
791 toReplacements({{"", 1, 1, ""}, {"", 2, 1, ""}}),
792 toReplacements({{"", 0, 2, "cc"}}));
793 mergeAndTestRewrite("aa", "abbba", "abcbcba",
794 toReplacements({{"", 1, 0, "bbb"}}),
795 toReplacements({{"", 2, 0, "c"}, {"", 3, 0, "c"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000796
Eric Liu40ef2fb2016-08-01 10:16:37 +0000797 mergeAndTestRewrite(
798 "aaa", "abbab", "ccdd",
799 toReplacements({{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}}),
800 toReplacements({{"", 0, 2, "cc"}, {"", 2, 3, "dd"}}));
801 mergeAndTestRewrite(
802 "aa", "babbab", "ccdd",
803 toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}}),
804 toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000805}
806
Manuel Klimek3f001342012-05-23 16:29:20 +0000807} // end namespace tooling
808} // end namespace clang