<div dir="ltr">r282583 should fix this.<br></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 28, 2016 at 2:14 PM Eric Liu <<a href="mailto:ioeric@google.com">ioeric@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">This is causing buildbot failure. I am working on a fix.</div><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Wed, Sep 28, 2016 at 1:11 PM Eric Liu via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="gmail_msg" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ioeric<br class="gmail_msg">
Date: Wed Sep 28 06:02:16 2016<br class="gmail_msg">
New Revision: 282577<br class="gmail_msg">
<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=282577&view=rev" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project?rev=282577&view=rev</a><br class="gmail_msg">
Log:<br class="gmail_msg">
Merge conflicting replacements when they are order-independent.<br class="gmail_msg">
<br class="gmail_msg">
Summary:<br class="gmail_msg">
Now two replacements are considered order-independent if applying them in<br class="gmail_msg">
either order produces the same result. These include (but not restricted<br class="gmail_msg">
to) replacements that:<br class="gmail_msg">
- don't overlap (being directly adjacent is fine) and<br class="gmail_msg">
- are overlapping deletions.<br class="gmail_msg">
- are insertions at the same offset and applying them in either order<br class="gmail_msg">
has the same effect, i.e. X + Y = Y + X if one inserts text X and the<br class="gmail_msg">
other inserts text Y.<br class="gmail_msg">
<br class="gmail_msg">
Discussion about this design can be found in D24717<br class="gmail_msg">
<br class="gmail_msg">
Reviewers: djasper, klimek<br class="gmail_msg">
<br class="gmail_msg">
Subscribers: omtcyfz, cfe-commits<br class="gmail_msg">
<br class="gmail_msg">
Differential Revision: <a href="https://reviews.llvm.org/D24800" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D24800</a><br class="gmail_msg">
<br class="gmail_msg">
Modified:<br class="gmail_msg">
cfe/trunk/include/clang/Tooling/Core/Replacement.h<br class="gmail_msg">
cfe/trunk/lib/Tooling/Core/Replacement.cpp<br class="gmail_msg">
cfe/trunk/unittests/Tooling/RefactoringTest.cpp<br class="gmail_msg">
<br class="gmail_msg">
Modified: cfe/trunk/include/clang/Tooling/Core/Replacement.h<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Core/Replacement.h?rev=282577&r1=282576&r2=282577&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Core/Replacement.h?rev=282577&r1=282576&r2=282577&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- cfe/trunk/include/clang/Tooling/Core/Replacement.h (original)<br class="gmail_msg">
+++ cfe/trunk/include/clang/Tooling/Core/Replacement.h Wed Sep 28 06:02:16 2016<br class="gmail_msg">
@@ -167,10 +167,25 @@ class Replacements {<br class="gmail_msg">
/// order-dependent replacements. To control the order in which<br class="gmail_msg">
/// order-dependent replacements are applied, use merge({R}) with R referring<br class="gmail_msg">
/// to the changed code after applying all existing replacements.<br class="gmail_msg">
- /// Two replacements are considered order-independent if they:<br class="gmail_msg">
+ /// Two replacements A and B are considered order-independent if applying them<br class="gmail_msg">
+ /// in either order produces the same result. Note that the range of the<br class="gmail_msg">
+ /// replacement that is applied later still refers to the original code.<br class="gmail_msg">
+ /// These include (but not restricted to) replacements that:<br class="gmail_msg">
/// - don't overlap (being directly adjacent is fine) and<br class="gmail_msg">
- /// - aren't both inserts at the same code location (would be<br class="gmail_msg">
- /// order-dependent).<br class="gmail_msg">
+ /// - are overlapping deletions.<br class="gmail_msg">
+ /// - are insertions at the same offset and applying them in either order<br class="gmail_msg">
+ /// has the same effect, i.e. X + Y = Y + X when inserting X and Y<br class="gmail_msg">
+ /// respectively.<br class="gmail_msg">
+ /// Examples:<br class="gmail_msg">
+ /// 1. Replacement A(0, 0, "a") and B(0, 0, "aa") are order-independent since<br class="gmail_msg">
+ /// applying them in either order gives replacement (0, 0, "aaa").<br class="gmail_msg">
+ /// However, A(0, 0, "a") and B(0, 0, "b") are order-dependent since<br class="gmail_msg">
+ /// applying A first gives (0, 0, "ab") while applying B first gives (B, A,<br class="gmail_msg">
+ /// "ba").<br class="gmail_msg">
+ /// 2. Replacement A(0, 2, "123") and B(0, 2, "123") are order-independent<br class="gmail_msg">
+ /// since applying them in either order gives (0, 2, "123").<br class="gmail_msg">
+ /// 3. Replacement A(0, 3, "123") and B(2, 3, "321") are order-independent<br class="gmail_msg">
+ /// since either order gives (0, 5, "12321").<br class="gmail_msg">
/// Replacements with offset UINT_MAX are special - we do not detect conflicts<br class="gmail_msg">
/// for such replacements since users may add them intentionally as a special<br class="gmail_msg">
/// category of replacements.<br class="gmail_msg">
@@ -213,6 +228,22 @@ private:<br class="gmail_msg">
<br class="gmail_msg">
Replacements mergeReplacements(const ReplacementsImpl &Second) const;<br class="gmail_msg">
<br class="gmail_msg">
+ // Returns `R` with new range that refers to code after `Replaces` being<br class="gmail_msg">
+ // applied.<br class="gmail_msg">
+ Replacement getReplacementInChangedCode(const Replacement &R) const;<br class="gmail_msg">
+<br class="gmail_msg">
+ // Returns a set of replacements that is equivalent to the current<br class="gmail_msg">
+ // replacements by merging all adjacent replacements. Two sets of replacements<br class="gmail_msg">
+ // are considered equivalent if they have the same effect when they are<br class="gmail_msg">
+ // applied.<br class="gmail_msg">
+ Replacements getCanonicalReplacements() const;<br class="gmail_msg">
+<br class="gmail_msg">
+ // If `R` and all existing replacements are order-indepedent, then merge it<br class="gmail_msg">
+ // with `Replaces` and returns the merged replacements; otherwise, returns an<br class="gmail_msg">
+ // error.<br class="gmail_msg">
+ llvm::Expected<Replacements><br class="gmail_msg">
+ mergeIfOrderIndependent(const Replacement &R) const;<br class="gmail_msg">
+<br class="gmail_msg">
ReplacementsImpl Replaces;<br class="gmail_msg">
};<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Modified: cfe/trunk/lib/Tooling/Core/Replacement.cpp<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/Replacement.cpp?rev=282577&r1=282576&r2=282577&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/Replacement.cpp?rev=282577&r1=282576&r2=282577&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- cfe/trunk/lib/Tooling/Core/Replacement.cpp (original)<br class="gmail_msg">
+++ cfe/trunk/lib/Tooling/Core/Replacement.cpp Wed Sep 28 06:02:16 2016<br class="gmail_msg">
@@ -134,14 +134,75 @@ void Replacement::setFromSourceRange(con<br class="gmail_msg">
ReplacementText);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-llvm::Error makeConflictReplacementsError(const Replacement &New,<br class="gmail_msg">
- const Replacement &Existing) {<br class="gmail_msg">
+Replacement<br class="gmail_msg">
+Replacements::getReplacementInChangedCode(const Replacement &R) const {<br class="gmail_msg">
+ unsigned NewStart = getShiftedCodePosition(R.getOffset());<br class="gmail_msg">
+ unsigned NewEnd = getShiftedCodePosition(R.getOffset() + R.getLength());<br class="gmail_msg">
+ return Replacement(R.getFilePath(), NewStart, NewEnd - NewStart,<br class="gmail_msg">
+ R.getReplacementText());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+static llvm::Error makeConflictReplacementsError(const Replacement &New,<br class="gmail_msg">
+ const Replacement &Existing) {<br class="gmail_msg">
return llvm::make_error<llvm::StringError>(<br class="gmail_msg">
"New replacement:\n" + New.toString() +<br class="gmail_msg">
"\nconflicts with existing replacement:\n" + Existing.toString(),<br class="gmail_msg">
llvm::inconvertibleErrorCode());<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
+Replacements Replacements::getCanonicalReplacements() const {<br class="gmail_msg">
+ std::vector<Replacement> NewReplaces;<br class="gmail_msg">
+ // Merge adjacent replacements.<br class="gmail_msg">
+ for (const auto &R : Replaces) {<br class="gmail_msg">
+ if (NewReplaces.empty()) {<br class="gmail_msg">
+ NewReplaces.push_back(R);<br class="gmail_msg">
+ continue;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ auto &Prev = NewReplaces.back();<br class="gmail_msg">
+ unsigned PrevEnd = Prev.getOffset() + Prev.getLength();<br class="gmail_msg">
+ if (PrevEnd < R.getOffset()) {<br class="gmail_msg">
+ NewReplaces.push_back(R);<br class="gmail_msg">
+ } else {<br class="gmail_msg">
+ assert(PrevEnd == R.getOffset() &&<br class="gmail_msg">
+ "Existing replacements must not overlap.");<br class="gmail_msg">
+ Replacement NewR(<br class="gmail_msg">
+ R.getFilePath(), Prev.getOffset(), Prev.getLength() + R.getLength(),<br class="gmail_msg">
+ (Prev.getReplacementText() + R.getReplacementText()).str());<br class="gmail_msg">
+ Prev = NewR;<br class="gmail_msg">
+ }<br class="gmail_msg">
+ }<br class="gmail_msg">
+ ReplacementsImpl NewReplacesImpl(NewReplaces.begin(), NewReplaces.end());<br class="gmail_msg">
+ return Replacements(NewReplacesImpl.begin(), NewReplacesImpl.end());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+// `R` and `Replaces` are order-independent if applying them in either order<br class="gmail_msg">
+// has the same effect, so we need to compare replacements associated to<br class="gmail_msg">
+// applying them in either order.<br class="gmail_msg">
+llvm::Expected<Replacements><br class="gmail_msg">
+Replacements::mergeIfOrderIndependent(const Replacement &R) const {<br class="gmail_msg">
+ Replacements Rs(R);<br class="gmail_msg">
+ // A Replacements set containg a single replacement that is `R` referring to<br class="gmail_msg">
+ // the code after the existing replacements `Replaces` are applied.<br class="gmail_msg">
+ Replacements RsShiftedByReplaces(getReplacementInChangedCode(R));<br class="gmail_msg">
+ // A Replacements set that is `Replaces` referring to the code after `R` is<br class="gmail_msg">
+ // applied.<br class="gmail_msg">
+ Replacements ReplacesShiftedByRs;<br class="gmail_msg">
+ for (const auto &Replace : Replaces)<br class="gmail_msg">
+ ReplacesShiftedByRs.Replaces.insert(<br class="gmail_msg">
+ Rs.getReplacementInChangedCode(Replace));<br class="gmail_msg">
+ // This is equivalent to applying `Replaces` first and then `R`.<br class="gmail_msg">
+ auto MergeShiftedRs = merge(RsShiftedByReplaces);<br class="gmail_msg">
+ // This is equivalent to applying `R` first and then `Replaces`.<br class="gmail_msg">
+ auto MergeShiftedReplaces = Rs.merge(ReplacesShiftedByRs);<br class="gmail_msg">
+<br class="gmail_msg">
+ // Since empty or segmented replacements around existing replacements might be<br class="gmail_msg">
+ // produced above, we need to compare replacements in canonical forms.<br class="gmail_msg">
+ if (MergeShiftedRs.getCanonicalReplacements() ==<br class="gmail_msg">
+ MergeShiftedReplaces.getCanonicalReplacements())<br class="gmail_msg">
+ return MergeShiftedRs;<br class="gmail_msg">
+ return makeConflictReplacementsError(R, *Replaces.begin());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
llvm::Error Replacements::add(const Replacement &R) {<br class="gmail_msg">
// Check the file path.<br class="gmail_msg">
if (!Replaces.empty() && R.getFilePath() != Replaces.begin()->getFilePath())<br class="gmail_msg">
@@ -172,8 +233,21 @@ llvm::Error Replacements::add(const Repl<br class="gmail_msg">
if (I != Replaces.end() && R.getOffset() == I->getOffset()) {<br class="gmail_msg">
assert(R.getLength() == 0);<br class="gmail_msg">
// `I` is also an insertion, `R` and `I` conflict.<br class="gmail_msg">
- if (I->getLength() == 0)<br class="gmail_msg">
- return makeConflictReplacementsError(R, *I);<br class="gmail_msg">
+ if (I->getLength() == 0) {<br class="gmail_msg">
+ // Check if two insertions are order-indepedent: if inserting them in<br class="gmail_msg">
+ // either order produces the same text, they are order-independent.<br class="gmail_msg">
+ if ((R.getReplacementText() + I->getReplacementText()).str() !=<br class="gmail_msg">
+ (I->getReplacementText() + R.getReplacementText()).str()) {<br class="gmail_msg">
+ return makeConflictReplacementsError(R, *I);<br class="gmail_msg">
+ }<br class="gmail_msg">
+ // If insertions are order-independent, we can merge them.<br class="gmail_msg">
+ Replacement NewR(<br class="gmail_msg">
+ R.getFilePath(), R.getOffset(), 0,<br class="gmail_msg">
+ (R.getReplacementText() + I->getReplacementText()).str());<br class="gmail_msg">
+ Replaces.erase(I);<br class="gmail_msg">
+ Replaces.insert(NewR);<br class="gmail_msg">
+ return llvm::Error::success();<br class="gmail_msg">
+ }<br class="gmail_msg">
// Insertion `R` is adjacent to a non-insertion replacement `I`, so they<br class="gmail_msg">
// are order-independent. It is safe to assume that `R` will not conflict<br class="gmail_msg">
// with any replacement before `I` since all replacements before `I` must<br class="gmail_msg">
@@ -192,10 +266,13 @@ llvm::Error Replacements::add(const Repl<br class="gmail_msg">
return llvm::Error::success();<br class="gmail_msg">
}<br class="gmail_msg">
--I;<br class="gmail_msg">
+ auto Overlap = [](const Replacement &R1, const Replacement &R2) -> bool {<br class="gmail_msg">
+ return Range(R1.getOffset(), R1.getLength())<br class="gmail_msg">
+ .overlapsWith(Range(R2.getOffset(), R2.getLength()));<br class="gmail_msg">
+ };<br class="gmail_msg">
// If the previous entry does not overlap, we know that entries before it<br class="gmail_msg">
// can also not overlap.<br class="gmail_msg">
- if (!Range(R.getOffset(), R.getLength())<br class="gmail_msg">
- .overlapsWith(Range(I->getOffset(), I->getLength()))) {<br class="gmail_msg">
+ if (!Overlap(R, *I)) {<br class="gmail_msg">
// If `R` and `I` do not have the same offset, it is safe to add `R` since<br class="gmail_msg">
// it must come after `I`. Otherwise:<br class="gmail_msg">
// - If `R` is an insertion, `I` must not be an insertion since it would<br class="gmail_msg">
@@ -204,9 +281,23 @@ llvm::Error Replacements::add(const Repl<br class="gmail_msg">
// and `I` would have overlapped.<br class="gmail_msg">
// In either case, we can safely insert `R`.<br class="gmail_msg">
Replaces.insert(R);<br class="gmail_msg">
- return llvm::Error::success();<br class="gmail_msg">
+ } else {<br class="gmail_msg">
+ // `I` overlaps with `R`. We need to check `R` against all overlapping<br class="gmail_msg">
+ // replacements to see if they are order-indepedent. If they are, merge `R`<br class="gmail_msg">
+ // with them and replace them with the merged replacements.<br class="gmail_msg">
+ auto MergeBegin = I;<br class="gmail_msg">
+ auto MergeEnd = std::next(I);<br class="gmail_msg">
+ while (I-- != Replaces.begin() && Overlap(R, *I))<br class="gmail_msg">
+ MergeBegin = I;<br class="gmail_msg">
+ Replacements OverlapReplaces(MergeBegin, MergeEnd);<br class="gmail_msg">
+ llvm::Expected<Replacements> Merged =<br class="gmail_msg">
+ OverlapReplaces.mergeIfOrderIndependent(R);<br class="gmail_msg">
+ if (!Merged)<br class="gmail_msg">
+ return Merged.takeError();<br class="gmail_msg">
+ Replaces.erase(MergeBegin, MergeEnd);<br class="gmail_msg">
+ Replaces.insert(Merged->begin(), Merged->end());<br class="gmail_msg">
}<br class="gmail_msg">
- return makeConflictReplacementsError(R, *I);<br class="gmail_msg">
+ return llvm::Error::success();<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
namespace {<br class="gmail_msg">
<br class="gmail_msg">
Modified: cfe/trunk/unittests/Tooling/RefactoringTest.cpp<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RefactoringTest.cpp?rev=282577&r1=282576&r2=282577&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RefactoringTest.cpp?rev=282577&r1=282576&r2=282577&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- cfe/trunk/unittests/Tooling/RefactoringTest.cpp (original)<br class="gmail_msg">
+++ cfe/trunk/unittests/Tooling/RefactoringTest.cpp Wed Sep 28 06:02:16 2016<br class="gmail_msg">
@@ -101,18 +101,56 @@ TEST_F(ReplacementTest, ReturnsInvalidPa<br class="gmail_msg">
<br class="gmail_msg">
TEST_F(ReplacementTest, FailAddReplacements) {<br class="gmail_msg">
Replacements Replaces;<br class="gmail_msg">
- auto Err = Replaces.add(Replacement("x.cc", 0, 10, "3"));<br class="gmail_msg">
+ Replacement Deletion("x.cc", 0, 10, "3");<br class="gmail_msg">
+ auto Err = Replaces.add(Deletion);<br class="gmail_msg">
EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
- Err = Replaces.add(Replacement("x.cc", 0, 2, ""));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 0, 2, "a"));<br class="gmail_msg">
EXPECT_TRUE((bool)Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
- Err = Replaces.add(Replacement("x.cc", 2, 2, ""));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 2, 2, "a"));<br class="gmail_msg">
EXPECT_TRUE((bool)Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
Err = Replaces.add(Replacement("y.cc", 20, 2, ""));<br class="gmail_msg">
EXPECT_TRUE((bool)Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Deletion, *Replaces.begin());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, DeletionInReplacements) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ Replacement R("x.cc", 0, 10, "3");<br class="gmail_msg">
+ auto Err = Replaces.add(R);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 0, 2, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 2, 2, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(R, *Replaces.begin());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, OverlappingReplacements) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ auto Err = Replaces.add(Replacement("x.cc", 0, 3, "345"));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 2, 3, "543"));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 2, 1, "5"));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {<br class="gmail_msg">
@@ -137,6 +175,116 @@ TEST_F(ReplacementTest, AddAdjacentInser<br class="gmail_msg">
EXPECT_EQ(Replaces.size(), 2u);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
+TEST_F(ReplacementTest, MergeNewDeletions) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ Replacement ContainingReplacement("x.cc", 0, 10, "");<br class="gmail_msg">
+ auto Err = Replaces.add(ContainingReplacement);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 5, 3, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 0, 10, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, MergeOverlappingButNotAdjacentReplacement) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Replacement After = Replacement("x.cc", 10, 5, "");<br class="gmail_msg">
+ Err = Replaces.add(After);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Replacement ContainingReplacement("x.cc", 0, 10, "");<br class="gmail_msg">
+ Err = Replaces.add(ContainingReplacement);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(2u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);<br class="gmail_msg">
+ EXPECT_EQ(*(++Replaces.begin()), After);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, InsertionBeforeMergedDeletions) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+<br class="gmail_msg">
+ Replacement Insertion("x.cc", 0, 0, "123");<br class="gmail_msg">
+ auto Err = Replaces.add(Insertion);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Replacement Deletion("x.cc", 0, 10, "");<br class="gmail_msg">
+ Err = Replaces.add(Deletion);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(2u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(*Replaces.begin(), Insertion);<br class="gmail_msg">
+ EXPECT_EQ(*(++Replaces.begin()), Deletion);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, MergeOverlappingDeletions) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 0, 5, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 0, 5, ""), *Replaces.begin());<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 1, 5, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 0, 6, ""), *Replaces.begin());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+TEST_F(ReplacementTest, FailedMergeExistingDeletions) {<br class="gmail_msg">
+ Replacements Replaces;<br class="gmail_msg">
+ Replacement First("x.cc", 0, 2, "");<br class="gmail_msg">
+ auto Err = Replaces.add(First);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Replacement Second("x.cc", 5, 5, "");<br class="gmail_msg">
+ Err = Replaces.add(Second);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 1, 10, ""));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 0, 11, ""), *Replaces.begin());<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
TEST_F(ReplacementTest, FailAddRegression) {<br class="gmail_msg">
Replacements Replaces;<br class="gmail_msg">
// Create two replacements, where the second one is an insertion of the empty<br class="gmail_msg">
@@ -155,7 +303,7 @@ TEST_F(ReplacementTest, FailAddRegressio<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
<br class="gmail_msg">
Err = Replaces.add(Replacement("x.cc", 10, 0, ""));<br class="gmail_msg">
- EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
@@ -179,7 +327,7 @@ TEST_F(ReplacementTest, InsertAtOffsetOf<br class="gmail_msg">
EXPECT_EQ(Replaces.size(), 2u);<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-TEST_F(ReplacementTest, FailAddInsertAtOtherInsert) {<br class="gmail_msg">
+TEST_F(ReplacementTest, AddInsertAtOtherInsertWhenOderIndependent) {<br class="gmail_msg">
Replacements Replaces;<br class="gmail_msg">
auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));<br class="gmail_msg">
EXPECT_TRUE(!Err);<br class="gmail_msg">
@@ -189,12 +337,14 @@ TEST_F(ReplacementTest, FailAddInsertAtO<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
<br class="gmail_msg">
Replaces.clear();<br class="gmail_msg">
- Err = Replaces.add(Replacement("x.cc", 10, 0, ""));<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));<br class="gmail_msg">
EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
- Err = Replaces.add(Replacement("x.cc", 10, 0, ""));<br class="gmail_msg">
- EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "aa"));<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(1u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 10, 0, "aaa"), *Replaces.begin());<br class="gmail_msg">
<br class="gmail_msg">
Replaces.clear();<br class="gmail_msg">
Err = Replaces.add(Replacement("x.cc", 10, 0, ""));<br class="gmail_msg">
@@ -204,8 +354,11 @@ TEST_F(ReplacementTest, FailAddInsertAtO<br class="gmail_msg">
EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
Err = Replaces.add(Replacement("x.cc", 10, 0, ""));<br class="gmail_msg">
- EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
+ EXPECT_EQ(2u, Replaces.size());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 10, 0, ""), *Replaces.begin());<br class="gmail_msg">
+ EXPECT_EQ(Replacement("x.cc", 10, 3, ""), *std::next(Replaces.begin()));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {<br class="gmail_msg">
@@ -256,7 +409,7 @@ TEST_F(ReplacementTest, AdjacentReplacem<br class="gmail_msg">
EXPECT_EQ("xy", Context.getRewrittenText(ID));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
-TEST_F(ReplacementTest, SkipsDuplicateReplacements) {<br class="gmail_msg">
+TEST_F(ReplacementTest, AddDuplicateReplacements) {<br class="gmail_msg">
FileID ID = Context.createInMemoryFile("input.cpp",<br class="gmail_msg">
"line1\nline2\nline3\nline4");<br class="gmail_msg">
auto Replaces = toReplacements({Replacement(<br class="gmail_msg">
@@ -264,18 +417,33 @@ TEST_F(ReplacementTest, SkipsDuplicateRe<br class="gmail_msg">
<br class="gmail_msg">
auto Err = Replaces.add(Replacement(<br class="gmail_msg">
Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));<br class="gmail_msg">
- EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
<br class="gmail_msg">
Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),<br class="gmail_msg">
5, "replaced"));<br class="gmail_msg">
- EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ EXPECT_TRUE(!Err);<br class="gmail_msg">
llvm::consumeError(std::move(Err));<br class="gmail_msg">
<br class="gmail_msg">
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));<br class="gmail_msg">
EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
+TEST_F(ReplacementTest, FailOrderDependentReplacements) {<br class="gmail_msg">
+ FileID ID = Context.createInMemoryFile("input.cpp",<br class="gmail_msg">
+ "line1\nline2\nline3\nline4");<br class="gmail_msg">
+ auto Replaces = toReplacements({Replacement(<br class="gmail_msg">
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "other")});<br class="gmail_msg">
+<br class="gmail_msg">
+ auto Err = Replaces.add(Replacement(<br class="gmail_msg">
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "rehto"));<br class="gmail_msg">
+ EXPECT_TRUE((bool)Err);<br class="gmail_msg">
+ llvm::consumeError(std::move(Err));<br class="gmail_msg">
+<br class="gmail_msg">
+ EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));<br class="gmail_msg">
+ EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {<br class="gmail_msg">
Replacements Replaces =<br class="gmail_msg">
toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
cfe-commits mailing list<br class="gmail_msg">
<a href="mailto:cfe-commits@lists.llvm.org" class="gmail_msg" target="_blank">cfe-commits@lists.llvm.org</a><br class="gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" class="gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="gmail_msg">
</blockquote></div></blockquote></div>