r217439 - Tooling: Ignore file names in tooling::deduplicate.

Benjamin Kramer benny.kra at googlemail.com
Tue Sep 9 06:53:30 PDT 2014


Author: d0k
Date: Tue Sep  9 08:53:29 2014
New Revision: 217439

URL: http://llvm.org/viewvc/llvm-project?rev=217439&view=rev
Log:
Tooling: Ignore file names in tooling::deduplicate.

This was horribly broken due to how the sort predicate works. We would
report a conflict for files with a replacement in the same position but
different names if the length differed. Just ignore paths as this is often
what the user wants. Files can occur with different names (due to symlinks
or relative paths) and we don't ever want to do the same edit in one file
twice.

Modified:
    cfe/trunk/include/clang/Tooling/Refactoring.h
    cfe/trunk/lib/Tooling/Refactoring.cpp
    cfe/trunk/unittests/Tooling/RefactoringTest.cpp

Modified: cfe/trunk/include/clang/Tooling/Refactoring.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring.h?rev=217439&r1=217438&r2=217439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring.h Tue Sep  9 08:53:29 2014
@@ -171,7 +171,7 @@ unsigned shiftedCodePosition(const std::
                              unsigned Position);
 
 /// \brief Removes duplicate Replacements and reports if Replacements conflict
-/// with one another.
+/// with one another. All Replacements are assumed to be in the same file.
 ///
 /// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
 ///

Modified: cfe/trunk/lib/Tooling/Refactoring.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring.cpp?rev=217439&r1=217438&r2=217439&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring.cpp Tue Sep  9 08:53:29 2014
@@ -238,11 +238,25 @@ void deduplicate(std::vector<Replacement
   if (Replaces.empty())
     return;
 
-  // Deduplicate
-  std::sort(Replaces.begin(), Replaces.end());
-  std::vector<Replacement>::iterator End =
-      std::unique(Replaces.begin(), Replaces.end());
-  Replaces.erase(End, Replaces.end());
+  auto LessNoPath = [](const Replacement &LHS, const Replacement &RHS) {
+    if (LHS.getOffset() != RHS.getOffset())
+      return LHS.getOffset() < RHS.getOffset();
+    if (LHS.getLength() != RHS.getLength())
+      return LHS.getLength() < RHS.getLength();
+    return LHS.getReplacementText() < RHS.getReplacementText();
+  };
+
+  auto EqualNoPath = [](const Replacement &LHS, const Replacement &RHS) {
+    return LHS.getOffset() == RHS.getOffset() &&
+           LHS.getLength() == RHS.getLength() &&
+           LHS.getReplacementText() == RHS.getReplacementText();
+  };
+
+  // Deduplicate. We don't want to deduplicate based on the path as we assume
+  // that all replacements refer to the same file (or are symlinks).
+  std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
+  Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
+                 Replaces.end());
 
   // Detect conflicts
   Range ConflictRange(Replaces.front().getOffset(),

Modified: cfe/trunk/unittests/Tooling/RefactoringTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RefactoringTest.cpp?rev=217439&r1=217438&r2=217439&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RefactoringTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RefactoringTest.cpp Tue Sep  9 08:53:29 2014
@@ -393,6 +393,8 @@ TEST(DeduplicateTest, removesDuplicates)
   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!
 
@@ -403,12 +405,14 @@ TEST(DeduplicateTest, removesDuplicates)
   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", 51, 3, " bar "));
+  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);
 
-  ASSERT_TRUE(Expected == Input);
+  EXPECT_EQ(3U, Conflicts.size());
+  EXPECT_EQ(Expected, Input);
 }
 
 TEST(DeduplicateTest, detectsConflicts) {





More information about the cfe-commits mailing list