summaryrefslogtreecommitdiff
path: root/unittests/Tooling/RefactoringTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Tooling/RefactoringTest.cpp')
-rw-r--r--unittests/Tooling/RefactoringTest.cpp855
1 files changed, 606 insertions, 249 deletions
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index df96bb159dea7..c29f8d7d71230 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ReplacementTest.h"
#include "RewriterTestContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -18,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
@@ -26,22 +28,11 @@
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Path.h"
#include "gtest/gtest.h"
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);
@@ -109,62 +100,412 @@ TEST_F(ReplacementTest, ReturnsInvalidPath) {
EXPECT_TRUE(Replace2.getFilePath().empty());
}
+// Checks that an llvm::Error instance contains a ReplacementError with expected
+// error code, expected new replacement, and expected existing replacement.
+static bool checkReplacementError(
+ llvm::Error&& Error, replacement_error ExpectedErr,
+ llvm::Optional<Replacement> ExpectedExisting,
+ llvm::Optional<Replacement> ExpectedNew) {
+ if (!Error) {
+ llvm::errs() << "Error is a success.";
+ return false;
+ }
+ std::string ErrorMessage;
+ llvm::raw_string_ostream OS(ErrorMessage);
+ llvm::handleAllErrors(std::move(Error), [&](const ReplacementError &RE) {
+ llvm::errs() << "Handling error...\n";
+ if (ExpectedErr != RE.get())
+ OS << "Unexpected error code: " << int(RE.get()) << "\n";
+ if (ExpectedExisting != RE.getExistingReplacement()) {
+ OS << "Expected Existing != Actual Existing.\n";
+ if (ExpectedExisting.hasValue())
+ OS << "Expected existing replacement: " << ExpectedExisting->toString()
+ << "\n";
+ if (RE.getExistingReplacement().hasValue())
+ OS << "Actual existing replacement: "
+ << RE.getExistingReplacement()->toString() << "\n";
+ }
+ if (ExpectedNew != RE.getNewReplacement()) {
+ OS << "Expected New != Actual New.\n";
+ if (ExpectedNew.hasValue())
+ OS << "Expected new replacement: " << ExpectedNew->toString() << "\n";
+ if (RE.getNewReplacement().hasValue())
+ OS << "Actual new replacement: " << RE.getNewReplacement()->toString()
+ << "\n";
+ }
+ });
+ OS.flush();
+ if (ErrorMessage.empty()) return true;
+ llvm::errs() << ErrorMessage;
+ return false;
+}
+
+TEST_F(ReplacementTest, FailAddReplacements) {
+ Replacements Replaces;
+ Replacement Deletion("x.cc", 0, 10, "3");
+ auto Err = Replaces.add(Deletion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement OverlappingReplacement("x.cc", 0, 2, "a");
+ Err = Replaces.add(OverlappingReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ Deletion, OverlappingReplacement));
+
+ Replacement ContainedReplacement("x.cc", 2, 2, "a");
+ Err = Replaces.add(Replacement(ContainedReplacement));
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ Deletion, ContainedReplacement));
+
+ Replacement WrongPathReplacement("y.cc", 20, 2, "");
+ Err = Replaces.add(WrongPathReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::wrong_file_path,
+ Deletion, WrongPathReplacement));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Deletion, *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, DeletionInReplacements) {
+ Replacements Replaces;
+ Replacement R("x.cc", 0, 10, "3");
+ auto Err = Replaces.add(R);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(R, *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, OverlappingReplacements) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 3, "345"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 2, 3, "543"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
+
+ Err = Replaces.add(Replacement("x.cc", 2, 1, "5"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {
+ Replacements Replaces;
+ // Test adding an insertion at the offset of an existing replacement.
+ auto Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+
+ Replaces.clear();
+ // Test overlap with an existing insertion.
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+}
+
+TEST_F(ReplacementTest, MergeNewDeletions) {
+ Replacements Replaces;
+ Replacement ContainingReplacement("x.cc", 0, 10, "");
+ auto Err = Replaces.add(ContainingReplacement);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 3, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 0, 10, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
+}
+
+TEST_F(ReplacementTest, MergeOverlappingButNotAdjacentReplacement) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement After = Replacement("x.cc", 10, 5, "");
+ Err = Replaces.add(After);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement ContainingReplacement("x.cc", 0, 10, "");
+ Err = Replaces.add(ContainingReplacement);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
+ EXPECT_EQ(*(++Replaces.begin()), After);
+}
+
+TEST_F(ReplacementTest, InsertionBeforeMergedDeletions) {
+ Replacements Replaces;
+
+ Replacement Insertion("x.cc", 0, 0, "123");
+ auto Err = Replaces.add(Insertion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement Deletion("x.cc", 0, 10, "");
+ Err = Replaces.add(Deletion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), Insertion);
+ EXPECT_EQ(*(++Replaces.begin()), Deletion);
+}
+
+TEST_F(ReplacementTest, MergeOverlappingDeletions) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 0, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, ""), *Replaces.begin());
+
+ Err = Replaces.add(Replacement("x.cc", 1, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 6, ""), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, FailedMergeExistingDeletions) {
+ Replacements Replaces;
+ Replacement First("x.cc", 0, 2, "");
+ auto Err = Replaces.add(First);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement Second("x.cc", 5, 5, "");
+ Err = Replaces.add(Second);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 1, 10, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 11, ""), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, FailAddRegression) {
+ Replacements Replaces;
+ // Create two replacements, where the second one is an insertion of the empty
+ // string exactly at the end of the first one.
+ auto Err = Replaces.add(Replacement("x.cc", 0, 10, "1"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ // Make sure we find the overlap with the first entry when inserting a
+ // replacement that ends exactly at the seam of the existing replacements.
+ Replacement OverlappingReplacement("x.cc", 5, 5, "fail");
+ Err = Replaces.add(OverlappingReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ *Replaces.begin(), OverlappingReplacement));
+
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+}
+
+TEST_F(ReplacementTest, InsertAtOffsetOfReplacement) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+}
+
+TEST_F(ReplacementTest, AddInsertAtOtherInsertWhenOderIndependent) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Replacement ConflictInsertion("x.cc", 10, 0, "b");
+ Err = Replaces.add(ConflictInsertion);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::insert_conflict,
+ *Replaces.begin(), ConflictInsertion));
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "aa"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 10, 0, "aaa"), *Replaces.begin());
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 3, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 10, 0, ""), *Replaces.begin());
+ EXPECT_EQ(Replacement("x.cc", 10, 3, ""), *std::next(Replaces.begin()));
+}
+
+TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 5, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 8, 2, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+}
+
TEST_F(ReplacementTest, CanApplyReplacements) {
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, 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));
}
-// 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) {
+// Verifies that replacement/deletion is applied before insertion at the same
+// offset.
+TEST_F(ReplacementTest, InsertAndDelete) {
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), 6, ""),
+ Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 0,
+ "other\n")});
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
- EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
+ EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, AdjacentReplacements) {
+ FileID ID = Context.createInMemoryFile("input.cpp",
+ "ab");
+ Replacements Replaces = toReplacements(
+ {Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 1, "x"),
+ Replacement(Context.Sources, Context.getLocation(ID, 1, 2), 1, "y")});
+ EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
+ EXPECT_EQ("xy", Context.getRewrittenText(ID));
}
-TEST_F(ReplacementTest, SkipsDuplicateReplacements) {
+TEST_F(ReplacementTest, AddDuplicateReplacements) {
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(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
+ 5, "replaced"));
+ EXPECT_TRUE(!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, FailOrderDependentReplacements) {
+ FileID ID = Context.createInMemoryFile("input.cpp",
+ "line1\nline2\nline3\nline4");
+ auto Replaces = toReplacements({Replacement(
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "other")});
+
+ Replacement ConflictReplacement(Context.Sources,
+ Context.getLocation(ID, 2, 1), 5, "rehto");
+ auto Err = Replaces.add(ConflictReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ *Replaces.begin(), ConflictReplacement));
+
+ EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
+ EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
+}
+
+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) {
@@ -180,76 +521,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, " "));
+ 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|
-}
-
-// 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, " "));
- // 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 {
@@ -305,9 +636,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",
@@ -455,12 +785,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);
@@ -469,25 +798,43 @@ TEST(Range, CalculateRangesOfReplacements) {
EXPECT_TRUE(Ranges[1].getLength() == 22);
}
+TEST(Range, CalculateRangesOfInsertionAroundReplacement) {
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 0, 2, ""), Replacement("foo", 0, 0, "ba")});
+
+ std::vector<Range> Ranges = Replaces.getAffectedRanges();
+
+ EXPECT_EQ(1ul, Ranges.size());
+ EXPECT_EQ(0u, Ranges[0].getOffset());
+ EXPECT_EQ(2u, Ranges[0].getLength());
+}
+
+TEST(Range, RangesAfterEmptyReplacements) {
+ std::vector<Range> Ranges = {Range(5, 6), Range(10, 5)};
+ Replacements Replaces;
+ std::vector<Range> Expected = {Range(5, 10)};
+ EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
+}
+
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));
@@ -495,9 +842,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));
@@ -506,9 +853,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));
@@ -516,122 +863,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 {
@@ -647,7 +924,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);
@@ -661,7 +938,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);
@@ -674,62 +951,142 @@ 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"}}));
+}
+
+TEST(DeduplicateByFileTest, PathsWithDots) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "a/b/.././c.h";
+ StringRef Path2 = "a/c.h";
+#else
+ StringRef Path1 = "a\\b\\..\\.\\c.h";
+ StringRef Path2 = "a\\c.h";
+#endif
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, PathWithDotSlash) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
+#else
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
+#endif
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, NonExistingFilePath) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
+#else
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
+#endif
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_TRUE(FileToReplaces.empty());
}
} // end namespace tooling