|
@@ -7,6 +7,7 @@
|
|
|
//
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
+#include "ReplacementTest.h"
|
|
|
#include "RewriterTestContext.h"
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
|
#include "clang/AST/ASTContext.h"
|
|
@@ -31,16 +32,6 @@
|
|
|
namespace clang {
|
|
|
namespace tooling {
|
|
|
|
|
|
-class ReplacementTest : public ::testing::Test {
|
|
|
- protected:
|
|
|
- Replacement createReplacement(SourceLocation Start, unsigned Length,
|
|
|
- llvm::StringRef ReplacementText) {
|
|
|
- return Replacement(Context.Sources, Start, Length, ReplacementText);
|
|
|
- }
|
|
|
-
|
|
|
- RewriterTestContext Context;
|
|
|
-};
|
|
|
-
|
|
|
TEST_F(ReplacementTest, CanDeleteAllText) {
|
|
|
FileID ID = Context.createInMemoryFile("input.cpp", "text");
|
|
|
SourceLocation Location = Context.getLocation(ID, 1, 1);
|
|
@@ -108,29 +99,30 @@ TEST_F(ReplacementTest, ReturnsInvalidPath) {
|
|
|
EXPECT_TRUE(Replace2.getFilePath().empty());
|
|
|
}
|
|
|
|
|
|
-TEST_F(ReplacementTest, CanApplyReplacements) {
|
|
|
- FileID ID = Context.createInMemoryFile("input.cpp",
|
|
|
- "line1\nline2\nline3\nline4");
|
|
|
+TEST_F(ReplacementTest, FailAddReplacements) {
|
|
|
Replacements Replaces;
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 3, 1),
|
|
|
- 5, "other"));
|
|
|
- EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
|
|
|
- EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
|
|
|
+ auto Err = Replaces.add(Replacement("x.cc", 0, 10, "3"));
|
|
|
+ EXPECT_TRUE(!Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
+ Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
|
|
|
+ EXPECT_TRUE((bool)Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
+ Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
|
|
|
+ EXPECT_TRUE((bool)Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
+ Err = Replaces.add(Replacement("y.cc", 20, 2, ""));
|
|
|
+ EXPECT_TRUE((bool)Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
}
|
|
|
|
|
|
-// FIXME: Remove this test case when Replacements is implemented as std::vector
|
|
|
-// instead of std::set. The other ReplacementTest tests will need to be updated
|
|
|
-// at that point as well.
|
|
|
-TEST_F(ReplacementTest, VectorCanApplyReplacements) {
|
|
|
+TEST_F(ReplacementTest, CanApplyReplacements) {
|
|
|
FileID ID = Context.createInMemoryFile("input.cpp",
|
|
|
"line1\nline2\nline3\nline4");
|
|
|
- std::vector<Replacement> Replaces;
|
|
|
- Replaces.push_back(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
- Replaces.push_back(
|
|
|
- Replacement(Context.Sources, Context.getLocation(ID, 3, 1), 5, "other"));
|
|
|
+ Replacements Replaces =
|
|
|
+ toReplacements({Replacement(Context.Sources,
|
|
|
+ Context.getLocation(ID, 2, 1), 5, "replaced"),
|
|
|
+ Replacement(Context.Sources,
|
|
|
+ Context.getLocation(ID, 3, 1), 5, "other")});
|
|
|
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
|
|
|
EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
|
|
|
}
|
|
@@ -138,32 +130,28 @@ TEST_F(ReplacementTest, VectorCanApplyReplacements) {
|
|
|
TEST_F(ReplacementTest, SkipsDuplicateReplacements) {
|
|
|
FileID ID = Context.createInMemoryFile("input.cpp",
|
|
|
"line1\nline2\nline3\nline4");
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
+ auto Replaces = toReplacements({Replacement(
|
|
|
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
|
|
|
+
|
|
|
+ auto Err = Replaces.add(Replacement(
|
|
|
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));
|
|
|
+ EXPECT_TRUE((bool)Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
+
|
|
|
+ Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
+ 5, "replaced"));
|
|
|
+ EXPECT_TRUE((bool)Err);
|
|
|
+ llvm::consumeError(std::move(Err));
|
|
|
+
|
|
|
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
|
|
|
EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
|
|
|
}
|
|
|
|
|
|
-TEST_F(ReplacementTest, ApplyAllFailsIfOneApplyFails) {
|
|
|
- // This test depends on the value of the file name of an invalid source
|
|
|
- // location being in the range ]a, z[.
|
|
|
- FileID IDa = Context.createInMemoryFile("a.cpp", "text");
|
|
|
- FileID IDz = Context.createInMemoryFile("z.cpp", "text");
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDa, 1, 1),
|
|
|
- 4, "a"));
|
|
|
- Replaces.insert(Replacement(Context.Sources, SourceLocation(),
|
|
|
- 5, "2"));
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDz, 1, 1),
|
|
|
- 4, "z"));
|
|
|
+TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {
|
|
|
+ Replacements Replaces =
|
|
|
+ toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});
|
|
|
+
|
|
|
EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
|
|
|
- EXPECT_EQ("a", Context.getRewrittenText(IDa));
|
|
|
- EXPECT_EQ("z", Context.getRewrittenText(IDz));
|
|
|
}
|
|
|
|
|
|
TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
|
|
@@ -179,76 +167,66 @@ TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
|
|
|
std::string Expected2 = "int x =\n"
|
|
|
" 1234567890123;\n"
|
|
|
"int y = 10;";
|
|
|
- FileID ID1 = Context.createInMemoryFile("format_1.cpp", Code1);
|
|
|
- FileID ID2 = Context.createInMemoryFile("format_2.cpp", Code2);
|
|
|
+ StringRef File1 = "format_1.cpp";
|
|
|
+ StringRef File2 = "format_2.cpp";
|
|
|
+ FileID ID1 = Context.createInMemoryFile(File1, Code1);
|
|
|
+ FileID ID2 = Context.createInMemoryFile(File2, Code2);
|
|
|
|
|
|
- tooling::Replacements Replaces;
|
|
|
// Scrambled the order of replacements.
|
|
|
- Replaces.insert(tooling::Replacement(
|
|
|
- Context.Sources, Context.getLocation(ID2, 1, 12), 0, "4567890123"));
|
|
|
- Replaces.insert(tooling::Replacement(
|
|
|
- Context.Sources, Context.getLocation(ID1, 1, 1), 6, "auto "));
|
|
|
- Replaces.insert(tooling::Replacement(
|
|
|
- Context.Sources, Context.getLocation(ID2, 2, 9), 1, "10"));
|
|
|
- Replaces.insert(tooling::Replacement(
|
|
|
- Context.Sources, Context.getLocation(ID1, 3, 10), 1, "12345678901"));
|
|
|
-
|
|
|
- EXPECT_TRUE(formatAndApplyAllReplacements(
|
|
|
- Replaces, Context.Rewrite, "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
|
|
|
+ std::map<std::string, Replacements> FileToReplaces;
|
|
|
+ FileToReplaces[File1] = toReplacements(
|
|
|
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID1, 1, 1), 6,
|
|
|
+ "auto "),
|
|
|
+ tooling::Replacement(Context.Sources, Context.getLocation(ID1, 3, 10), 1,
|
|
|
+ "12345678901")});
|
|
|
+ FileToReplaces[File2] = toReplacements(
|
|
|
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID2, 1, 12), 0,
|
|
|
+ "4567890123"),
|
|
|
+ tooling::Replacement(Context.Sources, Context.getLocation(ID2, 2, 9), 1,
|
|
|
+ "10")});
|
|
|
+ EXPECT_TRUE(
|
|
|
+ formatAndApplyAllReplacements(FileToReplaces, Context.Rewrite,
|
|
|
+ "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
|
|
|
EXPECT_EQ(Expected1, Context.getRewrittenText(ID1));
|
|
|
EXPECT_EQ(Expected2, Context.getRewrittenText(ID2));
|
|
|
}
|
|
|
|
|
|
TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement("", 0, 1, ""));
|
|
|
- Replaces.insert(Replacement("", 4, 3, " "));
|
|
|
- // Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
|
|
|
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int i;
|
|
|
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); // |nt i;
|
|
|
- EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
|
|
|
- EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
|
|
|
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
|
|
|
- EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
|
|
|
-}
|
|
|
-
|
|
|
-// FIXME: Remove this test case when Replacements is implemented as std::vector
|
|
|
-// instead of std::set. The other ReplacementTest tests will need to be updated
|
|
|
-// at that point as well.
|
|
|
-TEST(ShiftedCodePositionTest, VectorFindsNewCodePositionWithInserts) {
|
|
|
- std::vector<Replacement> Replaces;
|
|
|
- Replaces.push_back(Replacement("", 0, 1, ""));
|
|
|
- Replaces.push_back(Replacement("", 4, 3, " "));
|
|
|
+ Replacements Replaces =
|
|
|
+ toReplacements({Replacement("", 0, 1, ""), Replacement("", 4, 3, " ")});
|
|
|
// Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
|
|
|
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int i;
|
|
|
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); // |nt i;
|
|
|
- EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
|
|
|
- EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
|
|
|
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
|
|
|
- EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
|
|
|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0)); // |int i;
|
|
|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(1)); // |nt i;
|
|
|
+ EXPECT_EQ(1u, Replaces.getShiftedCodePosition(2)); // i|t i;
|
|
|
+ EXPECT_EQ(2u, Replaces.getShiftedCodePosition(3)); // in| i;
|
|
|
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(4)); // int| i;
|
|
|
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(5)); // int | i;
|
|
|
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(6)); // int |i;
|
|
|
+ EXPECT_EQ(4u, Replaces.getShiftedCodePosition(7)); // int |;
|
|
|
+ EXPECT_EQ(5u, Replaces.getShiftedCodePosition(8)); // int i|
|
|
|
}
|
|
|
|
|
|
TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement("", 4, 0, "\"\n\""));
|
|
|
+ Replacements Replaces = toReplacements({Replacement("", 4, 0, "\"\n\"")});
|
|
|
// Assume '"12345678"' is turned into '"1234"\n"5678"'.
|
|
|
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 3)); // "123|5678"
|
|
|
- EXPECT_EQ(7u, shiftedCodePosition(Replaces, 4)); // "1234|678"
|
|
|
- EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "12345|78"
|
|
|
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(3)); // "123|5678"
|
|
|
+ EXPECT_EQ(7u, Replaces.getShiftedCodePosition(4)); // "1234|678"
|
|
|
+ EXPECT_EQ(8u, Replaces.getShiftedCodePosition(5)); // "12345|78"
|
|
|
}
|
|
|
|
|
|
TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
|
|
|
- Replacements Replaces;
|
|
|
// Replace the first four characters with "abcd".
|
|
|
- Replaces.insert(Replacement("", 0, 4, "abcd"));
|
|
|
+ auto Replaces = toReplacements({Replacement("", 0, 4, "abcd")});
|
|
|
for (unsigned i = 0; i < 3; ++i)
|
|
|
- EXPECT_EQ(i, shiftedCodePosition(Replaces, i));
|
|
|
+ EXPECT_EQ(i, Replaces.getShiftedCodePosition(i));
|
|
|
+}
|
|
|
+
|
|
|
+TEST(ShiftedCodePositionTest, NoReplacementText) {
|
|
|
+ Replacements Replaces = toReplacements({Replacement("", 0, 42, "")});
|
|
|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0));
|
|
|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(39));
|
|
|
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(45));
|
|
|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(42));
|
|
|
}
|
|
|
|
|
|
class FlushRewrittenFilesTest : public ::testing::Test {
|
|
@@ -304,9 +282,8 @@ public:
|
|
|
|
|
|
TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
|
|
|
FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
|
|
|
- 5, "replaced"));
|
|
|
+ Replacements Replaces = toReplacements({Replacement(
|
|
|
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
|
|
|
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
|
|
|
EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
|
|
|
EXPECT_EQ("line1\nreplaced\nline3\nline4",
|
|
@@ -454,12 +431,11 @@ TEST(Range, contains) {
|
|
|
TEST(Range, CalculateRangesOfReplacements) {
|
|
|
// Before: aaaabbbbbbz
|
|
|
// After : bbbbbbzzzzzzoooooooooooooooo
|
|
|
- Replacements Replaces;
|
|
|
- Replaces.insert(Replacement("foo", 0, 4, ""));
|
|
|
- Replaces.insert(Replacement("foo", 10, 1, "zzzzzz"));
|
|
|
- Replaces.insert(Replacement("foo", 11, 0, "oooooooooooooooo"));
|
|
|
+ Replacements Replaces = toReplacements(
|
|
|
+ {Replacement("foo", 0, 4, ""), Replacement("foo", 10, 1, "zzzzzz"),
|
|
|
+ Replacement("foo", 11, 0, "oooooooooooooooo")});
|
|
|
|
|
|
- std::vector<Range> Ranges = calculateChangedRanges(Replaces);
|
|
|
+ std::vector<Range> Ranges = Replaces.getAffectedRanges();
|
|
|
|
|
|
EXPECT_EQ(2ul, Ranges.size());
|
|
|
EXPECT_TRUE(Ranges[0].getOffset() == 0);
|
|
@@ -470,23 +446,23 @@ TEST(Range, CalculateRangesOfReplacements) {
|
|
|
|
|
|
TEST(Range, RangesAfterReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 0, 2, "1234")};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 0, 2, "1234")});
|
|
|
std::vector<Range> Expected = {Range(0, 4), Range(7, 2), Range(12, 5)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, RangesBeforeReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 20, 2, "1234")};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 20, 2, "1234")});
|
|
|
std::vector<Range> Expected = {Range(5, 2), Range(10, 5), Range(20, 4)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, NotAffectedByReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 3, 2, "12"),
|
|
|
- Replacement("foo", 12, 2, "12"),
|
|
|
- Replacement("foo", 20, 5, "")};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 3, 2, "12"),
|
|
|
+ Replacement("foo", 12, 2, "12"),
|
|
|
+ Replacement("foo", 20, 5, "")});
|
|
|
std::vector<Range> Expected = {Range(0, 2), Range(3, 4), Range(10, 5),
|
|
|
Range(20, 0)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
@@ -494,9 +470,9 @@ TEST(Range, NotAffectedByReplacements) {
|
|
|
|
|
|
TEST(Range, RangesWithNonOverlappingReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 3, 1, ""),
|
|
|
- Replacement("foo", 6, 1, "123"),
|
|
|
- Replacement("foo", 20, 2, "12345")};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 3, 1, ""),
|
|
|
+ Replacement("foo", 6, 1, "123"),
|
|
|
+ Replacement("foo", 20, 2, "12345")});
|
|
|
std::vector<Range> Expected = {Range(0, 2), Range(3, 0), Range(4, 4),
|
|
|
Range(11, 5), Range(21, 5)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
@@ -505,9 +481,9 @@ TEST(Range, RangesWithNonOverlappingReplacements) {
|
|
|
TEST(Range, RangesWithOverlappingReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5),
|
|
|
Range(30, 5)};
|
|
|
- Replacements Replaces = {
|
|
|
- Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
|
|
|
- Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")};
|
|
|
+ Replacements Replaces = toReplacements(
|
|
|
+ {Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
|
|
|
+ Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")});
|
|
|
std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(12, 5),
|
|
|
Range(22, 0)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
@@ -515,122 +491,52 @@ TEST(Range, RangesWithOverlappingReplacements) {
|
|
|
|
|
|
TEST(Range, MergeIntoOneRange) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 1, 15, "1234567890")};
|
|
|
+ Replacements Replaces =
|
|
|
+ toReplacements({Replacement("foo", 1, 15, "1234567890")});
|
|
|
std::vector<Range> Expected = {Range(0, 15)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, ReplacementsStartingAtRangeOffsets) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 5), Range(15, 5)};
|
|
|
- Replacements Replaces = {
|
|
|
- Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
|
|
|
- Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")};
|
|
|
+ Replacements Replaces = toReplacements(
|
|
|
+ {Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
|
|
|
+ Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")});
|
|
|
std::vector<Range> Expected = {Range(0, 2), Range(5, 9), Range(18, 2)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, ReplacementsEndingAtRangeEnds) {
|
|
|
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 6, 1, "123"),
|
|
|
- Replacement("foo", 17, 3, "12")};
|
|
|
+ Replacements Replaces = toReplacements(
|
|
|
+ {Replacement("foo", 6, 1, "123"), Replacement("foo", 17, 3, "12")});
|
|
|
std::vector<Range> Expected = {Range(0, 2), Range(5, 4), Range(17, 4)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, AjacentReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(0, 0), Range(15, 5)};
|
|
|
- Replacements Replaces = {Replacement("foo", 1, 2, "123"),
|
|
|
- Replacement("foo", 12, 3, "1234")};
|
|
|
+ Replacements Replaces = toReplacements(
|
|
|
+ {Replacement("foo", 1, 2, "123"), Replacement("foo", 12, 3, "1234")});
|
|
|
std::vector<Range> Expected = {Range(0, 0), Range(1, 3), Range(13, 9)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
TEST(Range, MergeRangesAfterReplacements) {
|
|
|
std::vector<Range> Ranges = {Range(8, 0), Range(5, 2), Range(9, 0), Range(0, 1)};
|
|
|
- Replacements Replaces = {Replacement("foo", 1, 3, ""),
|
|
|
- Replacement("foo", 7, 0, "12"), Replacement("foo", 9, 2, "")};
|
|
|
- std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0), Range(8, 0)};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 1, 3, ""),
|
|
|
+ Replacement("foo", 7, 0, "12"),
|
|
|
+ Replacement("foo", 9, 2, "")});
|
|
|
+ std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0),
|
|
|
+ Range(8, 0)};
|
|
|
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
-TEST(DeduplicateTest, removesDuplicates) {
|
|
|
- std::vector<Replacement> Input;
|
|
|
- Input.push_back(Replacement("fileA", 50, 0, " foo "));
|
|
|
- Input.push_back(Replacement("fileA", 10, 3, " bar "));
|
|
|
- Input.push_back(Replacement("fileA", 10, 2, " bar ")); // Length differs
|
|
|
- Input.push_back(Replacement("fileA", 9, 3, " bar ")); // Offset differs
|
|
|
- Input.push_back(Replacement("fileA", 50, 0, " foo ")); // Duplicate
|
|
|
- Input.push_back(Replacement("fileA", 51, 3, " bar "));
|
|
|
- Input.push_back(Replacement("fileB", 51, 3, " bar ")); // Filename differs!
|
|
|
- Input.push_back(Replacement("fileB", 60, 1, " bar "));
|
|
|
- Input.push_back(Replacement("fileA", 60, 2, " bar "));
|
|
|
- Input.push_back(Replacement("fileA", 51, 3, " moo ")); // Replacement text
|
|
|
- // differs!
|
|
|
-
|
|
|
- std::vector<Replacement> Expected;
|
|
|
- Expected.push_back(Replacement("fileA", 9, 3, " bar "));
|
|
|
- Expected.push_back(Replacement("fileA", 10, 2, " bar "));
|
|
|
- Expected.push_back(Replacement("fileA", 10, 3, " bar "));
|
|
|
- Expected.push_back(Replacement("fileA", 50, 0, " foo "));
|
|
|
- Expected.push_back(Replacement("fileA", 51, 3, " bar "));
|
|
|
- Expected.push_back(Replacement("fileA", 51, 3, " moo "));
|
|
|
- Expected.push_back(Replacement("fileB", 60, 1, " bar "));
|
|
|
- Expected.push_back(Replacement("fileA", 60, 2, " bar "));
|
|
|
-
|
|
|
- std::vector<Range> Conflicts; // Ignored for this test
|
|
|
- deduplicate(Input, Conflicts);
|
|
|
-
|
|
|
- EXPECT_EQ(3U, Conflicts.size());
|
|
|
- EXPECT_EQ(Expected, Input);
|
|
|
-}
|
|
|
-
|
|
|
-TEST(DeduplicateTest, detectsConflicts) {
|
|
|
- {
|
|
|
- std::vector<Replacement> Input;
|
|
|
- Input.push_back(Replacement("fileA", 0, 5, " foo "));
|
|
|
- Input.push_back(Replacement("fileA", 0, 5, " foo ")); // Duplicate not a
|
|
|
- // conflict.
|
|
|
- Input.push_back(Replacement("fileA", 2, 6, " bar "));
|
|
|
- Input.push_back(Replacement("fileA", 7, 3, " moo "));
|
|
|
-
|
|
|
- std::vector<Range> Conflicts;
|
|
|
- deduplicate(Input, Conflicts);
|
|
|
-
|
|
|
- // One duplicate is removed and the remaining three items form one
|
|
|
- // conflicted range.
|
|
|
- ASSERT_EQ(3u, Input.size());
|
|
|
- ASSERT_EQ(1u, Conflicts.size());
|
|
|
- ASSERT_EQ(0u, Conflicts.front().getOffset());
|
|
|
- ASSERT_EQ(3u, Conflicts.front().getLength());
|
|
|
- }
|
|
|
- {
|
|
|
- std::vector<Replacement> Input;
|
|
|
-
|
|
|
- // Expected sorted order is shown. It is the sorted order to which the
|
|
|
- // returned conflict info refers to.
|
|
|
- Input.push_back(Replacement("fileA", 0, 5, " foo ")); // 0
|
|
|
- Input.push_back(Replacement("fileA", 5, 5, " bar ")); // 1
|
|
|
- Input.push_back(Replacement("fileA", 6, 0, " bar ")); // 3
|
|
|
- Input.push_back(Replacement("fileA", 5, 5, " moo ")); // 2
|
|
|
- Input.push_back(Replacement("fileA", 7, 2, " bar ")); // 4
|
|
|
- Input.push_back(Replacement("fileA", 15, 5, " golf ")); // 5
|
|
|
- Input.push_back(Replacement("fileA", 16, 5, " bag ")); // 6
|
|
|
- Input.push_back(Replacement("fileA", 10, 3, " club ")); // 7
|
|
|
-
|
|
|
- // #3 is special in that it is completely contained by another conflicting
|
|
|
- // Replacement. #4 ensures #3 hasn't messed up the conflicting range size.
|
|
|
-
|
|
|
- std::vector<Range> Conflicts;
|
|
|
- deduplicate(Input, Conflicts);
|
|
|
-
|
|
|
- // No duplicates
|
|
|
- ASSERT_EQ(8u, Input.size());
|
|
|
- ASSERT_EQ(2u, Conflicts.size());
|
|
|
- ASSERT_EQ(1u, Conflicts[0].getOffset());
|
|
|
- ASSERT_EQ(4u, Conflicts[0].getLength());
|
|
|
- ASSERT_EQ(6u, Conflicts[1].getOffset());
|
|
|
- ASSERT_EQ(2u, Conflicts[1].getLength());
|
|
|
- }
|
|
|
+TEST(Range, ConflictingRangesBeforeReplacements) {
|
|
|
+ std::vector<Range> Ranges = {Range(8, 3), Range(5, 4), Range(9, 1)};
|
|
|
+ Replacements Replaces = toReplacements({Replacement("foo", 1, 3, "")});
|
|
|
+ std::vector<Range> Expected = {Range(1, 0), Range(2, 6)};
|
|
|
+ EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
|
|
|
}
|
|
|
|
|
|
class MergeReplacementsTest : public ::testing::Test {
|
|
@@ -646,7 +552,7 @@ protected:
|
|
|
EXPECT_EQ(Intermediate, *AfterFirst);
|
|
|
EXPECT_EQ(Result, *InSequenceRewrite);
|
|
|
|
|
|
- tooling::Replacements Merged = mergeReplacements(First, Second);
|
|
|
+ tooling::Replacements Merged = First.merge(Second);
|
|
|
auto MergedRewrite = applyAllReplacements(Code, Merged);
|
|
|
EXPECT_TRUE(static_cast<bool>(MergedRewrite));
|
|
|
EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
|
|
@@ -660,7 +566,7 @@ protected:
|
|
|
auto AfterFirst = applyAllReplacements(Code, First);
|
|
|
EXPECT_TRUE(static_cast<bool>(AfterFirst));
|
|
|
auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
|
|
|
- tooling::Replacements Merged = mergeReplacements(First, Second);
|
|
|
+ tooling::Replacements Merged = First.merge(Second);
|
|
|
auto MergedRewrite = applyAllReplacements(Code, Merged);
|
|
|
EXPECT_TRUE(static_cast<bool>(MergedRewrite));
|
|
|
EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
|
|
@@ -673,62 +579,82 @@ protected:
|
|
|
|
|
|
TEST_F(MergeReplacementsTest, Offsets) {
|
|
|
mergeAndTestRewrite("aaa", "aabab", "cacabab",
|
|
|
- {{"", 2, 0, "b"}, {"", 3, 0, "b"}},
|
|
|
- {{"", 0, 0, "c"}, {"", 1, 0, "c"}});
|
|
|
+ toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
|
|
|
+ toReplacements({{"", 0, 0, "c"}, {"", 1, 0, "c"}}));
|
|
|
mergeAndTestRewrite("aaa", "babaa", "babacac",
|
|
|
- {{"", 0, 0, "b"}, {"", 1, 0, "b"}},
|
|
|
- {{"", 4, 0, "c"}, {"", 5, 0, "c"}});
|
|
|
- mergeAndTestRewrite("aaaa", "aaa", "aac", {{"", 1, 1, ""}},
|
|
|
- {{"", 2, 1, "c"}});
|
|
|
+ toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "b"}}),
|
|
|
+ toReplacements({{"", 4, 0, "c"}, {"", 5, 0, "c"}}));
|
|
|
+ mergeAndTestRewrite("aaaa", "aaa", "aac", toReplacements({{"", 1, 1, ""}}),
|
|
|
+ toReplacements({{"", 2, 1, "c"}}));
|
|
|
|
|
|
mergeAndTestRewrite("aa", "bbabba", "bbabcba",
|
|
|
- {{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}, {{"", 4, 0, "c"}});
|
|
|
+ toReplacements({{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}),
|
|
|
+ toReplacements({{"", 4, 0, "c"}}));
|
|
|
}
|
|
|
|
|
|
TEST_F(MergeReplacementsTest, Concatenations) {
|
|
|
// Basic concatenations. It is important to merge these into a single
|
|
|
// replacement to ensure the correct order.
|
|
|
- EXPECT_EQ((Replacements{{"", 0, 0, "ab"}}),
|
|
|
- mergeReplacements({{"", 0, 0, "a"}}, {{"", 1, 0, "b"}}));
|
|
|
- EXPECT_EQ((Replacements{{"", 0, 0, "ba"}}),
|
|
|
- mergeReplacements({{"", 0, 0, "a"}}, {{"", 0, 0, "b"}}));
|
|
|
- mergeAndTestRewrite("", "a", "ab", {{"", 0, 0, "a"}}, {{"", 1, 0, "b"}});
|
|
|
- mergeAndTestRewrite("", "a", "ba", {{"", 0, 0, "a"}}, {{"", 0, 0, "b"}});
|
|
|
+ {
|
|
|
+ auto First = toReplacements({{"", 0, 0, "a"}});
|
|
|
+ auto Second = toReplacements({{"", 1, 0, "b"}});
|
|
|
+ EXPECT_EQ(toReplacements({{"", 0, 0, "ab"}}), First.merge(Second));
|
|
|
+ }
|
|
|
+ {
|
|
|
+ auto First = toReplacements({{"", 0, 0, "a"}});
|
|
|
+ auto Second = toReplacements({{"", 0, 0, "b"}});
|
|
|
+ EXPECT_EQ(toReplacements({{"", 0, 0, "ba"}}), First.merge(Second));
|
|
|
+ }
|
|
|
+ mergeAndTestRewrite("", "a", "ab", toReplacements({{"", 0, 0, "a"}}),
|
|
|
+ toReplacements({{"", 1, 0, "b"}}));
|
|
|
+ mergeAndTestRewrite("", "a", "ba", toReplacements({{"", 0, 0, "a"}}),
|
|
|
+ toReplacements({{"", 0, 0, "b"}}));
|
|
|
}
|
|
|
|
|
|
TEST_F(MergeReplacementsTest, NotChangingLengths) {
|
|
|
- mergeAndTestRewrite("aaaa", "abba", "acca", {{"", 1, 2, "bb"}},
|
|
|
- {{"", 1, 2, "cc"}});
|
|
|
- mergeAndTestRewrite("aaaa", "abba", "abcc", {{"", 1, 2, "bb"}},
|
|
|
- {{"", 2, 2, "cc"}});
|
|
|
- mergeAndTestRewrite("aaaa", "abba", "ccba", {{"", 1, 2, "bb"}},
|
|
|
- {{"", 0, 2, "cc"}});
|
|
|
+ mergeAndTestRewrite("aaaa", "abba", "acca",
|
|
|
+ toReplacements({{"", 1, 2, "bb"}}),
|
|
|
+ toReplacements({{"", 1, 2, "cc"}}));
|
|
|
+ mergeAndTestRewrite("aaaa", "abba", "abcc",
|
|
|
+ toReplacements({{"", 1, 2, "bb"}}),
|
|
|
+ toReplacements({{"", 2, 2, "cc"}}));
|
|
|
+ mergeAndTestRewrite("aaaa", "abba", "ccba",
|
|
|
+ toReplacements({{"", 1, 2, "bb"}}),
|
|
|
+ toReplacements({{"", 0, 2, "cc"}}));
|
|
|
mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
|
|
|
- {{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}, {{"", 2, 2, "cc"}});
|
|
|
+ toReplacements({{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}),
|
|
|
+ toReplacements({{"", 2, 2, "cc"}}));
|
|
|
}
|
|
|
|
|
|
TEST_F(MergeReplacementsTest, OverlappingRanges) {
|
|
|
mergeAndTestRewrite("aaa", "bbd", "bcbcd",
|
|
|
- {{"", 0, 1, "bb"}, {"", 1, 2, "d"}},
|
|
|
- {{"", 1, 0, "c"}, {"", 2, 0, "c"}});
|
|
|
+ toReplacements({{"", 0, 1, "bb"}, {"", 1, 2, "d"}}),
|
|
|
+ toReplacements({{"", 1, 0, "c"}, {"", 2, 0, "c"}}));
|
|
|
|
|
|
- mergeAndTestRewrite("aaaa", "aabbaa", "acccca", {{"", 2, 0, "bb"}},
|
|
|
- {{"", 1, 4, "cccc"}});
|
|
|
+ mergeAndTestRewrite("aaaa", "aabbaa", "acccca",
|
|
|
+ toReplacements({{"", 2, 0, "bb"}}),
|
|
|
+ toReplacements({{"", 1, 4, "cccc"}}));
|
|
|
mergeAndTestRewrite("aaaa", "aababa", "acccca",
|
|
|
- {{"", 2, 0, "b"}, {"", 3, 0, "b"}}, {{"", 1, 4, "cccc"}});
|
|
|
- mergeAndTestRewrite("aaaaaa", "abbbba", "abba", {{"", 1, 4, "bbbb"}},
|
|
|
- {{"", 2, 2, ""}});
|
|
|
- mergeAndTestRewrite("aaaa", "aa", "cc", {{"", 1, 1, ""}, {"", 2, 1, ""}},
|
|
|
- {{"", 0, 2, "cc"}});
|
|
|
- mergeAndTestRewrite("aa", "abbba", "abcbcba", {{"", 1, 0, "bbb"}},
|
|
|
- {{"", 2, 0, "c"}, {"", 3, 0, "c"}});
|
|
|
-
|
|
|
- mergeAndTestRewrite("aaa", "abbab", "ccdd",
|
|
|
- {{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}},
|
|
|
- {{"", 0, 2, "cc"}, {"", 2, 3, "dd"}});
|
|
|
- mergeAndTestRewrite("aa", "babbab", "ccdd",
|
|
|
- {{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}},
|
|
|
- {{"", 0, 3, "cc"}, {"", 3, 3, "dd"}});
|
|
|
+ toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
|
|
|
+ toReplacements({{"", 1, 4, "cccc"}}));
|
|
|
+ mergeAndTestRewrite("aaaaaa", "abbbba", "abba",
|
|
|
+ toReplacements({{"", 1, 4, "bbbb"}}),
|
|
|
+ toReplacements({{"", 2, 2, ""}}));
|
|
|
+ mergeAndTestRewrite("aaaa", "aa", "cc",
|
|
|
+ toReplacements({{"", 1, 1, ""}, {"", 2, 1, ""}}),
|
|
|
+ toReplacements({{"", 0, 2, "cc"}}));
|
|
|
+ mergeAndTestRewrite("aa", "abbba", "abcbcba",
|
|
|
+ toReplacements({{"", 1, 0, "bbb"}}),
|
|
|
+ toReplacements({{"", 2, 0, "c"}, {"", 3, 0, "c"}}));
|
|
|
+
|
|
|
+ mergeAndTestRewrite(
|
|
|
+ "aaa", "abbab", "ccdd",
|
|
|
+ toReplacements({{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}}),
|
|
|
+ toReplacements({{"", 0, 2, "cc"}, {"", 2, 3, "dd"}}));
|
|
|
+ mergeAndTestRewrite(
|
|
|
+ "aa", "babbab", "ccdd",
|
|
|
+ toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}}),
|
|
|
+ toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
|
|
|
}
|
|
|
|
|
|
} // end namespace tooling
|