private static ImmutableArray<ISymbol> GetSymbolsOffOfBoundExpression( CSharpSyntaxContext context, ExpressionSyntax originalExpression, ExpressionSyntax expression, SymbolInfo leftHandBinding, INamespaceOrTypeSymbol container, CancellationToken cancellationToken) { var useBaseReferenceAccessibility = false; var excludeInstance = false; var excludeStatic = false; var symbol = leftHandBinding.GetBestOrAllSymbols().FirstOrDefault(); if (symbol != null) { // If the thing on the left is a type, namespace or alias and the original // expression was parenthesized, we shouldn't show anything in IntelliSense. if (originalExpression.IsKind(SyntaxKind.ParenthesizedExpression) && symbol.MatchesKind(SymbolKind.NamedType, SymbolKind.Namespace, SymbolKind.Alias)) { return ImmutableArray<ISymbol>.Empty; } // If the thing on the left is a lambda expression, we shouldn't show anything. if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).MethodKind == MethodKind.AnonymousFunction) { return ImmutableArray<ISymbol>.Empty; } // If the thing on the left is an event that can't be used as a field, we shouldn't show anything if (symbol.Kind == SymbolKind.Event && !context.SemanticModel.IsEventUsableAsField(originalExpression.SpanStart, (IEventSymbol)symbol)) { return ImmutableArray<ISymbol>.Empty; } // If the thing on the left is a this parameter (e.g. this or base) and we're in a static context, // we shouldn't show anything if (symbol.IsThisParameter() && expression.IsInStaticContext()) { return ImmutableArray<ISymbol>.Empty; } // What is the thing on the left? switch (symbol.Kind) { case SymbolKind.NamedType: case SymbolKind.Namespace: excludeInstance = true; container = (INamespaceOrTypeSymbol)symbol; break; case SymbolKind.Alias: excludeInstance = true; container = ((IAliasSymbol)symbol).Target; break; case SymbolKind.Parameter: var parameter = (IParameterSymbol)symbol; excludeStatic = true; // case: // base.| if (parameter.IsThis && !object.Equals(parameter.Type, container)) { useBaseReferenceAccessibility = true; } break; default: excludeStatic = true; break; } } else if (container != null) { excludeStatic = true; } else { return ImmutableArray<ISymbol>.Empty; } Debug.Assert(!excludeInstance || !excludeStatic); Debug.Assert(!excludeInstance || !useBaseReferenceAccessibility); // nameof(X.| // Show static and instance members. if (context.IsNameOfContext) { excludeInstance = false; excludeStatic = false; } var position = originalExpression.SpanStart; var symbols = useBaseReferenceAccessibility ? context.SemanticModel.LookupBaseMembers(position) : excludeInstance ? context.SemanticModel.LookupStaticMembers(position, container) : SuppressDefaultTupleElements(container, context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true)); // If we're showing instance members, don't include nested types return excludeStatic ? symbols.WhereAsArray(s => !s.IsStatic && !(s is ITypeSymbol)) : symbols; }
private static IEnumerable <ISymbol> GetSymbolsOffOfBoundExpression( CSharpSyntaxContext context, ExpressionSyntax originalExpression, ExpressionSyntax expression, SymbolInfo leftHandBinding, INamespaceOrTypeSymbol container, CancellationToken cancellationToken) { var useBaseReferenceAccessibility = false; var excludeInstance = false; var excludeStatic = false; var symbol = leftHandBinding.GetBestOrAllSymbols().FirstOrDefault(); if (symbol != null) { // If the thing on the left is a type, namespace or alias and the original // expression was parenthesized, we shouldn't show anything in IntelliSense. if (originalExpression.IsKind(SyntaxKind.ParenthesizedExpression) && symbol.MatchesKind(SymbolKind.NamedType, SymbolKind.Namespace, SymbolKind.Alias)) { return(SpecializedCollections.EmptyEnumerable <ISymbol>()); } // If the thing on the left is a lambda expression, we shouldn't show anything. if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).MethodKind == MethodKind.AnonymousFunction) { return(SpecializedCollections.EmptyEnumerable <ISymbol>()); } // If the thing on the left is an event that can't be used as a field, we shouldn't show anything if (symbol.Kind == SymbolKind.Event && !context.SemanticModel.IsEventUsableAsField(originalExpression.SpanStart, (IEventSymbol)symbol)) { return(SpecializedCollections.EmptyEnumerable <ISymbol>()); } // If the thing on the left is a this parameter (e.g. this or base) and we're in a static context, // we shouldn't show anything if (symbol.IsThisParameter() && expression.IsInStaticContext()) { return(SpecializedCollections.EmptyEnumerable <ISymbol>()); } // What is the thing on the left? switch (symbol.Kind) { case SymbolKind.NamedType: case SymbolKind.Namespace: excludeInstance = true; container = (INamespaceOrTypeSymbol)symbol; break; case SymbolKind.Alias: excludeInstance = true; container = ((IAliasSymbol)symbol).Target; break; case SymbolKind.Parameter: var parameter = (IParameterSymbol)symbol; excludeStatic = true; // case: // base.| if (parameter.IsThis && !object.Equals(parameter.Type, container)) { useBaseReferenceAccessibility = true; } break; default: excludeStatic = true; break; } } else if (container != null) { excludeStatic = true; } else { return(SpecializedCollections.EmptyEnumerable <ISymbol>()); } Debug.Assert(!excludeInstance || !excludeStatic); Debug.Assert(!excludeInstance || !useBaseReferenceAccessibility); // nameof(X.| // Show static and instance members. if (context.IsNameOfContext) { excludeInstance = false; excludeStatic = false; } var position = originalExpression.SpanStart; IEnumerable <ISymbol> symbols = useBaseReferenceAccessibility ? context.SemanticModel.LookupBaseMembers(position) : excludeInstance ? context.SemanticModel.LookupStaticMembers(position, container) : context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true); // If we're showing instance members, don't include nested types return(excludeStatic ? symbols.Where(s => !s.IsStatic && !(s is ITypeSymbol)) : symbols); }