diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
index 6cdee8bd66656d4de481094cb368dc9610ca6ba1..dbb70796874b921ee5f74d0b32d344dea61650ea 100644
--- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
+++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
@@ -206,6 +206,7 @@
+
@@ -359,10 +360,10 @@
-
+
-
-
+
+
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
index de8f5d1dc9cb466811d50219f485a268f418b802..fd1498a675945d239658415bc0ac5e98af6919f8 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.Methods.cs
@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class ActiveStatementTests_Methods : RudeEditTestBase
+ public class ActiveStatementTests_Methods : EditingTestBase
{
#region Methods
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
index a35d25546fbc3ad399f97b61dcd8b5956056f793..ee80967d296dc1f99f951df38d0e4dd981fe3919 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTests.cs
@@ -7,7 +7,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class ActiveStatementTests : RudeEditTestBase
+ public class ActiveStatementTests : EditingTestBase
{
#region Update
@@ -8457,7 +8457,7 @@ static void Foo()
#region C# 7.0
[Fact]
- public void MethodUpdate_IsPattern()
+ public void UpdateAroundActiveStatement_IsPattern()
{
string src1 = @"
class C
@@ -8486,7 +8486,7 @@ static void F(object x)
}
[Fact]
- public void MethodUpdate_DeconstructionDeclarationStatement()
+ public void UpdateAroundActiveStatement_DeconstructionDeclarationStatement()
{
string src1 = @"
class C
@@ -8515,7 +8515,7 @@ static void F(object x)
}
[Fact]
- public void MethodUpdate_DeconstructionForEach()
+ public void UpdateAroundActiveStatement_DeconstructionForEach()
{
string src1 = @"
class C
@@ -8544,7 +8544,7 @@ static void F(object o)
}
[Fact]
- public void MethodUpdate_VarDeconstruction()
+ public void UpdateAroundActiveStatement_VarDeconstruction()
{
string src1 = @"
class C
@@ -8573,7 +8573,7 @@ static void F(object o1, object o2)
}
[Fact]
- public void MethodUpdate_TypedDeconstruction()
+ public void UpdateAroundActiveStatement_TypedDeconstruction()
{
string src1 = @"
class C
@@ -8602,7 +8602,7 @@ static void F(object o1, object o2)
}
[Fact]
- public void MethodUpdate_Tuple()
+ public void UpdateAroundActiveStatement_Tuple()
{
string src1 = @"
class C
@@ -8631,7 +8631,7 @@ static void F(object o)
}
[Fact]
- public void MethodUpdate_LocalFunction()
+ public void UpdateAroundActiveStatement_LocalFunction()
{
string src1 = @"
class C
@@ -8661,7 +8661,7 @@ static void F(object o)
}
[Fact]
- public void MethodUpdate_OutVar()
+ public void UpdateAroundActiveStatement_OutVar()
{
string src1 = @"
class C
@@ -8690,7 +8690,7 @@ static void F()
}
[Fact]
- public void MethodUpdate_OutVarRemoved()
+ public void UpdateAroundActiveStatement_OutVarRemoved()
{
string src1 = @"
class C
@@ -8718,7 +8718,7 @@ static void F()
}
[Fact]
- public void MethodUpdate_Ref()
+ public void UpdateAroundActiveStatement_Ref()
{
string src1 = @"
class C
@@ -8747,7 +8747,7 @@ static void F()
}
[Fact]
- public void MethodUpdate_DeconstructionDeclaration()
+ public void UpdateAroundActiveStatement_DeconstructionDeclaration()
{
string src1 = @"
class C
@@ -8776,7 +8776,7 @@ static void F(object o1, object o2)
}
[Fact]
- public void MethodUpdate_DeconstructionAssignment()
+ public void UpdateAroundActiveStatement_DeconstructionAssignment()
{
string src1 = @"
class C
@@ -8807,7 +8807,7 @@ static void F(object o1, object o2)
}
[Fact]
- public void MethodUpdate_SwitchWithPattern()
+ public void UpdateAroundActiveStatement_SwitchWithPattern()
{
string src1 = @"
class C
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTrackingServiceTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTrackingServiceTests.cs
index f4f988c1ae7fd959e308e3466edeb94d34c9538a..db2ae98fe1d845e65e35920fedb64c4cf6552a1d 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTrackingServiceTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/ActiveStatementTrackingServiceTests.cs
@@ -5,7 +5,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class ActiveStatementTrackingServiceTests : RudeEditTestBase
+ public class ActiveStatementTrackingServiceTests : EditingTestBase
{
[Fact, WorkItem(846042, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/846042")]
public void MovedOutsideOfMethod1()
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/RudeEditTestBase.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
similarity index 99%
rename from src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/RudeEditTestBase.cs
rename to src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
index 17da36a6fd6f8a8bb0104e5a1305b159e86f6081..903ab3411163a4d5fb3857a6b07f2f342e443f22 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/RudeEditTestBase.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs
@@ -13,7 +13,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public abstract class RudeEditTestBase : CSharpTestBase
+ public abstract class EditingTestBase : CSharpTestBase
{
internal static readonly CSharpEditAndContinueAnalyzer Analyzer = new CSharpEditAndContinueAnalyzer();
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
index 220d96032f452c28a620ac46c1fb50d9f1d8f0c6..0e894cc9d3e6928f72d02b0eb2025b0594b81588 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/LineEditTests.cs
@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class LineEditTests : RudeEditTestBase
+ public class LineEditTests : EditingTestBase
{
#region Methods
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditStatementTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
similarity index 76%
rename from src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditStatementTests.cs
rename to src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
index be1d05a8cd185a651c5d84cd10d40340fd1d0e6b..4abd5f9ad5dc47a2eb7c9d1a6f25d8cb8718bf13 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditStatementTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementEditingTests.cs
@@ -11,1421 +11,9 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class RudeEditStatementTests : RudeEditTestBase
+ public class StatementEditingTests : EditingTestBase
{
- #region Matching
-
- [Fact]
- public void Match1()
- {
- var src1 = @"
-int x = 1;
-Console.WriteLine(1);
-x++/*1A*/;
-Console.WriteLine(2);
-
-while (true)
-{
- x++/*2A*/;
-}
-
-Console.WriteLine(1);
-";
- var src2 = @"
-int x = 1;
-x++/*1B*/;
-for (int i = 0; i < 10; i++) {}
-y++;
-if (x > 1)
-{
- while (true)
- {
- x++/*2B*/;
- }
-
- Console.WriteLine(1);
-}";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "int x = 1;", "int x = 1;" },
- { "int x = 1", "int x = 1" },
- { "x = 1", "x = 1" },
- { "Console.WriteLine(1);", "Console.WriteLine(1);" },
- { "x++/*1A*/;", "x++/*1B*/;" },
- { "Console.WriteLine(2);", "y++;" },
- { "while (true) { x++/*2A*/; }", "while (true) { x++/*2B*/; }" },
- { "{ x++/*2A*/; }", "{ x++/*2B*/; }" },
- { "x++/*2A*/;", "x++/*2B*/;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void KnownMatches_Root()
- {
- string src1 = @"
-Console.WriteLine(1);
-";
-
- string src2 = @"
-Console.WriteLine(2);
-";
-
- var m1 = MakeMethodBody(src1);
- var m2 = MakeMethodBody(src2);
-
- var knownMatches = new[] { new KeyValuePair(m1, m2) };
- var match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2, knownMatches);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "Console.WriteLine(1);", "Console.WriteLine(2);" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void Locals_Rename()
- {
- var src1 = @"
-int x = 1;
-";
- var src2 = @"
-int y = 1;
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "int x = 1;", "int y = 1;" },
- { "int x = 1", "int y = 1" },
- { "x = 1", "y = 1" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void Locals_TypeChange()
- {
- var src1 = @"
-int x = 1;
-";
- var src2 = @"
-byte x = 1;
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "int x = 1;", "byte x = 1;" },
- { "int x = 1", "byte x = 1" },
- { "x = 1", "x = 1" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void BlocksWithLocals1()
- {
- var src1 = @"
-{
- int a = 1;
-}
-{
- int b = 2;
-}
-";
- var src2 = @"
-{
- int a = 3;
- int b = 4;
-}
-{
- int b = 5;
-}
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "{ int a = 1; }", "{ int a = 3; int b = 4; }" },
- { "int a = 1;", "int a = 3;" },
- { "int a = 1", "int a = 3" },
- { "a = 1", "a = 3" },
- { "{ int b = 2; }", "{ int b = 5; }" },
- { "int b = 2;", "int b = 5;" },
- { "int b = 2", "int b = 5" },
- { "b = 2", "b = 5" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void IfBlocksWithLocals1()
- {
- var src1 = @"
-if (X)
-{
- int a = 1;
-}
-if (Y)
-{
- int b = 2;
-}
-";
- var src2 = @"
-if (Y)
-{
- int a = 3;
- int b = 4;
-}
-if (X)
-{
- int b = 5;
-}
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "if (X) { int a = 1; }", "if (Y) { int a = 3; int b = 4; }" },
- { "{ int a = 1; }", "{ int a = 3; int b = 4; }" },
- { "int a = 1;", "int a = 3;" },
- { "int a = 1", "int a = 3" },
- { "a = 1", "a = 3" },
- { "if (Y) { int b = 2; }", "if (X) { int b = 5; }" },
- { "{ int b = 2; }", "{ int b = 5; }" },
- { "int b = 2;", "int b = 5;" },
- { "int b = 2", "int b = 5" },
- { "b = 2", "b = 5" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void BlocksWithLocals2()
- {
- var src1 = @"
-{
- int a = 1;
-}
-{
- {
- int b = 2;
- }
-}
-";
- var src2 = @"
-{
- int b = 1;
-}
-{
- {
- int a = 2;
- }
-}
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "{ int a = 1; }", "{ int a = 2; }" },
- { "int a = 1;", "int a = 2;" },
- { "int a = 1", "int a = 2" },
- { "a = 1", "a = 2" },
- { "{ { int b = 2; } }", "{ { int a = 2; } }" },
- { "{ int b = 2; }", "{ int b = 1; }" },
- { "int b = 2;", "int b = 1;" },
- { "int b = 2", "int b = 1" },
- { "b = 2", "b = 1" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void BlocksWithLocals3()
- {
- var src1 = @"
-{
- int a = 1, b = 2, c = 3;
- Console.WriteLine(a + b + c);
-}
-{
- int c = 4, b = 5, a = 6;
- Console.WriteLine(a + b + c);
-}
-{
- int a = 7, b = 8;
- Console.WriteLine(a + b);
-}
-";
- var src2 = @"
-{
- int a = 9, b = 10;
- Console.WriteLine(a + b);
-}
-{
- int c = 11, b = 12, a = 13;
- Console.WriteLine(a + b + c);
-}
-{
- int a = 14, b = 15, c = 16;
- Console.WriteLine(a + b + c);
-}
-";
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "{ int a = 1, b = 2, c = 3; Console.WriteLine(a + b + c); }", "{ int a = 14, b = 15, c = 16; Console.WriteLine(a + b + c); }" },
- { "int a = 1, b = 2, c = 3;", "int a = 14, b = 15, c = 16;" },
- { "int a = 1, b = 2, c = 3", "int a = 14, b = 15, c = 16" },
- { "a = 1", "a = 14" },
- { "b = 2", "b = 15" },
- { "c = 3", "c = 16" },
- { "Console.WriteLine(a + b + c);", "Console.WriteLine(a + b + c);" },
- { "{ int c = 4, b = 5, a = 6; Console.WriteLine(a + b + c); }", "{ int c = 11, b = 12, a = 13; Console.WriteLine(a + b + c); }" },
- { "int c = 4, b = 5, a = 6;", "int c = 11, b = 12, a = 13;" },
- { "int c = 4, b = 5, a = 6", "int c = 11, b = 12, a = 13" },
- { "c = 4", "c = 11" },
- { "b = 5", "b = 12" },
- { "a = 6", "a = 13" },
- { "Console.WriteLine(a + b + c);", "Console.WriteLine(a + b + c);" },
- { "{ int a = 7, b = 8; Console.WriteLine(a + b); }", "{ int a = 9, b = 10; Console.WriteLine(a + b); }" },
- { "int a = 7, b = 8;", "int a = 9, b = 10;" },
- { "int a = 7, b = 8", "int a = 9, b = 10" },
- { "a = 7", "a = 9" },
- { "b = 8", "b = 10" },
- { "Console.WriteLine(a + b);", "Console.WriteLine(a + b);" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas1()
- {
- var src1 = "Action x = a => a;";
- var src2 = "Action x = (a) => a;";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "Action x = a => a;", "Action x = (a) => a;" },
- { "Action x = a => a", "Action x = (a) => a" },
- { "x = a => a", "x = (a) => a" },
- { "a => a", "(a) => a" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas2a()
- {
- var src1 = @"
-F(x => x + 1, 1, y => y + 1, delegate(int x) { return x; }, async u => u);
-";
- var src2 = @"
-F(y => y + 1, G(), x => x + 1, (int x) => x, u => u, async (u, v) => u + v);
-";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "F(x => x + 1, 1, y => y + 1, delegate(int x) { return x; }, async u => u);", "F(y => y + 1, G(), x => x + 1, (int x) => x, u => u, async (u, v) => u + v);" },
- { "x => x + 1", "x => x + 1" },
- { "y => y + 1", "y => y + 1" },
- { "delegate(int x) { return x; }", "(int x) => x" },
- { "async u => u", "async (u, v) => u + v" },
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact, WorkItem(830419, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/830419")]
- public void MatchLambdas2b()
- {
- var src1 = @"
-F(delegate { return x; });
-";
- var src2 = @"
-F((a) => x, () => x);
-";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "F(delegate { return x; });", "F((a) => x, () => x);" },
- { "delegate { return x; }", "() => x" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas3()
- {
- var src1 = @"
-a += async u => u;
-";
- var src2 = @"
-a += u => u;
-";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "a += async u => u;", "a += u => u;" },
- { "async u => u", "u => u" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas4()
- {
- var src1 = @"
-foreach (var a in z)
-{
- var e = from q in a.Where(l => l > 10) select q + 1;
-}
-";
- var src2 = @"
-foreach (var a in z)
-{
- var e = from q in a.Where(l => l < 0) select q + 1;
-}
-";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "foreach (var a in z) { var e = from q in a.Where(l => l > 10) select q + 1; }", "foreach (var a in z) { var e = from q in a.Where(l => l < 0) select q + 1; }" },
- { "{ var e = from q in a.Where(l => l > 10) select q + 1; }", "{ var e = from q in a.Where(l => l < 0) select q + 1; }" },
- { "var e = from q in a.Where(l => l > 10) select q + 1;", "var e = from q in a.Where(l => l < 0) select q + 1;" },
- { "var e = from q in a.Where(l => l > 10) select q + 1", "var e = from q in a.Where(l => l < 0) select q + 1" },
- { "e = from q in a.Where(l => l > 10) select q + 1", "e = from q in a.Where(l => l < 0) select q + 1" },
- { "from q in a.Where(l => l > 10)", "from q in a.Where(l => l < 0)" },
- { "l => l > 10", "l => l < 0" },
- { "select q + 1", "select q + 1" }, // select clause
- { "select q + 1", "select q + 1" } // query body
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas5()
- {
- var src1 = @"
-F(a => b => c => d);
-";
- var src2 = @"
-F(a => b => c => d);
-";
-
- var matches = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(matches);
-
- var expected = new MatchingPairs
- {
- { "F(a => b => c => d);", "F(a => b => c => d);" },
- { "a => b => c => d", "a => b => c => d" },
- { "b => c => d", "b => c => d" },
- { "c => d", "c => d" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas6()
- {
- var src1 = @"
-F(a => b => c => d);
-";
- var src2 = @"
-F(a => G(b => H(c => I(d))));
-";
-
- var matches = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(matches);
-
- var expected = new MatchingPairs
- {
- { "F(a => b => c => d);", "F(a => G(b => H(c => I(d))));" },
- { "a => b => c => d", "a => G(b => H(c => I(d)))" },
- { "b => c => d", "b => H(c => I(d))" },
- { "c => d", "c => I(d)" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLambdas7()
- {
- var src1 = @"
-F(a =>
-{
- F(c => /*1*/d);
- F((u, v) =>
- {
- F((w) => c => /*2*/d);
- F(p => p);
- });
-});
-";
- var src2 = @"
-F(a =>
-{
- F(c => /*1*/d + 1);
- F((u, v) =>
- {
- F((w) => c => /*2*/d + 1);
- F(p => p*2);
- });
-});
-";
-
- var matches = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(matches);
-
- var expected = new MatchingPairs
- {
- { "F(a => { F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); });",
- "F(a => { F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); });" },
- { "a => { F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); }",
- "a => { F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); }" },
- { "{ F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); }",
- "{ F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); }" },
- { "F(c => /*1*/d);", "F(c => /*1*/d + 1);" },
- { "c => /*1*/d", "c => /*1*/d + 1" },
- { "F((u, v) => { F((w) => c => /*2*/d); F(p => p); });", "F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); });" },
- { "(u, v) => { F((w) => c => /*2*/d); F(p => p); }", "(u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }" },
- { "{ F((w) => c => /*2*/d); F(p => p); }", "{ F((w) => c => /*2*/d + 1); F(p => p*2); }" },
- { "F((w) => c => /*2*/d);", "F((w) => c => /*2*/d + 1);" },
- { "(w) => c => /*2*/d", "(w) => c => /*2*/d + 1" },
- { "c => /*2*/d", "c => /*2*/d + 1" },
- { "F(p => p);", "F(p => p*2);" },
- { "p => p", "p => p*2" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchQueries1()
- {
- var src1 = @"
-var q = from c in cars
- from ud in users_details
- from bd in bids
- select 1;
-";
- var src2 = @"
-var q = from c in cars
- from bd in bids
- from ud in users_details
- select 2;
-";
-
- var match = GetMethodMatch(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var q = from c in cars from ud in users_details from bd in bids select 1;", "var q = from c in cars from bd in bids from ud in users_details select 2;" },
- { "var q = from c in cars from ud in users_details from bd in bids select 1", "var q = from c in cars from bd in bids from ud in users_details select 2" },
- { "q = from c in cars from ud in users_details from bd in bids select 1", "q = from c in cars from bd in bids from ud in users_details select 2" },
- { "from c in cars", "from c in cars" },
- { "from ud in users_details from bd in bids select 1", "from bd in bids from ud in users_details select 2" },
- { "from ud in users_details", "from ud in users_details" },
- { "from bd in bids", "from bd in bids" },
- { "select 1", "select 2" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchQueries2()
- {
- var src1 = @"
-var q = from c in cars
- from ud in users_details
- from bd in bids
- orderby c.listingOption descending
- where a.userID == ud.userid
- let images = from ai in auction_images
- where ai.belongs_to == c.id
- select ai
- let bid = (from b in bids
- orderby b.id descending
- where b.carID == c.id
- select b.bidamount).FirstOrDefault()
- select bid;
-";
- var src2 = @"
-var q = from c in cars
- from ud in users_details
- from bd in bids
- orderby c.listingOption descending
- where a.userID == ud.userid
- let images = from ai in auction_images
- where ai.belongs_to == c.id2
- select ai + 1
- let bid = (from b in bids
- orderby b.id ascending
- where b.carID == c.id2
- select b.bidamount).FirstOrDefault()
- select bid;
-";
-
- var match = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid;",
- "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid;" },
- { "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid",
- "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
- { "q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid",
- "q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
- { "from c in cars", "from c in cars" },
- { "from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid", "from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
- { "from ud in users_details", "from ud in users_details" },
- { "from bd in bids", "from bd in bids" },
- { "orderby c.listingOption descending", "orderby c.listingOption descending" },
- { "c.listingOption descending", "c.listingOption descending" },
- { "where a.userID == ud.userid", "where a.userID == ud.userid" },
- { "let images = from ai in auction_images where ai.belongs_to == c.id select ai",
- "let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1" },
- { "from ai in auction_images", "from ai in auction_images" },
- { "where ai.belongs_to == c.id select ai", "where ai.belongs_to == c.id2 select ai + 1" },
- { "where ai.belongs_to == c.id", "where ai.belongs_to == c.id2" },
- { "select ai", "select ai + 1" },
- { "let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault()",
- "let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault()" },
- { "from b in bids", "from b in bids" },
- { "orderby b.id descending where b.carID == c.id select b.bidamount", "orderby b.id ascending where b.carID == c.id2 select b.bidamount" },
- { "orderby b.id descending", "orderby b.id ascending" },
- { "b.id descending", "b.id ascending" },
- { "where b.carID == c.id", "where b.carID == c.id2" },
- { "select b.bidamount", "select b.bidamount" },
- { "select bid", "select bid" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchQueries3()
- {
- var src1 = @"
-var q = from a in await seq1
- join c in await seq2 on F(u => u) equals G(s => s) into g1
- join l in await seq3 on F(v => v) equals G(t => t) into g2
- select a;
-
-";
- var src2 = @"
-var q = from a in await seq1
- join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1
- join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2
- select a + 1;
-";
-
- var match = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a;", "var q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1;" },
- { "var q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "var q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
- { "q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
- { "from a in await seq1", "from a in await seq1" },
- { "await seq1", "await seq1" },
- { "join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
- { "join c in await seq2 on F(u => u) equals G(s => s) into g1", "join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1" },
- { "await seq2", "await seq2" },
- { "u => u", "u => u + 1" },
- { "s => s", "s => s + 3" },
- { "into g1", "into g1" },
- { "join l in await seq3 on F(v => v) equals G(t => t) into g2", "join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2" },
- { "await seq3", "await seq3" },
- { "v => v", "vv => vv + 2" },
- { "t => t", "tt => tt + 4" },
- { "into g2", "into g2" },
- { "select a", "select a + 1" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchQueries4()
- {
- var src1 = "F(from a in await b from x in y select c);";
- var src2 = "F(from a in await c from x in y select c);";
-
- var match = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "F(from a in await b from x in y select c);", "F(from a in await c from x in y select c);" },
- { "from a in await b", "from a in await c" },
- { "await b", "await c" },
- { "from x in y select c", "from x in y select c" },
- { "from x in y", "from x in y" },
- { "select c", "select c" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchQueries5()
- {
- var src1 = "F(from a in b group a by a.x into g select g);";
- var src2 = "F(from a in b group z by z.y into h select h);";
-
- var match = GetMethodMatches(src1, src2);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "F(from a in b group a by a.x into g select g);", "F(from a in b group z by z.y into h select h);" },
- { "from a in b", "from a in b" },
- { "group a by a.x into g select g", "group z by z.y into h select h" },
- { "group a by a.x", "group z by z.y" },
- { "into g select g", "into h select h" },
- { "select g", "select h" },
- { "select g", "select h" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchYields()
- {
- var src1 = @"
-yield return /*1*/ 1;
-
-{
- yield return /*2*/ 2;
-}
-
-foreach (var x in y) { yield return /*3*/ 3; }
-";
- var src2 = @"
-yield return /*1*/ 1;
-yield return /*2*/ 3;
-foreach (var x in y) { yield return /*3*/ 2; }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Iterator);
- var actual = ToMatchingPairs(match);
-
- // note that yield returns are matched in source order, regardless of the yielded expressions:
- var expected = new MatchingPairs
- {
- { "yield return /*1*/ 1;", "yield return /*1*/ 1;" },
- { "{ yield return /*2*/ 2; }", "{ yield return /*3*/ 2; }" },
- { "yield return /*2*/ 2;", "yield return /*2*/ 3;" },
- { "foreach (var x in y) { yield return /*3*/ 3; }", "foreach (var x in y) { yield return /*3*/ 2; }" },
- { "yield return /*3*/ 3;", "yield return /*3*/ 2;" },
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void KnownMatches()
- {
- string src1 = @"
-Console.WriteLine(1)/*1*/;
-Console.WriteLine(1)/*2*/;
-";
-
- string src2 = @"
-Console.WriteLine(1)/*3*/;
-Console.WriteLine(1)/*4*/;
-";
-
- var m1 = MakeMethodBody(src1);
- var m2 = MakeMethodBody(src2);
-
- var knownMatches = new KeyValuePair[]
- {
- new KeyValuePair(m1.Statements[1], m2.Statements[0])
- };
-
- // pre-matched:
-
- var match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2, knownMatches);
-
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "Console.WriteLine(1)/*1*/;", "Console.WriteLine(1)/*4*/;" },
- { "Console.WriteLine(1)/*2*/;", "Console.WriteLine(1)/*3*/;" }
- };
-
- expected.AssertEqual(actual);
-
- // not pre-matched:
-
- match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2);
-
- actual = ToMatchingPairs(match);
-
- expected = new MatchingPairs
- {
- { "Console.WriteLine(1)/*1*/;", "Console.WriteLine(1)/*3*/;" },
- { "Console.WriteLine(1)/*2*/;", "Console.WriteLine(1)/*4*/;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchConstructorWithInitializer1()
- {
- var src1 = @"
-(int x = 1) : base(a => a + 1) { Console.WriteLine(1); }
-";
- var src2 = @"
-(int x = 1) : base(a => a + 1) { Console.WriteLine(1); }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.ConstructorWithParameters);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "a => a + 1", "a => a + 1" },
- { "{ Console.WriteLine(1); }", "{ Console.WriteLine(1); }" },
- { "Console.WriteLine(1);", "Console.WriteLine(1);" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchConstructorWithInitializer2()
- {
- var src1 = @"
-() : base(a => a + 1) { Console.WriteLine(1); }
-";
- var src2 = @"
-() { Console.WriteLine(1); }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.ConstructorWithParameters);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "{ Console.WriteLine(1); }", "{ Console.WriteLine(1); }" },
- { "Console.WriteLine(1);", "Console.WriteLine(1);" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchExceptionHandlers()
- {
- var src1 = @"
-try { throw new InvalidOperationException(1); }
-catch (IOException e) when (filter(e)) { Console.WriteLine(2); }
-catch (Exception e) when (filter(e)) { Console.WriteLine(3); }
-";
- var src2 = @"
-try { throw new InvalidOperationException(10); }
-catch (IOException e) when (filter(e)) { Console.WriteLine(20); }
-catch (Exception e) when (filter(e)) { Console.WriteLine(30); }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "try { throw new InvalidOperationException(1); } catch (IOException e) when (filter(e)) { Console.WriteLine(2); } catch (Exception e) when (filter(e)) { Console.WriteLine(3); }", "try { throw new InvalidOperationException(10); } catch (IOException e) when (filter(e)) { Console.WriteLine(20); } catch (Exception e) when (filter(e)) { Console.WriteLine(30); }" },
- { "{ throw new InvalidOperationException(1); }", "{ throw new InvalidOperationException(10); }" },
- { "throw new InvalidOperationException(1);", "throw new InvalidOperationException(10);" },
- { "catch (IOException e) when (filter(e)) { Console.WriteLine(2); }", "catch (IOException e) when (filter(e)) { Console.WriteLine(20); }" },
- { "(IOException e)", "(IOException e)" },
- { "when (filter(e))", "when (filter(e))" },
- { "{ Console.WriteLine(2); }", "{ Console.WriteLine(20); }" },
- { "Console.WriteLine(2);", "Console.WriteLine(20);" },
- { "catch (Exception e) when (filter(e)) { Console.WriteLine(3); }", "catch (Exception e) when (filter(e)) { Console.WriteLine(30); }" },
- { "(Exception e)", "(Exception e)" },
- { "when (filter(e))", "when (filter(e))" },
- { "{ Console.WriteLine(3); }", "{ Console.WriteLine(30); }" },
- { "Console.WriteLine(3);", "Console.WriteLine(30);" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchTuple()
- {
- var src1 = @"
-return (1, 2);
-return (d, 6);
-return (10, e, 22);
-return (2, () => {
- int a = 6;
- return 1;
-});";
-
- var src2 = @"
-return (1, 2, 3);
-return (d, 5);
-return (10, e);
-return (2, () => {
- int a = 6;
- return 5;
-});";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "return (1, 2);", "return (1, 2, 3);" },
- { "return (d, 6);", "return (d, 5);" },
- { "return (10, e, 22);", "return (10, e);" },
- { "return (2, () => { int a = 6; return 1; });", "return (2, () => { int a = 6; return 5; });" },
- { "() => { int a = 6; return 1; }", "() => { int a = 6; return 5; }" },
- { "{ int a = 6; return 1; }", "{ int a = 6; return 5; }" },
- { "int a = 6;", "int a = 6;" },
- { "int a = 6", "int a = 6" },
- { "a = 6", "a = 6" },
- { "return 1;", "return 5;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchLocalFunctionDefinitions()
- {
- var src1 = @"
-(int a, string c) F1(int i) { return null; }
-(int a, int b) F2(int i) { return null; }
-(int a, int b, int c) F3(int i) { return null; }
-";
-
- var src2 = @"
-(int a, int b) F1(int i) { return null; }
-(int a, int b, string c) F2(int i) { return null; }
-(int a, int b) F3(int i) { return null; }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "(int a, string c) F1(int i) { return null; }", "(int a, int b) F1(int i) { return null; }" },
- { "{ return null; }", "{ return null; }" },
- { "return null;", "return null;" },
- { "(int a, int b) F2(int i) { return null; }", "(int a, int b, string c) F2(int i) { return null; }" },
- { "{ return null; }", "{ return null; }" },
- { "return null;", "return null;" },
- { "(int a, int b, int c) F3(int i) { return null; }", "(int a, int b) F3(int i) { return null; }" },
- { "{ return null; }", "{ return null; }" },
- { "return null;", "return null;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchVariableDesignations()
- {
- var src1 = @"
-M(out int z);
-N(out var a);
-";
-
- var src2 = @"
-M(out var z);
-N(out var b);
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "M(out int z);", "M(out var z);" },
- { "z", "z" },
- { "N(out var a);", "N(out var b);" },
- { "a", "b" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchParenthesizedVariable_Update()
- {
- var src1 = @"
-var (x1, (x2, x3)) = (1, (2, true));
-var (a1, a2) = (1, () => { return 7; });
-";
-
- var src2 = @"
-var (x1, (x3, x4)) = (1, (2, true));
-var (a1, a3) = (1, () => { return 8; });
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var (x1, (x2, x3)) = (1, (2, true));", "var (x1, (x3, x4)) = (1, (2, true));" },
- { "x1", "x1" },
- { "x2", "x4" },
- { "x3", "x3" },
- { "var (a1, a2) = (1, () => { return 7; });", "var (a1, a3) = (1, () => { return 8; });" },
- { "a1", "a1" },
- { "a2", "a3" },
- { "() => { return 7; }", "() => { return 8; }" },
- { "{ return 7; }", "{ return 8; }" },
- { "return 7;", "return 8;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchParenthesizedVariable_Insert()
- {
- var src1 = @"var (z1, z2) = (1, 2);";
- var src2 = @"var (z1, z2, z3) = (1, 2, 5);";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var (z1, z2) = (1, 2);", "var (z1, z2, z3) = (1, 2, 5);" },
- { "z1", "z1" },
- { "z2", "z2" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchParenthesizedVariable_Delete()
- {
- var src1 = @"var (y1, y2, y3) = (1, 2, 7);";
- var src2 = @"var (y1, y2) = (1, 4);";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "var (y1, y2, y3) = (1, 2, 7);", "var (y1, y2) = (1, 4);" },
- { "y1", "y1" },
- { "y2", "y2" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchForeachVariable_Update1()
- {
- var src1 = @"
-foreach (var (a1, a2) in e) { A1(); }
-foreach ((var b1, var b2) in e) { A2(); }
-";
-
- var src2 = @"
-foreach (var (a1, a3) in e) { A1(); }
-foreach ((var b3, int b2) in e) { A2(); }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "foreach (var (a1, a2) in e) { A1(); }", "foreach (var (a1, a3) in e) { A1(); }" },
- { "a1", "a1" },
- { "a2", "a3" },
- { "{ A1(); }", "{ A1(); }" },
- { "A1();", "A1();" },
- { "foreach ((var b1, var b2) in e) { A2(); }", "foreach ((var b3, int b2) in e) { A2(); }" },
- { "b1", "b3" },
- { "b2", "b2" },
- { "{ A2(); }", "{ A2(); }" },
- { "A2();", "A2();" },
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchForeachVariable_Update2()
- {
- var src1 = @"
-foreach (_ in e2) { yield return 4; }
-foreach (_ in e3) { A(); }
-";
-
- var src2 = @"
-foreach (_ in e4) { A(); }
-foreach (var b in e2) { yield return 4; }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "foreach (_ in e2) { yield return 4; }", "foreach (var b in e2) { yield return 4; }" },
- { "{ yield return 4; }", "{ yield return 4; }" },
- { "yield return 4;", "yield return 4;" },
- { "foreach (_ in e3) { A(); }", "foreach (_ in e4) { A(); }" },
- { "{ A(); }", "{ A(); }" },
- { "A();", "A();" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchForeachVariable_Insert()
- {
- var src1 = @"
-foreach (var (a3, a4) in e) { }
-foreach ((var b4, var b5) in e) { }
-";
-
- var src2 = @"
-foreach (var (a3, a5, a4) in e) { }
-foreach ((var b6, var b4, var b5) in e) { }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "foreach (var (a3, a4) in e) { }", "foreach (var (a3, a5, a4) in e) { }" },
- { "a3", "a3" },
- { "a4", "a4" },
- { "{ }", "{ }" },
- { "foreach ((var b4, var b5) in e) { }", "foreach ((var b6, var b4, var b5) in e) { }" },
- { "b4", "b4" },
- { "b5", "b5" },
- { "{ }", "{ }" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchForeachVariable_Delete()
- {
- var src1 = @"
-foreach (var (a11, a12, a13) in e) { A1(); }
-foreach ((var b7, var b8, var b9) in e) { A2(); }
-";
-
- var src2 = @"
-foreach (var (a12, a13) in e1) { A1(); }
-foreach ((var b7, var b9) in e) { A2(); }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "foreach (var (a11, a12, a13) in e) { A1(); }", "foreach (var (a12, a13) in e1) { A1(); }" },
- { "a12", "a12" },
- { "a13", "a13" },
- { "{ A1(); }", "{ A1(); }" },
- { "A1();", "A1();" },
- { "foreach ((var b7, var b8, var b9) in e) { A2(); }", "foreach ((var b7, var b9) in e) { A2(); }" },
- { "b7", "b7" },
- { "b9", "b9" },
- { "{ A2(); }", "{ A2(); }" },
- { "A2();", "A2();" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchConstantPattern()
- {
- var src1 = @"
-if ((o is null) && (y == 7)) return 3;
-if (a is 7) return 5;
-";
-
- var src2 = @"
-if ((o1 is null) && (y == 7)) return 3;
-if (a is 77) return 5;
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs {
- { "if ((o is null) && (y == 7)) return 3;", "if ((o1 is null) && (y == 7)) return 3;" },
- { "return 3;", "return 3;" },
- { "if (a is 7) return 5;", "if (a is 77) return 5;" },
- { "return 5;", "return 5;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchDeclarationPattern()
- {
- var src1 = @"
-if (!(o is int i) && (y == 7)) return;
-if (!(a is string s)) return;
-if (!(b is string t)) return;
-if (!(c is int j)) return;
-";
-
- var src2 = @"
-if (!(b is string t1)) return;
-if (!(o1 is int i) && (y == 7)) return;
-if (!(c is int)) return;
-if (!(a is int s)) return;
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs {
- { "if (!(o is int i) && (y == 7)) return;", "if (!(o1 is int i) && (y == 7)) return;" },
- { "i", "i" },
- { "return;", "return;" },
- { "if (!(a is string s)) return;", "if (!(a is int s)) return;" },
- { "s", "s" },
- { "return;", "return;" },
- { "if (!(b is string t)) return;", "if (!(b is string t1)) return;" },
- { "t", "t1" },
- { "return;", "return;" },
- { "if (!(c is int j)) return;", "if (!(c is int)) return;" },
- { "return;", "return;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchCasePattern_UpdateInsert()
- {
- var src1 = @"
-switch(shape)
-{
- case Circle c: return 1;
- default: return 4;
-}
-";
-
- var src2 = @"
-switch(shape)
-{
- case Circle c1: return 1;
- case Point p: return 0;
- default: return 4;
-}
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs {
- { "switch(shape) { case Circle c: return 1; default: return 4; }", "switch(shape) { case Circle c1: return 1; case Point p: return 0; default: return 4; }" },
- { "case Circle c: return 1;", "case Circle c1: return 1;" },
- { "case Circle c:", "case Circle c1:" },
- { "c", "c1" },
- { "return 1;", "return 1;" },
- { "default: return 4;", "default: return 4;" },
- { "return 4;", "return 4;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchWhenCondition()
- {
- var src1 = @"
-switch(shape)
-{
- case Circle c when (c < 10): return 1;
- case Circle c when (c > 100): return 2;
-}
-";
-
- var src2 = @"
-switch(shape)
-{
- case Circle c when (c < 5): return 1;
- case Circle c2 when (c2 > 100): return 2;
-}
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "switch(shape) { case Circle c when (c < 10): return 1; case Circle c when (c > 100): return 2; }", "switch(shape) { case Circle c when (c < 5): return 1; case Circle c2 when (c2 > 100): return 2; }" },
- { "case Circle c when (c < 10): return 1;", "case Circle c when (c < 5): return 1;" },
- { "case Circle c when (c < 10):", "case Circle c when (c < 5):" },
- { "c", "c" },
- { "when (c < 10)", "when (c < 5)" },
- { "return 1;", "return 1;" },
- { "case Circle c when (c > 100): return 2;", "case Circle c2 when (c2 > 100): return 2;" },
- { "case Circle c when (c > 100):", "case Circle c2 when (c2 > 100):" },
- { "c", "c2" },
- { "when (c > 100)", "when (c2 > 100)" },
- { "return 2;", "return 2;" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchRef()
- {
- var src1 = @"
-ref int a = ref G(new int[] { 1, 2 });
- ref int G(int[] p)
- {
- return ref p[1];
- }
-";
-
- var src2 = @"
-ref int32 a = ref G1(new int[] { 1, 2 });
- ref int G1(int[] p)
- {
- return ref p[2];
- }
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "ref int a = ref G(new int[] { 1, 2 });", "ref int32 a = ref G1(new int[] { 1, 2 });" },
- { "ref int a = ref G(new int[] { 1, 2 })", "ref int32 a = ref G1(new int[] { 1, 2 })" },
- { "a = ref G(new int[] { 1, 2 })", "a = ref G1(new int[] { 1, 2 })" },
- { "ref int G(int[] p) { return ref p[1]; }", "ref int G1(int[] p) { return ref p[2]; }" },
- { "{ return ref p[1]; }", "{ return ref p[2]; }" },
- { "return ref p[1];", "return ref p[2];" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchThrowException_UpdateInsert()
- {
- var src1 = @"
-return a > 3 ? a : throw new Exception();
-return c > 7 ? c : 7;
-";
-
- var src2 = @"
-return a > 3 ? a : throw new ArgumentException();
-return c > 7 ? c : throw new IndexOutOfRangeException();
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "return a > 3 ? a : throw new Exception();", "return a > 3 ? a : throw new ArgumentException();" },
- { "return c > 7 ? c : 7;", "return c > 7 ? c : throw new IndexOutOfRangeException();" }
- };
-
- expected.AssertEqual(actual);
- }
-
- [Fact]
- public void MatchThrowException_UpdateDelete()
- {
- var src1 = @"
-return a > 3 ? a : throw new Exception();
-return b > 5 ? b : throw new OperationCanceledException();
-";
-
- var src2 = @"
-return a > 3 ? a : throw new ArgumentException();
-return b > 5 ? b : 5;
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs
- {
- { "return a > 3 ? a : throw new Exception();", "return a > 3 ? a : throw new ArgumentException();" },
- { "return b > 5 ? b : throw new OperationCanceledException();", "return b > 5 ? b : 5;" }
- };
-
- expected.AssertEqual(actual);
- }
+ #region Strings
[Fact]
public void StringLiteral_update()
@@ -1483,38 +71,6 @@ public void InterpolationFormatClause_update()
edits.VerifyEdits("Update [x = $\"Hello{123:N1}\"]@8 -> [x = $\"Hello{123:N2}\"]@8");
}
- [Fact]
- public void MatchCasePattern_UpdateDelete()
- {
- var src1 = @"
-switch(shape)
-{
- case Point p: return 0;
- case Circle c: return 1;
-}
-";
-
- var src2 = @"
-switch(shape)
-{
- case Circle circle: return 1;
-}
-";
-
- var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
- var actual = ToMatchingPairs(match);
-
- var expected = new MatchingPairs {
- { "switch(shape) { case Point p: return 0; case Circle c: return 1; }", "switch(shape) { case Circle circle: return 1; }" },
- { "case Circle c: return 1;", "case Circle circle: return 1;" },
- { "case Circle c:", "case Circle circle:" },
- { "c", "circle" },
- { "return 1;", "return 1;" }
- };
-
- expected.AssertEqual(actual);
- }
-
#endregion
#region Variable Declaration
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/StatementMatchingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementMatchingTests.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5be548928ec0952bdce071f06f574948d609a13c
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/StatementMatchingTests.cs
@@ -0,0 +1,1500 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
+{
+ public class StatementMatchingTests : EditingTestBase
+ {
+ #region Known Matches
+
+ [Fact]
+ public void KnownMatches()
+ {
+ string src1 = @"
+Console.WriteLine(1)/*1*/;
+Console.WriteLine(1)/*2*/;
+";
+
+ string src2 = @"
+Console.WriteLine(1)/*3*/;
+Console.WriteLine(1)/*4*/;
+";
+
+ var m1 = MakeMethodBody(src1);
+ var m2 = MakeMethodBody(src2);
+
+ var knownMatches = new KeyValuePair[]
+ {
+ new KeyValuePair(m1.Statements[1], m2.Statements[0])
+ };
+
+ // pre-matched:
+
+ var match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2, knownMatches);
+
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "Console.WriteLine(1)/*1*/;", "Console.WriteLine(1)/*4*/;" },
+ { "Console.WriteLine(1)/*2*/;", "Console.WriteLine(1)/*3*/;" }
+ };
+
+ expected.AssertEqual(actual);
+
+ // not pre-matched:
+
+ match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2);
+
+ actual = ToMatchingPairs(match);
+
+ expected = new MatchingPairs
+ {
+ { "Console.WriteLine(1)/*1*/;", "Console.WriteLine(1)/*3*/;" },
+ { "Console.WriteLine(1)/*2*/;", "Console.WriteLine(1)/*4*/;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void KnownMatches_Root()
+ {
+ string src1 = @"
+Console.WriteLine(1);
+";
+
+ string src2 = @"
+Console.WriteLine(2);
+";
+
+ var m1 = MakeMethodBody(src1);
+ var m2 = MakeMethodBody(src2);
+
+ var knownMatches = new[] { new KeyValuePair(m1, m2) };
+ var match = StatementSyntaxComparer.Default.ComputeMatch(m1, m2, knownMatches);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "Console.WriteLine(1);", "Console.WriteLine(2);" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Statements
+
+ [Fact]
+ public void MiscStatements()
+ {
+ var src1 = @"
+int x = 1;
+Console.WriteLine(1);
+x++/*1A*/;
+Console.WriteLine(2);
+
+while (true)
+{
+ x++/*2A*/;
+}
+
+Console.WriteLine(1);
+";
+ var src2 = @"
+int x = 1;
+x++/*1B*/;
+for (int i = 0; i < 10; i++) {}
+y++;
+if (x > 1)
+{
+ while (true)
+ {
+ x++/*2B*/;
+ }
+
+ Console.WriteLine(1);
+}";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "int x = 1;", "int x = 1;" },
+ { "int x = 1", "int x = 1" },
+ { "x = 1", "x = 1" },
+ { "Console.WriteLine(1);", "Console.WriteLine(1);" },
+ { "x++/*1A*/;", "x++/*1B*/;" },
+ { "Console.WriteLine(2);", "y++;" },
+ { "while (true) { x++/*2A*/; }", "while (true) { x++/*2B*/; }" },
+ { "{ x++/*2A*/; }", "{ x++/*2B*/; }" },
+ { "x++/*2A*/;", "x++/*2B*/;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ThrowException_UpdateInsert()
+ {
+ var src1 = @"
+return a > 3 ? a : throw new Exception();
+return c > 7 ? c : 7;
+";
+
+ var src2 = @"
+return a > 3 ? a : throw new ArgumentException();
+return c > 7 ? c : throw new IndexOutOfRangeException();
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "return a > 3 ? a : throw new Exception();", "return a > 3 ? a : throw new ArgumentException();" },
+ { "return c > 7 ? c : 7;", "return c > 7 ? c : throw new IndexOutOfRangeException();" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ThrowException_UpdateDelete()
+ {
+ var src1 = @"
+return a > 3 ? a : throw new Exception();
+return b > 5 ? b : throw new OperationCanceledException();
+";
+
+ var src2 = @"
+return a > 3 ? a : throw new ArgumentException();
+return b > 5 ? b : 5;
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "return a > 3 ? a : throw new Exception();", "return a > 3 ? a : throw new ArgumentException();" },
+ { "return b > 5 ? b : throw new OperationCanceledException();", "return b > 5 ? b : 5;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Tuple()
+ {
+ var src1 = @"
+return (1, 2);
+return (d, 6);
+return (10, e, 22);
+return (2, () => {
+ int a = 6;
+ return 1;
+});";
+
+ var src2 = @"
+return (1, 2, 3);
+return (d, 5);
+return (10, e);
+return (2, () => {
+ int a = 6;
+ return 5;
+});";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "return (1, 2);", "return (1, 2, 3);" },
+ { "return (d, 6);", "return (d, 5);" },
+ { "return (10, e, 22);", "return (10, e);" },
+ { "return (2, () => { int a = 6; return 1; });", "return (2, () => { int a = 6; return 5; });" },
+ { "() => { int a = 6; return 1; }", "() => { int a = 6; return 5; }" },
+ { "{ int a = 6; return 1; }", "{ int a = 6; return 5; }" },
+ { "int a = 6;", "int a = 6;" },
+ { "int a = 6", "int a = 6" },
+ { "a = 6", "a = 6" },
+ { "return 1;", "return 5;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Local Variables
+
+ [Fact]
+ public void Locals_Rename()
+ {
+ var src1 = @"
+int x = 1;
+";
+ var src2 = @"
+int y = 1;
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "int x = 1;", "int y = 1;" },
+ { "int x = 1", "int y = 1" },
+ { "x = 1", "y = 1" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Locals_TypeChange()
+ {
+ var src1 = @"
+int x = 1;
+";
+ var src2 = @"
+byte x = 1;
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "int x = 1;", "byte x = 1;" },
+ { "int x = 1", "byte x = 1" },
+ { "x = 1", "x = 1" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void BlocksWithLocals1()
+ {
+ var src1 = @"
+{
+ int a = 1;
+}
+{
+ int b = 2;
+}
+";
+ var src2 = @"
+{
+ int a = 3;
+ int b = 4;
+}
+{
+ int b = 5;
+}
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "{ int a = 1; }", "{ int a = 3; int b = 4; }" },
+ { "int a = 1;", "int a = 3;" },
+ { "int a = 1", "int a = 3" },
+ { "a = 1", "a = 3" },
+ { "{ int b = 2; }", "{ int b = 5; }" },
+ { "int b = 2;", "int b = 5;" },
+ { "int b = 2", "int b = 5" },
+ { "b = 2", "b = 5" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void IfBlocksWithLocals1()
+ {
+ var src1 = @"
+if (X)
+{
+ int a = 1;
+}
+if (Y)
+{
+ int b = 2;
+}
+";
+ var src2 = @"
+if (Y)
+{
+ int a = 3;
+ int b = 4;
+}
+if (X)
+{
+ int b = 5;
+}
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "if (X) { int a = 1; }", "if (Y) { int a = 3; int b = 4; }" },
+ { "{ int a = 1; }", "{ int a = 3; int b = 4; }" },
+ { "int a = 1;", "int a = 3;" },
+ { "int a = 1", "int a = 3" },
+ { "a = 1", "a = 3" },
+ { "if (Y) { int b = 2; }", "if (X) { int b = 5; }" },
+ { "{ int b = 2; }", "{ int b = 5; }" },
+ { "int b = 2;", "int b = 5;" },
+ { "int b = 2", "int b = 5" },
+ { "b = 2", "b = 5" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void BlocksWithLocals2()
+ {
+ var src1 = @"
+{
+ int a = 1;
+}
+{
+ {
+ int b = 2;
+ }
+}
+";
+ var src2 = @"
+{
+ int b = 1;
+}
+{
+ {
+ int a = 2;
+ }
+}
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "{ int a = 1; }", "{ int a = 2; }" },
+ { "int a = 1;", "int a = 2;" },
+ { "int a = 1", "int a = 2" },
+ { "a = 1", "a = 2" },
+ { "{ { int b = 2; } }", "{ { int a = 2; } }" },
+ { "{ int b = 2; }", "{ int b = 1; }" },
+ { "int b = 2;", "int b = 1;" },
+ { "int b = 2", "int b = 1" },
+ { "b = 2", "b = 1" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void BlocksWithLocals3()
+ {
+ var src1 = @"
+{
+ int a = 1, b = 2, c = 3;
+ Console.WriteLine(a + b + c);
+}
+{
+ int c = 4, b = 5, a = 6;
+ Console.WriteLine(a + b + c);
+}
+{
+ int a = 7, b = 8;
+ Console.WriteLine(a + b);
+}
+";
+ var src2 = @"
+{
+ int a = 9, b = 10;
+ Console.WriteLine(a + b);
+}
+{
+ int c = 11, b = 12, a = 13;
+ Console.WriteLine(a + b + c);
+}
+{
+ int a = 14, b = 15, c = 16;
+ Console.WriteLine(a + b + c);
+}
+";
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "{ int a = 1, b = 2, c = 3; Console.WriteLine(a + b + c); }", "{ int a = 14, b = 15, c = 16; Console.WriteLine(a + b + c); }" },
+ { "int a = 1, b = 2, c = 3;", "int a = 14, b = 15, c = 16;" },
+ { "int a = 1, b = 2, c = 3", "int a = 14, b = 15, c = 16" },
+ { "a = 1", "a = 14" },
+ { "b = 2", "b = 15" },
+ { "c = 3", "c = 16" },
+ { "Console.WriteLine(a + b + c);", "Console.WriteLine(a + b + c);" },
+ { "{ int c = 4, b = 5, a = 6; Console.WriteLine(a + b + c); }", "{ int c = 11, b = 12, a = 13; Console.WriteLine(a + b + c); }" },
+ { "int c = 4, b = 5, a = 6;", "int c = 11, b = 12, a = 13;" },
+ { "int c = 4, b = 5, a = 6", "int c = 11, b = 12, a = 13" },
+ { "c = 4", "c = 11" },
+ { "b = 5", "b = 12" },
+ { "a = 6", "a = 13" },
+ { "Console.WriteLine(a + b + c);", "Console.WriteLine(a + b + c);" },
+ { "{ int a = 7, b = 8; Console.WriteLine(a + b); }", "{ int a = 9, b = 10; Console.WriteLine(a + b); }" },
+ { "int a = 7, b = 8;", "int a = 9, b = 10;" },
+ { "int a = 7, b = 8", "int a = 9, b = 10" },
+ { "a = 7", "a = 9" },
+ { "b = 8", "b = 10" },
+ { "Console.WriteLine(a + b);", "Console.WriteLine(a + b);" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void VariableDesignations()
+ {
+ var src1 = @"
+M(out int z);
+N(out var a);
+";
+
+ var src2 = @"
+M(out var z);
+N(out var b);
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "M(out int z);", "M(out var z);" },
+ { "z", "z" },
+ { "N(out var a);", "N(out var b);" },
+ { "a", "b" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ParenthesizedVariable_Update()
+ {
+ var src1 = @"
+var (x1, (x2, x3)) = (1, (2, true));
+var (a1, a2) = (1, () => { return 7; });
+";
+
+ var src2 = @"
+var (x1, (x3, x4)) = (1, (2, true));
+var (a1, a3) = (1, () => { return 8; });
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var (x1, (x2, x3)) = (1, (2, true));", "var (x1, (x3, x4)) = (1, (2, true));" },
+ { "x1", "x1" },
+ { "x2", "x4" },
+ { "x3", "x3" },
+ { "var (a1, a2) = (1, () => { return 7; });", "var (a1, a3) = (1, () => { return 8; });" },
+ { "a1", "a1" },
+ { "a2", "a3" },
+ { "() => { return 7; }", "() => { return 8; }" },
+ { "{ return 7; }", "{ return 8; }" },
+ { "return 7;", "return 8;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ParenthesizedVariable_Insert()
+ {
+ var src1 = @"var (z1, z2) = (1, 2);";
+ var src2 = @"var (z1, z2, z3) = (1, 2, 5);";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var (z1, z2) = (1, 2);", "var (z1, z2, z3) = (1, 2, 5);" },
+ { "z1", "z1" },
+ { "z2", "z2" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ParenthesizedVariable_Delete()
+ {
+ var src1 = @"var (y1, y2, y3) = (1, 2, 7);";
+ var src2 = @"var (y1, y2) = (1, 4);";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var (y1, y2, y3) = (1, 2, 7);", "var (y1, y2) = (1, 4);" },
+ { "y1", "y1" },
+ { "y2", "y2" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void RefVariable()
+ {
+ var src1 = @"
+ref int a = ref G(new int[] { 1, 2 });
+ ref int G(int[] p)
+ {
+ return ref p[1];
+ }
+";
+
+ var src2 = @"
+ref int32 a = ref G1(new int[] { 1, 2 });
+ ref int G1(int[] p)
+ {
+ return ref p[2];
+ }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "ref int a = ref G(new int[] { 1, 2 });", "ref int32 a = ref G1(new int[] { 1, 2 });" },
+ { "ref int a = ref G(new int[] { 1, 2 })", "ref int32 a = ref G1(new int[] { 1, 2 })" },
+ { "a = ref G(new int[] { 1, 2 })", "a = ref G1(new int[] { 1, 2 })" },
+ { "ref int G(int[] p) { return ref p[1]; }", "ref int G1(int[] p) { return ref p[2]; }" },
+ { "{ return ref p[1]; }", "{ return ref p[2]; }" },
+ { "return ref p[1];", "return ref p[2];" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Lambdas
+
+ [Fact]
+ public void Lambdas1()
+ {
+ var src1 = "Action x = a => a;";
+ var src2 = "Action x = (a) => a;";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "Action x = a => a;", "Action x = (a) => a;" },
+ { "Action x = a => a", "Action x = (a) => a" },
+ { "x = a => a", "x = (a) => a" },
+ { "a => a", "(a) => a" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas2a()
+ {
+ var src1 = @"
+F(x => x + 1, 1, y => y + 1, delegate(int x) { return x; }, async u => u);
+";
+ var src2 = @"
+F(y => y + 1, G(), x => x + 1, (int x) => x, u => u, async (u, v) => u + v);
+";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "F(x => x + 1, 1, y => y + 1, delegate(int x) { return x; }, async u => u);", "F(y => y + 1, G(), x => x + 1, (int x) => x, u => u, async (u, v) => u + v);" },
+ { "x => x + 1", "x => x + 1" },
+ { "y => y + 1", "y => y + 1" },
+ { "delegate(int x) { return x; }", "(int x) => x" },
+ { "async u => u", "async (u, v) => u + v" },
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact, WorkItem(830419, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/830419")]
+ public void Lambdas2b()
+ {
+ var src1 = @"
+F(delegate { return x; });
+";
+ var src2 = @"
+F((a) => x, () => x);
+";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "F(delegate { return x; });", "F((a) => x, () => x);" },
+ { "delegate { return x; }", "() => x" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas3()
+ {
+ var src1 = @"
+a += async u => u;
+";
+ var src2 = @"
+a += u => u;
+";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "a += async u => u;", "a += u => u;" },
+ { "async u => u", "u => u" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas4()
+ {
+ var src1 = @"
+foreach (var a in z)
+{
+ var e = from q in a.Where(l => l > 10) select q + 1;
+}
+";
+ var src2 = @"
+foreach (var a in z)
+{
+ var e = from q in a.Where(l => l < 0) select q + 1;
+}
+";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "foreach (var a in z) { var e = from q in a.Where(l => l > 10) select q + 1; }", "foreach (var a in z) { var e = from q in a.Where(l => l < 0) select q + 1; }" },
+ { "{ var e = from q in a.Where(l => l > 10) select q + 1; }", "{ var e = from q in a.Where(l => l < 0) select q + 1; }" },
+ { "var e = from q in a.Where(l => l > 10) select q + 1;", "var e = from q in a.Where(l => l < 0) select q + 1;" },
+ { "var e = from q in a.Where(l => l > 10) select q + 1", "var e = from q in a.Where(l => l < 0) select q + 1" },
+ { "e = from q in a.Where(l => l > 10) select q + 1", "e = from q in a.Where(l => l < 0) select q + 1" },
+ { "from q in a.Where(l => l > 10)", "from q in a.Where(l => l < 0)" },
+ { "l => l > 10", "l => l < 0" },
+ { "select q + 1", "select q + 1" }, // select clause
+ { "select q + 1", "select q + 1" } // query body
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas5()
+ {
+ var src1 = @"
+F(a => b => c => d);
+";
+ var src2 = @"
+F(a => b => c => d);
+";
+
+ var matches = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(matches);
+
+ var expected = new MatchingPairs
+ {
+ { "F(a => b => c => d);", "F(a => b => c => d);" },
+ { "a => b => c => d", "a => b => c => d" },
+ { "b => c => d", "b => c => d" },
+ { "c => d", "c => d" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas6()
+ {
+ var src1 = @"
+F(a => b => c => d);
+";
+ var src2 = @"
+F(a => G(b => H(c => I(d))));
+";
+
+ var matches = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(matches);
+
+ var expected = new MatchingPairs
+ {
+ { "F(a => b => c => d);", "F(a => G(b => H(c => I(d))));" },
+ { "a => b => c => d", "a => G(b => H(c => I(d)))" },
+ { "b => c => d", "b => H(c => I(d))" },
+ { "c => d", "c => I(d)" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Lambdas7()
+ {
+ var src1 = @"
+F(a =>
+{
+ F(c => /*1*/d);
+ F((u, v) =>
+ {
+ F((w) => c => /*2*/d);
+ F(p => p);
+ });
+});
+";
+ var src2 = @"
+F(a =>
+{
+ F(c => /*1*/d + 1);
+ F((u, v) =>
+ {
+ F((w) => c => /*2*/d + 1);
+ F(p => p*2);
+ });
+});
+";
+
+ var matches = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(matches);
+
+ var expected = new MatchingPairs
+ {
+ { "F(a => { F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); });",
+ "F(a => { F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); });" },
+ { "a => { F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); }",
+ "a => { F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); }" },
+ { "{ F(c => /*1*/d); F((u, v) => { F((w) => c => /*2*/d); F(p => p); }); }",
+ "{ F(c => /*1*/d + 1); F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }); }" },
+ { "F(c => /*1*/d);", "F(c => /*1*/d + 1);" },
+ { "c => /*1*/d", "c => /*1*/d + 1" },
+ { "F((u, v) => { F((w) => c => /*2*/d); F(p => p); });", "F((u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); });" },
+ { "(u, v) => { F((w) => c => /*2*/d); F(p => p); }", "(u, v) => { F((w) => c => /*2*/d + 1); F(p => p*2); }" },
+ { "{ F((w) => c => /*2*/d); F(p => p); }", "{ F((w) => c => /*2*/d + 1); F(p => p*2); }" },
+ { "F((w) => c => /*2*/d);", "F((w) => c => /*2*/d + 1);" },
+ { "(w) => c => /*2*/d", "(w) => c => /*2*/d + 1" },
+ { "c => /*2*/d", "c => /*2*/d + 1" },
+ { "F(p => p);", "F(p => p*2);" },
+ { "p => p", "p => p*2" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Local Functions
+
+ [Fact]
+ public void LocalFunctionDefinitions()
+ {
+ var src1 = @"
+(int a, string c) F1(int i) { return null; }
+(int a, int b) F2(int i) { return null; }
+(int a, int b, int c) F3(int i) { return null; }
+";
+
+ var src2 = @"
+(int a, int b) F1(int i) { return null; }
+(int a, int b, string c) F2(int i) { return null; }
+(int a, int b) F3(int i) { return null; }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "(int a, string c) F1(int i) { return null; }", "(int a, int b) F1(int i) { return null; }" },
+ { "{ return null; }", "{ return null; }" },
+ { "return null;", "return null;" },
+ { "(int a, int b) F2(int i) { return null; }", "(int a, int b, string c) F2(int i) { return null; }" },
+ { "{ return null; }", "{ return null; }" },
+ { "return null;", "return null;" },
+ { "(int a, int b, int c) F3(int i) { return null; }", "(int a, int b) F3(int i) { return null; }" },
+ { "{ return null; }", "{ return null; }" },
+ { "return null;", "return null;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region LINQ
+
+ [Fact]
+ public void Queries1()
+ {
+ var src1 = @"
+var q = from c in cars
+ from ud in users_details
+ from bd in bids
+ select 1;
+";
+ var src2 = @"
+var q = from c in cars
+ from bd in bids
+ from ud in users_details
+ select 2;
+";
+
+ var match = GetMethodMatch(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var q = from c in cars from ud in users_details from bd in bids select 1;", "var q = from c in cars from bd in bids from ud in users_details select 2;" },
+ { "var q = from c in cars from ud in users_details from bd in bids select 1", "var q = from c in cars from bd in bids from ud in users_details select 2" },
+ { "q = from c in cars from ud in users_details from bd in bids select 1", "q = from c in cars from bd in bids from ud in users_details select 2" },
+ { "from c in cars", "from c in cars" },
+ { "from ud in users_details from bd in bids select 1", "from bd in bids from ud in users_details select 2" },
+ { "from ud in users_details", "from ud in users_details" },
+ { "from bd in bids", "from bd in bids" },
+ { "select 1", "select 2" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Queries2()
+ {
+ var src1 = @"
+var q = from c in cars
+ from ud in users_details
+ from bd in bids
+ orderby c.listingOption descending
+ where a.userID == ud.userid
+ let images = from ai in auction_images
+ where ai.belongs_to == c.id
+ select ai
+ let bid = (from b in bids
+ orderby b.id descending
+ where b.carID == c.id
+ select b.bidamount).FirstOrDefault()
+ select bid;
+";
+ var src2 = @"
+var q = from c in cars
+ from ud in users_details
+ from bd in bids
+ orderby c.listingOption descending
+ where a.userID == ud.userid
+ let images = from ai in auction_images
+ where ai.belongs_to == c.id2
+ select ai + 1
+ let bid = (from b in bids
+ orderby b.id ascending
+ where b.carID == c.id2
+ select b.bidamount).FirstOrDefault()
+ select bid;
+";
+
+ var match = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid;",
+ "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid;" },
+ { "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid",
+ "var q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
+ { "q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid",
+ "q = from c in cars from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
+ { "from c in cars", "from c in cars" },
+ { "from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id select ai let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault() select bid", "from ud in users_details from bd in bids orderby c.listingOption descending where a.userID == ud.userid let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1 let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault() select bid" },
+ { "from ud in users_details", "from ud in users_details" },
+ { "from bd in bids", "from bd in bids" },
+ { "orderby c.listingOption descending", "orderby c.listingOption descending" },
+ { "c.listingOption descending", "c.listingOption descending" },
+ { "where a.userID == ud.userid", "where a.userID == ud.userid" },
+ { "let images = from ai in auction_images where ai.belongs_to == c.id select ai",
+ "let images = from ai in auction_images where ai.belongs_to == c.id2 select ai + 1" },
+ { "from ai in auction_images", "from ai in auction_images" },
+ { "where ai.belongs_to == c.id select ai", "where ai.belongs_to == c.id2 select ai + 1" },
+ { "where ai.belongs_to == c.id", "where ai.belongs_to == c.id2" },
+ { "select ai", "select ai + 1" },
+ { "let bid = (from b in bids orderby b.id descending where b.carID == c.id select b.bidamount).FirstOrDefault()",
+ "let bid = (from b in bids orderby b.id ascending where b.carID == c.id2 select b.bidamount).FirstOrDefault()" },
+ { "from b in bids", "from b in bids" },
+ { "orderby b.id descending where b.carID == c.id select b.bidamount", "orderby b.id ascending where b.carID == c.id2 select b.bidamount" },
+ { "orderby b.id descending", "orderby b.id ascending" },
+ { "b.id descending", "b.id ascending" },
+ { "where b.carID == c.id", "where b.carID == c.id2" },
+ { "select b.bidamount", "select b.bidamount" },
+ { "select bid", "select bid" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Queries3()
+ {
+ var src1 = @"
+var q = from a in await seq1
+ join c in await seq2 on F(u => u) equals G(s => s) into g1
+ join l in await seq3 on F(v => v) equals G(t => t) into g2
+ select a;
+
+";
+ var src2 = @"
+var q = from a in await seq1
+ join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1
+ join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2
+ select a + 1;
+";
+
+ var match = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "var q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a;", "var q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1;" },
+ { "var q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "var q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
+ { "q = from a in await seq1 join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "q = from a in await seq1 join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
+ { "from a in await seq1", "from a in await seq1" },
+ { "await seq1", "await seq1" },
+ { "join c in await seq2 on F(u => u) equals G(s => s) into g1 join l in await seq3 on F(v => v) equals G(t => t) into g2 select a", "join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1 join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2 select a + 1" },
+ { "join c in await seq2 on F(u => u) equals G(s => s) into g1", "join c in await seq2 on F(u => u + 1) equals G(s => s + 3) into g1" },
+ { "await seq2", "await seq2" },
+ { "u => u", "u => u + 1" },
+ { "s => s", "s => s + 3" },
+ { "into g1", "into g1" },
+ { "join l in await seq3 on F(v => v) equals G(t => t) into g2", "join c in await seq3 on F(vv => vv + 2) equals G(tt => tt + 4) into g2" },
+ { "await seq3", "await seq3" },
+ { "v => v", "vv => vv + 2" },
+ { "t => t", "tt => tt + 4" },
+ { "into g2", "into g2" },
+ { "select a", "select a + 1" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Queries4()
+ {
+ var src1 = "F(from a in await b from x in y select c);";
+ var src2 = "F(from a in await c from x in y select c);";
+
+ var match = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "F(from a in await b from x in y select c);", "F(from a in await c from x in y select c);" },
+ { "from a in await b", "from a in await c" },
+ { "await b", "await c" },
+ { "from x in y select c", "from x in y select c" },
+ { "from x in y", "from x in y" },
+ { "select c", "select c" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void Queries5()
+ {
+ var src1 = "F(from a in b group a by a.x into g select g);";
+ var src2 = "F(from a in b group z by z.y into h select h);";
+
+ var match = GetMethodMatches(src1, src2);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "F(from a in b group a by a.x into g select g);", "F(from a in b group z by z.y into h select h);" },
+ { "from a in b", "from a in b" },
+ { "group a by a.x into g select g", "group z by z.y into h select h" },
+ { "group a by a.x", "group z by z.y" },
+ { "into g select g", "into h select h" },
+ { "select g", "select h" },
+ { "select g", "select h" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Iterators
+
+ [Fact]
+ public void Yields()
+ {
+ var src1 = @"
+yield return /*1*/ 1;
+
+{
+ yield return /*2*/ 2;
+}
+
+foreach (var x in y) { yield return /*3*/ 3; }
+";
+ var src2 = @"
+yield return /*1*/ 1;
+yield return /*2*/ 3;
+foreach (var x in y) { yield return /*3*/ 2; }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Iterator);
+ var actual = ToMatchingPairs(match);
+
+ // note that yield returns are matched in source order, regardless of the yielded expressions:
+ var expected = new MatchingPairs
+ {
+ { "yield return /*1*/ 1;", "yield return /*1*/ 1;" },
+ { "{ yield return /*2*/ 2; }", "{ yield return /*3*/ 2; }" },
+ { "yield return /*2*/ 2;", "yield return /*2*/ 3;" },
+ { "foreach (var x in y) { yield return /*3*/ 3; }", "foreach (var x in y) { yield return /*3*/ 2; }" },
+ { "yield return /*3*/ 3;", "yield return /*3*/ 2;" },
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Constructors
+
+ [Fact]
+ public void ConstructorWithInitializer1()
+ {
+ var src1 = @"
+(int x = 1) : base(a => a + 1) { Console.WriteLine(1); }
+";
+ var src2 = @"
+(int x = 1) : base(a => a + 1) { Console.WriteLine(1); }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.ConstructorWithParameters);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "a => a + 1", "a => a + 1" },
+ { "{ Console.WriteLine(1); }", "{ Console.WriteLine(1); }" },
+ { "Console.WriteLine(1);", "Console.WriteLine(1);" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ConstructorWithInitializer2()
+ {
+ var src1 = @"
+() : base(a => a + 1) { Console.WriteLine(1); }
+";
+ var src2 = @"
+() { Console.WriteLine(1); }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.ConstructorWithParameters);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "{ Console.WriteLine(1); }", "{ Console.WriteLine(1); }" },
+ { "Console.WriteLine(1);", "Console.WriteLine(1);" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Exception Handlers
+
+ [Fact]
+ public void ExceptionHandlers()
+ {
+ var src1 = @"
+try { throw new InvalidOperationException(1); }
+catch (IOException e) when (filter(e)) { Console.WriteLine(2); }
+catch (Exception e) when (filter(e)) { Console.WriteLine(3); }
+";
+ var src2 = @"
+try { throw new InvalidOperationException(10); }
+catch (IOException e) when (filter(e)) { Console.WriteLine(20); }
+catch (Exception e) when (filter(e)) { Console.WriteLine(30); }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "try { throw new InvalidOperationException(1); } catch (IOException e) when (filter(e)) { Console.WriteLine(2); } catch (Exception e) when (filter(e)) { Console.WriteLine(3); }", "try { throw new InvalidOperationException(10); } catch (IOException e) when (filter(e)) { Console.WriteLine(20); } catch (Exception e) when (filter(e)) { Console.WriteLine(30); }" },
+ { "{ throw new InvalidOperationException(1); }", "{ throw new InvalidOperationException(10); }" },
+ { "throw new InvalidOperationException(1);", "throw new InvalidOperationException(10);" },
+ { "catch (IOException e) when (filter(e)) { Console.WriteLine(2); }", "catch (IOException e) when (filter(e)) { Console.WriteLine(20); }" },
+ { "(IOException e)", "(IOException e)" },
+ { "when (filter(e))", "when (filter(e))" },
+ { "{ Console.WriteLine(2); }", "{ Console.WriteLine(20); }" },
+ { "Console.WriteLine(2);", "Console.WriteLine(20);" },
+ { "catch (Exception e) when (filter(e)) { Console.WriteLine(3); }", "catch (Exception e) when (filter(e)) { Console.WriteLine(30); }" },
+ { "(Exception e)", "(Exception e)" },
+ { "when (filter(e))", "when (filter(e))" },
+ { "{ Console.WriteLine(3); }", "{ Console.WriteLine(30); }" },
+ { "Console.WriteLine(3);", "Console.WriteLine(30);" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Foreach
+
+ [Fact]
+ public void ForeachVariable_Update1()
+ {
+ var src1 = @"
+foreach (var (a1, a2) in e) { A1(); }
+foreach ((var b1, var b2) in e) { A2(); }
+";
+
+ var src2 = @"
+foreach (var (a1, a3) in e) { A1(); }
+foreach ((var b3, int b2) in e) { A2(); }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "foreach (var (a1, a2) in e) { A1(); }", "foreach (var (a1, a3) in e) { A1(); }" },
+ { "a1", "a1" },
+ { "a2", "a3" },
+ { "{ A1(); }", "{ A1(); }" },
+ { "A1();", "A1();" },
+ { "foreach ((var b1, var b2) in e) { A2(); }", "foreach ((var b3, int b2) in e) { A2(); }" },
+ { "b1", "b3" },
+ { "b2", "b2" },
+ { "{ A2(); }", "{ A2(); }" },
+ { "A2();", "A2();" },
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ForeachVariable_Update2()
+ {
+ var src1 = @"
+foreach (_ in e2) { yield return 4; }
+foreach (_ in e3) { A(); }
+";
+
+ var src2 = @"
+foreach (_ in e4) { A(); }
+foreach (var b in e2) { yield return 4; }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "foreach (_ in e2) { yield return 4; }", "foreach (var b in e2) { yield return 4; }" },
+ { "{ yield return 4; }", "{ yield return 4; }" },
+ { "yield return 4;", "yield return 4;" },
+ { "foreach (_ in e3) { A(); }", "foreach (_ in e4) { A(); }" },
+ { "{ A(); }", "{ A(); }" },
+ { "A();", "A();" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ForeachVariable_Insert()
+ {
+ var src1 = @"
+foreach (var (a3, a4) in e) { }
+foreach ((var b4, var b5) in e) { }
+";
+
+ var src2 = @"
+foreach (var (a3, a5, a4) in e) { }
+foreach ((var b6, var b4, var b5) in e) { }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "foreach (var (a3, a4) in e) { }", "foreach (var (a3, a5, a4) in e) { }" },
+ { "a3", "a3" },
+ { "a4", "a4" },
+ { "{ }", "{ }" },
+ { "foreach ((var b4, var b5) in e) { }", "foreach ((var b6, var b4, var b5) in e) { }" },
+ { "b4", "b4" },
+ { "b5", "b5" },
+ { "{ }", "{ }" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void ForeachVariable_Delete()
+ {
+ var src1 = @"
+foreach (var (a11, a12, a13) in e) { A1(); }
+foreach ((var b7, var b8, var b9) in e) { A2(); }
+";
+
+ var src2 = @"
+foreach (var (a12, a13) in e1) { A1(); }
+foreach ((var b7, var b9) in e) { A2(); }
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "foreach (var (a11, a12, a13) in e) { A1(); }", "foreach (var (a12, a13) in e1) { A1(); }" },
+ { "a12", "a12" },
+ { "a13", "a13" },
+ { "{ A1(); }", "{ A1(); }" },
+ { "A1();", "A1();" },
+ { "foreach ((var b7, var b8, var b9) in e) { A2(); }", "foreach ((var b7, var b9) in e) { A2(); }" },
+ { "b7", "b7" },
+ { "b9", "b9" },
+ { "{ A2(); }", "{ A2(); }" },
+ { "A2();", "A2();" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+
+ #region Patterns
+
+ [Fact]
+ public void ConstantPattern()
+ {
+ var src1 = @"
+if ((o is null) && (y == 7)) return 3;
+if (a is 7) return 5;
+";
+
+ var src2 = @"
+if ((o1 is null) && (y == 7)) return 3;
+if (a is 77) return 5;
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs {
+ { "if ((o is null) && (y == 7)) return 3;", "if ((o1 is null) && (y == 7)) return 3;" },
+ { "return 3;", "return 3;" },
+ { "if (a is 7) return 5;", "if (a is 77) return 5;" },
+ { "return 5;", "return 5;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void DeclarationPattern()
+ {
+ var src1 = @"
+if (!(o is int i) && (y == 7)) return;
+if (!(a is string s)) return;
+if (!(b is string t)) return;
+if (!(c is int j)) return;
+";
+
+ var src2 = @"
+if (!(b is string t1)) return;
+if (!(o1 is int i) && (y == 7)) return;
+if (!(c is int)) return;
+if (!(a is int s)) return;
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs {
+ { "if (!(o is int i) && (y == 7)) return;", "if (!(o1 is int i) && (y == 7)) return;" },
+ { "i", "i" },
+ { "return;", "return;" },
+ { "if (!(a is string s)) return;", "if (!(a is int s)) return;" },
+ { "s", "s" },
+ { "return;", "return;" },
+ { "if (!(b is string t)) return;", "if (!(b is string t1)) return;" },
+ { "t", "t1" },
+ { "return;", "return;" },
+ { "if (!(c is int j)) return;", "if (!(c is int)) return;" },
+ { "return;", "return;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void CasePattern_UpdateInsert()
+ {
+ var src1 = @"
+switch(shape)
+{
+ case Circle c: return 1;
+ default: return 4;
+}
+";
+
+ var src2 = @"
+switch(shape)
+{
+ case Circle c1: return 1;
+ case Point p: return 0;
+ default: return 4;
+}
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs {
+ { "switch(shape) { case Circle c: return 1; default: return 4; }", "switch(shape) { case Circle c1: return 1; case Point p: return 0; default: return 4; }" },
+ { "case Circle c: return 1;", "case Circle c1: return 1;" },
+ { "case Circle c:", "case Circle c1:" },
+ { "c", "c1" },
+ { "return 1;", "return 1;" },
+ { "default: return 4;", "default: return 4;" },
+ { "return 4;", "return 4;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void CasePattern_UpdateDelete()
+ {
+ var src1 = @"
+switch(shape)
+{
+ case Point p: return 0;
+ case Circle c: return 1;
+}
+";
+
+ var src2 = @"
+switch(shape)
+{
+ case Circle circle: return 1;
+}
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs {
+ { "switch(shape) { case Point p: return 0; case Circle c: return 1; }", "switch(shape) { case Circle circle: return 1; }" },
+ { "case Circle c: return 1;", "case Circle circle: return 1;" },
+ { "case Circle c:", "case Circle circle:" },
+ { "c", "circle" },
+ { "return 1;", "return 1;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ [Fact]
+ public void WhenCondition()
+ {
+ var src1 = @"
+switch(shape)
+{
+ case Circle c when (c < 10): return 1;
+ case Circle c when (c > 100): return 2;
+}
+";
+
+ var src2 = @"
+switch(shape)
+{
+ case Circle c when (c < 5): return 1;
+ case Circle c2 when (c2 > 100): return 2;
+}
+";
+
+ var match = GetMethodMatches(src1, src2, kind: MethodKind.Regular);
+ var actual = ToMatchingPairs(match);
+
+ var expected = new MatchingPairs
+ {
+ { "switch(shape) { case Circle c when (c < 10): return 1; case Circle c when (c > 100): return 2; }", "switch(shape) { case Circle c when (c < 5): return 1; case Circle c2 when (c2 > 100): return 2; }" },
+ { "case Circle c when (c < 10): return 1;", "case Circle c when (c < 5): return 1;" },
+ { "case Circle c when (c < 10):", "case Circle c when (c < 5):" },
+ { "c", "c" },
+ { "when (c < 10)", "when (c < 5)" },
+ { "return 1;", "return 1;" },
+ { "case Circle c when (c > 100): return 2;", "case Circle c2 when (c2 > 100): return 2;" },
+ { "case Circle c when (c > 100):", "case Circle c2 when (c2 > 100):" },
+ { "c", "c2" },
+ { "when (c > 100)", "when (c2 > 100)" },
+ { "return 2;", "return 2;" }
+ };
+
+ expected.AssertEqual(actual);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditTopLevelTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
similarity index 99%
rename from src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditTopLevelTests.cs
rename to src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
index d2aa6170d44f5cfb9ec61e750aaabff02584df4a..5a291a6904ca38061c6f8b07621024429c8ad6f6 100644
--- a/src/EditorFeatures/CSharpTest/EditAndContinue/RudeEditTopLevelTests.cs
+++ b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs
@@ -12,7 +12,7 @@
namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests
{
- public class RudeEditTopLevelTests : RudeEditTestBase
+ public class TopLevelEditingTests : EditingTestBase
{
#region Usings