Skip to content

Commit

Permalink
Convert more lambda rude edits to runtime rude edits (#75285)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat authored Oct 4, 2024
1 parent 9ff81f4 commit 97d1c60
Show file tree
Hide file tree
Showing 34 changed files with 1,197 additions and 557 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9850,5 +9850,103 @@ .maxstack 8
})
.Verify();
}

/// <summary>
/// Some lambda rude edits are simpler to detect in the IDE. They are specified via <see cref="RuntimeRudeEdit"/>.
/// The IDE tests cover the specific cases.
/// </summary>
[Fact]
public void IdeDetectedRuntimeRudeEdit()
{
using var _ = new EditAndContinueTest()
.AddBaseline(
source: """
using System;
class C
{
public void F()
<N:0>{
_ = new Func<int>(<N:1>() => 1</N:1>);
}</N:0>
}
""",
validator: g =>
{
g.VerifySynthesizedMembers(displayTypeKind: true,
[
"class C: {<>c}",
"class C.<>c: {<>9__0_0, <F>b__0_0}"
]);
})

.AddGeneration(
source: """
using System;
class C
{
public void F()
<N:0>{
_ = new Func<double>(<N:1>() => 1.0</N:1>);
}</N: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, <F>b__0_0#1}");
g.VerifyMethodDefNames(
"F", "<F>b__0_0", ".ctor", "<F>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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -3947,6 +3949,100 @@ End Class
IL_0011: ldloc.0
IL_0012: ret
}
")
End Sub).
Verify()
End Using
End Sub

''' <summary>
''' Some lambda rude edits are simpler to detect in the IDE. They are specified via <see cref="RuntimeRudeEdit"/>.
''' The IDE tests cover the specific cases.
''' </summary>
<Fact>
Public Sub IdeDetectedRuntimeRudeEdit()
Using test = New EditAndContinueTest()
test.AddBaseline(
source:="
Imports System
Class C
Sub F()
Dim f1 = New Func(Of Integer)(<N:0>Function() 1</N:0>)
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)(<N:0>Function() 1.0</N: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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests;
internal static class EditAndContinueValidation
{
internal static void VerifyLineEdits(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
SourceLineUpdate[] lineEdits,
SemanticEditDescription[]? semanticEdits = null,
RudeEditDiagnosticDescription[]? diagnostics = null,
Expand All @@ -31,7 +31,7 @@ internal static void VerifyLineEdits(
}

internal static void VerifyLineEdits(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
SequencePointUpdates[] lineEdits,
SemanticEditDescription[]? semanticEdits = null,
RudeEditDiagnosticDescription[]? diagnostics = null,
Expand All @@ -46,30 +46,30 @@ internal static void VerifyLineEdits(
}

internal static void VerifySemanticDiagnostics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
params RudeEditDiagnosticDescription[] diagnostics)
{
VerifySemanticDiagnostics(editScript, activeStatements: null, targetFrameworks: null, capabilities: null, diagnostics);
}

internal static void VerifySemanticDiagnostics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
ActiveStatementsDescription activeStatements,
params RudeEditDiagnosticDescription[] diagnostics)
{
VerifySemanticDiagnostics(editScript, activeStatements, targetFrameworks: null, capabilities: null, diagnostics);
}

internal static void VerifySemanticDiagnostics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
RudeEditDiagnosticDescription[] diagnostics,
EditAndContinueCapabilities? capabilities)
{
VerifySemanticDiagnostics(editScript, activeStatements: null, targetFrameworks: null, capabilities, diagnostics);
}

internal static void VerifySemanticDiagnostics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
ActiveStatementsDescription? activeStatements = null,
TargetFramework[]? targetFrameworks = null,
EditAndContinueCapabilities? capabilities = null,
Expand All @@ -83,7 +83,7 @@ [new DocumentAnalysisResultsDescription(activeStatements: activeStatements, diag
}

internal static void VerifySemantics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
ActiveStatementsDescription activeStatements,
SemanticEditDescription[] semanticEdits,
EditAndContinueCapabilities? capabilities = null)
Expand All @@ -95,22 +95,22 @@ [new DocumentAnalysisResultsDescription(activeStatements, semanticEdits: semanti
}

internal static void VerifySemantics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
SemanticEditDescription[] semanticEdits,
EditAndContinueCapabilities capabilities)
{
VerifySemantics(editScript, ActiveStatementsDescription.Empty, semanticEdits, capabilities);
}

internal static void VerifySemantics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
params SemanticEditDescription[] semanticEdits)
{
VerifySemantics(editScript, ActiveStatementsDescription.Empty, semanticEdits, capabilities: null);
}

internal static void VerifySemantics(
this EditScript<SyntaxNode> editScript,
this EditScriptDescription editScript,
SemanticEditDescription[] semanticEdits,
RudeEditDiagnosticDescription[] warnings,
EditAndContinueCapabilities? capabilities = null)
Expand All @@ -122,7 +122,7 @@ [new DocumentAnalysisResultsDescription(ActiveStatementsDescription.Empty, seman
}

internal static void VerifySemantics(
EditScript<SyntaxNode>[] editScripts,
EditScriptDescription[] editScripts,
DocumentAnalysisResultsDescription[] results,
TargetFramework[]? targetFrameworks = null,
EditAndContinueCapabilities? capabilities = null)
Expand Down
Loading

0 comments on commit 97d1c60

Please sign in to comment.