From c30102b3260fc6a11fe80289d1a84f5390aa0aa5 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Fri, 1 May 2015 16:20:55 -0700 Subject: [PATCH] Allow correct type to be used when generating a variable Fixes #642 --- .../GenerateVariable/GenerateVariableTests.cs | 26 +++++++++++++++++++ .../GenerateVariable/GenerateVariableTests.vb | 24 +++++++++++++++++ .../AbstractGenerateVariableService.State.cs | 20 ++++++++++---- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateVariable/GenerateVariableTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateVariable/GenerateVariableTests.cs index fd439e72ac8..2318b85af00 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateVariable/GenerateVariableTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateVariable/GenerateVariableTests.cs @@ -2784,5 +2784,31 @@ public void TestGenerateLocalInDictionaryInitializer3() @"using System . Collections . Generic ; class Program { static void Main ( string [ ] args ) { int i = 0 ; var x = new Dictionary < string , int > { [ ""Zero"" ] = i } ; } } ", index: 3); } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateVariable)] + public void TestGenerateVariableFromLambda() + { + Test( +@"using System ; class Program { static void Main ( string [ ] args ) { [|foo|] = ( ) => { return 0 ; } ; } } ", +@"using System ; class Program { private static Func < int > foo ; static void Main ( string [ ] args ) { foo = ( ) => { return 0 ; } ; } } "); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateVariable)] + public void TestGenerateVariableFromLambda2() + { + Test( +@"using System ; class Program { static void Main ( string [ ] args ) { [|foo|] = ( ) => { return 0 ; } ; } } ", +@"using System ; class Program { public static Func < int > foo { get ; private set ; } static void Main ( string [ ] args ) { foo = ( ) => { return 0 ; } ; } } ", +index: 1); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateVariable)] + public void TestGenerateVariableFromLambda3() + { + Test( +@"using System ; class Program { static void Main ( string [ ] args ) { [|foo|] = ( ) => { return 0 ; } ; } } ", +@"using System ; class Program { static void Main ( string [ ] args ) { Func < int > foo = ( ) => { return 0 ; } ; } } ", +index: 2); + } } } diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb index 5c86a5cfd98..1eb8f4a4b57 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/GenerateVariable/GenerateVariableTests.vb @@ -909,5 +909,29 @@ NewLines("Module C \n Sub Test() \n If TypeOf [|B|] Is String Then \n End If \n NewLines("Module C \n Sub Test() \n Dim B As String = Nothing \n If TypeOf B Is String Then \n End If \n End Sub \n End Module"), index:=3) End Sub + + + Public Sub TestGenerateVariableFromLambda() + Test( +NewLines("Class [Class] \n Private Sub Method(i As Integer) \n [|foo|] = Function() \n Return 2 \n End Function \n End Sub \n End Class"), +NewLines("Imports System\n\nClass [Class]\n Private foo As Func(Of Integer)\n\n Private Sub Method(i As Integer)\n foo = Function()\n Return 2\n End Function\n End Sub\nEnd Class"), +index:=0) + End Sub + + + Public Sub TestGenerateVariableFromLambda2() + Test( +NewLines("Class [Class] \n Private Sub Method(i As Integer) \n [|foo|] = Function() \n Return 2 \n End Function \n End Sub \n End Class"), +NewLines("Imports System\n\nClass [Class]\n Public Property foo As Func(Of Integer)\n\n Private Sub Method(i As Integer)\n foo = Function()\n Return 2\n End Function\n End Sub\nEnd Class"), +index:=1) + End Sub + + + Public Sub TestGenerateVariableFromLambda3() + Test( +NewLines("Class [Class] \n Private Sub Method(i As Integer) \n [|foo|] = Function() \n Return 2 \n End Function \n End Sub \n End Class"), +NewLines("Class [Class] \n Private Sub Method(i As Integer)\n Dim foo As System.Func(Of Integer)\n foo = Function() \n Return 2 \n End Function \n End Sub \n End Class"), +index:=2) + End Sub End Class End Namespace diff --git a/src/Features/Core/GenerateMember/GenerateVariable/AbstractGenerateVariableService.State.cs b/src/Features/Core/GenerateMember/GenerateVariable/AbstractGenerateVariableService.State.cs index 15cb38492a0..e73ebcf15ca 100644 --- a/src/Features/Core/GenerateMember/GenerateVariable/AbstractGenerateVariableService.State.cs +++ b/src/Features/Core/GenerateMember/GenerateVariable/AbstractGenerateVariableService.State.cs @@ -273,8 +273,9 @@ internal bool CanGenerateLocal() document.SemanticModel, this.SimpleNameOrMemberAccessExpressionOpt, objectAsDefault: true, cancellationToken: cancellationToken); + var compilation = document.SemanticModel.Compilation; inferredType = inferredType.SpecialType == SpecialType.System_Void - ? document.SemanticModel.Compilation.ObjectType + ? compilation.ObjectType : inferredType; if (this.IsInConditionalAccessExpression) @@ -282,17 +283,26 @@ internal bool CanGenerateLocal() inferredType = inferredType.RemoveNullableIfPresent(); } + if (inferredType.IsDelegateType() && !inferredType.CanBeReferencedByName) + { + var namedDelegateType = inferredType.GetDelegateType(compilation)?.DelegateInvokeMethod?.ConvertToType(compilation); + if (namedDelegateType != null) + { + inferredType = namedDelegateType; + } + } + // Substitute 'object' for all captured method type parameters. Note: we may need to // do this for things like anonymous types, as well as captured type parameters that // aren't in scope in the destination type. var capturedMethodTypeParameters = inferredType.GetReferencedMethodTypeParameters(); var mapping = capturedMethodTypeParameters.ToDictionary(tp => tp, - tp => document.SemanticModel.Compilation.ObjectType); + tp => compilation.ObjectType); - this.TypeMemberType = inferredType.SubstituteTypes(mapping, document.SemanticModel.Compilation); + this.TypeMemberType = inferredType.SubstituteTypes(mapping, compilation); var availableTypeParameters = this.TypeToGenerateIn.GetAllTypeParameters(); this.TypeMemberType = TypeMemberType.RemoveUnavailableTypeParameters( - document.SemanticModel.Compilation, availableTypeParameters); + compilation, availableTypeParameters); var enclosingMethodSymbol = document.SemanticModel.GetEnclosingSymbol(this.SimpleNameOrMemberAccessExpressionOpt.SpanStart, cancellationToken); if (enclosingMethodSymbol != null && enclosingMethodSymbol.TypeParameters != null && enclosingMethodSymbol.TypeParameters.Count() != 0) @@ -301,7 +311,7 @@ internal bool CanGenerateLocal() combinedTypeParameters.AddRange(availableTypeParameters); combinedTypeParameters.AddRange(enclosingMethodSymbol.TypeParameters); this.LocalType = inferredType.RemoveUnavailableTypeParameters( - document.SemanticModel.Compilation, combinedTypeParameters); + compilation, combinedTypeParameters); } else { -- GitLab