> GetElementAccessExpressionParameterLists(
            SemanticModel semanticModel,
            int position,
            ElementAccessExpressionSyntax elementAccessExpression,
            CancellationToken cancellationToken
        )
        {
            var expressionSymbol = semanticModel
                .GetSymbolInfo(elementAccessExpression.Expression, cancellationToken)
                .GetAnySymbol();
            var expressionType =
                semanticModel.GetTypeInfo(
                    elementAccessExpression.Expression,
                    cancellationToken
                ).Type;

            if (expressionSymbol != null && expressionType != null)
            {
                var indexers = semanticModel
                    .LookupSymbols(position, expressionType, WellKnownMemberNames.Indexer)
                    .OfType<IPropertySymbol>();
                var within = semanticModel.GetEnclosingNamedTypeOrAssembly(
                    position,
                    cancellationToken
                );
                if (within != null)
                {
                    return indexers
                        .Where(i => i.IsAccessibleWithin(within, throughType: expressionType))
                        .Select(i => i.Parameters);
                }
            }

            return null;
        }
        private IEnumerable <ImmutableArray <IParameterSymbol> > GetInvocationExpressionParameterLists(
            SemanticModel semanticModel,
            int position,
            InvocationExpressionSyntax invocationExpression,
            CancellationToken cancellationToken)
        {
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);

            if (within != null)
            {
                var methodGroup    = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken).OfType <IMethodSymbol>();
                var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol;

                if (methodGroup.Any())
                {
                    return(methodGroup.Where(m => m.IsAccessibleWithin(within))
                           .Select(m => m.Parameters));
                }
                else if (expressionType.IsDelegateType())
                {
                    var delegateType = expressionType;
                    return(SpecializedCollections.SingletonEnumerable(delegateType.DelegateInvokeMethod.Parameters));
                }
            }

            return(null);
        }
        private IEnumerable <ISymbol> GetAttributeNamedParameters(
            SemanticModel semanticModel,
            int position,
            AttributeSyntax attribute,
            CancellationToken cancellationToken)
        {
            var within        = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            var attributeType = semanticModel.GetTypeInfo(attribute, cancellationToken).Type as INamedTypeSymbol;

            return(attributeType.GetAttributeNamedParameters(semanticModel.Compilation, within));
        }
        private IEnumerable <ImmutableArray <IParameterSymbol> > GetParameterLists(
            SemanticModel semanticModel,
            int position,
            AttributeSyntax attribute,
            CancellationToken cancellationToken)
        {
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);

            if (within != null && semanticModel.GetTypeInfo(attribute, cancellationToken).Type is INamedTypeSymbol attributeType)
            {
                return(attributeType.InstanceConstructors.Where(c => c.IsAccessibleWithin(within))
                       .Select(c => c.Parameters));
            }

            return(SpecializedCollections.EmptyEnumerable <ImmutableArray <IParameterSymbol> >());
        }
