未验证 提交 c9f142dd 编写于 作者: R Rikki Gibson 提交者: GitHub

Merge pull request #39258 from ashmind/sourcetext-getchanges-merge-fix

Fix SourceText.GetChanges exception on merging certain changes
......@@ -636,6 +636,48 @@ public void TestMergeChanges_Overlapping_NewInsideOld()
Assert.Equal("Cool ", changes[0].NewText);
}
[Fact]
[WorkItem(22289, "https://github.com/dotnet/roslyn/issues/22289")]
public void TestMergeChanges_Overlapping_NewInsideOld_AndOldHasDeletion()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 3), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(2, 0), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa4", change1.ToString());
Assert.Equal("0abba4", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 3), "abba") }, changes);
}
[Fact]
[WorkItem(22289, "https://github.com/dotnet/roslyn/issues/22289")]
public void TestMergeChanges_Overlapping_NewInsideOld_AndOldHasLeadingDeletion_SmallerThanLeadingInsertion()
{
var original = SourceText.From("012");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 1), "aaa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(3, 0), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aaa2", change1.ToString());
Assert.Equal("0aabba2", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 1), "aabba") }, changes);
}
[Fact]
[WorkItem(22289, "https://github.com/dotnet/roslyn/issues/22289")]
public void TestMergeChanges_Overlapping_NewInsideOld_AndBothHaveDeletion_NewDeletionSmallerThanOld()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 3), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(2, 1), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa4", change1.ToString());
Assert.Equal("0abb4", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 3), "abb") }, changes);
}
[Fact]
public void TestMergeChanges_Overlapping_OldInsideNew()
{
......@@ -678,6 +720,85 @@ public void TestMergeChanges_Overlapping_OldBeforeNew()
Assert.Equal("Cwazy V", changes[0].NewText);
}
[Fact]
public void TestMergeChanges_SameStart()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 0), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 0), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa1234", change1.ToString());
Assert.Equal("0bbaa1234", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 0), "bbaa") }, changes);
}
[Fact]
public void TestMergeChanges_SameStart_AndOldHasDeletion()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 3), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 0), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa4", change1.ToString());
Assert.Equal("0bbaa4", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 3), "bbaa") }, changes);
}
[Fact]
public void TestMergeChanges_SameStart_AndNewHasDeletion_SmallerThanOldInsertion()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 0), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 1), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa1234", change1.ToString());
Assert.Equal("0bba1234", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 0), "bba") }, changes);
}
[Fact]
public void TestMergeChanges_SameStart_AndNewHasDeletion_EqualToOldInsertion()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 0), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 2), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa1234", change1.ToString());
Assert.Equal("0bb1234", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 0), "bb") }, changes);
}
[Fact]
public void TestMergeChanges_SameStart_AndNewHasDeletion_LargerThanOldInsertion()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 0), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 3), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa1234", change1.ToString());
Assert.Equal("0bb234", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 1), "bb") }, changes);
}
[Fact]
[WorkItem(22289, "https://github.com/dotnet/roslyn/issues/22289")]
public void TestMergeChanges_SameStart_AndBothHaveDeletion_NewDeletionSmallerThanOld()
{
var original = SourceText.From("01234");
var change1 = original.WithChanges(new TextChange(new TextSpan(1, 3), "aa"));
var change2 = change1.WithChanges(new TextChange(new TextSpan(1, 1), "bb"));
var changes = change2.GetTextChanges(original);
Assert.Equal("0aa4", change1.ToString());
Assert.Equal("0bba4", change2.ToString());
Assert.Equal(new[] { new TextChange(new TextSpan(1, 3), "bba") }, changes);
}
[Fact]
public void TestMergeChanges_AfterAdjacent()
{
......
......@@ -299,10 +299,10 @@ private static ImmutableArray<TextChangeRange> Merge(ImmutableArray<TextChangeRa
// new change starts after old change, but overlaps
// add as much of the old change as possible and try again
var oldChangeLeadingInsertion = newChange.Span.Start - (oldChange.Span.Start + oldDelta);
AddRange(list, new TextChangeRange(oldChange.Span, oldChangeLeadingInsertion));
oldDelta = oldDelta - oldChange.Span.Length + oldChangeLeadingInsertion;
oldChange = new TextChangeRange(new TextSpan(oldChange.Span.Start, 0), oldChange.NewLength - oldChangeLeadingInsertion);
newChange = new TextChangeRange(new TextSpan(oldChange.Span.Start + oldDelta, newChange.Span.Length), newChange.NewLength);
var oldChangeLeadingDeletion = Math.Min(oldChange.Span.Length, oldChangeLeadingInsertion);
AddRange(list, new TextChangeRange(new TextSpan(oldChange.Span.Start, oldChangeLeadingDeletion), oldChangeLeadingInsertion));
oldDelta = oldDelta - oldChangeLeadingDeletion + oldChangeLeadingInsertion;
oldChange = new TextChangeRange(new TextSpan(newChange.Span.Start - oldDelta, oldChange.Span.Length - oldChangeLeadingDeletion), oldChange.NewLength - oldChangeLeadingInsertion);
goto tryAgain;
}
else if (newChange.Span.Start == oldChange.Span.Start + oldDelta)
......@@ -316,11 +316,12 @@ private static ImmutableArray<TextChangeRange> Merge(ImmutableArray<TextChangeRa
oldIndex++;
goto nextOldChange;
}
else if (newChange.Span.Length == 0)
else if (newChange.Span.Length <= oldChange.NewLength)
{
// new change is just an insertion, go ahead and tack it on with old change
AddRange(list, new TextChangeRange(oldChange.Span, oldChange.NewLength + newChange.NewLength));
oldDelta = oldDelta - oldChange.Span.Length + oldChange.NewLength;
// new change deletes fewer characters than old change inserted
// add new change insertion, then the remaining trailing characters of the old change insertion
AddRange(list, new TextChangeRange(oldChange.Span, oldChange.NewLength + newChange.NewLength - newChange.Span.Length));
oldDelta = oldDelta - oldChange.Span.Length + oldChange.NewLength - newChange.Span.Length;
oldIndex++;
newIndex++;
goto nextNewChange;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册