diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests_ExtensionMethods.cs b/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests_ExtensionMethods.cs index f8c135203d06d..81eea70188659 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests_ExtensionMethods.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/AddUsing/AddUsingTests_ExtensionMethods.cs @@ -76,5 +76,115 @@ public void TestExtensionWithThePresenceOfTheSameNameExtensionPrivateMethod() @"using NS2; namespace NS1 { class Program { void Main() { [|new C().Foo(4);|] } } class C { } } namespace NS2 { static class CExt { private static void Foo(this NS1.C c, int x) { } } } namespace NS3 { static class CExt { public static void Foo(this NS1.C c, int x) { } } } ", @"using NS2; using NS3; namespace NS1 { class Program { void Main() { new C().Foo(4); } } class C { } } namespace NS2 { static class CExt { private static void Foo(this NS1.C c, int x) { } } } namespace NS3 { static class CExt { public static void Foo(this NS1.C c, int x) { } } } "); } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { [|1|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { 1 } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod2() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { 1 , 2 , [|3|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { 1 , 2 , 3 } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod3() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { 1 , [|2|] , 3 } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { 1 , 2 , 3 } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod4() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , [|{ 4 , 5 , 6 }|] , { 7 , 8 , 9 } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { 4 , 5 , 6 } , { 7 , 8 , 9 } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod5() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { 4 , 5 , 6 } , [|{ 7 , 8 , 9 }|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { 4 , 5 , 6 } , { 7 , 8 , 9 } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod6() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { ""Four"" , ""Five"" , ""Six"" } , [|{ '7' , '8' , '9' }|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod7() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , [|{ ""Four"" , ""Five"" , ""Six"" }|] , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod8() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { [|{ 1 , 2 , 3 }|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod9() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { [|""This""|] } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { ""This"" } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod10() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { [|{ 1 , 2 , 3 }|] , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } namespace Ext2 { static class Extensions { public static void Add ( this X x , object [ ] i ) { } } } ", +@"using System ; using System . Collections ; using Ext ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } namespace Ext2 { static class Extensions { public static void Add ( this X x , object [ ] i ) { } } } ", +null, 0, true, true, null, false, null); + } + + [WorkItem(269)] + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsAddUsing)] + public void TestAddUsingForAddExentionMethod11() + { + Test( +@"using System ; using System . Collections ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { [|{ 1 , 2 , 3 }|] , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } namespace Ext2 { static class Extensions { public static void Add ( this X x , object [ ] i ) { } } } ", +@"using System ; using System . Collections ; using Ext2 ; class X : IEnumerable { public IEnumerator GetEnumerator ( ) { new X { { 1 , 2 , 3 } , { ""Four"" , ""Five"" , ""Six"" } , { '7' , '8' , '9' } } ; return null ; } } namespace Ext { static class Extensions { public static void Add ( this X x , int i ) { } } } namespace Ext2 { static class Extensions { public static void Add ( this X x , object [ ] i ) { } } } ", +null, 1, true, true, null, false, null); + } } } diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb index 24e1f8da58502..691f719e27e3c 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests.vb @@ -997,6 +997,69 @@ End Module TestMissing(initial) End Sub + + + Public Sub TestAddImportForAddExentionMethod() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {1}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {1} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod2() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {1, 2, 3}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {1, 2, 3} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod3() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod4() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {{1, 2, 3}, {""Four"", ""Five"", ""Six""}, {7, 8, 9}}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {{1, 2, 3}, {""Four"", ""Five"", ""Six""}, {7, 8, 9}} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod5() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {""This""}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {""This""} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod6() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {""This""}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace \n Namespace Ext2 \n Module Extensions \n \n Public Sub Add(x As X, i As Object()) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {""This""} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace \n Namespace Ext2 \n Module Extensions \n \n Public Sub Add(x As X, i As Object()) \n End Sub \n End Module \n End Namespace"), +Nothing, 0, True, True, Nothing, False, Nothing) + End Sub + + + + Public Sub TestAddImportForAddExentionMethod7() + Test( +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X [|From {""This""}|] \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace \n Namespace Ext2 \n Module Extensions \n \n Public Sub Add(x As X, i As Object()) \n End Sub \n End Module \n End Namespace"), +NewLines("Imports System \n Imports System.Collections \n Imports System.Runtime.CompilerServices \n Imports Ext2 \n Class X \n Implements IEnumerable \n Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator \n Dim a = New X From {""This""} \n Return a.GetEnumerator() \n End Function \n End Class \n Namespace Ext \n Module Extensions \n \n Public Sub Add(x As X, i As Integer) \n End Sub \n End Module \n End Namespace \n Namespace Ext2 \n Module Extensions \n \n Public Sub Add(x As X, i As Object()) \n End Sub \n End Module \n End Namespace"), +Nothing, 1, True, True, Nothing, False, Nothing) + End Sub + Public Class AddImportTestsWithAddImportDiagnosticProvider Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest @@ -1056,7 +1119,6 @@ Class MultiDictionary(Of K, V) End Sub End Class") End Sub - End Class End Class End Namespace diff --git a/src/Features/CSharp/CodeFixes/AddImport/CSharpAddImportCodeFixProvider.cs b/src/Features/CSharp/CodeFixes/AddImport/CSharpAddImportCodeFixProvider.cs index 61126826c1d13..59a159ab23480 100644 --- a/src/Features/CSharp/CodeFixes/AddImport/CSharpAddImportCodeFixProvider.cs +++ b/src/Features/CSharp/CodeFixes/AddImport/CSharpAddImportCodeFixProvider.cs @@ -159,6 +159,10 @@ protected override bool CanAddImportForMethod(Diagnostic diagnostic, ISyntaxFact { node = (node as MemberBindingExpressionSyntax).Name; } + else if (node.Parent.IsKind(SyntaxKind.CollectionInitializerExpression)) + { + return true; + } break; case CS0122: @@ -559,7 +563,14 @@ protected override bool IsViableExtensionMethod(IMethodSymbol method, SyntaxNode var leftExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(expression) ?? syntaxFacts.GetExpressionOfConditionalMemberAccessExpression(expression); if (leftExpression == null) { - return false; + if (expression.IsKind(SyntaxKind.CollectionInitializerExpression)) + { + leftExpression = expression.GetAncestor(); + } + else + { + return false; + } } var semanticInfo = semanticModel.GetTypeInfo(leftExpression, cancellationToken); @@ -609,5 +620,21 @@ private bool IsViablePropertyOrField(ISymbol propertyOrField, SyntaxNode express return string.Compare(propertyOrField.ContainingType.Name, leftName.Identifier.Text, this.IgnoreCase) == 0; } + + internal override bool IsAddMethodContext(SyntaxNode node, SemanticModel semanticModel) + { + if (node.Parent.IsKind(SyntaxKind.CollectionInitializerExpression)) + { + var objectCreationExpressionSyntax = node.GetAncestor(); + if (objectCreationExpressionSyntax == null) + { + return false; + } + + return true; + } + + return false; + } } } diff --git a/src/Features/Core/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs b/src/Features/Core/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs index 3e0195b11f3c6..7a8286891ff49 100644 --- a/src/Features/Core/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs +++ b/src/Features/Core/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs @@ -33,6 +33,8 @@ internal abstract partial class AbstractAddImportCodeFixProvider : CodeFixProvid protected abstract IEnumerable GetProposedTypes(string name, List accessibleTypeSymbols, SemanticModel semanticModel, ISet namespacesInScope); internal abstract bool IsViableField(IFieldSymbol field, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken); internal abstract bool IsViableProperty(IPropertySymbol property, SyntaxNode expression, SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken); + internal abstract bool IsAddMethodContext(SyntaxNode node, SemanticModel semanticModel); + public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { @@ -237,14 +239,24 @@ private async Task> GetNamespacesForMatchingExtens var expression = node.Parent; + var extensionMethods = SpecializedCollections.EmptyEnumerable(); var symbols = await GetSymbolsAsync(project, node, semanticModel, syntaxFacts, cancellationToken).ConfigureAwait(false); - if (symbols != null) { - return FilterForExtensionMethods(semanticModel, namespacesInScope, syntaxFacts, expression, symbols, cancellationToken); + extensionMethods = FilterForExtensionMethods(semanticModel, namespacesInScope, syntaxFacts, expression, symbols, cancellationToken); } - return null; + var addMethods = SpecializedCollections.EmptyEnumerable(); + var methodSymbols = await GetAddMethodsAsync(project, diagnostic, node, semanticModel, namespacesInScope, syntaxFacts, expression, cancellationToken).ConfigureAwait(false); + if (methodSymbols != null) + { + addMethods = GetProposedNamespaces( + methodSymbols.Select(s => s.ContainingNamespace), + semanticModel, + namespacesInScope); + } + + return extensionMethods.Concat(addMethods); } private async Task> GetNamespacesForMatchingFieldsAndPropertiesAsync( @@ -305,16 +317,51 @@ private Task> GetSymbolsAsync( // See if the name binds. If it does, there's nothing further we need to do. if (ExpressionBinds(node, semanticModel, cancellationToken, checkForExtensionMethods: true)) { - return null; + return SpecializedTasks.EmptyEnumerable(); } string name; int arity; syntaxFacts.GetNameAndArityOfSimpleName(node, out name, out arity); + if (name == null) + { + return SpecializedTasks.EmptyEnumerable(); + } return SymbolFinder.FindDeclarationsAsync(project, name, this.IgnoreCase, SymbolFilter.Member, cancellationToken); } + private async Task> GetAddMethodsAsync( + Project project, + Diagnostic diagnostic, + SyntaxNode node, + SemanticModel semanticModel, + ISet namespacesInScope, + ISyntaxFactsService syntaxFacts, + SyntaxNode expression, + CancellationToken cancellationToken) + { + string name; + int arity; + syntaxFacts.GetNameAndArityOfSimpleName(node, out name, out arity); + if (name != null) + { + return SpecializedCollections.EmptyEnumerable(); + } + + if (IsAddMethodContext(node, semanticModel)) + { + var symbols = await SymbolFinder.FindDeclarationsAsync(project, "Add", this.IgnoreCase, SymbolFilter.Member, cancellationToken).ConfigureAwait(false); + return symbols + .OfType() + .Where(method => method.IsExtensionMethod && + method.ContainingType?.IsAccessibleWithin(semanticModel.Compilation.Assembly) == true && + IsViableExtensionMethod(method, expression, semanticModel, syntaxFacts, cancellationToken)); + } + + return SpecializedCollections.EmptyEnumerable(); + } + private IEnumerable FilterForExtensionMethods(SemanticModel semanticModel, ISet namespacesInScope, ISyntaxFactsService syntaxFacts, SyntaxNode expression, IEnumerable symbols, CancellationToken cancellationToken) { var extensionMethodSymbols = symbols diff --git a/src/Features/VisualBasic/CodeFixes/AddImport/VisualBasicAddImportCodeFixProvider.vb b/src/Features/VisualBasic/CodeFixes/AddImport/VisualBasicAddImportCodeFixProvider.vb index 96e296a20c06d..c15f9729a6c8a 100644 --- a/src/Features/VisualBasic/CodeFixes/AddImport/VisualBasicAddImportCodeFixProvider.vb +++ b/src/Features/VisualBasic/CodeFixes/AddImport/VisualBasicAddImportCodeFixProvider.vb @@ -60,6 +60,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport ''' Friend Const BC36610 = "BC36610" + ''' + ''' Cannot initialize the type 'A' with a collection initializer because it does not have an accessible 'Add' method + ''' + Friend Const BC36719 = "BC36719" + ''' ''' Option Strict On disallows implicit conversions from 'Integer' to 'String'. ''' @@ -82,7 +87,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport Public Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String) Get - Return ImmutableArray.Create(BC30002, BC30451, BC30456, BC32042, BC36593, BC32045, BC30389, BC31504, BC36610, BC30512, BC30390, BC42309, BC30182) + Return ImmutableArray.Create(BC30002, BC30451, BC30456, BC32042, BC36593, BC32045, BC30389, BC31504, BC36610, BC36719, BC30512, BC30390, BC42309, BC30182) End Get End Property @@ -117,6 +122,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport node = parent.Expression End If Exit Select + Case BC36719 + If node.IsKind(SyntaxKind.ObjectCollectionInitializer) Then + Return True + End If + + Return False Case Else Return False End Select @@ -292,9 +303,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport If syntaxFacts.IsInvocationExpression(expression) Then leftExpressionType = semanticModel.GetEnclosingNamedType(expression.SpanStart, cancellationToken) Else - Dim leftExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(expression) - If leftExpression Is Nothing Then - Return False + Dim leftExpression As SyntaxNode + If TypeOf expression Is ObjectCreationExpressionSyntax Then + leftExpression = expression + Else + leftExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(expression) + If leftExpression Is Nothing Then + Return False + End If End If Dim semanticInfo = semanticModel.GetTypeInfo(leftExpression, cancellationToken) @@ -316,5 +332,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.AddImport Friend Overrides Function IsViableProperty([property] As IPropertySymbol, expression As SyntaxNode, semanticModel As SemanticModel, syntaxFacts As ISyntaxFactsService, cancellationToken As CancellationToken) As Boolean Return False End Function + + Friend Overrides Function IsAddMethodContext(node As SyntaxNode, semanticModel As SemanticModel) As Boolean + If node.IsKind(SyntaxKind.ObjectCollectionInitializer) Then + Dim objectCreateExpression = node.GetAncestor(Of ObjectCreationExpressionSyntax) + If objectCreateExpression Is Nothing Then + Return False + End If + + Return True + End If + + Return False + End Function End Class End Namespace