private async Task <IList <SymbolReference> > GetNamespacesForMatchingTypesAsync(SearchScope searchScope) { searchScope.CancellationToken.ThrowIfCancellationRequested(); TSimpleNameSyntax nameNode; if (!_owner.CanAddImportForType(_diagnostic, _node, out nameNode)) { return(null); } string name; int arity; bool inAttributeContext, hasIncompleteParentMember; CalculateContext(nameNode, _syntaxFacts, out name, out arity, out inAttributeContext, out hasIncompleteParentMember); var symbols = await GetTypeSymbols(searchScope, name, nameNode, inAttributeContext).ConfigureAwait(false); if (symbols == null) { return(null); } return(GetNamespacesForMatchingTypesAsync(searchScope, arity, inAttributeContext, hasIncompleteParentMember, symbols)); }
/// <summary> /// Searches for types that match the name the user has written. Returns <see cref="SymbolReference"/>s /// to the <see cref="INamespaceSymbol"/>s or <see cref="INamedTypeSymbol"/>s those types are /// contained in. /// </summary> private async Task <ImmutableArray <SymbolReference> > GetReferencesForMatchingTypesAsync(SearchScope searchScope) { searchScope.CancellationToken.ThrowIfCancellationRequested(); if (!_owner.CanAddImportForType(_diagnostic, _node, out var nameNode)) { return(ImmutableArray <SymbolReference> .Empty); } CalculateContext(nameNode, _syntaxFacts, out var name, out var arity, out var inAttributeContext, out var hasIncompleteParentMember); if (ExpressionBinds(nameNode, checkForExtensionMethods: false, cancellationToken: searchScope.CancellationToken)) { // If the expression bound, there's nothing to do. return(ImmutableArray <SymbolReference> .Empty); } var symbols = await searchScope.FindDeclarationsAsync(name, nameNode, SymbolFilter.Type).ConfigureAwait(false); // also lookup type symbols with the "Attribute" suffix if necessary. if (inAttributeContext) { var attributeSymbols = await searchScope.FindDeclarationsAsync(name + AttributeSuffix, nameNode, SymbolFilter.Type).ConfigureAwait(false); symbols = symbols.AddRange( attributeSymbols.Select(r => r.WithDesiredName(r.DesiredName.GetWithoutAttributeSuffix(isCaseSensitive: false)))); } var typeSymbols = OfType <ITypeSymbol>(symbols); // Only keep symbols which are accessible from the current location. var accessibleTypeSymbols = typeSymbols.WhereAsArray( s => ArityAccessibilityAndAttributeContextAreCorrect( s.Symbol, arity, inAttributeContext, hasIncompleteParentMember)); // These types may be contained within namespaces, or they may be nested // inside generic types. Record these namespaces/types if it would be // legal to add imports for them. var typesContainedDirectlyInNamespaces = accessibleTypeSymbols.WhereAsArray(s => s.Symbol.ContainingSymbol is INamespaceSymbol); var typesContainedDirectlyInTypes = accessibleTypeSymbols.WhereAsArray(s => s.Symbol.ContainingType != null); var namespaceReferences = GetNamespaceSymbolReferences(searchScope, typesContainedDirectlyInNamespaces.SelectAsArray(r => r.WithSymbol(r.Symbol.ContainingNamespace))); var typeReferences = typesContainedDirectlyInTypes.SelectAsArray( r => searchScope.CreateReference(r.WithSymbol(r.Symbol.ContainingType))); return(namespaceReferences.Concat(typeReferences)); }