diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs index e9ed78e02f952..360612057dd26 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs @@ -607,6 +607,13 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, return; } + body = ExtensionMethodReferenceRewriter.Rewrite(body); + + if (body.HasErrors) + { + return; + } + // Variables may have been captured by lambdas in the original method // or in the expression, and we need to preserve the existing values of // those variables in the expression. This requires rewriting the variables diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs index 9fdba7ca87e7d..132fdc0b7fa21 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ExpressionCompilerTests.cs @@ -11872,5 +11872,127 @@ public static int P3 Assert.Equal("error CS0103: The name 'field' does not exist in the current context", error); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/81171")] + public void Extension_01() + { + var source = """ +public class C +{ + public static void Main() + { +#line 999 + var y = 5.Property; + System.Console.WriteLine(y); + } +} + +public static class E +{ + extension(int i) + { + public int Property => 42; + } +} +"""; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugExe); + + // First verify the base compilation is valid + compilation0.VerifyEmitDiagnostics(); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.Main", atLineNumber: 999); + + ResultProperties resultProperties; + string error; + ImmutableArray missingAssemblyIdentities; + var testData = new CompilationTestData(); + + var result = context.CompileExpression( + "5.Property", + DkmEvaluationFlags.TreatAsExpression, + NoAliases, + DebuggerDiagnosticFormatter.Instance, + out resultProperties, + out error, + out missingAssemblyIdentities, + EnsureEnglishUICulture.PreferredOrNull, + testData: testData); + + Assert.Null(error); + + testData.GetMethodData("<>x.<>m0").VerifyIL(""" +{ + // Code size 7 (0x7) + .maxstack 1 + .locals init (int V_0) //y + IL_0000: ldc.i4.5 + IL_0001: call "int E.get_Property(int)" + IL_0006: ret +} +"""); + }); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/81171")] + public void Extension_02() + { + var source = """ +public class C +{ + public static void Main() + { +#line 999 + var y = int.Method(); + System.Console.WriteLine(y); + } +} + +public static class E +{ + extension(int) + { + public static int Method() => 42; + } +} +"""; + var compilation0 = CreateCompilation(source, options: TestOptions.DebugExe); + + // First verify the base compilation is valid + compilation0.VerifyEmitDiagnostics(); + + WithRuntimeInstance(compilation0, runtime => + { + var context = CreateMethodContext(runtime, "C.Main", atLineNumber: 999); + ResultProperties resultProperties; + string error; + ImmutableArray missingAssemblyIdentities; + var testData = new CompilationTestData(); + + var result = context.CompileExpression( + "int.Method()", + DkmEvaluationFlags.TreatAsExpression, + NoAliases, + DebuggerDiagnosticFormatter.Instance, + out resultProperties, + out error, + out missingAssemblyIdentities, + EnsureEnglishUICulture.PreferredOrNull, + testData: testData); + + Assert.Null(error); + + testData.GetMethodData("<>x.<>m0").VerifyIL(""" +{ + // Code size 6 (0x6) + .maxstack 1 + .locals init (int V_0) //y + IL_0000: call "int E.Method()" + IL_0005: ret +} +"""); + }); + } } }