diff --git a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs index ae2c82d7968363483836b325be9f2939f73c9f00..d89ad27db7b05ce4fdbe263f6146d5e50a5071ed 100644 --- a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs +++ b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs @@ -311,11 +311,23 @@ private async Task> GetReferencesForMatchingExte private ImmutableArray> GetViableExtensionMethods( ImmutableArray> methodSymbols, SyntaxNode expression, CancellationToken cancellationToken) + { + return GetViableExtensionMethodsWorker(methodSymbols, cancellationToken).WhereAsArray( + s => _owner.IsViableExtensionMethod(s.Symbol, expression, _semanticModel, _syntaxFacts, cancellationToken)); + } + private ImmutableArray> GetViableExtensionMethods( + ImmutableArray> methodSymbols, + ITypeSymbol typeSymbol, CancellationToken cancellationToken) + { + return GetViableExtensionMethodsWorker(methodSymbols, cancellationToken).WhereAsArray( + s => _owner.IsViableExtensionMethod(s.Symbol, typeSymbol)); + } + private ImmutableArray> GetViableExtensionMethodsWorker( + ImmutableArray> methodSymbols, CancellationToken cancellationToken) { return methodSymbols.WhereAsArray( s => s.Symbol.IsExtensionMethod && - s.Symbol.IsAccessibleWithin(_semanticModel.Compilation.Assembly) && - _owner.IsViableExtensionMethod(s.Symbol, expression, _semanticModel, _syntaxFacts, cancellationToken)); + s.Symbol.IsAccessibleWithin(_semanticModel.Compilation.Assembly)); } /// @@ -352,6 +364,39 @@ private async Task> GetReferencesForCollectionIn viableMethods.SelectAsArray(m => m.WithSymbol(m.Symbol.ContainingNamespace))); } + /// + /// Searches for extension methods exactly called 'Select'. Returns + /// s to the s that contain + /// the static classes that those extension methods are contained in. + /// + private async Task> GetReferencesForQueryPatternsAsync(SearchScope searchScope) + { + searchScope.CancellationToken.ThrowIfCancellationRequested(); + + if (_owner.CanAddImportForQuery(_diagnostic, _node)) + { + var type = _owner.GetQueryClauseInfo(_semanticModel, _node, searchScope.CancellationToken); + if (type != null) + { + // find extension methods named "Select" + var symbols = await searchScope.FindDeclarationsAsync( + nameof(Enumerable.Select), nameNode: null, filter: SymbolFilter.Member).ConfigureAwait(false); + + // Note: there is no "desiredName" when doing this. We're not going to do any + // renames of the user code. We're just looking for an extension method called + // "Select", but that name has no bearing on the code in question that we're + // trying to fix up. + var methodSymbols = OfType(symbols).SelectAsArray(s => s.WithDesiredName(null)); + var viableExtensionMethods = GetViableExtensionMethods(methodSymbols, type, searchScope.CancellationToken); + var namespaceSymbols = viableExtensionMethods.SelectAsArray(s => s.WithSymbol(s.Symbol.ContainingNamespace)); + + return GetNamespaceSymbolReferences(searchScope, namespaceSymbols); + } + } + + return ImmutableArray.Empty; + } + internal async Task FindNugetOrReferenceAssemblyReferencesAsync( ArrayBuilder allReferences, CancellationToken cancellationToken) { @@ -603,36 +648,6 @@ private static string GetDesiredName(bool isAttributeSearch, string typeName) return symbolInfo.Symbol != null; } - private async Task> GetReferencesForQueryPatternsAsync(SearchScope searchScope) - { - searchScope.CancellationToken.ThrowIfCancellationRequested(); - - if (!_owner.CanAddImportForQuery(_diagnostic, _node)) - { - return ImmutableArray.Empty; - } - - var type = _owner.GetQueryClauseInfo(_semanticModel, _node, searchScope.CancellationToken); - if (type == null) - { - return ImmutableArray.Empty; - } - - // find extension methods named "Select" - var symbols = await searchScope.FindDeclarationsAsync("Select", nameNode: null, filter: SymbolFilter.Member).ConfigureAwait(false); - - // Note: there is no "desiredName" when doing this. We're not going to do any - // renames of the user code. We're just looking for an extension method called - // "Select", but that name has no bearing on the code in question that we're - // trying to fix up. - var extensionMethodSymbols = OfType(symbols) - .WhereAsArray(s => s.Symbol.IsExtensionMethod && _owner.IsViableExtensionMethod(s.Symbol, type)) - .SelectAsArray(s => s.WithDesiredName(null)); - - return GetNamespaceSymbolReferences( - searchScope, extensionMethodSymbols.SelectAsArray(s => s.WithSymbol(s.Symbol.ContainingNamespace))); - } - private ImmutableArray GetNamespaceSymbolReferences( SearchScope scope, ImmutableArray> namespaces) {