Exemplo n.º 5
0
        ParameterHintingResult HandleObjectCreationExpression(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
        {
            // var info = semanticModel.GetSymbolInfo(node, cancellationToken);
            var result = new ParameterHintingResult(node.SpanStart);
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(node.SpanStart, cancellationToken);

            var targetTypeInfo = semanticModel.GetTypeInfo(node);

            if (targetTypeInfo.Type != null)
            {
                foreach (IMethodSymbol c in targetTypeInfo.Type.GetMembers().OfType <IMethodSymbol>().Where(m => m.MethodKind == MethodKind.Constructor))
                {
                    if (c.IsAccessibleWithin(within))
                    {
                        result.AddData(factory.CreateConstructorProvider(c));
                    }
                }
            }
            return(result);
        }
        > GetRecordBaseTypeParameterLists(
            SemanticModel semanticModel,
            int position,
            PrimaryConstructorBaseTypeSyntax recordBaseType,
            CancellationToken cancellationToken
        )
        {
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
            if (within != null)
            {
                var type =
                    semanticModel.GetTypeInfo(recordBaseType.Type, cancellationToken).Type
                    as INamedTypeSymbol;

                return type?.InstanceConstructors.Where(m => m.IsAccessibleWithin(within))
                    .Select(m => m.Parameters);
            }

            return null;
        }
Exemplo n.º 7
0
        ParameterHintingResult HandleElementAccessExpression(SemanticModel semanticModel, ElementAccessExpressionSyntax node, CancellationToken cancellationToken)
        {
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(node.SpanStart, cancellationToken);

            var         targetTypeInfo = semanticModel.GetTypeInfo(node.Expression);
            ITypeSymbol type           = targetTypeInfo.Type;

            if (type == null)
            {
                return(ParameterHintingResult.Empty);
            }

            var result = new ParameterHintingResult(node.SpanStart);

            if (type.TypeKind == TypeKind.Array)
            {
                result.AddData(factory.CreateArrayDataProvider((IArrayTypeSymbol)type));
                return(result);
            }

            var addedProperties = new List <IPropertySymbol> ();

            for (; type != null; type = type.BaseType)
            {
                foreach (var indexer in type.GetMembers().OfType <IPropertySymbol> ().Where(p => p.IsIndexer))
                {
                    if (addedProperties.Any(added => SignatureComparer.HaveSameSignature(indexer, added, true)))
                    {
                        continue;
                    }

                    if (indexer.IsAccessibleWithin(within))
                    {
                        addedProperties.Add(indexer);
                        result.AddData(factory.CreateIndexerParameterDataProvider(indexer, node));
                    }
                }
            }
            return(result);
        }
Exemplo n.º 8
0
        ParameterHintingResult HandleConstructorInitializer(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken)
        {
            var info           = semanticModel.GetSymbolInfo(node, cancellationToken);
            var result         = new ParameterHintingResult(node.SpanStart);
            var resolvedMethod = info.Symbol as IMethodSymbol;

            if (resolvedMethod != null)
            {
                var type   = resolvedMethod.ContainingType;
                var within = semanticModel.GetEnclosingNamedTypeOrAssembly(node.SpanStart, cancellationToken);

                result.AddRange(type.GetMembers()
                                .OfType <IMethodSymbol> ()
                                .Where(m => m.MethodKind == MethodKind.Constructor && m.IsAccessibleWithin(within))
                                .Select(factory.CreateConstructorProvider));
            }
            else
            {
                result.AddRange(info.CandidateSymbols.OfType <IMethodSymbol> ().Select(factory.CreateConstructorProvider));
            }
            return(result);
        }
Exemplo n.º 9
0
        ParameterHintingResult HandleInvocationExpression(SemanticModel semanticModel, InvocationExpressionSyntax node, CancellationToken cancellationToken)
        {
            var info   = semanticModel.GetSymbolInfo(node, cancellationToken);
            var result = new ParameterHintingResult(node.SpanStart);

            var targetTypeInfo = semanticModel.GetTypeInfo(node.Expression);

            if (targetTypeInfo.Type != null && targetTypeInfo.Type.TypeKind == TypeKind.Delegate)
            {
                result.AddData(factory.CreateMethodDataProvider(targetTypeInfo.Type.GetDelegateInvokeMethod()));
                return(result);
            }

            var         within = semanticModel.GetEnclosingNamedTypeOrAssembly(node.SpanStart, cancellationToken);
            ITypeSymbol type;
            var         ma           = node.Expression as MemberAccessExpressionSyntax;
            string      name         = null;
            bool        staticLookup = false;

            if (ma != null)
            {
                staticLookup = semanticModel.GetSymbolInfo(ma.Expression).Symbol is ITypeSymbol;
                type         = semanticModel.GetTypeInfo(ma.Expression).Type;
                name         = info.Symbol?.Name ?? ma.Name.Identifier.ValueText;
            }
            else
            {
                type = within as ITypeSymbol;
                name = info.Symbol?.Name ?? node.Expression.ToString();
                var sym = semanticModel.GetEnclosingSymbol(node.SpanStart, cancellationToken);
                staticLookup = sym.IsStatic;
            }
            var addedMethods = new List <IMethodSymbol> ();
            var filterMethod = new HashSet <IMethodSymbol> ();

            for (; type != null; type = type.BaseType)
            {
                foreach (var method in type.GetMembers().OfType <IMethodSymbol> ().Concat(GetExtensionMethods(semanticModel, type, node, cancellationToken)).Where(m => m.Name == name))
                {
                    if (staticLookup && !method.IsStatic)
                    {
                        continue;
                    }
                    if (method.OverriddenMethod != null)
                    {
                        filterMethod.Add(method.OverriddenMethod);
                    }
                    if (filterMethod.Contains(method))
                    {
                        continue;
                    }
                    if (addedMethods.Any(added => SignatureComparer.HaveSameSignature(method, added, true)))
                    {
                        continue;
                    }
                    if (method.IsAccessibleWithin(within))
                    {
                        if (info.Symbol != null)
                        {
                            var smethod = (IMethodSymbol)info.Symbol;
                            if (smethod != null && smethod.OriginalDefinition == method)
                            {
                                continue;
                            }
                        }
                        addedMethods.Add(method);
                        result.AddData(factory.CreateMethodDataProvider(method));
                    }
                }
            }
            if (info.Symbol != null && !addedMethods.Contains(info.Symbol))
            {
                if (!staticLookup || info.Symbol.IsStatic)
                {
                    result.AddData(factory.CreateMethodDataProvider((IMethodSymbol)info.Symbol));
                }
            }
            return(result);
        }
Exemplo n.º 10
0
        public static bool IsExpressionContext(
            this SyntaxTree syntaxTree,
            int position,
            SyntaxToken tokenOnLeftOfPosition,
            bool attributes,
            CancellationToken cancellationToken,
            SemanticModel semanticModelOpt = null)
        {
            // cases:
            //   var q = |
            //   var q = a|
            // this list is *not* exhaustive.

            var token = tokenOnLeftOfPosition.GetPreviousTokenIfTouchingWord(position);

            if (token.GetAncestor<ConditionalDirectiveTriviaSyntax>() != null)
            {
                return false;
            }

            if (!attributes)
            {
                if (token.GetAncestor<AttributeListSyntax>() != null)
                {
                    return false;
                }
            }

            if (syntaxTree.IsConstantExpressionContext(position, tokenOnLeftOfPosition, cancellationToken))
            {
                return true;
            }

            // no expressions after .   ::   ->
            if (token.IsKind(SyntaxKind.DotToken) ||
                token.IsKind(SyntaxKind.ColonColonToken) ||
                token.IsKind(SyntaxKind.MinusGreaterThanToken))
            {
                return false;
            }

            // Normally you can have any sort of expression after an equals. However, this does not
            // apply to a "using Foo = ..." situation.
            if (token.IsKind(SyntaxKind.EqualsToken))
            {
                if (token.Parent.IsKind(SyntaxKind.NameEquals) &&
                    token.Parent.IsParentKind(SyntaxKind.UsingDirective))
                {
                    return false;
                }
            }

            // q = |
            // q -= |
            // q *= |
            // q += |
            // q /= |
            // q ^= |
            // q %= |
            // q &= |
            // q |= |
            // q <<= |
            // q >>= |
            if (token.IsKind(SyntaxKind.EqualsToken) ||
                token.IsKind(SyntaxKind.MinusEqualsToken) ||
                token.IsKind(SyntaxKind.AsteriskEqualsToken) ||
                token.IsKind(SyntaxKind.PlusEqualsToken) ||
                token.IsKind(SyntaxKind.SlashEqualsToken) ||
                token.IsKind(SyntaxKind.ExclamationEqualsToken) ||
                token.IsKind(SyntaxKind.CaretEqualsToken) ||
                token.IsKind(SyntaxKind.AmpersandEqualsToken) ||
                token.IsKind(SyntaxKind.BarEqualsToken) ||
                token.IsKind(SyntaxKind.PercentEqualsToken) ||
                token.IsKind(SyntaxKind.LessThanLessThanEqualsToken) ||
                token.IsKind(SyntaxKind.GreaterThanGreaterThanEqualsToken))
            {
                return true;
            }

            // ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.Parent.IsKind(SyntaxKind.ParenthesizedExpression))
            {
                return true;
            }

            // - |
            // + |
            // ~ |
            // ! |
            if (token.Parent is PrefixUnaryExpressionSyntax)
            {
                var prefix = token.Parent as PrefixUnaryExpressionSyntax;
                return prefix.OperatorToken == token;
            }

            // not sure about these:
            //   ++ |
            //   -- |
#if false
                token.Kind == SyntaxKind.PlusPlusToken ||
                token.Kind == SyntaxKind.DashDashToken)
#endif
            // await |
            if (token.Parent is AwaitExpressionSyntax)
            {
                var awaitExpression = token.Parent as AwaitExpressionSyntax;
                return awaitExpression.AwaitKeyword == token;
            }

            // Check for binary operators.
            // Note:
            //   - We handle < specially as it can be ambiguous with generics.
            //   - We handle * specially because it can be ambiguous with pointer types.

            // a *
            // a /
            // a %
            // a +
            // a -
            // a <<
            // a >>
            // a <
            // a >
            // a &&
            // a ||
            // a &
            // a |
            // a ^
            if (token.Parent is BinaryExpressionSyntax)
            {
                // If the client provided a binding, then check if this is actually generic.  If so,
                // then this is not an expression context. i.e. if we have "Foo < |" then it could
                // be an expression context, or it could be a type context if Foo binds to a type or
                // method.
                if (semanticModelOpt != null && syntaxTree.IsGenericTypeArgumentContext(position, tokenOnLeftOfPosition, cancellationToken, semanticModelOpt))
                {
                    return false;
                }

                var binary = token.Parent as BinaryExpressionSyntax;
                if (binary.OperatorToken == token)
                {
                    // If this is a multiplication expression and a semantic model was passed in,
                    // check to see if the expression to the left is a type name. If it is, treat
                    // this as a pointer type.
                    if (token.IsKind(SyntaxKind.AsteriskToken) && semanticModelOpt != null)
                    {
                        var type = binary.Left as TypeSyntax;
                        if (type != null && type.IsPotentialTypeName(semanticModelOpt, cancellationToken))
                        {
                            return false;
                        }
                    }

                    return true;
                }
            }

            // Special case:
            //    Foo * bar
            //    Foo ? bar
            // This parses as a local decl called bar of type Foo* or Foo?
            if (tokenOnLeftOfPosition.IntersectsWith(position) &&
                tokenOnLeftOfPosition.IsKind(SyntaxKind.IdentifierToken))
            {
                var previousToken = tokenOnLeftOfPosition.GetPreviousToken(includeSkipped: true);
                if (previousToken.IsKind(SyntaxKind.AsteriskToken) ||
                    previousToken.IsKind(SyntaxKind.QuestionToken))
                {
                    if (previousToken.Parent.IsKind(SyntaxKind.PointerType) ||
                        previousToken.Parent.IsKind(SyntaxKind.NullableType))
                    {
                        var type = previousToken.Parent as TypeSyntax;
                        if (type.IsParentKind(SyntaxKind.VariableDeclaration) &&
                            type.Parent.IsParentKind(SyntaxKind.LocalDeclarationStatement))
                        {
                            var declStatement = type.Parent.Parent as LocalDeclarationStatementSyntax;

                            // note, this doesn't apply for cases where we know it 
                            // absolutely is not multiplication or a conditional expression.
                            var underlyingType = type is PointerTypeSyntax
                                ? ((PointerTypeSyntax)type).ElementType
                                : ((NullableTypeSyntax)type).ElementType;

                            if (!underlyingType.IsPotentialTypeName(semanticModelOpt, cancellationToken))
                            {
                                return true;
                            }
                        }
                    }
                }
            }

            // new int[|
            // new int[expr, |
            if (token.IsKind(SyntaxKind.OpenBracketToken) ||
                token.IsKind(SyntaxKind.CommaToken))
            {
                if (token.Parent.IsKind(SyntaxKind.ArrayRankSpecifier))
                {
                    return true;
                }
            }

            // foo ? |
            if (token.IsKind(SyntaxKind.QuestionToken) &&
                token.Parent.IsKind(SyntaxKind.ConditionalExpression))
            {
                // If the condition is simply a TypeSyntax that binds to a type, treat this as a nullable type.
                var conditionalExpression = (ConditionalExpressionSyntax)token.Parent;
                var type = conditionalExpression.Condition as TypeSyntax;

                return type == null
                    || !type.IsPotentialTypeName(semanticModelOpt, cancellationToken);
            }

            // foo ? bar : |
            if (token.IsKind(SyntaxKind.ColonToken) &&
                token.Parent.IsKind(SyntaxKind.ConditionalExpression))
            {
                return true;
            }

            // typeof(|
            // default(|
            // sizeof(|
            if (token.IsKind(SyntaxKind.OpenParenToken))
            {
                if (token.Parent.IsKind(SyntaxKind.TypeOfExpression, SyntaxKind.DefaultExpression, SyntaxKind.SizeOfExpression))
                {
                    return false;
                }
            }

            // var(|
            // var(id, |
            // Those are more likely to be deconstruction-declarations being typed than invocations a method "var"
            if (token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.CommaToken) &&
                token.IsInvocationOfVarExpression())
            {
                return false;
            }

            // Foo(|
            // Foo(expr, |
            // this[|
            // var t = (1, |
            // var t = (| , 2)
            if (token.IsKind(SyntaxKind.OpenParenToken) ||
                token.IsKind(SyntaxKind.OpenBracketToken) ||
                token.IsKind(SyntaxKind.CommaToken))
            {
                if (token.Parent.IsKind(SyntaxKind.ArgumentList, SyntaxKind.BracketedArgumentList, SyntaxKind.TupleExpression))
                {
                    return true;
                }
            }

            // [Foo(|
            // [Foo(expr, |
            if (attributes)
            {
                if (token.IsKind(SyntaxKind.OpenParenToken) ||
                    token.IsKind(SyntaxKind.CommaToken))
                {
                    if (token.Parent.IsKind(SyntaxKind.AttributeArgumentList))
                    {
                        return true;
                    }
                }
            }

            // Foo(ref |
            // Foo(bar |
            if (token.IsKind(SyntaxKind.RefKeyword) ||
                token.IsKind(SyntaxKind.OutKeyword))
            {
                if (token.Parent.IsKind(SyntaxKind.Argument))
                {
                    return true;
                }
            }

            // Foo(bar: |
            if (token.IsKind(SyntaxKind.ColonToken) &&
                token.Parent.IsKind(SyntaxKind.NameColon) &&
                token.Parent.IsParentKind(SyntaxKind.Argument))
            {
                return true;
            }

            // a => |
            if (token.IsKind(SyntaxKind.EqualsGreaterThanToken))
            {
                return true;
            }

            // new List<int> { |
            // new List<int> { expr, |
            if (token.IsKind(SyntaxKind.OpenBraceToken) ||
                token.IsKind(SyntaxKind.CommaToken))
            {
                if (token.Parent is InitializerExpressionSyntax)
                {
                    // The compiler treats the ambiguous case as an object initializer, so we'll say
                    // expressions are legal here
                    if (token.Parent.IsKind(SyntaxKind.ObjectInitializerExpression) && token.IsKind(SyntaxKind.OpenBraceToken))
                    {
                        // In this position { a$$ =, the user is trying to type an object initializer.
                        if (!token.IntersectsWith(position) && token.GetNextToken().GetNextToken().IsKind(SyntaxKind.EqualsToken))
                        {
                            return false;
                        }

                        return true;
                    }

                    // Perform a semantic check to determine whether or not the type being created
                    // can support a collection initializer. If not, this must be an object initializer
                    // and can't be an expression context.
                    if (semanticModelOpt != null &&
                        token.Parent.IsParentKind(SyntaxKind.ObjectCreationExpression))
                    {
                        var objectCreation = (ObjectCreationExpressionSyntax)token.Parent.Parent;
                        var type = semanticModelOpt.GetSymbolInfo(objectCreation.Type, cancellationToken).Symbol as ITypeSymbol;
                        var containingSymbol = semanticModelOpt.GetEnclosingNamedTypeOrAssembly(position, cancellationToken);
                        if (type != null && !type.CanSupportCollectionInitializer(containingSymbol))
                        {
                            return false;
                        }
                    }

                    return true;
                }
            }

            // for (; |
            // for (; ; |
            if (token.IsKind(SyntaxKind.SemicolonToken) &&
                token.Parent.IsKind(SyntaxKind.ForStatement))
            {
                var forStatement = (ForStatementSyntax)token.Parent;
                if (token == forStatement.FirstSemicolonToken ||
                    token == forStatement.SecondSemicolonToken)
                {
                    return true;
                }
            }

            // for ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.Parent.IsKind(SyntaxKind.ForStatement))
            {
                var forStatement = (ForStatementSyntax)token.Parent;
                if (token == forStatement.OpenParenToken)
                {
                    return true;
                }
            }

            // for (; ; Foo(), | 
            // for ( Foo(), |
            if (token.IsKind(SyntaxKind.CommaToken) &&
                token.Parent.IsKind(SyntaxKind.ForStatement))
            {
                return true;
            }

            // foreach (var v in |
            // from a in |
            // join b in |
            if (token.IsKind(SyntaxKind.InKeyword))
            {
                if (token.Parent.IsKind(SyntaxKind.ForEachStatement,
                                        SyntaxKind.ForEachComponentStatement,
                                        SyntaxKind.FromClause,
                                        SyntaxKind.JoinClause))
                {
                    return true;
                }
            }

            // join x in y on |
            // join x in y on a equals |
            if (token.IsKind(SyntaxKind.OnKeyword) ||
                token.IsKind(SyntaxKind.EqualsKeyword))
            {
                if (token.Parent.IsKind(SyntaxKind.JoinClause))
                {
                    return true;
                }
            }

            // where |
            if (token.IsKind(SyntaxKind.WhereKeyword) &&
                token.Parent.IsKind(SyntaxKind.WhereClause))
            {
                return true;
            }

            // orderby |
            // orderby a, |
            if (token.IsKind(SyntaxKind.OrderByKeyword) ||
                token.IsKind(SyntaxKind.CommaToken))
            {
                if (token.Parent.IsKind(SyntaxKind.OrderByClause))
                {
                    return true;
                }
            }

            // select |
            if (token.IsKind(SyntaxKind.SelectKeyword) &&
                token.Parent.IsKind(SyntaxKind.SelectClause))
            {
                return true;
            }

            // group |
            // group expr by |
            if (token.IsKind(SyntaxKind.GroupKeyword) ||
                token.IsKind(SyntaxKind.ByKeyword))
            {
                if (token.Parent.IsKind(SyntaxKind.GroupClause))
                {
                    return true;
                }
            }

            // return |
            // yield return |
            // but not: [return |
            if (token.IsKind(SyntaxKind.ReturnKeyword))
            {
                if (token.GetPreviousToken(includeSkipped: true).Kind() != SyntaxKind.OpenBracketToken)
                {
                    return true;
                }
            }

            // throw |
            if (token.IsKind(SyntaxKind.ThrowKeyword))
            {
                return true;
            }

            // while ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.WhileKeyword))
            {
                return true;
            }

            // todo: handle 'for' cases.

            // using ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.UsingKeyword))
            {
                return true;
            }

            // lock ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.LockKeyword))
            {
                return true;
            }

            // lock ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.IfKeyword))
            {
                return true;
            }

            // switch ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.SwitchKeyword))
            {
                return true;
            }

            // checked ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.CheckedKeyword))
            {
                return true;
            }

            // unchecked ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.UncheckedKeyword))
            {
                return true;
            }

            // when ( |
            if (token.IsKind(SyntaxKind.OpenParenToken) &&
                token.GetPreviousToken(includeSkipped: true).IsKind(SyntaxKind.WhenKeyword))
            {
                return true;
            }

            // (SomeType) |
            if (token.IsAfterPossibleCast())
            {
                return true;
            }

            // In anonymous type initializer.
            //
            // new { | We allow new inside of anonymous object member declarators, so that the user
            // can dot into a member afterward. For example:
            //
            // var a = new { new C().Foo };
            if (token.IsKind(SyntaxKind.OpenBraceToken) || token.IsKind(SyntaxKind.CommaToken))
            {
                if (token.Parent.IsKind(SyntaxKind.AnonymousObjectCreationExpression))
                {
                    return true;
                }
            }

            // $"{ |
            // $@"{ |
            // $"{x} { |
            // $@"{x} { |
            if (token.IsKind(SyntaxKind.OpenBraceToken))
            {
                return token.Parent.IsKind(SyntaxKind.Interpolation)
                    && ((InterpolationSyntax)token.Parent).OpenBraceToken == token;
            }

            return false;
        }
