Author: djasper Date: Mon Nov 23 02:33:48 2015 New Revision: 253859 URL: http://llvm.org/viewvc/llvm-project?rev=253859&view=rev Log: Fix calculation of shifted cursor/code positions. Specifically support the case where a specific range is replaced by new text. Previously, the calculation would shift any position from within a replaced region to the first character after the region. This is undersirable, e.g. for clang-format's include sorting.
Modified: cfe/trunk/lib/Tooling/Core/Replacement.cpp cfe/trunk/unittests/Tooling/RefactoringTest.cpp Modified: cfe/trunk/lib/Tooling/Core/Replacement.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/Replacement.cpp?rev=253859&r1=253858&r2=253859&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/Core/Replacement.cpp (original) +++ cfe/trunk/lib/Tooling/Core/Replacement.cpp Mon Nov 23 02:33:48 2015 @@ -143,34 +143,32 @@ void Replacement::setFromSourceRange(con ReplacementText); } -unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) { - unsigned NewPosition = Position; - for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; - ++I) { - if (I->getOffset() >= Position) - break; - if (I->getOffset() + I->getLength() > Position) - NewPosition += I->getOffset() + I->getLength() - Position; - NewPosition += I->getReplacementText().size() - I->getLength(); +template <typename T> +unsigned shiftedCodePositionInternal(const T &Replaces, unsigned Position) { + unsigned Offset = 0; + for (const auto& R : Replaces) { + if (R.getOffset() + R.getLength() <= Position) { + Offset += R.getReplacementText().size() - R.getLength(); + continue; + } + if (R.getOffset() < Position && + R.getOffset() + R.getReplacementText().size() <= Position) { + Position = R.getOffset() + R.getReplacementText().size() - 1; + } + break; } - return NewPosition; + return Position + Offset; +} + +unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) { + return shiftedCodePositionInternal(Replaces, Position); } // FIXME: Remove this function when Replacements is implemented as std::vector // instead of std::set. unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces, unsigned Position) { - unsigned NewPosition = Position; - for (std::vector<Replacement>::const_iterator I = Replaces.begin(), - E = Replaces.end(); - I != E; ++I) { - if (I->getOffset() >= Position) - break; - if (I->getOffset() + I->getLength() > Position) - NewPosition += I->getOffset() + I->getLength() - Position; - NewPosition += I->getReplacementText().size() - I->getLength(); - } - return NewPosition; + return shiftedCodePositionInternal(Replaces, Position); } void deduplicate(std::vector<Replacement> &Replaces, Modified: cfe/trunk/unittests/Tooling/RefactoringTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RefactoringTest.cpp?rev=253859&r1=253858&r2=253859&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/RefactoringTest.cpp (original) +++ cfe/trunk/unittests/Tooling/RefactoringTest.cpp Mon Nov 23 02:33:48 2015 @@ -176,8 +176,8 @@ TEST(ShiftedCodePositionTest, FindsNewCo 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(4u, shiftedCodePosition(Replaces, 5)); // int | i; - EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); // 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| } @@ -195,8 +195,8 @@ TEST(ShiftedCodePositionTest, VectorFind 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(4u, shiftedCodePosition(Replaces, 5)); // int | i; - EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); // 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| } @@ -205,8 +205,17 @@ TEST(ShiftedCodePositionTest, FindsNewCo Replacements Replaces; Replaces.insert(Replacement("", 4, 0, "\"\n\"")); // Assume '"12345678"' is turned into '"1234"\n"5678"'. - EXPECT_EQ(4u, shiftedCodePosition(Replaces, 4)); // "123|5678" - EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "1234|678" + EXPECT_EQ(3u, shiftedCodePosition(Replaces, 3)); // "123|5678" + EXPECT_EQ(7u, shiftedCodePosition(Replaces, 4)); // "1234|678" + EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "12345|78" +} + +TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) { + Replacements Replaces; + // Replace the first four characters with "abcd". + Replaces.insert(Replacement("", 0, 4, "abcd")); + for (unsigned i = 0; i < 3; ++i) + EXPECT_EQ(i, shiftedCodePosition(Replaces, i)); } class FlushRewrittenFilesTest : public ::testing::Test { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits