diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs index 5618ffc8b342..4f4d3c84cdba 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/EditAndContinue/EditAndContinueClosureTests.cs @@ -9850,5 +9850,103 @@ .maxstack 8 }) .Verify(); } + + /// + /// Some lambda rude edits are simpler to detect in the IDE. They are specified via . + /// The IDE tests cover the specific cases. + /// + [Fact] + public void IdeDetectedRuntimeRudeEdit() + { + using var _ = new EditAndContinueTest() + .AddBaseline( + source: """ + using System; + class C + { + public void F() + { + _ = new Func(() => 1); + } + } + """, + validator: g => + { + g.VerifySynthesizedMembers(displayTypeKind: true, + [ + "class C: {<>c}", + "class C.<>c: {<>9__0_0, b__0_0}" + ]); + }) + + .AddGeneration( + source: """ + using System; + class C + { + public void F() + { + _ = new Func(() => 1.0); + } + } + """, + edits: + [ + Edit(SemanticEditKind.Update, c => c.GetMember("C.F"), preserveLocalVariables: true, rudeEdits: _ => new RuntimeRudeEdit("Return type changed", 0x123)), + ], + validator: g => + { + g.VerifySynthesizedMembers( + "System.Runtime.CompilerServices.HotReloadException", + "C: {<>c}", + "C.<>c: {<>9__0_0#1, b__0_0#1}"); + + g.VerifyMethodDefNames( + "F", "b__0_0", ".ctor", "b__0_0#1"); + + g.VerifyIL( + """ + { + // Code size 30 (0x1e) + .maxstack 8 + IL_0000: nop + IL_0001: ldsfld 0x04000004 + IL_0006: brtrue.s IL_001d + IL_0008: ldsfld 0x04000001 + IL_000d: ldftn 0x06000007 + IL_0013: newobj 0x0A000008 + IL_0018: stsfld 0x04000004 + IL_001d: ret + } + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: ldstr 0x70000005 + IL_0005: ldc.i4 0x123 + IL_000a: newobj 0x06000006 + IL_000f: throw + } + { + // Code size 16 (0x10) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call 0x0A000009 + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldarg.2 + IL_000a: stfld 0x04000003 + IL_000f: ret + } + { + // Code size 10 (0xa) + .maxstack 8 + IL_0000: ldc.r8 1 + IL_0009: ret + } + """); + }) + .Verify(); + } } } diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb index 5d0139f6947f..8c83f670a045 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/EditAndContinue/EditAndContinueClosureTests.vb @@ -6,7 +6,9 @@ Imports System.Collections.Immutable Imports System.Reflection.Metadata.Ecma335 Imports Microsoft.CodeAnalysis.EditAndContinue.UnitTests Imports Microsoft.CodeAnalysis.Emit +Imports Microsoft.CodeAnalysis.Operations Imports Microsoft.CodeAnalysis.Test.Utilities +Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Roslyn.Test.Utilities @@ -3947,6 +3949,100 @@ End Class IL_0011: ldloc.0 IL_0012: ret } +") + End Sub). + Verify() + End Using + End Sub + + ''' + ''' Some lambda rude edits are simpler to detect in the IDE. They are specified via . + ''' The IDE tests cover the specific cases. + ''' + + Public Sub IdeDetectedRuntimeRudeEdit() + Using test = New EditAndContinueTest() + test.AddBaseline( + source:=" +Imports System +Class C + Sub F() + Dim f1 = New Func(Of Integer)(Function() 1) + End Sub +End Class +", + validator:= + Sub(g) + g.VerifySynthesizedMembers( + "C._Closure$__: {$I1-0, _Lambda$__1-0}", + "C: {_Closure$__}") + End Sub). + AddGeneration( + source:=" +Imports System +Class C + Sub F() + Dim f1 = New Func(Of Double)(Function() 1.0) + End Sub +End Class +", + edits:={Edit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), preserveLocalVariables:=True, + rudeEdits:=Function(node) New RuntimeRudeEdit("Return type changed", &H123))}, + validator:= + Sub(g) + g.VerifySynthesizedMembers( + "System.Runtime.CompilerServices.HotReloadException", + "C: {_Closure$__}", + "C._Closure$__: {$I1-0#1, _Lambda$__1-0#1}") + + g.VerifyMethodDefNames("F", "_Lambda$__1-0", ".ctor", "_Lambda$__1-0#1") + + g.VerifyIL(" +{ + // Code size 39 (0x27) + .maxstack 2 + IL_0000: nop + IL_0001: ldsfld 0x04000004 + IL_0006: brfalse.s IL_000f + IL_0008: ldsfld 0x04000004 + IL_000d: br.s IL_0025 + IL_000f: ldsfld 0x04000001 + IL_0014: ldftn 0x06000007 + IL_001a: newobj 0x0A000008 + IL_001f: dup + IL_0020: stsfld 0x04000004 + IL_0025: stloc.1 + IL_0026: ret +} +{ + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldstr 0x70000005 + IL_0005: ldc.i4.m1 + IL_0006: newobj 0x06000006 + IL_000b: throw +} +{ + // Code size 15 (0xf) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: call 0x0A000009 + IL_0007: ldarg.0 + IL_0008: ldarg.2 + IL_0009: stfld 0x04000003 + IL_000e: ret +} +{ + // Code size 15 (0xf) + .maxstack 1 + IL_0000: nop + IL_0001: ldc.r8 1 + IL_000a: stloc.0 + IL_000b: br.s IL_000d + IL_000d: ldloc.0 + IL_000e: ret +} ") End Sub). Verify() diff --git a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs index 16d3ce94a3b6..8fd0aa6a53a1 100644 --- a/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs +++ b/src/Features/CSharp/Portable/EditAndContinue/CSharpEditAndContinueAnalyzer.cs @@ -1865,7 +1865,8 @@ private static bool GroupBySignatureEquivalent(IMethodSymbol? oldMethod, IMethod return ((AnonymousObjectCreationExpressionSyntax)node).NewKeyword.Span; case SyntaxKind.ParenthesizedLambdaExpression: - return ((ParenthesizedLambdaExpressionSyntax)node).ParameterList.Span; + var parenthesizedLambda = (ParenthesizedLambdaExpressionSyntax)node; + return CombineSpans(parenthesizedLambda.ReturnType?.Span ?? default, parenthesizedLambda.ParameterList.Span, defaultSpan: default); case SyntaxKind.SimpleLambdaExpression: return ((SimpleLambdaExpressionSyntax)node).Parameter.Span; diff --git a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs index ca9091ad4a27..a72b9fb5894b 100644 --- a/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/ActiveStatementTests.cs @@ -10203,7 +10203,6 @@ static void Main(string[] args) var active = GetActiveStatements(src1, src2); edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "b", GetResource("lambda")), Diagnostic(RudeEditKind.ActiveStatementLambdaRemoved, "F(b);", GetResource("lambda"))); } diff --git a/src/Features/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs b/src/Features/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs index 02a6242602f2..09d4cd4e4559 100644 --- a/src/Features/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs +++ b/src/Features/CSharpTest/EditAndContinue/Helpers/EditAndContinueValidation.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests; internal static class EditAndContinueValidation { internal static void VerifyLineEdits( - this EditScript editScript, + this EditScriptDescription editScript, SourceLineUpdate[] lineEdits, SemanticEditDescription[]? semanticEdits = null, RudeEditDiagnosticDescription[]? diagnostics = null, @@ -31,7 +31,7 @@ internal static void VerifyLineEdits( } internal static void VerifyLineEdits( - this EditScript editScript, + this EditScriptDescription editScript, SequencePointUpdates[] lineEdits, SemanticEditDescription[]? semanticEdits = null, RudeEditDiagnosticDescription[]? diagnostics = null, @@ -46,14 +46,14 @@ internal static void VerifyLineEdits( } internal static void VerifySemanticDiagnostics( - this EditScript editScript, + this EditScriptDescription editScript, params RudeEditDiagnosticDescription[] diagnostics) { VerifySemanticDiagnostics(editScript, activeStatements: null, targetFrameworks: null, capabilities: null, diagnostics); } internal static void VerifySemanticDiagnostics( - this EditScript editScript, + this EditScriptDescription editScript, ActiveStatementsDescription activeStatements, params RudeEditDiagnosticDescription[] diagnostics) { @@ -61,7 +61,7 @@ internal static void VerifySemanticDiagnostics( } internal static void VerifySemanticDiagnostics( - this EditScript editScript, + this EditScriptDescription editScript, RudeEditDiagnosticDescription[] diagnostics, EditAndContinueCapabilities? capabilities) { @@ -69,7 +69,7 @@ internal static void VerifySemanticDiagnostics( } internal static void VerifySemanticDiagnostics( - this EditScript editScript, + this EditScriptDescription editScript, ActiveStatementsDescription? activeStatements = null, TargetFramework[]? targetFrameworks = null, EditAndContinueCapabilities? capabilities = null, @@ -83,7 +83,7 @@ [new DocumentAnalysisResultsDescription(activeStatements: activeStatements, diag } internal static void VerifySemantics( - this EditScript editScript, + this EditScriptDescription editScript, ActiveStatementsDescription activeStatements, SemanticEditDescription[] semanticEdits, EditAndContinueCapabilities? capabilities = null) @@ -95,7 +95,7 @@ [new DocumentAnalysisResultsDescription(activeStatements, semanticEdits: semanti } internal static void VerifySemantics( - this EditScript editScript, + this EditScriptDescription editScript, SemanticEditDescription[] semanticEdits, EditAndContinueCapabilities capabilities) { @@ -103,14 +103,14 @@ internal static void VerifySemantics( } internal static void VerifySemantics( - this EditScript editScript, + this EditScriptDescription editScript, params SemanticEditDescription[] semanticEdits) { VerifySemantics(editScript, ActiveStatementsDescription.Empty, semanticEdits, capabilities: null); } internal static void VerifySemantics( - this EditScript editScript, + this EditScriptDescription editScript, SemanticEditDescription[] semanticEdits, RudeEditDiagnosticDescription[] warnings, EditAndContinueCapabilities? capabilities = null) @@ -122,7 +122,7 @@ [new DocumentAnalysisResultsDescription(ActiveStatementsDescription.Empty, seman } internal static void VerifySemantics( - EditScript[] editScripts, + EditScriptDescription[] editScripts, DocumentAnalysisResultsDescription[] results, TargetFramework[]? targetFrameworks = null, EditAndContinueCapabilities? capabilities = null) diff --git a/src/Features/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs b/src/Features/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs index effc20078181..54dd440d1f2a 100644 --- a/src/Features/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs +++ b/src/Features/CSharpTest/EditAndContinue/Helpers/EditingTestBase.cs @@ -87,6 +87,10 @@ public static string GetResource(string keyword) "where clause" => CSharpFeaturesResources.where_clause, "select clause" => CSharpFeaturesResources.select_clause, "groupby clause" => CSharpFeaturesResources.groupby_clause, + "orderby clause" => CSharpFeaturesResources.orderby_clause, + "join clause" => CSharpFeaturesResources.join_clause, + "from clause" => CSharpFeaturesResources.from_clause, + "let clause" => CSharpFeaturesResources.let_clause, "top-level statement" => CSharpFeaturesResources.top_level_statement, "top-level code" => CSharpFeaturesResources.top_level_code, "class with explicit or sequential layout" => string.Format(FeaturesResources.class_with_explicit_or_sequential_layout), @@ -98,8 +102,11 @@ public static string GetResource(string keyword) internal static RudeEditDiagnosticDescription Diagnostic(RudeEditKind rudeEditKind, string squiggle, params string[] arguments) => new(rudeEditKind, squiggle, arguments, firstLine: null); - internal static RuntimeRudeEditDescription RuntimeRudeEdit(int marker, RudeEditKind rudeEditKind, (int displayLine, int displayColumn) position, params string[] arguments) - => new(marker, rudeEditKind, new LinePosition(position.displayLine - 1, position.displayColumn - 1), arguments); + internal static RuntimeRudeEditDescription RuntimeRudeEdit(int marker, RudeEditKind rudeEditKind, LinePosition position, params string[] arguments) + => new(marker, rudeEditKind, position, arguments); + + internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, SyntaxMapDescription.Mapping? syntaxMap, IEnumerable? rudeEdits = null, string? partialType = null) + => SemanticEdit(kind, symbolProvider, syntaxMap?.Spans, rudeEdits, partialType); internal static SemanticEditDescription SemanticEdit(SemanticEditKind kind, Func symbolProvider, IEnumerable<(TextSpan, TextSpan)>? syntaxMap, IEnumerable? rudeEdits = null, string? partialType = null) => new(kind, symbolProvider, (partialType != null) ? c => c.GetMember(partialType) : null, syntaxMap, rudeEdits, hasSyntaxMap: syntaxMap != null, deletedSymbolContainerProvider: null); @@ -125,7 +132,10 @@ private static SyntaxTree ParseSource(string markedSource, int documentIndex = 0 CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp12), path: GetDocumentFilePath(documentIndex)); - internal static EditScript GetTopEdits(string src1, string src2, int documentIndex = 0) + internal static EditScriptDescription GetTopEdits(string methodBody1, string methodBody2, MethodKind kind) + => GetTopEdits(WrapMethodBodyWithClass(methodBody1, kind), WrapMethodBodyWithClass(methodBody2, kind)); + + internal static EditScriptDescription GetTopEdits(string src1, string src2, int documentIndex = 0) { var tree1 = ParseSource(src1, documentIndex); var tree2 = ParseSource(src2, documentIndex); @@ -134,10 +144,10 @@ internal static EditScript GetTopEdits(string src1, string src2, int tree2.GetDiagnostics().Verify(); var match = SyntaxComparer.TopLevel.ComputeMatch(tree1.GetRoot(), tree2.GetRoot()); - return match.GetTreeEdits(); + return new(src1, src2, match.GetTreeEdits()); } - public static EditScript GetTopEdits(EditScript methodEdits) + internal static EditScriptDescription GetTopEdits(EditScriptDescription methodEdits) { var oldMethodSource = methodEdits.Match.OldRoot.ToFullString(); var newMethodSource = methodEdits.Match.NewRoot.ToFullString(); @@ -148,10 +158,10 @@ public static EditScript GetTopEdits(EditScript methodEd /// /// Gets method edits on the current level of the source hierarchy. This means that edits on lower labeled levels of the hierarchy are not expected to be returned. /// - internal static EditScript GetMethodEdits(string src1, string src2, MethodKind kind = MethodKind.Regular) + internal static EditScriptDescription GetMethodEdits(string src1, string src2, MethodKind kind = MethodKind.Regular) { var match = GetMethodMatch(src1, src2, kind); - return match.GetTreeEdits(); + return new(src1, src2, match.GetTreeEdits()); } internal static Match GetMethodMatch(string src1, string src2, MethodKind kind = MethodKind.Regular) @@ -227,7 +237,7 @@ internal static ActiveStatementsDescription GetActiveStatements(string oldSource internal static SyntaxMapDescription GetSyntaxMap(string oldSource, string newSource) => new(oldSource, newSource); - internal static void VerifyPreserveLocalVariables(EditScript edits, bool preserveLocalVariables) + internal static void VerifyPreserveLocalVariables(EditScriptDescription edits, bool preserveLocalVariables) { var oldDeclaration = (MethodDeclarationSyntax)((ClassDeclarationSyntax)((CompilationUnitSyntax)edits.Match.OldRoot).Members[0]).Members[0]; var oldBody = SyntaxUtilities.TryGetDeclarationBody(oldDeclaration, symbol: null); diff --git a/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs b/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs index 69596b3e5d0c..1911e5715d73 100644 --- a/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/StatementEditingTests.cs @@ -3183,7 +3183,7 @@ void G2(Func f) {} void F() { - G1(a => a); + G1(a => a); } } "; @@ -3197,14 +3197,18 @@ void G2(Func f) {} void F() { - G2(a => a); + G2(a => a); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "a", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3220,7 +3224,7 @@ void G2(Func f) {} void F() { - G1(a => a); + G1(a => a); } } "; @@ -3234,14 +3238,18 @@ void G2(Func f) {} void F() { - G2((a, b) => a + b); + G2((a, b) => a + b); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "(a, b)", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3257,7 +3265,7 @@ void G2(Func f) {} void F() { - G1(a => a); + G1(a => a); } } "; @@ -3271,14 +3279,18 @@ void G2(Func f) {} void F() { - G2(a => a); + G2(a => a); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "a", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3366,7 +3378,7 @@ void G2(Action f) {} void F() { - G1(a => { return 1; }); + G1(a => { return 1; }); } } "; @@ -3380,26 +3392,59 @@ void G2(Action f) {} void F() { - G2(a => { }); + G2(a => { }); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "a", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] public void Lambdas_Update_Signature_ReturnType2() { - var src1 = "var x = int (int a) => a;"; - var src2 = "var x = long (int a) => a;"; + var src1 = @" +using System; - var edits = GetMethodEdits(src1, src2); +class C +{ + void G1(Func f) {} + void G2(Action f) {} - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "(int a)", CSharpFeaturesResources.lambda)); + void F() + { + var x = int (int a) => a; + } +} +"; + var src2 = @" +using System; + +class C +{ + void G1(Func f) {} + void G2(Action f) {} + + void F() + { + var x = long (int a) => a; + } +} +"; + var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3412,7 +3457,7 @@ class C { void F() { - var x = (int* a, int b) => a; + var x = (int* a, int b) => a; } } "; @@ -3423,14 +3468,18 @@ class C { void F() { - var x = (int* a, int b) => b; + var x = (int* a, int b) => b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "(int* a, int b)", GetResource("lambda"))); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3521,7 +3570,7 @@ void G2(D2 f) {} void F() { - G1((ref int a) => 1); + G1((ref int a) => 1); } } "; @@ -3538,14 +3587,18 @@ void G2(D2 f) {} void F() { - G2((int a) => 2); + G2((int a) => 2); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "(int a)", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3729,7 +3782,7 @@ void G2(Func f) {} void F() { - G1(a => 1); + G1(a => 1); } } "; @@ -3743,14 +3796,18 @@ void G2(Func f) {} void F() { - G2(a => 2); + G2(a => 2); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "a", CSharpFeaturesResources.lambda)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3853,7 +3910,7 @@ void G2(D2 f) {} void F() { - G1(a => a); + G1(a => a); } } "; @@ -3872,13 +3929,18 @@ void G2(D2 f) {} void F() { - G2(a => a); + G2(a => a); } } "; var edits = GetTopEdits(src1, src2); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "a", CSharpFeaturesResources.lambda)); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3899,7 +3961,7 @@ void G2(D2 f) {} void F() { - G1(a => a); + G1(a => a); } } } @@ -3919,14 +3981,19 @@ void G2(D2 f) {} void F() { - G2(a => a); + G2(a => a); } } } "; var edits = GetTopEdits(src1, src2); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "a", CSharpFeaturesResources.lambda)); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("System.C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), arguments: [GetResource("lambda")]) + ])); } [Fact] @@ -3980,7 +4047,7 @@ void G2(D2 f) {} void F() { - G1((a, b) => 1); + G1((a, b) => 1); } } "; @@ -3995,13 +4062,18 @@ void G2(D2 f) {} void F() { - G2((a, b) => 1); + G2((a, b) => 1); } } "; var edits = GetTopEdits(src1, src2); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "(a, b)", CSharpFeaturesResources.lambda)); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), [GetResource("lambda")])]), + ]); } [Fact] @@ -6011,18 +6083,18 @@ class C { static void F() { - int X = 1; + int X = 1; Func f = () => X; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( - SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap[0], rudeEdits: + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: [ - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (8, 13), ["x", "X"]) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"]) ])); } @@ -6036,7 +6108,7 @@ class C { static void F() { - int x = 1; + int x = 1; Func f = () => x; } }"; @@ -6047,19 +6119,20 @@ class C { static void F() { - byte x = 1; + byte x = 1; Func f = () => x; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); + edits.VerifySemantics( SemanticEdit( SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.ChangingCapturedVariableType, (8, 14), ["x", "int"])])); + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.ChangingCapturedVariableType, syntaxMap.Position(0), ["x", "int"])])); } [Fact] @@ -6080,19 +6153,19 @@ static void F(int x) class C { - static void F(int X) + static void F(int X) { Func f = () => X; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, (6, 23), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6114,16 +6187,16 @@ static void G(Func f) {} class C { static void G(Func f) {} - static void F(int X) => G(() => X); + static void F(int X) => G(() => X); }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, (7, 23), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6159,12 +6232,12 @@ static void F() }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, (8, 29), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, syntaxMap.NodePosition(1), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6198,12 +6271,12 @@ static void F() }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, (10, 39), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 2, RudeEditKind.RenamingCapturedVariable, syntaxMap.NodePosition(1), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6230,20 +6303,20 @@ class B(Func f); class C { - C(int X, int Y) : base(() => X) + C(int X, int Y) : base(() => X) { Func g = () => Y; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), syntaxMap, // only the first rude edit is reported for each node: - rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, (8, 16), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6263,16 +6336,16 @@ class B(Func f); class B(Func f); -class C(int X) : B(() => X); +class C(int X) : B(() => X); "; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2)[0]; + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C..ctor"), syntaxMap, - rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, (6, 18), ["x", "X"])]), + rudeEdits: [RuntimeRudeEdit(marker: 0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"])]), ], capabilities: EditAndContinueCapabilities.UpdateParameters); } @@ -6915,7 +6988,7 @@ class C void F() { - G(a => a); + G(a => a); } } "; @@ -6928,16 +7001,21 @@ class C void F() { - int localF(int a) { return a; } + int localF(int a) { return a; } G(localF); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - // To be removed when we will enable EnC for local functions - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.SwitchBetweenLambdaAndLocalFunction, "localF")); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.SwitchBetweenLambdaAndLocalFunction, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -6952,7 +7030,7 @@ class C void F() { - int localF(int a) { return a; } + int localF(int a) { return a; } G(localF); } } @@ -6966,15 +7044,19 @@ class C void F() { - G(a => a); + G(a => a); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.SwitchBetweenLambdaAndLocalFunction, "a")); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.SwitchBetweenLambdaAndLocalFunction, syntaxMap.NodePosition(0), arguments: []) + ])); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21499")] @@ -7479,7 +7561,7 @@ class C { void F() { - int f(int a) => a; + int f(int a) => a; } } "; @@ -7490,14 +7572,20 @@ class C { void F() { - long f(long a) => a; + long f(long a) => a; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "f", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -7510,7 +7598,7 @@ class C { void F() { - int f(int a) => a; + int f(int a) => a; } } "; @@ -7521,14 +7609,20 @@ class C { void F() { - int f(int a, int b) => a + b; + int f(int a, int b) => a + b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "f", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -7541,7 +7635,7 @@ class C { void F() { - int f(int a) => a; + int f(int a) => a; } } "; @@ -7552,14 +7646,20 @@ class C { void F() { - long f(int a) => a; + long f(int a) => a; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "f", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -7572,7 +7672,7 @@ class C { void F() { - int f(int a) { return 1; } + int f(int a) { return 1; } } } "; @@ -7583,14 +7683,20 @@ class C { void F() { - void f(int a) { } + void f(int a) { } } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "f", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -7667,7 +7773,7 @@ class C { void F() { - int f(ref int a) => 1; + int f(ref int a) => 1; } } "; @@ -7678,14 +7784,20 @@ class C { void F() { - int f(int a) => 2; + int f(int a) => 2; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "f", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -8718,19 +8830,19 @@ class C { static void F() { - int X = 1; + int X = 1; int f() => X; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ - SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap[0], rudeEdits: + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: [ - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (9, 13), ["x", "X"]) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"]) ]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition); @@ -8756,20 +8868,20 @@ static void F(int x) class C { - static void F(int X) + static void F(int X) { int f() => X; } }"; var edits = GetTopEdits(src1, src2); - var syntaxMap = GetSyntaxMap(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); edits.VerifySemantics( [ - SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap[0], rudeEdits: + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: [ - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (7, 23), ["x", "X"]) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), ["x", "X"]) ]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.NewTypeDefinition | EditAndContinueCapabilities.UpdateParameters); @@ -8838,31 +8950,35 @@ public void LocalFunction_In_Parameter_InsertWhole() [Fact] public void LocalFunction_In_Parameter_InsertParameter() { - var src1 = @"class Test { void M() { void local() { throw null; } } }"; - var src2 = @"class Test { void M() { void local(in int b) { throw null; } } }"; + var src1 = @"class C { void F() { void local() { throw null; } } }"; + var src2 = @"class C { void F() { void local(in int b) { throw null; } } }"; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Update [void M() { void local() { throw null; } }]@13 -> [void M() { void local(in int b) { throw null; } }]@13"); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "local", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), arguments: [GetResource("local function")]) + ])); } [Fact] public void LocalFunction_In_Parameter_Update() { - var src1 = @"class Test { void M() { void local(int b) { throw null; } } }"; - var src2 = @"class Test { void M() { void local(in int b) { throw null; } } }"; + var src1 = @"class C { void F() { void local(int b) { throw null; } } }"; + var src2 = @"class C { void F() { void local(in int b) { throw null; } } }"; var edits = GetTopEdits(src1, src2); - edits.VerifyEdits( - "Update [void M() { void local(int b) { throw null; } }]@13 -> [void M() { void local(in int b) { throw null; } }]@13"); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "local", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.Position(0), arguments: [GetResource("local function")]) + ])); } [Fact] @@ -8883,16 +8999,17 @@ public void LocalFunction_ReadOnlyRef_ReturnType_Insert() [Fact] public void LocalFunction_ReadOnlyRef_ReturnType_Update() { - var src1 = @"class Test { void M() { int local() { throw null; } } }"; - var src2 = @"class Test { void M() { ref readonly int local() { throw null; } } }"; + var src1 = @"class C { void F() { int local() { throw null; } } }"; + var src2 = @"class C { void F() { ref readonly int local() { throw null; } } }"; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifyEdits( - "Update [void M() { int local() { throw null; } }]@13 -> [void M() { ref readonly int local() { throw null; } }]@13"); - - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "local", CSharpFeaturesResources.local_function)); + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.Position(0), arguments: [GetResource("local function")]) + ])); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37128")] @@ -9268,78 +9385,36 @@ public void LocalFunction_TypeParameter_ReorderAttribute() GetTopEdits(edits).VerifySemanticDiagnostics(); } - [Fact] - public void LocalFunctions_TypeParameter_Insert1() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; - - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Insert []@8", - "Insert [A]@9"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } - - [Fact] - public void LocalFunctions_TypeParameter_Insert2() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; - - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Update []@8 -> []@8", - "Insert [B]@11"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } - - [Fact] - public void LocalFunctions_TypeParameter_Delete1() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; - - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Delete []@8", - "Delete [A]@9"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } - - [Fact] - public void LocalFunctions_TypeParameter_Delete2() + [Theory] + // insert: + [InlineData("void L() {}", "void L() {}", new[] { "Update []@13 -> []@24", "Insert [B]@27" })] + [InlineData("void L() {}", "void L() {}", new[] { "Insert []@24", "Insert [A]@25" })] + // delete: + [InlineData("void L() {}", "void L() {}", new[] { "Delete []@13", "Delete [A]@14" })] + [InlineData("void L() {}", "void L() {}", new[] { "Update []@13 -> []@24", "Delete [A]@14" })] + // update: + [InlineData("void L() {}", "void L() {}", new[] { "Update [A]@14 -> [B]@25" })] + // reorder: + [InlineData("void L() {}", "void L() {}", new[] { "Reorder [B]@16 -> @25" })] + // reorder and update: + [InlineData("void L() {}", "void L() {}", new[] { "Reorder [B]@16 -> @25", "Update [A]@14 -> [C]@27" })] + public void VerifyChangingLocalFunctionTypeParameters(string localFunctionSource1, string localFunctionSource2, string[] expectedMethodEdits) { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; + var src1 = $"{localFunctionSource1}"; + var src2 = $"{localFunctionSource2}"; - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Update []@8 -> []@8", - "Delete [A]@9"); + GetMethodEdits(src1, src2).VerifyEdits(expectedMethodEdits); - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } - - [Fact] - public void LocalFunctions_TypeParameter_Update() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; + var edits = GetTopEdits(src1, src2, MethodKind.Regular); + var syntaxMap = edits.GetSyntaxMap(); - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Update [A]@9 -> [B]@9"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Theory] @@ -9347,16 +9422,22 @@ public void LocalFunctions_TypeParameter_Update() [InlineData("IDisposable", "IDisposable, new()")] public void LocalFunctions_TypeParameter_Constraint_Clause_Update(string oldConstraint, string newConstraint) { - var src1 = "void L() where A : " + oldConstraint + " {}"; - var src2 = "void L() where A : " + newConstraint + " {}"; + var src1 = "void L() where A : " + oldConstraint + " {}"; + var src2 = "void L() where A : " + newConstraint + " {}"; - var edits = GetMethodEdits(src1, src2); + GetMethodEdits(src1, src2).VerifyEdits( + "Update [where A : " + oldConstraint + "]@19 -> [where A : " + newConstraint + "]@30"); - edits.VerifyEdits( - "Update [where A : " + oldConstraint + "]@14 -> [where A : " + newConstraint + "]@14"); + var edits = GetTopEdits(src1, src2, MethodKind.Regular); + var syntaxMap = edits.GetSyntaxMap(); - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Theory] @@ -9369,60 +9450,43 @@ public void LocalFunctions_TypeParameter_Constraint_Clause_Update(string oldCons [InlineData("System.Delegate")] public void LocalFunctions_TypeParameter_Constraint_Clause_Delete(string oldConstraint) { - var src1 = "void L() where A : " + oldConstraint + " {}"; - var src2 = "void L() {}"; + var src1 = "void L() where A : " + oldConstraint + " {}"; + var src2 = "void L() {}"; - var edits = GetMethodEdits(src1, src2); + GetMethodEdits(src1, src2).VerifyEdits( + "Delete [where A : " + oldConstraint + "]@19"); - edits.VerifyEdits( - "Delete [where A : " + oldConstraint + "]@14"); + var edits = GetTopEdits(src1, src2, MethodKind.Regular); + var syntaxMap = edits.GetSyntaxMap(); - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] public void LocalFunctions_TypeParameter_Constraint_Clause_Add() { - var src1 = "void L() where A : new() {}"; - var src2 = "void L() where A : new() where B : System.IDisposable {}"; - - var edits = GetMethodEdits(src1, src2); - - edits.VerifyEdits( - "Insert [where B : System.IDisposable]@32"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } - - [Fact] - public void LocalFunctions_TypeParameter_Reorder() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; + var src1 = "void L() where A : new() {}"; + var src2 = "void L() where A : new() where B : System.IDisposable {}"; - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Reorder [B]@11 -> @9"); + GetMethodEdits(src1, src2).VerifyEdits( + "Insert [where B : System.IDisposable]@48"); - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); - } + var edits = GetTopEdits(src1, src2, MethodKind.Regular); + var syntaxMap = edits.GetSyntaxMap(); - [Fact] - public void LocalFunctions_TypeParameter_ReorderAndUpdate() - { - var src1 = @"void L() {}"; - var src2 = @"void L() {} "; - - var edits = GetMethodEdits(src1, src2); - edits.VerifyEdits( - "Reorder [B]@11 -> @9", - "Update [A]@9 -> [C]@11"); - - GetTopEdits(edits).VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingTypeParameters, "L", FeaturesResources.local_function)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingTypeParameters, syntaxMap.Position(0), [GetResource("local function")]) + ]) + ]); } [Fact] @@ -9693,7 +9757,7 @@ class C { void F() { - var result = from a in new[] {1} select a; + var result = from a in new[] {1} select a; } } "; @@ -9705,14 +9769,21 @@ class C { void F() { - var result = from a in new[] {1.0} select a; + var result = from a in new[] {1.0} select a; } } "; + var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "select", CSharpFeaturesResources.select_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("select clause")]) + ]) + ]); } [Fact] @@ -9726,7 +9797,7 @@ class C { void F() { - var result = from a in new[] {1} select a; + var result = from a in new[] {1} select a; } } "; @@ -9738,14 +9809,20 @@ class C { void F() { - var result = from a in new[] {1} select a.ToString(); + var result = from a in new[] {1} select a.ToString(); } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "select", CSharpFeaturesResources.select_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("select clause")]) + ]) + ]); } [Fact] @@ -9759,7 +9836,7 @@ class C { void F() { - var result = from a in new[] {1} from b in new[] {2} select b; + var result = from a in new[] {1} from b in new[] {2} select b; } } "; @@ -9771,14 +9848,20 @@ class C { void F() { - var result = from long a in new[] {1} from b in new[] {2} select b; + var result = from long a in new[] {1} from b in new[] {2} select b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "from", CSharpFeaturesResources.from_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("from clause")]) + ]) + ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); } [Fact] @@ -9859,7 +9942,7 @@ class C { void F() { - var result = from a in new[] {1} let b = 1 select a; + var result = from a in new[] {1} let b = 1 select a; } } "; @@ -9872,14 +9955,20 @@ class C { void F() { - var result = from a in new[] {1} let b = 1.0 select a; + var result = from a in new[] {1} let b = 1.0 select a; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "let", CSharpFeaturesResources.let_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("let clause")]) + ]) + ]); } [Fact] @@ -9894,7 +9983,7 @@ class C { void F() { - var result = from a in new[] {1} orderby a + 1 descending, a + 2 ascending select a; + var result = from a in new[] {1} orderby a + 1 descending, a + 2 ascending select a; } } "; @@ -9907,14 +9996,20 @@ class C { void F() { - var result = from a in new[] {1} orderby a + 1.0 descending, a + 2 ascending select a; + var result = from a in new[] {1} orderby a + 1.0 descending, a + 2 ascending select a; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "a + 1.0 descending", CSharpFeaturesResources.orderby_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("orderby clause")]) + ]) + ]); } [Fact] @@ -9929,7 +10024,7 @@ class C { void F() { - var result = from a in new[] {1} orderby a + 1 descending, a + 2 ascending select a; + var result = from a in new[] {1} orderby a + 1 descending, a + 2 ascending select a; } } "; @@ -9942,14 +10037,20 @@ class C { void F() { - var result = from a in new[] {1} orderby a + 1 descending, a + 2.0 ascending select a; + var result = from a in new[] {1} orderby a + 1 descending, a + 2.0 ascending select a; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "a + 2.0 ascending", CSharpFeaturesResources.orderby_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("orderby clause")]) + ]) + ]); } [Fact] @@ -9964,7 +10065,7 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a equals b select b; + var result = from a in new[] {1} join b in new[] {1} on a equals b select b; } } "; @@ -9977,14 +10078,21 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1.0} on a equals b select b; + var result = from a in new[] {1} join b in new[] {1.0} on a equals b select b; } } "; + var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "join", CSharpFeaturesResources.join_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")]) + ]) + ]); } [Fact] @@ -9999,7 +10107,7 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a equals b select b; + var result = from a in new[] {1} join b in new[] {1} on a equals b select b; } } "; @@ -10012,14 +10120,20 @@ class C { void F() { - var result = from a in new[] {1} join byte b in new[] {1} on a equals b select b; + var result = from a in new[] {1} join byte b in new[] {1} on a equals b select b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "join", CSharpFeaturesResources.join_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")]) + ]) + ]); } [Fact] @@ -10034,7 +10148,7 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a + 1 equals b select b; + var result = from a in new[] {1} join b in new[] {1} on a + 1 equals b select b; } } "; @@ -10047,14 +10161,20 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a + 1.0 equals b select b; + var result = from a in new[] {1} join b in new[] {1} on a + 1.0 equals b select b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "join", CSharpFeaturesResources.join_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")]) + ]) + ]); } [Fact] @@ -10069,7 +10189,7 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a equals b + 1 select b; + var result = from a in new[] {1} join b in new[] {1} on a equals b + 1 select b; } } "; @@ -10082,14 +10202,20 @@ class C { void F() { - var result = from a in new[] {1} join b in new[] {1} on a equals b + 1.0 select b; + var result = from a in new[] {1} join b in new[] {1} on a equals b + 1.0 select b; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "join", CSharpFeaturesResources.join_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("join clause")]) + ]) + ]); } [Fact] @@ -10104,7 +10230,7 @@ class C { void F() { - var result = from a in new[] {1} group a + 1 by a into z select z; + var result = from a in new[] {1} group a + 1 by a into z select z; } } "; @@ -10117,14 +10243,20 @@ class C { void F() { - var result = from a in new[] {1} group a + 1.0 by a into z select z; + var result = from a in new[] {1} group a + 1.0 by a into z select z; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "group", CSharpFeaturesResources.groupby_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")]) + ]) + ]); } [Fact] @@ -10139,7 +10271,7 @@ class C { void F() { - var result = from a in new[] {1} group a by a into z select z; + var result = from a in new[] {1} group a by a into z select z; } } "; @@ -10152,14 +10284,20 @@ class C { void F() { - var result = from a in new[] {1} group a by a + 1.0 into z select z; + var result = from a in new[] {1} group a by a + 1.0 into z select z; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "group", CSharpFeaturesResources.groupby_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")]) + ]) + ]); } [Fact] @@ -10217,7 +10355,7 @@ class C void F() { - var result = from a in new[] {1} group G1(a) by a into z select z; + var result = from a in new[] {1} group G1(a) by a into z select z; } } "; @@ -10233,14 +10371,20 @@ class C void F() { - var result = from a in new[] {1} group G2(a) by a into z select z; + var result = from a in new[] {1} group G2(a) by a into z select z; } } "; var edits = GetTopEdits(src1, src2); + var syntaxMap = edits.GetSyntaxMap(); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "group", CSharpFeaturesResources.groupby_clause)); + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")]) + ]) + ]); } [Fact] @@ -10422,7 +10566,7 @@ class C { void F() { - var result = from a in new[] {1} group a by a; + var result = from a in new[] {1} group a by a; } } "; @@ -10434,13 +10578,20 @@ class C { void F() { - var result = from a in new[] {1} group a + 1.0 by a; + var result = from a in new[] {1} group a + 1.0 by a; } } "; var edits = GetTopEdits(src1, src2); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "group", CSharpFeaturesResources.groupby_clause)); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")]) + ]) + ]); } [Fact] @@ -10485,7 +10636,7 @@ class C { void F() { - var result = from a in new[] {1} group a + 1.0 by a; + var result = from a in new[] {1} group a + 1.0 by a; } } "; @@ -10497,13 +10648,20 @@ class C { void F() { - var result = from a in new[] {1} group a by a; + var result = from a in new[] {1} group a by a; } } "; var edits = GetTopEdits(src1, src2); - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "group", CSharpFeaturesResources.groupby_clause)); + var syntaxMap = edits.GetSyntaxMap(); + + edits.VerifySemantics( + [ + SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C.F"), syntaxMap, rudeEdits: + [ + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), [GetResource("groupby clause")]) + ]) + ]); } [Fact] diff --git a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index 960cd5c325a9..9764cbb17155 100644 --- a/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/Features/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -14242,7 +14242,7 @@ partial class C SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Int32"), partialType: "C", syntaxMap: syntaxMapB), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Boolean"), partialType: "C", syntaxMap: syntaxMapB), SemanticEdit(SemanticEditKind.Update, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "UInt32"), partialType: "C", syntaxMap: syntaxMapB), - SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Byte"), partialType: "C", syntaxMap: null), + SemanticEdit(SemanticEditKind.Insert, c => c.GetMember("C").Constructors.Single(c => c.Parameters.Single().Type.Name == "Byte"), partialType: "C"), ]) ], capabilities: EditAndContinueCapabilities.AddMethodToExistingType); diff --git a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs index b5242a5245b4..b52c11867bb6 100644 --- a/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs +++ b/src/Features/Core/Portable/EditAndContinue/AbstractEditAndContinueAnalyzer.cs @@ -4954,6 +4954,9 @@ public void Report(RudeEditKind kind, SyntaxNode locationNode, CancellationToken /// The rude edit will be associated with the syntax kind of newDeclaration in telemetry. /// public void Report(RudeEditKind kind, CancellationToken cancellationToken, TextSpan? span = null, string?[]? arguments = null) + => diagnostics.Add(CreateRudeEdit(kind, cancellationToken, span, arguments)); + + public RudeEditDiagnostic CreateRudeEdit(RudeEditKind kind, CancellationToken cancellationToken, TextSpan? span = null, string?[]? arguments = null) { var node = GetDiagnosticNode(out var distance, cancellationToken); @@ -4961,7 +4964,7 @@ public void Report(RudeEditKind kind, CancellationToken cancellationToken, TextS ? analyzer.GetDiagnosticSpan(node, (distance > 0 || kind == RudeEditKind.ChangeImplicitMainReturnType) ? EditKind.Delete : EditKind.Update) : diagnosticSpan; - diagnostics.Add(new RudeEditDiagnostic( + return new RudeEditDiagnostic( kind, span.Value, node, @@ -4974,16 +4977,16 @@ RudeEditKind.GenericTypeUpdate or RudeEditKind.SwitchBetweenLambdaAndLocalFunction or RudeEditKind.AccessorKindUpdate or RudeEditKind.InsertConstructorToTypeWithInitializersWithLambdas - => Array.Empty(), + => [], RudeEditKind.ChangingReloadableTypeNotSupportedByRuntime - => new[] { CreateNewOnMetadataUpdateAttributeName }, + => [CreateNewOnMetadataUpdateAttributeName], RudeEditKind.Renamed - => new[] { analyzer.GetDisplayKindAndName(oldSymbol!, fullyQualify: false) }, + => [analyzer.GetDisplayKindAndName(oldSymbol!, fullyQualify: false)], - _ => new[] - { + _ => + [ // Use name of oldSymbol, in case the symbol we are refering to has been renamed: ((oldSymbol ?? newSymbol) is not { } symbol) ? analyzer.GetDisplayName(node) @@ -4991,8 +4994,8 @@ RudeEditKind.AccessorKindUpdate or : distance > 0 ? analyzer.GetDisplayKindAndName(symbol, fullyQualify: distance > 1) : analyzer.GetDisplayKind(symbol) - } - })); + ] + }); } public void ReportTypeLayoutUpdateRudeEdits(CancellationToken cancellationToken) @@ -5497,9 +5500,10 @@ private void ReportLambdaAndClosureRudeEdits( hasLambdaBodyUpdate = false; runtimeRudeEdits = null; + using var _ = PooledDictionary.GetInstance(out var runtimeRudeEditsBuilder); + if (activeOrMatchedLambdas != null) { - var anySignatureErrors = false; var hasUnmatchedLambdas = false; foreach (var (oldLambdaBody, newLambdaInfo) in activeOrMatchedLambdas) { @@ -5566,8 +5570,7 @@ private void ReportLambdaAndClosureRudeEdits( // query signatures are analyzed separately: if (isNestedFunction) { - ReportLambdaSignatureRudeEdits(diagnosticContext, oldLambda, newLambda, capabilities, out var hasErrors, cancellationToken); - anySignatureErrors |= hasErrors; + ReportLambdaSignatureRudeEdits(diagnosticContext, oldLambda, newLambda, capabilities, runtimeRudeEditsBuilder, cancellationToken); } } @@ -5598,17 +5601,10 @@ group clause by GetContainingQueryExpression(clause) into clausesByQuery select clausesByQuery.First()) { var diagnosticContext = CreateDiagnosticContext(diagnostics, oldSymbol: null, newSymbol: null, newQueryClause, newModel, topMatch: null); - diagnosticContext.Report(RudeEditKind.ChangingQueryLambdaType, cancellationToken); + runtimeRudeEditsBuilder[newQueryClause] = diagnosticContext.CreateRudeEdit(RudeEditKind.ChangingQueryLambdaType, cancellationToken); } lazyNewErroneousClauses.Free(); - anySignatureErrors = true; - } - - // only dig into captures if lambda signatures match - if (anySignatureErrors) - { - return; } } @@ -5677,8 +5673,6 @@ select clausesByQuery.First()) // { old capture index -> old closure scope or null for "this" } using var _3 = ArrayBuilder.GetInstance(oldInLambdaCaptures.Length, fillWithValue: null, out var oldCapturesToClosureScopes); - using var _4 = PooledDictionary.GetInstance(out var closureRudeEdits); - CalculateCapturedVariablesMaps( oldInLambdaCaptures, oldDeclaration, @@ -5690,12 +5684,12 @@ select clausesByQuery.First()) reverseCapturesMap, newCapturesToClosureScopes, oldCapturesToClosureScopes, - closureRudeEdits, + runtimeRudeEditsBuilder, cancellationToken); - if (closureRudeEdits.Any()) + if (runtimeRudeEditsBuilder.Any()) { - var rudeEdits = closureRudeEdits.ToImmutableSegmentedDictionary( + var rudeEdits = runtimeRudeEditsBuilder.ToImmutableSegmentedDictionary( static item => item.Key, static item => new RuntimeRudeEdit(item.Value.ToDiagnostic(item.Key.SyntaxTree).ToString(), (int)item.Value.Kind)); @@ -6303,18 +6297,15 @@ private void ReportLambdaSignatureRudeEdits( SyntaxNode oldLambda, SyntaxNode newLambda, EditAndContinueCapabilitiesGrantor capabilities, - out bool hasSignatureErrors, + IDictionary runtimeRudeEditsBuilder, CancellationToken cancellationToken) { - hasSignatureErrors = false; - Debug.Assert(IsNestedFunction(newLambda)); Debug.Assert(IsNestedFunction(oldLambda)); if (IsLocalFunction(oldLambda) != IsLocalFunction(newLambda)) { - diagnosticContext.Report(RudeEditKind.SwitchBetweenLambdaAndLocalFunction, cancellationToken); - hasSignatureErrors = true; + runtimeRudeEditsBuilder[newLambda] = diagnosticContext.CreateRudeEdit(RudeEditKind.SwitchBetweenLambdaAndLocalFunction, cancellationToken); return; } @@ -6324,23 +6315,20 @@ private void ReportLambdaSignatureRudeEdits( // signature validation: if (!ParameterTypesEquivalent(oldLambdaSymbol.Parameters, newLambdaSymbol.Parameters, exact: false)) { - diagnosticContext.Report(RudeEditKind.ChangingLambdaParameters, cancellationToken); - hasSignatureErrors = true; - } - else if (!ReturnTypesEquivalent(oldLambdaSymbol, newLambdaSymbol, exact: false)) - { - diagnosticContext.Report(RudeEditKind.ChangingLambdaReturnType, cancellationToken); - hasSignatureErrors = true; + runtimeRudeEditsBuilder[newLambda] = diagnosticContext.CreateRudeEdit(RudeEditKind.ChangingLambdaParameters, cancellationToken); + return; } - else if (!TypeParametersEquivalent(oldLambdaSymbol.TypeParameters, newLambdaSymbol.TypeParameters, exact: false) || - !oldLambdaSymbol.TypeParameters.SequenceEqual(newLambdaSymbol.TypeParameters, static (p, q) => p.Name == q.Name)) + + if (!ReturnTypesEquivalent(oldLambdaSymbol, newLambdaSymbol, exact: false)) { - diagnosticContext.Report(RudeEditKind.ChangingTypeParameters, cancellationToken); - hasSignatureErrors = true; + runtimeRudeEditsBuilder[newLambda] = diagnosticContext.CreateRudeEdit(RudeEditKind.ChangingLambdaReturnType, cancellationToken); + return; } - if (hasSignatureErrors) + if (!TypeParametersEquivalent(oldLambdaSymbol.TypeParameters, newLambdaSymbol.TypeParameters, exact: false) || + !oldLambdaSymbol.TypeParameters.SequenceEqual(newLambdaSymbol.TypeParameters, static (p, q) => p.Name == q.Name)) { + runtimeRudeEditsBuilder[newLambda] = diagnosticContext.CreateRudeEdit(RudeEditKind.ChangingTypeParameters, cancellationToken); return; } diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs index c4f134f6bbc5..0ce5dcb32db2 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs @@ -107,7 +107,7 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddRudeEdit(RudeEditKind.ChangingCapturedVariableScope, nameof(FeaturesResources.Changing_the_declaration_scope_of_a_captured_variable_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ChangingLambdaParameters, nameof(FeaturesResources.Changing_the_parameters_of_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ChangingLambdaReturnType, nameof(FeaturesResources.Changing_the_return_type_of_0_requires_restarting_the_application)); - AddRudeEdit(RudeEditKind.ChangingQueryLambdaType, nameof(FeaturesResources.Changing_the_signature_of_0_requires_restarting_the_application_because_it_is_not_supported_by_the_runtime)); + AddRudeEdit(RudeEditKind.ChangingQueryLambdaType, nameof(FeaturesResources.Changing_the_signature_of_0_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ActiveStatementUpdate, nameof(FeaturesResources.Updating_an_active_statement_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.ActiveStatementLambdaRemoved, nameof(FeaturesResources.Removing_0_that_contains_an_active_statement_requires_restarting_the_application)); AddRudeEdit(RudeEditKind.PartiallyExecutedActiveStatementUpdate, nameof(FeaturesResources.Updating_an_active_statement_requires_restarting_the_application)); diff --git a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs index ad21348734f9..a8d9fcbeda3b 100644 --- a/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs +++ b/src/Features/Core/Portable/EditAndContinue/RudeEditKind.cs @@ -67,13 +67,13 @@ internal enum RudeEditKind : ushort // DeletingCapturedVariable = 50, ChangingCapturedVariableType = 51, ChangingCapturedVariableScope = 52, - ChangingLambdaParameters = 53, - ChangingLambdaReturnType = 54, + ChangingLambdaParameters = 53, // runtime rude edit + ChangingLambdaReturnType = 54, // runtime rude edit // AccessingCapturedVariableInLambda = 55, // NotAccessingCapturedVariableInLambda = 56, // InsertLambdaWithMultiScopeCapture = 57, // DeleteLambdaWithMultiScopeCapture = 58, - ChangingQueryLambdaType = 59, + ChangingQueryLambdaType = 59, // runtime rude edit InsertAroundActiveStatement = 60, DeleteAroundActiveStatement = 61, @@ -85,7 +85,7 @@ internal enum RudeEditKind : ushort UpdateStaticLocal = 67, InsertConstructorToTypeWithInitializersWithLambdas = 68, - RenamingCapturedVariable = 69, + RenamingCapturedVariable = 69, // runtime rude edit InsertHandlesClause = 70, InsertFile = 71, @@ -94,7 +94,7 @@ internal enum RudeEditKind : ushort UpdatingStateMachineMethodAroundActiveStatement = 74, UpdatingStateMachineMethodMissingAttribute = 75, - SwitchBetweenLambdaAndLocalFunction = 76, + SwitchBetweenLambdaAndLocalFunction = 76, // runtime rude edit //RefStruct = 77, //ReadOnlyStruct = 78, //ReadOnlyReferences = 79, @@ -128,7 +128,7 @@ internal enum RudeEditKind : ushort ChangingAttributesNotSupportedByRuntime = 101, ChangeImplicitMainReturnType = 102, ChangingParameterTypes = 103, - ChangingTypeParameters = 104, + ChangingTypeParameters = 104, // runtime rude edit for lambdas ChangingConstraints = 105, ChangingReloadableTypeNotSupportedByRuntime = 106, RenamingNotSupportedByRuntime = 107, diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 0c9edac5be33..f523b6591874 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -348,6 +348,9 @@ Changing the return type of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 7e1015fd2763..a81bb9ffc059 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -465,9 +465,14 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Změna návratového typu {0} vyžaduje restartování aplikace. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Změna podpisu {0} vyžaduje restartování aplikace, protože ji modul runtime nepodporuje. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index 1ed73b6c9693..547b935ddafb 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -465,9 +465,14 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Das Ändern des Rückgabetyps von {0} erfordert einen Neustart der Anwendung. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Das Ändern der Signatur von {0} erfordert einen Neustart der Anwendung, da es von der Runtime nicht unterstützt wird. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index b9286ae1a3c9..9a72a0c63650 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -465,9 +465,14 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Para cambiar el tipo de valor devuelto de {0} es necesario reiniciar la aplicación. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Para cambiar la firma de {0} es necesario reiniciar la aplicación porque no es compatible con el tiempo de ejecución. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 23e9ffd7d194..c40a49c0447b 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -465,9 +465,14 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai La modification du type de retour de {0} requiert le redémarrage de l’application. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - La modification de la signature de {0} nécessite le redémarrage de l'application car elle n'est pas prise en charge par le runtime. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 6bb8dd3d96c3..98e92e8ee187 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -465,9 +465,14 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Se si modifica il tipo restituito di {0}, è necessario riavviare l'applicazione. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Se si modifica la firma di {0}, è necessario riavviare l'applicazione perché l'operazione non è supportata dal runtime. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index dd5559fc36b4..fbc217017ced 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -465,9 +465,14 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0} の戻り値の型を変更するには、アプリケーションを再起動する必要があります。 + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - ランタイムでサポートされていないため、{0} をの署名を変更するには、アプリケーションを再起動する必要があります。 + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 2dc354351b93..0ba5938ed206 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -465,9 +465,14 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma {0}의 반환 형식을 변경하려면 애플리케이션을 다시 시작해야 합니다. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - 런타임에서 지원하지 않기 때문에 {0} 서명을 변경하려면 애플리케이션을 다시 시작해야 합니다. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 055583a50262..910e8a7b9470 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -465,9 +465,14 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Zmiana zwracanego typu elementu {0} wymaga ponownego uruchomienia aplikacji. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Zmienianie podpisu {0} wymaga ponownego uruchomienia aplikacji, ponieważ nie jest to obsługiwane przez środowisko uruchomieniowe. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 57b63326b5c4..2f2758579dde 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -465,9 +465,14 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess Alterar o tipo de retorno de {0} requer o reinício do aplicativo. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - A alteração da assinatura de {0} requer a reinicialização do aplicativo porque não há suporte com o tempo de execução. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index b5fb73b44bf1..1dc11bc29ad5 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -465,9 +465,14 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Для изменения типа возвращаемого значения {0} требуется перезапустить приложение. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - Для изменения подписи {0} требуется перезапустить приложение, так как это не поддерживается средой выполнения. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 2b409d687a5b..ea3c6124efe4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -465,9 +465,14 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be {0} öğesinin dönüş türünün değiştirilmesi, uygulamanın yeniden başlatılmasını gerektirir. + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - {0} imzasının silinmesi, çalışma zamanı tarafından desteklenmediğinden uygulamanın yeniden başlatılmasını gerektirir. + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 03533f977762..6475b9ef2fc5 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -465,9 +465,14 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 更改 {0} 的返回类型需要重启应用程序。 + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - 更改 {0} 的签名需要重新启动应用程序,因为不受运行时支持。 + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index ee02eac9cef4..e2f8c645f0ba 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -465,9 +465,14 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 變更 {0} 的傳回型別需要重新啟動應用程式。 + + Changing the signature of {0} requires restarting the application. + Changing the signature of {0} requires restarting the application. + + Changing the signature of {0} requires restarting the application because is not supported by the runtime. - 變更 {0} 的簽章需要重新啟動應用程式,因為執行階段不支援它。 + Changing the signature of {0} requires restarting the application because is not supported by the runtime. diff --git a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs index 7a3b064a2419..3cb4688c41dc 100644 --- a/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs +++ b/src/Features/TestUtilities/EditAndContinue/EditAndContinueTestVerifier.cs @@ -90,7 +90,7 @@ private void VerifyDocumentActiveStatementsAndExceptionRegions( } internal void VerifyLineEdits( - EditScript editScript, + EditScriptDescription editScript, SequencePointUpdates[] expectedLineEdits, SemanticEditDescription[]? expectedSemanticEdits, RudeEditDiagnosticDescription[]? expectedDiagnostics, @@ -104,7 +104,7 @@ [new DocumentAnalysisResultsDescription(semanticEdits: expectedSemanticEdits, li } internal void VerifySemantics( - EditScript[] editScripts, + EditScriptDescription[] editScripts, TargetFramework targetFramework, DocumentAnalysisResultsDescription[] expectedResults, EditAndContinueCapabilities? capabilities = null) @@ -412,13 +412,26 @@ private static void VerifySyntaxMaps( var actualOldNode = actualSyntaxMaps.MatchingNodes(newNode); Assert.Equal(expectedOldNode, actualOldNode); - AssertEx.Equal( - expectedRuntimeRudeEdit?.GetMessage(newRoot.SyntaxTree), - actualSyntaxMaps.RuntimeRudeEdits?.Invoke(newNode)?.Message); + var expected = expectedRuntimeRudeEdit?.GetMessage(newRoot.SyntaxTree); + var actual = actualSyntaxMaps.RuntimeRudeEdits?.Invoke(newNode)?.Message; + + if (expected != actual) + { + Assert.Fail($""" + Unexpected runtime rude edit. + + Expected message: + '{expected}' + Actual message: + '{actual}' + Node ({newNode.GetType().Name}): + `{newNode}` + """); + } } } - private void CreateProjects(EditScript[] editScripts, AdhocWorkspace workspace, TargetFramework targetFramework, out Project oldProject, out Project newProject) + private void CreateProjects(EditScriptDescription[] editScripts, AdhocWorkspace workspace, TargetFramework targetFramework, out Project oldProject, out Project newProject) { var projectInfo = ProjectInfo.Create( new ProjectInfo.ProjectAttributes( @@ -518,16 +531,4 @@ public static void SetDocumentsState(DebuggingSession session, Solution solution } } } - - internal static class EditScriptTestUtils - { - public static void VerifyEdits(this EditScript actual) - => VerifyEdits(actual, Array.Empty()); - - public static void VerifyEdits(this EditScript actual, params string[] expected) - => AssertEx.Equal(expected, actual.Edits.Select(e => e.GetDebuggerDisplay()), itemSeparator: ",\r\n", itemInspector: s => $"\"{s}\""); - - public static void VerifyEdits(this EditScript actual, params EditKind[] expected) - => AssertEx.Equal(expected, actual.Edits.Select(e => e.Kind)); - } } diff --git a/src/Features/TestUtilities/EditAndContinue/EditScriptDescription.cs b/src/Features/TestUtilities/EditAndContinue/EditScriptDescription.cs new file mode 100644 index 000000000000..457be67c5091 --- /dev/null +++ b/src/Features/TestUtilities/EditAndContinue/EditScriptDescription.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.Differencing; +using Roslyn.Test.Utilities; + +namespace Microsoft.CodeAnalysis.EditAndContinue.UnitTests; + +internal readonly struct EditScriptDescription(string oldMarkedSource, string newMarkedSource, EditScript edits) +{ + public readonly string OldMarkedSource = oldMarkedSource; + public readonly string NewMarkedSource = newMarkedSource; + public readonly EditScript Script = edits; + + public Match Match => Script.Match; + public ImmutableArray> Edits => Script.Edits; + + public SyntaxMapDescription.Mapping GetSyntaxMap() + => GetSyntaxMaps().Single(); + + public SyntaxMapDescription GetSyntaxMaps() + => new(OldMarkedSource, NewMarkedSource, Match); + + public void VerifyEdits() + => VerifyEdits(Array.Empty()); + + public void VerifyEdits(params string[] expected) + => AssertEx.Equal(expected, Edits.Select(e => e.GetDebuggerDisplay()), itemSeparator: ",\r\n", itemInspector: s => $"\"{s}\""); + + public void VerifyEdits(params EditKind[] expected) + => AssertEx.Equal(expected, Edits.Select(e => e.Kind)); +} diff --git a/src/Features/TestUtilities/EditAndContinue/SourceMarkers.cs b/src/Features/TestUtilities/EditAndContinue/SourceMarkers.cs index 9dda298b5d62..fb8ca73810f8 100644 --- a/src/Features/TestUtilities/EditAndContinue/SourceMarkers.cs +++ b/src/Features/TestUtilities/EditAndContinue/SourceMarkers.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis.Text; @@ -16,7 +17,7 @@ namespace Microsoft.CodeAnalysis.EditAndContinue.UnitTests; internal static class SourceMarkers { private static readonly Regex s_tags = new( - "[<] (?/?) (?(AS|ER|N|TS))[:] (?[.0-9,]+) (?/?) [>]", RegexOptions.IgnorePatternWhitespace); + "[<] (?/?) (?(AS|ER|N|S|TS))[:] (?[.0-9,]+) (?/?) [>]", RegexOptions.IgnorePatternWhitespace); public static readonly Regex ExceptionRegionPattern = new( @"[<]ER[:] (?(?:[0-9]+[.][0-9]+[,]?)+) [>] @@ -41,7 +42,7 @@ internal static string[] Clear(string[] sources) let parts = ids.Split('.') select (int.Parse(parts[0]), (parts.Length > 1) ? int.Parse(parts[1]) : -1); - private static IEnumerable<((int major, int minor) id, TextSpan span)> GetSpans(string markedSource, string tagName) + private static IEnumerable<((int major, int minor) id, TextSpan span)> ParseSpans(string markedSource, string tagName) { // id -> content start index var tagMap = new Dictionary<(int major, int minor), (int start, int end)>(); @@ -82,7 +83,7 @@ internal static string[] Clear(string[] sources) } public static IEnumerable<(TextSpan Span, int Id)> GetActiveSpans(string markedSource) - => GetSpans(markedSource, tagName: "AS").Select(s => (s.span, s.id.major)); + => ParseSpans(markedSource, tagName: "AS").Select(s => (s.span, s.id.major)); public static (int id, TextSpan span)[] GetTrackingSpans(string src) { @@ -140,7 +141,7 @@ public static ImmutableArray> GetNodeSpans(string marke { var result = new List>(); - foreach (var ((major, minor), span) in GetSpans(markedSource, tagName: "N")) + foreach (var ((major, minor), span) in ParseSpans(markedSource, tagName: "N")) { var (i, j) = (minor >= 0) ? (major, minor) : (0, major); @@ -150,7 +151,21 @@ public static ImmutableArray> GetNodeSpans(string marke result[i][j] = span; } - return result.Select(r => r.AsImmutableOrEmpty()).AsImmutableOrEmpty(); + return result.Select(r => r.AsImmutableOrEmpty()).ToImmutableArray(); + } + + public static ImmutableArray GetSpans(string markedSource, string tagName) + { + var result = new List(); + + foreach (var ((major, minor), span) in ParseSpans(markedSource, tagName)) + { + Debug.Assert(minor == -1); + EnsureSlot(result, major); + result[major] = span; + } + + return result.ToImmutableArray(); } public static int IndexOfDifferent(ReadOnlySpan span, char c) diff --git a/src/Features/TestUtilities/EditAndContinue/SyntaxMapDescription.cs b/src/Features/TestUtilities/EditAndContinue/SyntaxMapDescription.cs index bb82a7810b10..dad5ba2fe15e 100644 --- a/src/Features/TestUtilities/EditAndContinue/SyntaxMapDescription.cs +++ b/src/Features/TestUtilities/EditAndContinue/SyntaxMapDescription.cs @@ -2,30 +2,69 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Immutable; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Differencing; using Microsoft.CodeAnalysis.Text; using Xunit; namespace Microsoft.CodeAnalysis.EditAndContinue.UnitTests; -public sealed class SyntaxMapDescription +internal sealed class SyntaxMapDescription { + public readonly struct Mapping(ImmutableArray<(TextSpan oldSpan, TextSpan newSpan)> nodeSpans, ImmutableArray newSpans, Match? match) + { + public readonly ImmutableArray<(TextSpan oldSpan, TextSpan newSpan)> Spans = nodeSpans; + + public LinePosition NodePosition(int index) + { + Debug.Assert(match != null, "Must be created from edit script"); + Debug.Assert(index < Spans.Length, $"Marker not present in new source"); + + return match.NewRoot.SyntaxTree.GetLineSpan(Spans[index].newSpan).StartLinePosition; + } + + public LinePosition Position(int index) + { + Debug.Assert(match != null, "Must be created from edit script"); + Debug.Assert(index < newSpans.Length, $"Marker not present in new source"); + + return match.NewRoot.SyntaxTree.GetLineSpan(newSpans[index]).StartLinePosition; + } + } + // Spans from markers. Indexed by major and then minor. - public readonly ImmutableArray> OldSpans; - public readonly ImmutableArray> NewSpans; + // Used for matching spans between old source and new source (syntax map). + public readonly ImmutableArray> OldNodeSpans; + public readonly ImmutableArray> NewNodeSpans; + + // Spans from markers. Used for general span marking in new source. + public readonly ImmutableArray NewSpans; + + public readonly Match? Match; - public SyntaxMapDescription(string oldSource, string newSource) + public SyntaxMapDescription(string oldSource, string newSource, Match? match = null) { - OldSpans = SourceMarkers.GetNodeSpans(oldSource); - NewSpans = SourceMarkers.GetNodeSpans(newSource); + OldNodeSpans = SourceMarkers.GetNodeSpans(oldSource); + NewNodeSpans = SourceMarkers.GetNodeSpans(newSource); - Assert.Equal(OldSpans.Length, NewSpans.Length); - for (var i = 0; i < OldSpans.Length; i++) + Assert.Equal(OldNodeSpans.Length, NewNodeSpans.Length); + for (var i = 0; i < OldNodeSpans.Length; i++) { - Assert.Equal(OldSpans[i].Length, NewSpans[i].Length); + Assert.Equal(OldNodeSpans[i].Length, NewNodeSpans[i].Length); } + + NewSpans = SourceMarkers.GetSpans(newSource, tagName: "S"); + Match = match; + } + + public Mapping Single() + { + Debug.Assert(OldNodeSpans.Length == 1); + return this[0]; } - internal ImmutableArray<(TextSpan oldSpan, TextSpan newSpan)> this[int i] - => OldSpans[i].ZipAsArray(NewSpans[i], static (oldSpan, newSpan) => (oldSpan, newSpan)); + public Mapping this[int i] + => new(OldNodeSpans[i].ZipAsArray(NewNodeSpans[i], static (oldSpan, newSpan) => (oldSpan, newSpan)), NewSpans, Match); } diff --git a/src/Features/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb b/src/Features/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb index 236320d22580..7704e978e529 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/ActiveStatementTests.vb @@ -4773,7 +4773,6 @@ End Class Dim edits = GetTopEdits(src1, src2) Dim active = GetActiveStatements(src1, src2) edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "Function(b)", GetResource("Lambda")), Diagnostic(RudeEditKind.ActiveStatementLambdaRemoved, "Function(b)", GetResource("Lambda"))) End Sub @@ -4802,7 +4801,6 @@ End Class Dim edits = GetTopEdits(src1, src2) Dim active = GetActiveStatements(src1, src2) edits.VerifySemanticDiagnostics(active, - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "Function(b)", GetResource("Lambda")), Diagnostic(RudeEditKind.ActiveStatementLambdaRemoved, "Function(b)", GetResource("Lambda"))) End Sub diff --git a/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditAndContinueValidation.vb b/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditAndContinueValidation.vb index 05982c571f1e..da54fa31538f 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditAndContinueValidation.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditAndContinueValidation.vb @@ -15,7 +15,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Module EditAndContinueValidation Friend Sub VerifyLineEdits( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, lineEdits As SourceLineUpdate(), Optional semanticEdits As SemanticEditDescription() = Nothing, Optional diagnostics As RudeEditDiagnosticDescription() = Nothing, @@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifyLineEdits( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, lineEdits As SequencePointUpdates(), Optional semanticEdits As SemanticEditDescription() = Nothing, Optional diagnostics As RudeEditDiagnosticDescription() = Nothing, @@ -45,7 +45,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemanticDiagnostics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, ParamArray diagnostics As RudeEditDiagnosticDescription()) VerifySemanticDiagnostics(editScript, activeStatements:=Nothing, targetFrameworks:=Nothing, capabilities:=Nothing, diagnostics) @@ -53,7 +53,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemanticDiagnostics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, activeStatements As ActiveStatementsDescription, ParamArray diagnostics As RudeEditDiagnosticDescription()) @@ -62,7 +62,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemanticDiagnostics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, diagnostics As RudeEditDiagnosticDescription(), capabilities As EditAndContinueCapabilities?) @@ -71,7 +71,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemanticDiagnostics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, Optional activeStatements As ActiveStatementsDescription = Nothing, Optional targetFrameworks As TargetFramework() = Nothing, Optional capabilities As EditAndContinueCapabilities? = Nothing, @@ -86,7 +86,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemantics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, Optional activeStatements As ActiveStatementsDescription = Nothing, Optional semanticEdits As SemanticEditDescription() = Nothing, Optional diagnostics As RudeEditDiagnosticDescription() = Nothing, @@ -102,7 +102,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemantics( - editScripts As EditScript(Of SyntaxNode)(), + editScripts As EditScriptDescription(), expected As DocumentAnalysisResultsDescription(), Optional targetFrameworks As TargetFramework() = Nothing, Optional capabilities As EditAndContinueCapabilities? = Nothing) @@ -115,7 +115,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemantics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, semanticEdits As SemanticEditDescription(), capabilities As EditAndContinueCapabilities) @@ -124,7 +124,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests Friend Sub VerifySemantics( - editScript As EditScript(Of SyntaxNode), + editScript As EditScriptDescription, ParamArray semanticEdits As SemanticEditDescription()) VerifySemantics(editScript, ActiveStatementsDescription.Empty, semanticEdits) diff --git a/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditingTestBase.vb b/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditingTestBase.vb index 213a3e7c505b..dcdf8673f37f 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditingTestBase.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/Helpers/EditingTestBase.vb @@ -116,6 +116,20 @@ End Namespace Return FeaturesResources.type_parameter Case "withevents field" Return VBFeaturesResources.WithEvents_field + Case "from clause" + Return VBFeaturesResources.From_clause + Case "where clause" + Return VBFeaturesResources.Where_clause + Case "join clause" + Return VBFeaturesResources.Join_clause + Case "let clause" + Return VBFeaturesResources.Let_clause + Case "orderby clause" + Return VBFeaturesResources.Ordering_clause + Case "groupby clause" + Return VBFeaturesResources.Group_By_clause + Case "select clause" + Return VBFeaturesResources.Select_clause Case Else Return Nothing End Select @@ -127,8 +141,17 @@ End Namespace Return New RudeEditDiagnosticDescription(rudeEditKind, squiggle, arguments, firstLine:=Nothing) End Function - Friend Shared Function RuntimeRudeEdit(marker As Integer, rudeEditKind As RudeEditKind, position As (displayLine As Integer, displayColumn As Integer), ParamArray arguments As String()) As RuntimeRudeEditDescription - Return New RuntimeRudeEditDescription(marker, rudeEditKind, New LinePosition(position.displayLine - 1, position.displayColumn - 1), arguments) + Friend Shared Function RuntimeRudeEdit(marker As Integer, rudeEditKind As RudeEditKind, position As LinePosition, ParamArray arguments As String()) As RuntimeRudeEditDescription + Return New RuntimeRudeEditDescription(marker, rudeEditKind, position, arguments) + End Function + + Friend Shared Function SemanticEdit(kind As SemanticEditKind, + symbolProvider As Func(Of Compilation, ISymbol), + syntaxMap As SyntaxMapDescription.Mapping?, + Optional rudeEdits As IEnumerable(Of RuntimeRudeEditDescription) = Nothing, + Optional partialType As String = Nothing, + Optional deletedSymbolContainerProvider As Func(Of Compilation, ISymbol) = Nothing) As SemanticEditDescription + Return SemanticEdit(kind, symbolProvider, syntaxMap?.Spans, rudeEdits, partialType, deletedSymbolContainerProvider) End Function Friend Shared Function SemanticEdit(kind As SemanticEditKind, @@ -184,7 +207,7 @@ End Namespace path:=GetDocumentFilePath(documentIndex)) End Function - Friend Shared Function GetTopEdits(src1 As String, src2 As String, Optional documentIndex As Integer = 0) As EditScript(Of SyntaxNode) + Friend Shared Function GetTopEdits(src1 As String, src2 As String, Optional documentIndex As Integer = 0) As EditScriptDescription Dim tree1 = ParseSource(src1, documentIndex) Dim tree2 = ParseSource(src2, documentIndex) @@ -192,19 +215,19 @@ End Namespace tree2.GetDiagnostics().Verify() Dim match = SyntaxComparer.TopLevel.ComputeMatch(tree1.GetRoot(), tree2.GetRoot()) - Return match.GetTreeEdits() + Return New EditScriptDescription(src1, src2, match.GetTreeEdits()) End Function - Public Shared Function GetTopEdits(methodEdits As EditScript(Of SyntaxNode)) As EditScript(Of SyntaxNode) + Friend Shared Function GetTopEdits(methodEdits As EditScriptDescription) As EditScriptDescription Dim oldMethodSource = methodEdits.Match.OldRoot.ToFullString() Dim newMethodSource = methodEdits.Match.NewRoot.ToFullString() Return GetTopEdits(WrapMethodBodyWithClass(oldMethodSource), WrapMethodBodyWithClass(newMethodSource)) End Function - Friend Shared Function GetMethodEdits(src1 As String, src2 As String, Optional methodKind As MethodKind = MethodKind.Regular) As EditScript(Of SyntaxNode) + Friend Shared Function GetMethodEdits(src1 As String, src2 As String, Optional methodKind As MethodKind = MethodKind.Regular) As EditScriptDescription Dim match = GetMethodMatch(src1, src2, methodKind) - Return match.GetTreeEdits() + Return New EditScriptDescription(src1, src2, match.GetTreeEdits()) End Function Friend Shared Function GetMethodMatch(src1 As String, src2 As String, Optional methodKind As MethodKind = MethodKind.Regular) As Match(Of SyntaxNode) diff --git a/src/Features/VisualBasicTest/EditAndContinue/StatementEditingTests.vb b/src/Features/VisualBasicTest/EditAndContinue/StatementEditingTests.vb index a6550aca7c31..ecf9d5bc1b19 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/StatementEditingTests.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/StatementEditingTests.vb @@ -4,10 +4,8 @@ Imports Microsoft.CodeAnalysis.EditAndContinue Imports Microsoft.CodeAnalysis.EditAndContinue.UnitTests -Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EditAndContinue Imports Microsoft.CodeAnalysis.Emit Imports Microsoft.CodeAnalysis.VisualBasic.Symbols -Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.EditAndContinue.UnitTests @@ -1258,7 +1256,7 @@ Class C End Sub Sub F() - G1(Function(a) a) + G1(Function(a) a) End Sub End Class " @@ -1273,13 +1271,18 @@ Class C End Sub Sub F() - G2(Function(a) a) + G2(Function(a) a) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1295,7 +1298,7 @@ Class C End Sub Sub F() - G1(Function(a) a) + G1(Function(a) a) End Sub End Class " @@ -1310,13 +1313,18 @@ Class C End Sub Sub F() - G2(Function(a, b) a + b) + G2(Function(a, b) a + b) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a, b)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1332,7 +1340,7 @@ Class C End Sub Sub F() - G1(Function(a) a) + G1(Function(a) a) End Sub End Class " @@ -1347,13 +1355,20 @@ Class C End Sub Sub F() - G2(Function(a) a) + G2(Function(a) a) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "Function(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), {GetResource("lambda")}) + }) + }) End Sub @@ -1370,8 +1385,8 @@ Class C Sub F() G1( -Sub(a) -End Sub) +Sub(a) +End Sub) End Sub End Class " @@ -1387,14 +1402,19 @@ Class C Sub F() G2( -Sub(a) -End Sub) +Sub(a) +End Sub) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Sub(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1411,8 +1431,8 @@ Class C Sub F() G1( -Sub() -End Sub) +Sub() +End Sub) End Sub End Class " @@ -1428,14 +1448,21 @@ Class C Sub F() G2( -Function() -End Function) +Function() +End Function) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "Function()", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), {GetResource("lambda")}) + }) + }) End Sub @@ -1487,9 +1514,9 @@ Class C End Sub Sub F() - G1(Function(a) + G1(Function(a) Return 1 - End Function) + End Function) End Sub End Class " @@ -1504,14 +1531,21 @@ Class C End Sub Sub F() - G2(Sub(a) - End Sub) + G2(Sub(a) + End Sub) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaReturnType, "Sub(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaReturnType, syntaxMap.NodePosition(0), {GetResource("lambda")}) + }) + }) End Sub @@ -1604,7 +1638,7 @@ Class C End Sub Sub F() - G1(Function(ByRef a As Integer) 1) + G1(Function(ByRef a As Integer) 1) End Sub End Class " @@ -1622,13 +1656,18 @@ Class C End Sub Sub F() - G2(Function(a As Integer) 2) + G2(Function(a As Integer) 2) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a As Integer)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1736,7 +1775,7 @@ Class C End Sub Sub F() - G1(Function(a) a) + G1(Function(a) a) End Sub End Class " @@ -1757,13 +1796,18 @@ Class C End Sub Sub F() - G2(Function(a) a) + G2(Function(a) a) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1786,7 +1830,7 @@ Namespace [System] End Sub Sub F() - G1(Function(a) a) + G1(Function(a) a) End Sub End Class End Namespace @@ -1808,14 +1852,19 @@ Namespace [System] End Sub Sub F() - G2(Function(a) a) + G2(Function(a) a) End Sub End Class End Namespace " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("System.C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -1871,7 +1920,7 @@ Class C End Sub Sub F() - G1(Function(a, b) 1) + G1(Function(a, b) 1) End Sub End Class " @@ -1887,13 +1936,18 @@ Class C End Sub Sub F() - G2(Function(a, b) 1) + G2(Function(a, b) 1) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a, b)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub @@ -3462,20 +3516,19 @@ Imports System Class C Shared Sub F() - Dim X As Integer = 1 + Dim X As Integer = 1 Dim f As Func(Of Integer) = Function() X End Sub End Class " Dim edits = GetTopEdits(src1, src2) + Dim syntaxMap = edits.GetSyntaxMap() ' Note that lifted variable is a field, which can't be renamed - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) - edits.VerifySemantics( SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (6, 13), {"x", "X"}) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "X"}) })) End Sub @@ -3496,19 +3549,19 @@ Imports System Class C Shared Sub F() - Dim y As Integer = 1 + Dim y As Integer = 1 Dim f As Func(Of Integer) = Function() y End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (6, 13), {"x", "y"}) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "y"}) })) End Sub @@ -3529,21 +3582,21 @@ Imports System Class C Shared Sub F() - Dim x As Byte = 1 + Dim x As Byte = 1 Dim f As Func(Of Integer) = Function() x End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( SemanticEdit( SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, - rudeEdits:={RuntimeRudeEdit(marker:=0, RudeEditKind.ChangingCapturedVariableType, (6, 13), {"x", "Integer"})})) + rudeEdits:={RuntimeRudeEdit(marker:=0, RudeEditKind.ChangingCapturedVariableType, syntaxMap.Position(0), {"x", "Integer"})})) End Sub @@ -3561,20 +3614,20 @@ End Class Imports System Class C - Shared Sub F(y As Integer) + Shared Sub F(y As Integer) Dim f As Func(Of Integer) = Function() y End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( { SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (5, 23), {"x", "y"}) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "y"}) }) }, capabilities:=EditAndContinueCapabilities.UpdateParameters) @@ -3598,7 +3651,7 @@ Imports System Class C Shared Sub F(x As Integer) - Dim f1 = Function(y) + Dim f1 = Function(y) Dim f2 = Function() y End Function End Sub @@ -3606,13 +3659,13 @@ End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( { SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(1, RudeEditKind.RenamingCapturedVariable, (6, 32), {"x", "y"}) + RuntimeRudeEdit(1, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "y"}) }) }, capabilities:=EditAndContinueCapabilities.UpdateParameters) @@ -3642,19 +3695,19 @@ Class C End Function Shared Sub F(x As Integer) - Dim f1 = Function(y) G(Function() y) + Dim f1 = Function(y) G(Function() y) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( { SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(1, RudeEditKind.RenamingCapturedVariable, (10, 32), {"x", "y"}) + RuntimeRudeEdit(1, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "y"}) }) }, capabilities:=EditAndContinueCapabilities.UpdateParameters) @@ -3675,20 +3728,20 @@ End Class Imports System Class C - Sub New(y As Integer) + Sub New(y As Integer) Dim f As Func(Of Integer) = Function() y End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2)(0) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( { SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C..ctor"), syntaxMap, rudeEdits:= { - RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, (5, 18), {"x", "y"}) + RuntimeRudeEdit(0, RudeEditKind.RenamingCapturedVariable, syntaxMap.Position(0), {"x", "y"}) }) }, capabilities:=EditAndContinueCapabilities.UpdateParameters) @@ -3777,7 +3830,7 @@ Class C End Sub Sub F() - G1(Function(a) 1) + G1(Function(a) 1) End Sub End Class " @@ -3793,12 +3846,18 @@ Class C End Sub Sub F() - G2(Function(a) 2) + G2(Function(a) 2) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics(Diagnostic(RudeEditKind.ChangingLambdaParameters, "Function(a)", VBFeaturesResources.Lambda)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingLambdaParameters, syntaxMap.NodePosition(0), {GetResource("lambda")}) + })) End Sub #End Region @@ -3812,7 +3871,7 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1} Select a + Dim result = From a In {1} Select a End Sub End Class " @@ -3822,13 +3881,20 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1.0} Select a + Dim result = From a In {1.0} Select a End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "Select", VBFeaturesResources.Select_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), {GetResource("select clause")}) + }) + }) End Sub @@ -3839,7 +3905,7 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1} Select b = a + Dim result = From a In {1} Select b = a End Sub End Class " @@ -3849,13 +3915,20 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1.0} Select b = a.ToString() + Dim result = From a In {1.0} Select b = a.ToString() End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "Select", VBFeaturesResources.Select_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), {GetResource("select clause")}) + }) + }) End Sub @@ -3866,7 +3939,7 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1} Select b = a, c = a + Dim result = From a In {1} Select b = a, c = a End Sub End Class " @@ -3876,13 +3949,20 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1.0} Select b = a, c = a.ToString() + Dim result = From a In {1.0} Select b = a, c = a.ToString() End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "Select", VBFeaturesResources.Select_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), {GetResource("select clause")}) + }) + }) End Sub @@ -3893,7 +3973,7 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1} From b In {2} Select b + Dim result = From a In {1} From b In {2} Select b End Sub End Class " @@ -3903,13 +3983,20 @@ Imports System.Linq Class C Sub F() - Dim result = From a In {1.0} From b In {2} Select b + Dim result = From a In {1.0} From b In {2} Select b End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "From", VBFeaturesResources.From_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.Position(0), {GetResource("from clause")}) + }) + }) End Sub @@ -4068,7 +4155,7 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Let b = 1 Select a + Dim result = From a In {1} Let b = 1 Select a End Sub End Class " @@ -4079,13 +4166,20 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Let b = 1.0 Select a + Dim result = From a In {1} Let b = 1.0 Select a End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "Let", VBFeaturesResources.Let_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.Position(0), {GetResource("let clause")}) + }) + }) End Sub @@ -4097,7 +4191,7 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Order By a + 1 Descending, a + 2 Ascending Select a + Dim result = From a In {1} Order By a + 1 Descending, a + 2 Ascending Select a End Sub End Class " @@ -4108,13 +4202,20 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Order By a + 1.0 Descending, a + 2 Ascending Select a + Dim result = From a In {1} Order By a + 1.0 Descending, a + 2 Ascending Select a End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "a + 1.0 Descending", VBFeaturesResources.Ordering_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), {GetResource("orderby clause")}) + }) + }) End Sub @@ -4126,7 +4227,7 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Order By a + 1 Descending, a + 2 Ascending Select a + Dim result = From a In {1} Order By a + 1 Descending, a + 2 Ascending Select a End Sub End Class " @@ -4137,13 +4238,20 @@ Imports System.Collections.Generic Class C Sub F() - Dim result = From a In {1} Order By a + 1 Descending, a + 2.0 Ascending Select a + Dim result = From a In {1} Order By a + 1 Descending, a + 2.0 Ascending Select a End Sub End Class " Dim edits = GetTopEdits(src1, src2) - edits.VerifySemanticDiagnostics( - Diagnostic(RudeEditKind.ChangingQueryLambdaType, "a + 2.0 Ascending", VBFeaturesResources.Ordering_clause)) + Dim syntaxMap = edits.GetSyntaxMap() + + edits.VerifySemantics( + { + SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember("C.F"), syntaxMap, rudeEdits:= + { + RuntimeRudeEdit(0, RudeEditKind.ChangingQueryLambdaType, syntaxMap.NodePosition(0), {GetResource("orderby clause")}) + }) + }) End Sub diff --git a/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb b/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb index d09a8bd0b8ce..b2c61f23632f 100644 --- a/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb +++ b/src/Features/VisualBasicTest/EditAndContinue/TopLevelEditingTests.vb @@ -6843,17 +6843,17 @@ Partial Class C Return 0 End Function - Dim A1(F(Function(a1) a1 + 1)) - Dim A2 As Integer = F(Function(a2) a2 + 1) - Dim A3, A4 As New Func(Of Integer, Integer)(Function(a34) a34 + 1) - Dim A5(F(Function(a51) a51 + 1), F(Function(a52) a52 + 1)) As Integer + Dim A1(F(Function(a1) a1 + 1)) + Dim A2 As Integer = F(Function(a2) a2 + 1) + Dim A3, A4 As New Func(Of Integer, Integer)(Function(a34) a34 + 1) + Dim A5(F(Function(a51) a51 + 1), F(Function(a52) a52 + 1)) As Integer End Class Partial Class C - ReadOnly Property B As Integer = F(Function(b) b + 1) + ReadOnly Property B As Integer = F(Function(b) b + 1) Public Sub New() - F(Function(c) c + 1) + F(Function(c) c + 1) End Sub End Class " @@ -6865,27 +6865,27 @@ Partial Class C Return 0 End Function - Dim A1(F(Function(a1) a1 + 1)) - Dim A2 As Integer = F(Function(a2) a2 + 1) - Dim A3, A4 As New Func(Of Integer, Integer)(Function(a34) a34 + 1) - Dim A5(F(Function(a51) a51 + 1), F(Function(a52) a52 + 1)) As Integer + Dim A1(F(Function(a1) a1 + 1)) + Dim A2 As Integer = F(Function(a2) a2 + 1) + Dim A3, A4 As New Func(Of Integer, Integer)(Function(a34) a34 + 1) + Dim A5(F(Function(a51) a51 + 1), F(Function(a52) a52 + 1)) As Integer End Class Partial Class C - ReadOnly Property B As Integer = F(Function(b) b + 1) + ReadOnly Property B As Integer = F(Function(b) b + 1) Public Sub New() - F(Function(c) c + 2) + F(Function(c) c + 2) End Sub End Class " Dim edits = GetTopEdits(src1, src2) - Dim syntaxMap = GetSyntaxMap(src1, src2) + Dim syntaxMap = edits.GetSyntaxMap() edits.VerifySemantics( ActiveStatementsDescription.Empty, - {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(), syntaxMap(0))}) + {SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(), syntaxMap)}) End Sub @@ -7155,10 +7155,12 @@ Partial Class C End Sub End Class " - Dim syntaxMapB = GetSyntaxMap(srcB1, srcB2)(0) + Dim editsA = GetTopEdits(srcA1, srcA2) + Dim editsB = GetTopEdits(srcB1, srcB2) + Dim syntaxMapB = editsB.GetSyntaxMap() EditAndContinueValidation.VerifySemantics( - {GetTopEdits(srcA1, srcA2), GetTopEdits(srcB1, srcB2)}, + {editsA, editsB}, { DocumentResults(), DocumentResults( @@ -7167,7 +7169,7 @@ End Class SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(Function(m) m.Parameters.Single().Type.Name = "Int32"), partialType:="C", syntaxMap:=syntaxMapB), SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(Function(m) m.Parameters.Single().Type.Name = "Boolean"), partialType:="C", syntaxMap:=syntaxMapB), SemanticEdit(SemanticEditKind.Update, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(Function(m) m.Parameters.Single().Type.Name = "UInt32"), partialType:="C", syntaxMap:=syntaxMapB), - SemanticEdit(SemanticEditKind.Insert, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(Function(m) m.Parameters.Single().Type.Name = "Byte"), partialType:="C", syntaxMap:=Nothing) + SemanticEdit(SemanticEditKind.Insert, Function(c) c.GetMember(Of NamedTypeSymbol)("C").Constructors.Single(Function(m) m.Parameters.Single().Type.Name = "Byte"), partialType:="C") }) }, capabilities:=EditAndContinueCapabilities.AddMethodToExistingType)