Exemplo n.º 11
0
        ParameterHintingResult HandleInvocationExpression(SemanticModel semanticModel, InvocationExpressionSyntax node, CancellationToken cancellationToken)
        {
            var result = new ParameterHintingResult(node.SpanStart);

            var targetTypeInfo = semanticModel.GetTypeInfo(node.Expression);

            if (targetTypeInfo.Type != null && targetTypeInfo.Type.TypeKind == TypeKind.Delegate)
            {
                result.AddData(factory.CreateMethodDataProvider(targetTypeInfo.Type.GetDelegateInvokeMethod()));
                return(result);
            }

            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(node.SpanStart, cancellationToken);

            if (within == null)
            {
                return(result);
            }

            var memberGroup         = semanticModel.GetMemberGroup(node.Expression, cancellationToken).OfType <IMethodSymbol> ();
            var matchedMethodSymbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol as IMethodSymbol;

            // if the symbol could be bound, replace that item in the symbol list
            if (matchedMethodSymbol != null && matchedMethodSymbol.IsGenericMethod)
            {
                memberGroup = memberGroup.Select(m => matchedMethodSymbol.OriginalDefinition == m ? matchedMethodSymbol : m);
            }

            ITypeSymbol throughType = null;

            if (node.Expression is MemberAccessExpressionSyntax)
            {
                var throughExpression = ((MemberAccessExpressionSyntax)node.Expression).Expression;
                var throughSymbol     = semanticModel.GetSymbolInfo(throughExpression, cancellationToken).GetAnySymbol();

                // if it is via a base expression "base.", we know the "throughType" is the base class but
                // we need to be able to tell between "base.M()" and "new Base().M()".
                // currently, Access check methods do not differentiate between them.
                // so handle "base." primary-expression here by nulling out "throughType"
                if (!(throughExpression is BaseExpressionSyntax))
                {
                    throughType = semanticModel.GetTypeInfo(throughExpression, cancellationToken).Type;
                }

                var includeInstance = !throughExpression.IsKind(SyntaxKind.IdentifierName) ||
                                      semanticModel.LookupSymbols(throughExpression.SpanStart, name: throughSymbol.Name).Any(s => !(s is INamedTypeSymbol)) ||
                                      (!(throughSymbol is INamespaceOrTypeSymbol) && semanticModel.LookupSymbols(throughExpression.SpanStart, container: throughSymbol.ContainingType).Any(s => !(s is INamedTypeSymbol)));

                var includeStatic = throughSymbol is INamedTypeSymbol ||
                                    (throughExpression.IsKind(SyntaxKind.IdentifierName) &&
                                     semanticModel.LookupNamespacesAndTypes(throughExpression.SpanStart, name: throughSymbol.Name).Any(t => t.GetSymbolType() == throughType));

                memberGroup = memberGroup.Where(m => (m.IsStatic && includeStatic) || (!m.IsStatic && includeInstance));
            }
            else if (node.Expression is SimpleNameSyntax && node.IsInStaticContext())
            {
                memberGroup = memberGroup.Where(m => m.IsStatic);
            }

            var methodList = memberGroup.Where(member => member.IsAccessibleWithin(within, throughType)).ToList();

            memberGroup = methodList.Where(m => !IsHiddenByOtherMethod(m, methodList));
            foreach (var member in memberGroup)
            {
                result.AddData(factory.CreateMethodDataProvider(member));
            }
            return(result);
        }
Exemplo n.º 12
0
        static SignatureHelp CreateMethodGroupSignatureHelp(
            ExpressionSyntax expression,
            ArgumentListSyntax argumentList,
            int position,
            SemanticModel semanticModel)
        {
            var signatureHelp = new SignatureHelp();

            // Happens for object initializers with no preceding parens, as soon as user types comma
            if (argumentList == null)
            {
                return(signatureHelp);
            }

            int currentArg;

            if (TryGetCurrentArgumentIndex(argumentList, position, out currentArg))
            {
                signatureHelp.ActiveParameter = currentArg;
            }

            var symbolInfo      = semanticModel.GetSymbolInfo(expression);
            var bestGuessMethod = symbolInfo.Symbol as IMethodSymbol;

            // Include everything by default (global eval context)
            var includeInstance = true;
            var includeStatic   = true;

            ITypeSymbol throughType = null;

            // When accessing method via some member, only show static methods in static context and vice versa for instance methods.
            // This block based on https://github.com/dotnet/roslyn/blob/3b6536f4a616e5f3b8ede940c63663a828e68b5d/src/Features/CSharp/Portable/SignatureHelp/InvocationExpressionSignatureHelpProvider_MethodGroup.cs#L44-L50
            if (expression is MemberAccessExpressionSyntax memberAccessExpression)
            {
                var throughExpression = (memberAccessExpression).Expression;
                if (!(throughExpression is BaseExpressionSyntax))
                {
                    throughType = semanticModel.GetTypeInfo(throughExpression).Type;
                }
                var throughSymbolInfo = semanticModel.GetSymbolInfo(throughExpression);
                var throughSymbol     = throughSymbolInfo.Symbol ?? throughSymbolInfo.CandidateSymbols.FirstOrDefault();

                includeInstance = !throughExpression.IsKind(SyntaxKind.IdentifierName) ||
                                  semanticModel.LookupSymbols(throughExpression.SpanStart, name: throughSymbol.Name).Any(s => !(s is INamedTypeSymbol)) ||
                                  (!(throughSymbol is INamespaceOrTypeSymbol) && semanticModel.LookupSymbols(throughExpression.SpanStart, throughSymbol.ContainingType).Any(s => !(s is INamedTypeSymbol)));
                includeStatic = throughSymbol is INamedTypeSymbol ||
                                (throughExpression.IsKind(SyntaxKind.IdentifierName) &&
                                 semanticModel.LookupNamespacesAndTypes(throughExpression.SpanStart, name: throughSymbol.Name).Any(t => t.GetSymbolType() == throughType));
            }

            // TODO: Start taking CT in here? Most calls in this method have optional CT arg. Could make this async.
            var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, CancellationToken.None);

            var methods = semanticModel
                          .GetMemberGroup(expression)
                          .OfType <IMethodSymbol> ()
                          .Where(m => (m.IsStatic && includeStatic) || (!m.IsStatic && includeInstance))
                          .Where(m => m.IsAccessibleWithin(within, throughTypeOpt: throughType))
                          .ToArray();

            var signatures = new List <SignatureInformation> ();

            for (var i = 0; i < methods.Length; i++)
            {
                if (methods [i] == bestGuessMethod)
                {
                    signatureHelp.ActiveSignature = i;
                }

                var signatureInfo = new SignatureInformation(methods [i]);

                signatures.Add(signatureInfo);
            }

            signatureHelp.Signatures = signatures.ToArray();

            return(signatureHelp);
        }