protected override SyntaxNode GetSyntax(SyntaxToken token)
 {
     return token.GetAncestor<EventFieldDeclarationSyntax>()
         ?? token.GetAncestor<EventDeclarationSyntax>()
         ?? token.GetAncestor<PropertyDeclarationSyntax>()
         ?? token.GetAncestor<IndexerDeclarationSyntax>()
         ?? (SyntaxNode)token.GetAncestor<MethodDeclarationSyntax>();
 }
            private static InterpolatedStringExpressionSyntax TryGetInterpolatedStringExpression(
                SyntaxToken token, int position)
            {
                if (token.IsKind(SyntaxKind.InterpolatedStringTextToken) ||
                    token.IsKind(SyntaxKind.InterpolatedStringEndToken) ||
                    IsInterpolationOpenBrace(token, position))
                {
                    return token.GetAncestor<InterpolatedStringExpressionSyntax>();
                }

                return null;
            }
            internal IList<string> Do(CancellationToken cancellationToken)
            {
                // First, find the containing statement.  We'll want to add the expressions in this
                // statement to the result.
                _token = _syntaxTree.GetRoot(cancellationToken).FindToken(_position);
                _parentStatement = _token.GetAncestor<StatementSyntax>();
                if (_parentStatement == null)
                {
                    return null;
                }

                AddRelevantExpressions(_parentStatement, _expressions, includeDeclarations: false);
                AddPrecedingRelevantExpressions();
                AddFollowingRelevantExpressions(cancellationToken);
                AddCurrentDeclaration();
                AddMethodParameters();
                AddIndexerParameters();
                AddCatchParameters();
                AddThisExpression();
                AddValueExpression();

                var result = _expressions.Distinct().Where(e => e.Length > 0).ToList();
                return result.Count == 0 ? null : result;
            }
        private static SyntaxNode GetExpansionTarget(SyntaxToken token)
        {
            // get the directly enclosing statement
            var enclosingStatement = token.GetAncestors(n => n is StatementSyntax).FirstOrDefault();

            // see if there's an enclosing lambda expression
            SyntaxNode possibleLambdaExpression = enclosingStatement == null
                ? token.GetAncestors(n => n is SimpleLambdaExpressionSyntax || n is ParenthesizedLambdaExpressionSyntax).FirstOrDefault()
                : null;

            var enclosingNameMemberCrefOrnull = token.GetAncestors(n => n is NameMemberCrefSyntax).LastOrDefault();
            if (enclosingNameMemberCrefOrnull != null)
            {
                if (token.Parent is TypeSyntax && token.Parent.Parent is TypeSyntax)
                {
                    enclosingNameMemberCrefOrnull = null;
                }
            }

            var enclosingXmlNameAttr = token.GetAncestors(n => n is XmlNameAttributeSyntax).FirstOrDefault();
            if (enclosingXmlNameAttr != null)
            {
                return null;
            }

            var enclosingInitializer = token.GetAncestors<EqualsValueClauseSyntax>().FirstOrDefault();
            if (enclosingStatement == null && enclosingInitializer != null && enclosingInitializer.Parent is VariableDeclaratorSyntax)
            {
                return enclosingInitializer.Value;
            }

            var attributeSyntax = token.GetAncestor<AttributeSyntax>();
            if (attributeSyntax != null)
            {
                return attributeSyntax;
            }

            // there seems to be no statement above this one. Let's see if we can at least get an SimpleNameSyntax
            return enclosingStatement ?? enclosingNameMemberCrefOrnull ?? token.GetAncestors(n => n is SimpleNameSyntax).FirstOrDefault();
        }
        private IEnumerable<CompletionItem> GetTagsForMethod(IMethodSymbol symbol, TextSpan itemSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List<CompletionItem>();

            var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor<XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == ParamRefTagName)
                {
                    items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, p)));
                }
                else if (parentElementName == TypeParamRefTagName)
                {
                    items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, t)));
                }

                return items;
            }

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(itemSpan, ReturnsTagName));
            }

            return items;
        }
        // copied from compiler formatter to have same base forced format
        private int LineBreaksAfter(SyntaxToken previousToken, SyntaxToken currentToken)
        {
            if (currentToken.Kind() == SyntaxKind.None)
            {
                return 0;
            }

            switch (previousToken.Kind())
            {
                case SyntaxKind.None:
                    return 0;

                case SyntaxKind.OpenBraceToken:
                case SyntaxKind.FinallyKeyword:
                    return 1;

                case SyntaxKind.CloseBraceToken:
                    return LineBreaksAfterCloseBrace(currentToken);

                case SyntaxKind.CloseParenToken:
                    return (((previousToken.Parent is StatementSyntax) && currentToken.Parent != previousToken.Parent)
                        || currentToken.Kind() == SyntaxKind.OpenBraceToken) ? 1 : 0;

                case SyntaxKind.CloseBracketToken:
                    if (previousToken.Parent is AttributeListSyntax)
                    {
                        // Assembly and module-level attributes followed by non-attributes should have
                        // a blank line after them.
                        var parent = (AttributeListSyntax)previousToken.Parent;
                        if (parent.Target != null &&
                            (parent.Target.Identifier.IsKindOrHasMatchingText(SyntaxKind.AssemblyKeyword) ||
                             parent.Target.Identifier.IsKindOrHasMatchingText(SyntaxKind.ModuleKeyword)))
                        {
                            if (!(currentToken.Parent is AttributeListSyntax))
                            {
                                return 2;
                            }
                        }

                        if (previousToken.GetAncestor<ParameterSyntax>() == null)
                        {
                            return 1;
                        }
                    }

                    break;

                case SyntaxKind.SemicolonToken:
                    return LineBreaksAfterSemicolon(previousToken, currentToken);

                case SyntaxKind.CommaToken:
                    return previousToken.Parent is EnumDeclarationSyntax ? 1 : 0;

                case SyntaxKind.ElseKeyword:
                    return currentToken.Kind() != SyntaxKind.IfKeyword ? 1 : 0;

                case SyntaxKind.ColonToken:
                    if (previousToken.Parent is LabeledStatementSyntax || previousToken.Parent is SwitchLabelSyntax)
                    {
                        return 1;
                    }

                    break;
            }

            if ((currentToken.Kind() == SyntaxKind.FromKeyword && currentToken.Parent.Kind() == SyntaxKind.FromClause) ||
                (currentToken.Kind() == SyntaxKind.LetKeyword && currentToken.Parent.Kind() == SyntaxKind.LetClause) ||
                (currentToken.Kind() == SyntaxKind.WhereKeyword && currentToken.Parent.Kind() == SyntaxKind.WhereClause) ||
                (currentToken.Kind() == SyntaxKind.JoinKeyword && currentToken.Parent.Kind() == SyntaxKind.JoinClause) ||
                (currentToken.Kind() == SyntaxKind.JoinKeyword && currentToken.Parent.Kind() == SyntaxKind.JoinIntoClause) ||
                (currentToken.Kind() == SyntaxKind.OrderByKeyword && currentToken.Parent.Kind() == SyntaxKind.OrderByClause) ||
                (currentToken.Kind() == SyntaxKind.SelectKeyword && currentToken.Parent.Kind() == SyntaxKind.SelectClause) ||
                (currentToken.Kind() == SyntaxKind.GroupKeyword && currentToken.Parent.Kind() == SyntaxKind.GroupClause))
            {
                return 1;
            }

            switch (currentToken.Kind())
            {
                case SyntaxKind.OpenBraceToken:
                case SyntaxKind.CloseBraceToken:
                case SyntaxKind.ElseKeyword:
                case SyntaxKind.FinallyKeyword:
                    return 1;

                case SyntaxKind.OpenBracketToken:
                    if (currentToken.Parent is AttributeListSyntax)
                    {
                        // Assembly and module-level attributes preceded by non-attributes should have
                        // a blank line separating them.
                        var parent = (AttributeListSyntax)currentToken.Parent;
                        if (parent.Target != null)
                        {
                            if (parent.Target.Identifier == SyntaxFactory.Token(SyntaxKind.AssemblyKeyword) ||
                                parent.Target.Identifier == SyntaxFactory.Token(SyntaxKind.ModuleKeyword))
                            {
                                if (!(previousToken.Parent is AttributeListSyntax))
                                {
                                    return 2;
                                }
                            }
                        }

                        // Attributes on parameters should have no lines between them.
                        if (parent.Parent is ParameterSyntax)
                        {
                            return 0;
                        }

                        return 1;
                    }

                    break;

                case SyntaxKind.WhereKeyword:
                    return previousToken.Parent is TypeParameterListSyntax ? 1 : 0;
            }

            return 0;
        }
Beispiel #7
0
        private static bool IsLeftSideOfUsingAliasDirective(SyntaxToken leftToken, CancellationToken cancellationToken)
        {
            var usingDirective = leftToken.GetAncestor<UsingDirectiveSyntax>();

            if (usingDirective != null)
            {
                // No = token: 
                if (usingDirective.Alias == null || usingDirective.Alias.EqualsToken.IsMissing)
                {
                    return true;
                }

                return leftToken.SpanStart < usingDirective.Alias.EqualsToken.SpanStart;
            }

            return false;
        }
Beispiel #8
0
 protected override SyntaxNode GetContainingStatement(SyntaxToken token)
 // If we can't get a containing statement, such as for expression bodied members, then
 // return the arrow clause instead
 => (SyntaxNode)token.GetAncestor <StatementSyntax>() ?? token.GetAncestor <ArrowExpressionClauseSyntax>();
        private bool TryGetTextForPreProcessor(SyntaxToken token, Document document, ISyntaxFactsService syntaxFacts, out string text)
        {
            if (syntaxFacts.IsPreprocessorKeyword(token))
            {
                text = "#" + token.Text;
                return true;
            }

            if (token.IsKind(SyntaxKind.EndOfDirectiveToken) && token.GetAncestor<RegionDirectiveTriviaSyntax>() != null)
            {
                text = "#region";
                return true;
            }

            text = null;
            return false;
        }
Beispiel #10
0
 public static bool IsLastTokenOfNode <T>(this SyntaxToken token, [NotNullWhen(true)] out T node) where T : SyntaxNode
 {
     node = token.GetAncestor <T>();
     return(node != null && token == node.GetLastToken(includeZeroWidth: true));
 }
        // LookupSymbols doesn't return indexers or operators because they can't be referred to by name, so we'll have to try to 
        // find the innermost type declaration and return its operators and indexers
        private IEnumerable<ISymbol> GetOperatorsAndIndexers(SyntaxToken token, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var typeDeclaration = token.GetAncestor<TypeDeclarationSyntax>();

            var result = new List<ISymbol>();

            if (typeDeclaration != null)
            {
                var type = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken);

                result.AddRange(type.GetMembers().OfType<IPropertySymbol>().Where(p => p.IsIndexer));
                result.AddRange(type.GetAccessibleMembersInThisAndBaseTypes<IMethodSymbol>(type)
                                    .Where(m => m.MethodKind == MethodKind.UserDefinedOperator));
            }

            return result;
        }
            protected override IndentationResult GetDesiredIndentationWorker(
                SyntaxToken token, TextLine previousLine, int lastNonWhitespacePosition)
            {
                // okay, now check whether the text we found is trivia or actual token.
                if (token.Span.Contains(lastNonWhitespacePosition))
                {
                    // okay, it is a token case, do special work based on type of last token on previous line
                    return(GetIndentationBasedOnToken(token));
                }
                else
                {
                    // there must be trivia that contains or touch this position
                    Debug.Assert(token.FullSpan.Contains(lastNonWhitespacePosition));

                    // okay, now check whether the trivia is at the beginning of the line
                    var firstNonWhitespacePosition = previousLine.GetFirstNonWhitespacePosition();
                    if (!firstNonWhitespacePosition.HasValue)
                    {
                        return(IndentFromStartOfLine(0));
                    }

                    var trivia = Root.FindTrivia(firstNonWhitespacePosition.Value, findInsideTrivia: true);
                    if (trivia.Kind() == SyntaxKind.None || this.LineToBeIndented.LineNumber > previousLine.LineNumber + 1)
                    {
                        // If the token belongs to the next statement and is also the first token of the statement, then it means the user wants
                        // to start type a new statement. So get indentation from the start of the line but not based on the token.
                        // Case:
                        // static void Main(string[] args)
                        // {
                        //     // A
                        //     // B
                        //
                        //     $$
                        //     return;
                        // }

                        var containingStatement = token.GetAncestor <StatementSyntax>();
                        if (containingStatement != null && containingStatement.GetFirstToken() == token)
                        {
                            var position = GetCurrentPositionNotBelongToEndOfFileToken(LineToBeIndented.Start);
                            return(IndentFromStartOfLine(Finder.GetIndentationOfCurrentPosition(Tree, token, position, CancellationToken)));
                        }

                        // If the token previous of the base token happens to be a Comma from a separation list then we need to handle it different
                        // Case:
                        // var s = new List<string>
                        //                 {
                        //                     """",
                        //                             """",/*sdfsdfsdfsdf*/
                        //                                  // dfsdfsdfsdfsdf
                        //
                        //                             $$
                        //                 };
                        var previousToken = token.GetPreviousToken();
                        if (previousToken.IsKind(SyntaxKind.CommaToken))
                        {
                            return(GetIndentationFromCommaSeparatedList(previousToken));
                        }
                        else if (!previousToken.IsKind(SyntaxKind.None))
                        {
                            // okay, beginning of the line is not trivia, use the last token on the line as base token
                            return(GetIndentationBasedOnToken(token));
                        }
                    }

                    // this case we will keep the indentation of this trivia line
                    // this trivia can't be preprocessor by the way.
                    return(GetIndentationOfLine(previousLine));
                }
            }
        private static IndentationResult GetIndentationBasedOnToken(Indenter indenter, SyntaxToken token)
        {
            Contract.ThrowIfNull(indenter.Tree);
            Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None);

            var sourceText = indenter.LineToBeIndented.Text;

            RoslynDebug.AssertNotNull(sourceText);

            // case: """$$
            //       """
            if (token.IsKind(SyntaxKind.MultiLineRawStringLiteralToken))
            {
                var endLine       = sourceText.Lines.GetLineFromPosition(token.Span.End);
                var minimumOffset = endLine.GetFirstNonWhitespaceOffset();
                Contract.ThrowIfNull(minimumOffset);

                // If possible, indent to match the indentation of the previous non-whitespace line contained in the
                // same raw string. Otherwise, indent to match the ending line of the raw string.
                var startLine = sourceText.Lines.GetLineFromPosition(token.SpanStart);
                for (var currentLineNumber = indenter.LineToBeIndented.LineNumber - 1; currentLineNumber >= startLine.LineNumber + 1; currentLineNumber--)
                {
                    var currentLine = sourceText.Lines[currentLineNumber];
                    if (currentLine.GetFirstNonWhitespaceOffset() is { } priorLineOffset)
                    {
                        if (priorLineOffset >= minimumOffset.Value)
                        {
                            return(indenter.GetIndentationOfLine(currentLine));
                        }
                        else
                        {
                            // The prior line is not sufficiently indented, so use the ending delimiter for the indent
                            break;
                        }
                    }
                }

                return(indenter.GetIndentationOfLine(endLine));
            }

            // case 1: $"""$$
            //          """
            // case 2: $"""
            //          text$$
            //          """
            // case 3: $"""
            //          {value}$$
            //          """
            if (token.Kind() is SyntaxKind.InterpolatedMultiLineRawStringStartToken or SyntaxKind.InterpolatedStringTextToken ||
                (token.IsKind(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Interpolation)))
            {
                var interpolatedExpression = token.GetAncestor <InterpolatedStringExpressionSyntax>();
                Contract.ThrowIfNull(interpolatedExpression);
                if (interpolatedExpression.StringStartToken.IsKind(SyntaxKind.InterpolatedMultiLineRawStringStartToken))
                {
                    var endLine       = sourceText.Lines.GetLineFromPosition(interpolatedExpression.StringEndToken.Span.End);
                    var minimumOffset = endLine.GetFirstNonWhitespaceOffset();
                    Contract.ThrowIfNull(minimumOffset);

                    // If possible, indent to match the indentation of the previous non-whitespace line contained in the
                    // same raw string. Otherwise, indent to match the ending line of the raw string.
                    var startLine = sourceText.Lines.GetLineFromPosition(interpolatedExpression.StringStartToken.SpanStart);
                    for (var currentLineNumber = indenter.LineToBeIndented.LineNumber - 1; currentLineNumber >= startLine.LineNumber + 1; currentLineNumber--)
                    {
                        var currentLine = sourceText.Lines[currentLineNumber];
                        if (!indenter.Root.FindToken(currentLine.Start, findInsideTrivia: true).IsKind(SyntaxKind.InterpolatedStringTextToken))
                        {
                            // Avoid trying to indent to match the content of an interpolation. Example:
                            //
                            // _ = $"""
                            //     {
                            //  0}         <-- the start of this line is not part of the text content
                            //     """
                            //
                            continue;
                        }

                        if (currentLine.GetFirstNonWhitespaceOffset() is { } priorLineOffset)
                        {
                            if (priorLineOffset >= minimumOffset.Value)
                            {
                                return(indenter.GetIndentationOfLine(currentLine));
                            }
                            else
                            {
                                // The prior line is not sufficiently indented, so use the ending delimiter for the indent
                                break;
                            }
                        }
                    }

                    return(indenter.GetIndentationOfLine(endLine));
                }
            }

            // special cases
            // case 1: token belongs to verbatim token literal
            // case 2: $@"$${0}"
            // case 3: $@"Comment$$ in-between{0}"
            // case 4: $@"{0}$$"
            if (token.IsVerbatimStringLiteral() ||
                token.IsKind(SyntaxKind.InterpolatedVerbatimStringStartToken) ||
                token.IsKind(SyntaxKind.InterpolatedStringTextToken) ||
                (token.IsKind(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Interpolation)))
            {
                return(indenter.IndentFromStartOfLine(0));
            }

            // if previous statement belong to labeled statement, don't follow label's indentation
            // but its previous one.
            if (token.Parent is LabeledStatementSyntax || token.IsLastTokenInLabelStatement())
            {
                token = token.GetAncestor <LabeledStatementSyntax>() !.GetFirstToken(includeZeroWidth: true).GetPreviousToken(includeZeroWidth: true);
            }

            var position = indenter.GetCurrentPositionNotBelongToEndOfFileToken(indenter.LineToBeIndented.Start);

            // first check operation service to see whether we can determine indentation from it
            var indentation = indenter.Finder.FromIndentBlockOperations(indenter.Tree, token, position, indenter.CancellationToken);

            if (indentation.HasValue)
            {
                return(indenter.IndentFromStartOfLine(indentation.Value));
            }

            var alignmentTokenIndentation = indenter.Finder.FromAlignTokensOperations(indenter.Tree, token);

            if (alignmentTokenIndentation.HasValue)
            {
                return(indenter.IndentFromStartOfLine(alignmentTokenIndentation.Value));
            }

            // if we couldn't determine indentation from the service, use heuristic to find indentation.

            // If this is the last token of an embedded statement, walk up to the top-most parenting embedded
            // statement owner and use its indentation.
            //
            // cases:
            //   if (true)
            //     if (false)
            //       Goo();
            //
            //   if (true)
            //     { }

            if (token.IsSemicolonOfEmbeddedStatement() ||
                token.IsCloseBraceOfEmbeddedBlock())
            {
                RoslynDebug.Assert(
                    token.Parent != null &&
                    (token.Parent.Parent is StatementSyntax || token.Parent.Parent is ElseClauseSyntax));

                var embeddedStatementOwner = token.Parent.Parent;
                while (embeddedStatementOwner.IsEmbeddedStatement())
                {
                    RoslynDebug.AssertNotNull(embeddedStatementOwner.Parent);
                    embeddedStatementOwner = embeddedStatementOwner.Parent;
                }

                return(indenter.GetIndentationOfLine(sourceText.Lines.GetLineFromPosition(embeddedStatementOwner.GetFirstToken(includeZeroWidth: true).SpanStart)));
            }

            switch (token.Kind())
            {
            case SyntaxKind.SemicolonToken:
            {
                // special cases
                if (token.IsSemicolonInForStatement())
                {
                    return(GetDefaultIndentationFromToken(indenter, token));
                }

                return(indenter.IndentFromStartOfLine(indenter.Finder.GetIndentationOfCurrentPosition(indenter.Tree, token, position, indenter.CancellationToken)));
            }

            case SyntaxKind.CloseBraceToken:
            {
                if (token.Parent.IsKind(SyntaxKind.AccessorList) &&
                    token.Parent.Parent.IsKind(SyntaxKind.PropertyDeclaration))
                {
                    if (token.GetNextToken().IsEqualsTokenInAutoPropertyInitializers())
                    {
                        return(GetDefaultIndentationFromToken(indenter, token));
                    }
                }

                return(indenter.IndentFromStartOfLine(indenter.Finder.GetIndentationOfCurrentPosition(indenter.Tree, token, position, indenter.CancellationToken)));
            }

            case SyntaxKind.OpenBraceToken:
            {
                return(indenter.IndentFromStartOfLine(indenter.Finder.GetIndentationOfCurrentPosition(indenter.Tree, token, position, indenter.CancellationToken)));
            }

            case SyntaxKind.ColonToken:
            {
                var nonTerminalNode = token.Parent;
                Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                if (nonTerminalNode is SwitchLabelSyntax)
                {
                    return(indenter.GetIndentationOfLine(sourceText.Lines.GetLineFromPosition(nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart), indenter.Options.FormattingOptions.IndentationSize));
                }

                goto default;
            }

            case SyntaxKind.CloseBracketToken:
            {
                var nonTerminalNode = token.Parent;
                Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                // if this is closing an attribute, we shouldn't indent.
                if (nonTerminalNode is AttributeListSyntax)
                {
                    return(indenter.GetIndentationOfLine(sourceText.Lines.GetLineFromPosition(nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart)));
                }

                goto default;
            }

            case SyntaxKind.XmlTextLiteralToken:
            {
                return(indenter.GetIndentationOfLine(sourceText.Lines.GetLineFromPosition(token.SpanStart)));
            }

            case SyntaxKind.CommaToken:
            {
                return(GetIndentationFromCommaSeparatedList(indenter, token));
            }

            case SyntaxKind.CloseParenToken:
            {
                if (token.Parent.IsKind(SyntaxKind.ArgumentList))
                {
                    return(GetDefaultIndentationFromToken(indenter, token.Parent.GetFirstToken(includeZeroWidth: true)));
                }

                goto default;
            }

            default:
            {
                return(GetDefaultIndentationFromToken(indenter, token));
            }
            }
        }
Beispiel #14
0
            private IndentationResult?GetIndentationBasedOnToken(SyntaxToken token)
            {
                Contract.ThrowIfNull(LineToBeIndented);
                Contract.ThrowIfNull(Tree);
                Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None);

                // special cases
                // if token belongs to verbatim token literal
                if (token.IsVerbatimStringLiteral())
                {
                    return(IndentFromStartOfLine(0));
                }

                // if previous statement belong to labeled statement, don't follow label's indentation
                // but its previous one.
                if (token.Parent is LabeledStatementSyntax || token.IsLastTokenInLabelStatement())
                {
                    token = token.GetAncestor <LabeledStatementSyntax>().GetFirstToken(includeZeroWidth: true).GetPreviousToken(includeZeroWidth: true);
                }

                var position = GetCurrentPositionNotBelongToEndOfFileToken(LineToBeIndented.Start);

                // first check operation service to see whether we can determine indentation from it
                var indentation = Finder.FromIndentBlockOperations(Tree, token, position, CancellationToken);

                if (indentation.HasValue)
                {
                    return(IndentFromStartOfLine(indentation.Value));
                }

                var alignmentTokenIndentation = Finder.FromAlignTokensOperations(Tree, token);

                if (alignmentTokenIndentation.HasValue)
                {
                    return(IndentFromStartOfLine(alignmentTokenIndentation.Value));
                }

                // if we couldn't determine indentation from the service, use hueristic to find indentation.
                var snapshot = LineToBeIndented.Snapshot;

                // If this is the last token of an embedded statement, walk up to the top-most parenting embedded
                // statement owner and use its indentation.
                //
                // cases:
                //   if (true)
                //     if (false)
                //       Foo();
                //
                //   if (true)
                //     { }

                if (token.IsSemicolonOfEmbeddedStatement() ||
                    token.IsCloseBraceOfEmbeddedBlock())
                {
                    Contract.Requires(
                        token.Parent != null &&
                        (token.Parent.Parent is StatementSyntax || token.Parent.Parent is ElseClauseSyntax));

                    var embeddedStatementOwner = token.Parent.Parent;
                    while (embeddedStatementOwner.IsEmbeddedStatement())
                    {
                        embeddedStatementOwner = embeddedStatementOwner.Parent;
                    }

                    return(GetIndentationOfLine(snapshot.GetLineFromPosition(embeddedStatementOwner.GetFirstToken(includeZeroWidth: true).SpanStart)));
                }

                switch (token.Kind())
                {
                case SyntaxKind.SemicolonToken:
                {
                    // special cases
                    if (token.IsSemicolonInForStatement())
                    {
                        return(GetDefaultIndentationFromToken(token));
                    }

                    return(IndentFromStartOfLine(Finder.GetIndentationOfCurrentPosition(Tree, token, position, CancellationToken)));
                }

                case SyntaxKind.CloseBraceToken:
                {
                    return(IndentFromStartOfLine(Finder.GetIndentationOfCurrentPosition(Tree, token, position, CancellationToken)));
                }

                case SyntaxKind.OpenBraceToken:
                {
                    return(IndentFromStartOfLine(Finder.GetIndentationOfCurrentPosition(Tree, token, position, CancellationToken)));
                }

                case SyntaxKind.ColonToken:
                {
                    var nonTerminalNode = token.Parent;
                    Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                    if (nonTerminalNode is SwitchLabelSyntax)
                    {
                        return(GetIndentationOfLine(snapshot.GetLineFromPosition(nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart), OptionSet.GetOption(FormattingOptions.IndentationSize, token.Language)));
                    }

                    // default case
                    return(GetDefaultIndentationFromToken(token));
                }

                case SyntaxKind.CloseBracketToken:
                {
                    var nonTerminalNode = token.Parent;
                    Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                    // if this is closing an attribute, we shouldn't indent.
                    if (nonTerminalNode is AttributeListSyntax)
                    {
                        return(GetIndentationOfLine(snapshot.GetLineFromPosition(nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart)));
                    }

                    // default case
                    return(GetDefaultIndentationFromToken(token));
                }

                case SyntaxKind.XmlTextLiteralToken:
                {
                    return(GetIndentationOfLine(snapshot.GetLineFromPosition(token.SpanStart)));
                }

                case SyntaxKind.CommaToken:
                {
                    return(GetIndentationFromCommaSeparatedList(token));
                }

                default:
                {
                    return(GetDefaultIndentationFromToken(token));
                }
                }
            }
Beispiel #15
0
        internal static bool IsTriggerParenOrComma <TSyntaxNode>(SyntaxToken token, Func <char, bool> isTriggerCharacter) where TSyntaxNode : SyntaxNode
        {
            // Don't dismiss if the user types ( to start a parenthesized expression or tuple
            // Note that the tuple initially parses as a parenthesized expression
            if (token.IsKind(SyntaxKind.OpenParenToken) && token.Parent.IsKind(SyntaxKind.ParenthesizedExpression))
            {
                var parenthesizedExpr = ((ParenthesizedExpressionSyntax)token.Parent).WalkUpParentheses();
                if (parenthesizedExpr.Parent is ArgumentSyntax)
                {
                    var parent      = parenthesizedExpr.Parent;
                    var grandParent = parent.Parent;
                    if (grandParent is ArgumentListSyntax && grandParent.Parent is TSyntaxNode)
                    {
                        // Argument to TSyntaxNode's argument list
                        return(true);
                    }
                    else
                    {
                        // Argument to a tuple in TSyntaxNode's argument list
                        return(grandParent is TupleExpressionSyntax && parenthesizedExpr.GetAncestor <TSyntaxNode>() != null);
                    }
                }
                else
                {
                    // Not an argument
                    return(false);
                }
            }

            // Don't dismiss if the user types ',' to add a member to a tuple
            if (token.IsKind(SyntaxKind.CommaToken) && token.Parent is TupleExpressionSyntax && token.GetAncestor <TSyntaxNode>() != null)
            {
                return(true);
            }

            return(!token.IsKind(SyntaxKind.None) &&
                   token.ValueText.Length == 1 &&
                   isTriggerCharacter(token.ValueText[0]) &&
                   token.Parent is ArgumentListSyntax &&
                   token.Parent.Parent is TSyntaxNode);
        }
        public static bool IsBeginningOfGlobalStatementContext(this SyntaxToken token)
        {
            // cases:
            // }
            // |

            // ...;
            // |

            // extern alias Goo;
            // using System;
            // |

            // [assembly: Goo]
            // |

            if (token.Kind() == SyntaxKind.CloseBraceToken)
            {
                var memberDeclaration = token.GetAncestor <MemberDeclarationSyntax>();
                if (memberDeclaration != null && memberDeclaration.GetLastToken(includeZeroWidth: true) == token &&
                    memberDeclaration.IsParentKind(SyntaxKind.CompilationUnit))
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.SemicolonToken)
            {
                var globalStatement = token.GetAncestor <GlobalStatementSyntax>();
                if (globalStatement != null && globalStatement.GetLastToken(includeZeroWidth: true) == token)
                {
                    return(true);
                }

                // Need this check to check file scoped namespace declarations prior to a catch-all of
                // member declarations since otherwise it would return true.
                if (token.Parent is FileScopedNamespaceDeclarationSyntax namespaceDeclaration && namespaceDeclaration.SemicolonToken == token)
                {
                    return(false);
                }

                var memberDeclaration = token.GetAncestor <MemberDeclarationSyntax>();
                if (memberDeclaration != null && memberDeclaration.GetLastToken(includeZeroWidth: true) == token &&
                    memberDeclaration.IsParentKind(SyntaxKind.CompilationUnit))
                {
                    return(true);
                }

                var compUnit = token.GetAncestor <CompilationUnitSyntax>();
                if (compUnit != null)
                {
                    if (compUnit.Usings.Count > 0 && compUnit.Usings.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }

                    if (compUnit.Externs.Count > 0 && compUnit.Externs.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }
                }
            }

            if (token.Kind() == SyntaxKind.CloseBracketToken)
            {
                var compUnit = token.GetAncestor <CompilationUnitSyntax>();
                if (compUnit != null)
                {
                    if (compUnit.AttributeLists.Count > 0 && compUnit.AttributeLists.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }
                }

                if (token.Parent.IsKind(SyntaxKind.AttributeList))
                {
                    var container = token.Parent.Parent;
                    if (container is IncompleteMemberSyntax && container.Parent is CompilationUnitSyntax)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Beispiel #17
0
 protected override IMethodSymbol GetCurrentConstructor(SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken)
 => token.GetAncestor <ConstructorDeclarationSyntax>() is
 {
        private static bool IsValidElseKeywordContext(SyntaxToken token)
        {
            var statement = token.GetAncestor<StatementSyntax>();
            var ifStatement = statement.GetAncestorOrThis<IfStatementSyntax>();

            if (statement == null || ifStatement == null)
                return false;

            // cases:
            //   if (foo)
            //     Console.WriteLine();
            //   |
            //   if (foo)
            //     Console.WriteLine();
            //   e|
            if (token.IsKind(SyntaxKind.SemiToken) && ifStatement.Statement.GetLastToken(includeSkippedTokens: true) == token)
                return true;

            // if (foo) {
            //     Console.WriteLine();
            //   } |
            //   if (foo) {
            //     Console.WriteLine();
            //   } e|
            if (token.IsKind(SyntaxKind.CloseBraceToken) && ifStatement.Statement is BlockSyntax && token == ((BlockSyntax) ifStatement.Statement).CloseBraceToken)
                return true;

            return false;
        }
        public static bool IsBeginningOfStatementContext(this SyntaxToken token)
        {
            // cases:
            //    {
            //      |

            // }
            // |

            // Note, the following is *not* a legal statement context:
            //    do { } |

            // ...;
            // |

            // case 0:
            //   |

            // default:
            //   |

            // label:
            //   |

            // if (goo)
            //   |

            // while (true)
            //   |

            // do
            //   |

            // for (;;)
            //   |

            // foreach (var v in c)
            //   |

            // else
            //   |

            // using (expr)
            //   |

            // fixed (void* v = &expr)
            //   |

            // lock (expr)
            //   |

            // for ( ; ; Goo(), |

            // After attribute lists on a statement:
            //   [Bar]
            //   |

            switch (token.Kind())
            {
            case SyntaxKind.OpenBraceToken when token.Parent.IsKind(SyntaxKind.Block):
                return(true);

            case SyntaxKind.SemicolonToken:
                var statement = token.GetAncestor <StatementSyntax>();
                return(statement != null && !statement.IsParentKind(SyntaxKind.GlobalStatement) &&
                       statement.GetLastToken(includeZeroWidth: true) == token);

            case SyntaxKind.CloseBraceToken:
                if (token.Parent.IsKind(SyntaxKind.Block))
                {
                    if (token.Parent.Parent is StatementSyntax)
                    {
                        // Most blocks that are the child of statement are places
                        // that we can follow with another statement.  i.e.:
                        // if { }
                        // while () { }
                        // There are two exceptions.
                        // try {}
                        // do {}
                        if (!token.Parent.IsParentKind(SyntaxKind.TryStatement) &&
                            !token.Parent.IsParentKind(SyntaxKind.DoStatement))
                        {
                            return(true);
                        }
                    }
                    else if (
                        token.Parent.IsParentKind(SyntaxKind.ElseClause) ||
                        token.Parent.IsParentKind(SyntaxKind.FinallyClause) ||
                        token.Parent.IsParentKind(SyntaxKind.CatchClause) ||
                        token.Parent.IsParentKind(SyntaxKind.SwitchSection))
                    {
                        return(true);
                    }
                }

                if (token.Parent.IsKind(SyntaxKind.SwitchStatement))
                {
                    return(true);
                }

                return(false);

            case SyntaxKind.ColonToken:
                return(token.Parent.IsKind(SyntaxKind.CaseSwitchLabel,
                                           SyntaxKind.DefaultSwitchLabel,
                                           SyntaxKind.CasePatternSwitchLabel,
                                           SyntaxKind.LabeledStatement));

            case SyntaxKind.DoKeyword when token.Parent.IsKind(SyntaxKind.DoStatement):
                return(true);

            case SyntaxKind.CloseParenToken:
                var parent = token.Parent;
                return(parent.IsKind(SyntaxKind.ForStatement) ||
                       parent.IsKind(SyntaxKind.ForEachStatement) ||
                       parent.IsKind(SyntaxKind.ForEachVariableStatement) ||
                       parent.IsKind(SyntaxKind.WhileStatement) ||
                       parent.IsKind(SyntaxKind.IfStatement) ||
                       parent.IsKind(SyntaxKind.LockStatement) ||
                       parent.IsKind(SyntaxKind.UsingStatement) ||
                       parent.IsKind(SyntaxKind.FixedStatement));

            case SyntaxKind.ElseKeyword:
                return(token.Parent.IsKind(SyntaxKind.ElseClause));

            case SyntaxKind.CloseBracketToken:
                if (token.Parent.IsKind(SyntaxKind.AttributeList))
                {
                    // attributes can belong to a statement
                    var container = token.Parent.Parent;
                    if (container is StatementSyntax)
                    {
                        return(true);
                    }
                }

                return(false);
            }

            return(false);
        }
Beispiel #20
0
        // copied from compiler formatter to have same base forced format
        private int LineBreaksAfter(SyntaxToken previousToken, SyntaxToken currentToken)
        {
            if (currentToken.Kind() == SyntaxKind.None)
            {
                return(0);
            }

            switch (previousToken.Kind())
            {
            case SyntaxKind.None:
                return(0);

            case SyntaxKind.OpenBraceToken:
            case SyntaxKind.FinallyKeyword:
                return(1);

            case SyntaxKind.CloseBraceToken:
                return(LineBreaksAfterCloseBrace(currentToken));

            case SyntaxKind.CloseParenToken:
                return((((previousToken.Parent is StatementSyntax) && currentToken.Parent != previousToken.Parent) ||
                        currentToken.Kind() == SyntaxKind.OpenBraceToken) ? 1 : 0);

            case SyntaxKind.CloseBracketToken:
                // Assembly and module-level attributes followed by non-attributes should have
                // a blank line after them.
                if (previousToken.Parent is AttributeSyntax parent)
                {
                    if (parent.Target != null &&
                        (parent.Target.Identifier.IsKindOrHasMatchingText(SyntaxKind.AssemblyKeyword)))
                    {
                        if (!(currentToken.Parent is AttributeSyntax))
                        {
                            return(2);
                        }
                    }

                    if (previousToken.GetAncestor <ParameterSyntax>() == null)
                    {
                        return(1);
                    }
                }

                break;

            case SyntaxKind.SemicolonToken:
                return(LineBreaksAfterSemicolon(previousToken, currentToken));

            case SyntaxKind.CommaToken:
                return(previousToken.Parent is EnumDeclarationSyntax ? 1 : 0);

            case SyntaxKind.ElseKeyword:
                return(currentToken.Kind() != SyntaxKind.IfKeyword ? 1 : 0);

            case SyntaxKind.ColonToken:
                if (previousToken.Parent is LabeledStatementSyntax || previousToken.Parent is SwitchLabelSyntax)
                {
                    return(1);
                }

                break;
            }

            if ((currentToken.Kind() == SyntaxKind.FromKeyword && currentToken.Parent.Kind() == SyntaxKind.FromClause) ||
                (currentToken.Kind() == SyntaxKind.LetKeyword && currentToken.Parent.Kind() == SyntaxKind.LetClause) ||
                (currentToken.Kind() == SyntaxKind.WhereKeyword && currentToken.Parent.Kind() == SyntaxKind.WhereClause) ||
                (currentToken.Kind() == SyntaxKind.JoinKeyword && currentToken.Parent.Kind() == SyntaxKind.JoinClause) ||
                (currentToken.Kind() == SyntaxKind.JoinKeyword && currentToken.Parent.Kind() == SyntaxKind.JoinIntoClause) ||
                (currentToken.Kind() == SyntaxKind.OrderByKeyword && currentToken.Parent.Kind() == SyntaxKind.OrderByClause) ||
                (currentToken.Kind() == SyntaxKind.SelectKeyword && currentToken.Parent.Kind() == SyntaxKind.SelectClause) ||
                (currentToken.Kind() == SyntaxKind.GroupKeyword && currentToken.Parent.Kind() == SyntaxKind.GroupClause))
            {
                return(1);
            }

            switch (currentToken.Kind())
            {
            case SyntaxKind.OpenBraceToken:
            case SyntaxKind.CloseBraceToken:
            case SyntaxKind.ElseKeyword:
            case SyntaxKind.FinallyKeyword:
                return(1);

            case SyntaxKind.OpenBracketToken:
                // Assembly and module-level attributes preceded by non-attributes should have
                // a blank line separating them.
                if (currentToken.Parent is AttributeSyntax parent)
                {
                    if (parent.Target != null)
                    {
                        if (parent.Target.Identifier == SyntaxFactory.Token(SyntaxKind.AssemblyKeyword))
                        {
                            if (!(previousToken.Parent is AttributeSyntax))
                            {
                                return(2);
                            }
                        }
                    }

                    // Attributes on parameters should have no lines between them.
                    if (parent.Parent is ParameterSyntax)
                    {
                        return(0);
                    }

                    return(1);
                }

                break;

            case SyntaxKind.WhereKeyword:
                return(previousToken.Parent is TypeParameterListSyntax ? 1 : 0);
            }

            return(0);
        }
Beispiel #21
0
 public static SyntaxNode GetAncestor(this SyntaxToken token, Func <SyntaxNode, bool> predicate)
 {
     return(token.GetAncestor <SyntaxNode>(predicate));
 }
        // Copied from
        // https://github.com/dotnet/roslyn/blob/fb5d0b2a0daa2cbc66c88c1ff483b52d0ed4b9d5/src/Workspaces/CSharp/Portable/Extensions/ContextQuery/SyntaxTokenExtensions.cs#L51
        public static bool IsBeginningOfStatementContext(this SyntaxToken token)
        {
            // cases:
            //    {
            //      |

            // }
            // |

            // Note, the following is *not* a legal statement context:
            //    do { } |

            // ...;
            // |

            // case 0:
            //   |

            // default:
            //   |

            // if (foo)
            //   |

            // while (true)
            //   |

            // do
            //   |

            // for (;;)
            //   |

            // else
            //   |

            // for ( ; ; Foo(), |

            if (token.Kind == SyntaxKind.OpenBraceToken &&
                token.Parent.IsKind(SyntaxKind.Block))
            {
                return(true);
            }

            if (token.Kind == SyntaxKind.SemiToken)
            {
                var statement = token.GetAncestor <StatementSyntax>();
                if (statement != null && !statement.IsParentKind(SyntaxKind.GlobalStatement) &&
                    statement.GetLastToken(includeSkippedTokens: true) == token)
                {
                    return(true);
                }
            }

            if (token.Kind == SyntaxKind.CloseBraceToken &&
                token.Parent.IsKind(SyntaxKind.Block))
            {
                if (token.Parent.Parent is StatementSyntax)
                {
                    // Most blocks that are the child of statement are places
                    // that we can follow with another statement.  i.e.:
                    // if { }
                    // while () { }
                    // There is one exception.
                    // do {}
                    if (!token.Parent.IsParentKind(SyntaxKind.DoStatement))
                    {
                        return(true);
                    }
                }
                else if (
                    token.Parent.IsParentKind(SyntaxKind.ElseClause) ||
                    token.Parent.IsParentKind(SyntaxKind.SwitchSection))
                {
                    return(true);
                }
            }

            if (token.Kind == SyntaxKind.CloseBraceToken &&
                token.Parent.IsKind(SyntaxKind.SwitchStatement))
            {
                return(true);
            }

            if (token.Kind == SyntaxKind.ColonToken)
            {
                if (token.Parent.IsKind(SyntaxKind.CaseSwitchLabel, SyntaxKind.DefaultSwitchLabel))
                {
                    return(true);
                }
            }

            if (token.Kind == SyntaxKind.DoKeyword &&
                token.Parent.IsKind(SyntaxKind.DoStatement))
            {
                return(true);
            }

            if (token.Kind == SyntaxKind.CloseParenToken)
            {
                var parent = token.Parent;
                if (parent.IsKind(SyntaxKind.ForStatement) ||
                    parent.IsKind(SyntaxKind.WhileStatement) ||
                    parent.IsKind(SyntaxKind.IfStatement))
                {
                    return(true);
                }
            }

            if (token.Kind == SyntaxKind.ElseKeyword)
            {
                return(true);
            }

            return(false);
        }
        private IEnumerable<CompletionItem> GetTagsForMethod(IMethodSymbol symbol, TextSpan filterSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List<CompletionItem>();

            var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor<XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == "paramref")
                {
                    items.AddRange(parameters.Select(p => new XmlDocCommentCompletionItem(this, filterSpan, p, GetCompletionItemRules())));
                }
                else if (parentElementName == "typeparamref")
                {
                    items.AddRange(typeParameters.Select(t => new XmlDocCommentCompletionItem(this, filterSpan, t, GetCompletionItemRules())));
                }

                return items;
            }

            var returns = true;

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, "param"));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, "typeparam"));

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == "returns")
                    {
                        returns = false;
                        break;
                    }
                }
            }

            items.AddRange(parameters.Select(p => new XmlDocCommentCompletionItem(this, filterSpan, FormatParameter("param", p), GetCompletionItemRules())));
            items.AddRange(typeParameters.Select(t => new XmlDocCommentCompletionItem(this, filterSpan, FormatParameter("typeparam", t), GetCompletionItemRules())));

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(new XmlDocCommentCompletionItem(this, filterSpan, "returns", GetCompletionItemRules()));
            }

            return items;
        }
            private bool IsPartOfQueryExpression(SyntaxToken token)
            {
                var queryExpression = token.GetAncestor <QueryExpressionSyntax>();

                return(queryExpression != null);
            }
        private bool TryGetTextForSymbol(SyntaxToken token, SemanticModel semanticModel, Document document, CancellationToken cancellationToken, out string text)
        {
            ISymbol symbol;
            if (token.Parent is TypeArgumentListSyntax)
            {
                var genericName = token.GetAncestor<GenericNameSyntax>();
                symbol = semanticModel.GetSymbolInfo(genericName, cancellationToken).Symbol ?? semanticModel.GetTypeInfo(genericName, cancellationToken).Type;
            }
            else if (token.Parent is NullableTypeSyntax && token.IsKind(SyntaxKind.QuestionToken))
            {
                text = "System.Nullable`1";
                return true;
            }
            else
            {
                var symbols = semanticModel.GetSymbols(token, document.Project.Solution.Workspace, bindLiteralsToUnderlyingType: true, cancellationToken: cancellationToken);
                symbol = symbols.FirstOrDefault();

                if (symbol == null)
                {
                    var bindableParent = document.GetLanguageService<ISyntaxFactsService>().GetBindableParent(token);
                    var overloads = semanticModel.GetMemberGroup(bindableParent);
                    symbol = overloads.FirstOrDefault();
                }
            }

            // Local: return the name if it's the declaration, otherwise the type
            if (symbol is ILocalSymbol && !symbol.DeclaringSyntaxReferences.Any(d => d.GetSyntax().DescendantTokens().Contains(token)))
            {
                symbol = ((ILocalSymbol)symbol).Type;
            }

            // Range variable: use the type
            if (symbol is IRangeVariableSymbol)
            {
                var info = semanticModel.GetTypeInfo(token.Parent, cancellationToken);
                symbol = info.Type;
            }

            // Just use syntaxfacts for operators
            if (symbol is IMethodSymbol && ((IMethodSymbol)symbol).MethodKind == MethodKind.BuiltinOperator)
            {
                text = null;
                return false;
            }

            text = symbol != null ? Format(symbol) : null;
            return symbol != null;
        }
Beispiel #26
0
        private bool TryGetTextForSymbol(
            SyntaxToken token, SemanticModel semanticModel, Document document, CancellationToken cancellationToken,
            [NotNullWhen(true)] out string?text)
        {
            ISymbol?symbol = null;

            if (token.Parent is TypeArgumentListSyntax)
            {
                var genericName = token.GetAncestor <GenericNameSyntax>();
                if (genericName != null)
                {
                    symbol = semanticModel.GetSymbolInfo(genericName, cancellationToken).Symbol ?? semanticModel.GetTypeInfo(genericName, cancellationToken).Type;
                }
            }
            else if (token.Parent is NullableTypeSyntax && token.IsKind(SyntaxKind.QuestionToken))
            {
                text = "System.Nullable`1";
                return(true);
            }
            else
            {
                symbol = semanticModel.GetSemanticInfo(token, document.Project.Solution.Workspace.Services, cancellationToken)
                         .GetAnySymbol(includeType: true);

                if (symbol == null)
                {
                    var bindableParent = document.GetRequiredLanguageService <ISyntaxFactsService>().TryGetBindableParent(token);
                    var overloads      = bindableParent != null?semanticModel.GetMemberGroup(bindableParent) : ImmutableArray <ISymbol> .Empty;

                    symbol = overloads.FirstOrDefault();
                }
            }

            // Local: return the name if it's the declaration, otherwise the type
            if (symbol is ILocalSymbol localSymbol && !symbol.DeclaringSyntaxReferences.Any(d => d.GetSyntax().DescendantTokens().Contains(token)))
            {
                symbol = localSymbol.Type;
            }

            // Range variable: use the type
            if (symbol is IRangeVariableSymbol)
            {
                var info = semanticModel.GetTypeInfo(token.GetRequiredParent(), cancellationToken);
                symbol = info.Type;
            }

            // Just use syntaxfacts for operators
            if (symbol is IMethodSymbol method && method.MethodKind == MethodKind.BuiltinOperator)
            {
                text = null;
                return(false);
            }

            if (symbol is IDiscardSymbol)
            {
                text = Keyword("discard");
                return(true);
            }

            text = FormatSymbol(symbol);
            return(text != null);
        }
        private bool TryGetTextForKeyword(SyntaxToken token, Document document, ISyntaxFactsService syntaxFacts, out string text)
        {
            if (token.Kind() == SyntaxKind.InKeyword)
            {
                if (token.GetAncestor<FromClauseSyntax>() != null)
                {
                    text = "from_CSharpKeyword";
                    return true;
                }

                if (token.GetAncestor<JoinClauseSyntax>() != null)
                {
                    text = "join_CSharpKeyword";
                    return true;
                }
            }

            if (token.IsKeyword())
            {
                text = Keyword(token.Text);
                return true;
            }

            if (token.ValueText == "var" && token.IsKind(SyntaxKind.IdentifierToken) &&
                token.Parent.Parent is VariableDeclarationSyntax && token.Parent == ((VariableDeclarationSyntax)token.Parent.Parent).Type)
            {
                text = "var_CSharpKeyword";
                return true;
            }

            if (syntaxFacts.IsTypeNamedDynamic(token, token.Parent))
            {
                text = "dynamic_CSharpKeyword";
                return true;
            }

            text = null;
            return false;
        }
        private IEnumerable <CompletionData> GetTagsForMethod(CompletionEngine engine, IMethodSymbol symbol, TextSpan filterSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List <CompletionData>();

            var parameters     = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor <XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == "paramref")
                {
                    items.AddRange(parameters.Select(p => engine.Factory.CreateXmlDocCompletionData(this, p)));
                }
                else if (parentElementName == "typeparamref")
                {
                    items.AddRange(typeParameters.Select(t => engine.Factory.CreateXmlDocCompletionData(this, t)));
                }

                return(items);
            }

            var returns = true;

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, "param"));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, "typeparam"));

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == "returns")
                    {
                        returns = false;
                        break;
                    }
                }
            }

            items.AddRange(parameters.Select(p => engine.Factory.CreateXmlDocCompletionData(this, FormatParameter("param", p))));
            items.AddRange(typeParameters.Select(t => engine.Factory.CreateXmlDocCompletionData(this, FormatParameter("typeparam", t))));

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(engine.Factory.CreateXmlDocCompletionData(this, "returns"));
            }

            return(items);
        }
Beispiel #29
0
        private static IndentationResult GetIndentationBasedOnToken(
            Indenter indenter,
            SyntaxToken token
            )
        {
            Contract.ThrowIfNull(indenter.Tree);
            Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None);

            // special cases
            // case 1: token belongs to verbatim token literal
            // case 2: $@"$${0}"
            // case 3: $@"Comment$$ in-between{0}"
            // case 4: $@"{0}$$"
            if (
                token.IsVerbatimStringLiteral() ||
                token.IsKind(SyntaxKind.InterpolatedVerbatimStringStartToken) ||
                token.IsKind(SyntaxKind.InterpolatedStringTextToken) ||
                (
                    token.IsKind(SyntaxKind.CloseBraceToken) &&
                    token.Parent.IsKind(SyntaxKind.Interpolation)
                )
                )
            {
                return(indenter.IndentFromStartOfLine(0));
            }

            // if previous statement belong to labeled statement, don't follow label's indentation
            // but its previous one.
            if (token.Parent is LabeledStatementSyntax || token.IsLastTokenInLabelStatement())
            {
                token = token.GetAncestor <LabeledStatementSyntax>() !
                        .GetFirstToken(includeZeroWidth: true)
                        .GetPreviousToken(includeZeroWidth: true);
            }

            var position = indenter.GetCurrentPositionNotBelongToEndOfFileToken(
                indenter.LineToBeIndented.Start
                );

            // first check operation service to see whether we can determine indentation from it
            var indentation = indenter.Finder.FromIndentBlockOperations(
                indenter.Tree,
                token,
                position,
                indenter.CancellationToken
                );

            if (indentation.HasValue)
            {
                return(indenter.IndentFromStartOfLine(indentation.Value));
            }

            var alignmentTokenIndentation = indenter.Finder.FromAlignTokensOperations(
                indenter.Tree,
                token
                );

            if (alignmentTokenIndentation.HasValue)
            {
                return(indenter.IndentFromStartOfLine(alignmentTokenIndentation.Value));
            }

            // if we couldn't determine indentation from the service, use heuristic to find indentation.
            var sourceText = indenter.LineToBeIndented.Text;

            RoslynDebug.AssertNotNull(sourceText);

            // If this is the last token of an embedded statement, walk up to the top-most parenting embedded
            // statement owner and use its indentation.
            //
            // cases:
            //   if (true)
            //     if (false)
            //       Goo();
            //
            //   if (true)
            //     { }

            if (token.IsSemicolonOfEmbeddedStatement() || token.IsCloseBraceOfEmbeddedBlock())
            {
                Debug.Assert(
                    token.Parent != null &&
                    (
                        token.Parent.Parent is StatementSyntax ||
                        token.Parent.Parent is ElseClauseSyntax
                    )
                    );

                var embeddedStatementOwner = token.Parent.Parent;
                while (embeddedStatementOwner.IsEmbeddedStatement())
                {
                    RoslynDebug.AssertNotNull(embeddedStatementOwner.Parent);
                    embeddedStatementOwner = embeddedStatementOwner.Parent;
                }

                return(indenter.GetIndentationOfLine(
                           sourceText.Lines.GetLineFromPosition(
                               embeddedStatementOwner.GetFirstToken(includeZeroWidth: true).SpanStart
                               )
                           ));
            }

            switch (token.Kind())
            {
            case SyntaxKind.SemicolonToken:
            {
                // special cases
                if (token.IsSemicolonInForStatement())
                {
                    return(GetDefaultIndentationFromToken(indenter, token));
                }

                return(indenter.IndentFromStartOfLine(
                           indenter.Finder.GetIndentationOfCurrentPosition(
                               indenter.Tree,
                               token,
                               position,
                               indenter.CancellationToken
                               )
                           ));
            }

            case SyntaxKind.CloseBraceToken:
            {
                if (
                    token.Parent.IsKind(SyntaxKind.AccessorList) &&
                    token.Parent.Parent.IsKind(SyntaxKind.PropertyDeclaration)
                    )
                {
                    if (token.GetNextToken().IsEqualsTokenInAutoPropertyInitializers())
                    {
                        return(GetDefaultIndentationFromToken(indenter, token));
                    }
                }

                return(indenter.IndentFromStartOfLine(
                           indenter.Finder.GetIndentationOfCurrentPosition(
                               indenter.Tree,
                               token,
                               position,
                               indenter.CancellationToken
                               )
                           ));
            }

            case SyntaxKind.OpenBraceToken:
            {
                return(indenter.IndentFromStartOfLine(
                           indenter.Finder.GetIndentationOfCurrentPosition(
                               indenter.Tree,
                               token,
                               position,
                               indenter.CancellationToken
                               )
                           ));
            }

            case SyntaxKind.ColonToken:
            {
                var nonTerminalNode = token.Parent;
                Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                if (nonTerminalNode is SwitchLabelSyntax)
                {
                    return(indenter.GetIndentationOfLine(
                               sourceText.Lines.GetLineFromPosition(
                                   nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart
                                   ),
                               indenter.OptionSet.GetOption(
                                   FormattingOptions.IndentationSize,
                                   token.Language
                                   )
                               ));
                }

                goto default;
            }

            case SyntaxKind.CloseBracketToken:
            {
                var nonTerminalNode = token.Parent;
                Contract.ThrowIfNull(nonTerminalNode, @"Malformed code or bug in parser???");

                // if this is closing an attribute, we shouldn't indent.
                if (nonTerminalNode is AttributeListSyntax)
                {
                    return(indenter.GetIndentationOfLine(
                               sourceText.Lines.GetLineFromPosition(
                                   nonTerminalNode.GetFirstToken(includeZeroWidth: true).SpanStart
                                   )
                               ));
                }

                goto default;
            }

            case SyntaxKind.XmlTextLiteralToken:
            {
                return(indenter.GetIndentationOfLine(
                           sourceText.Lines.GetLineFromPosition(token.SpanStart)
                           ));
            }

            case SyntaxKind.CommaToken:
            {
                return(GetIndentationFromCommaSeparatedList(indenter, token));
            }

            case SyntaxKind.CloseParenToken:
            {
                if (token.Parent.IsKind(SyntaxKind.ArgumentList))
                {
                    return(GetDefaultIndentationFromToken(
                               indenter,
                               token.Parent.GetFirstToken(includeZeroWidth: true)
                               ));
                }

                goto default;
            }

            default:
            {
                return(GetDefaultIndentationFromToken(indenter, token));
            }
            }
        }
 public static SyntaxNode?GetAncestor(this SyntaxToken token, Func <SyntaxNode, bool>?predicate)
 => token.GetAncestor <SyntaxNode>(predicate);
        public override AdjustNewLinesOperation GetAdjustNewLinesOperation(SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation<AdjustNewLinesOperation> nextOperation)
        {
            if (previousToken.IsNestedQueryExpression())
            {
                return CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines);
            }

            // skip the very first from keyword
            if (currentToken.IsFirstFromKeywordInExpression())
            {
                return nextOperation.Invoke();
            }

            switch (currentToken.Kind())
            {
                case SyntaxKind.FromKeyword:
                case SyntaxKind.WhereKeyword:
                case SyntaxKind.LetKeyword:
                case SyntaxKind.JoinKeyword:
                case SyntaxKind.OrderByKeyword:
                case SyntaxKind.GroupKeyword:
                case SyntaxKind.SelectKeyword:
                    if (currentToken.GetAncestor<QueryExpressionSyntax>() != null)
                    {
                        if (optionSet.GetOption(CSharpFormattingOptions.NewLineForClausesInQuery))
                        {
                            return CreateAdjustNewLinesOperation(1, AdjustNewLinesOption.PreserveLines);
                        }
                        else
                        {
                            return CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines);
                        }
                    }

                    break;
            }

            return nextOperation.Invoke();
        }
        public static bool IsBeginningOfStatementContext(this SyntaxToken token)
        {
            // cases:
            //    {
            //      |

            // }
            // |

            // Note, the following is *not* a legal statement context:
            //    do { } |

            // ...;
            // |

            // case 0:
            //   |

            // default:
            //   |

            // label:
            //   |

            // if (foo)
            //   |

            // while (true)
            //   |

            // do
            //   |

            // for (;;)
            //   |

            // foreach (var v in c)
            //   |

            // else
            //   |

            // using (expr)
            //   |

            // fixed (void* v = &expr)
            //   |

            // lock (expr)
            //   |

            // for ( ; ; Foo(), |

            if (token.Kind() == SyntaxKind.OpenBraceToken &&
                token.Parent.IsKind(SyntaxKind.Block))
            {
                return(true);
            }

            if (token.Kind() == SyntaxKind.SemicolonToken)
            {
                var statement = token.GetAncestor <StatementSyntax>();
                if (statement != null && !statement.IsParentKind(SyntaxKind.GlobalStatement) &&
                    statement.GetLastToken(includeZeroWidth: true) == token)
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.CloseBraceToken &&
                token.Parent.IsKind(SyntaxKind.Block))
            {
                if (token.Parent.Parent is StatementSyntax)
                {
                    // Most blocks that are the child of statement are places
                    // that we can follow with another statement.  i.e.:
                    // if { }
                    // while () { }
                    // There are two exceptions.
                    // try {}
                    // do {}
                    if (!token.Parent.IsParentKind(SyntaxKind.TryStatement) &&
                        !token.Parent.IsParentKind(SyntaxKind.DoStatement))
                    {
                        return(true);
                    }
                }
                else if (
                    token.Parent.IsParentKind(SyntaxKind.ElseClause) ||
                    token.Parent.IsParentKind(SyntaxKind.FinallyClause) ||
                    token.Parent.IsParentKind(SyntaxKind.CatchClause) ||
                    token.Parent.IsParentKind(SyntaxKind.SwitchSection))
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.CloseBraceToken &&
                token.Parent.IsKind(SyntaxKind.SwitchStatement))
            {
                return(true);
            }

            if (token.Kind() == SyntaxKind.ColonToken)
            {
                if (token.Parent.IsKind(SyntaxKind.CaseSwitchLabel, SyntaxKind.DefaultSwitchLabel, SyntaxKind.LabeledStatement))
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.DoKeyword &&
                token.Parent.IsKind(SyntaxKind.DoStatement))
            {
                return(true);
            }

            if (token.Kind() == SyntaxKind.CloseParenToken)
            {
                var parent = token.Parent;
                if (parent.IsKind(SyntaxKind.ForStatement) ||
                    parent.IsKind(SyntaxKind.ForEachStatement) ||
                    parent.IsKind(SyntaxKind.ForEachComponentStatement) ||
                    parent.IsKind(SyntaxKind.WhileStatement) ||
                    parent.IsKind(SyntaxKind.IfStatement) ||
                    parent.IsKind(SyntaxKind.LockStatement) ||
                    parent.IsKind(SyntaxKind.UsingStatement) ||
                    parent.IsKind(SyntaxKind.FixedStatement))
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.ElseKeyword)
            {
                return(true);
            }

            return(false);
        }
        private IEnumerable<CompletionItem> GetTagsForProperty(IPropertySymbol symbol, TextSpan itemSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List<CompletionItem>();

            if (symbol.IsIndexer)
            {
                var parameters = symbol.GetParameters().Select(p => p.Name).ToSet();

                // User is trying to write a name, try to suggest only names.
                if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                    (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
                {
                    string parentElementName = null;

                    var emptyElement = token.GetAncestor<XmlEmptyElementSyntax>();
                    if (emptyElement != null)
                    {
                        parentElementName = emptyElement.Name.LocalName.Text;
                    }

                    // We're writing the name of a paramref
                    if (parentElementName == ParamRefTagName)
                    {
                        items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, p)));
                    }

                    return items;
                }

                RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
                items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, FormatParameter(ParamTagName, p))));
            }

            var typeParameters = symbol.GetTypeArguments().Select(p => p.Name).ToSet();
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, TypeParamTagName, NameAttributeName, t)));
            items.Add(CreateCompletionItem(itemSpan, "value"));
            return items;
        }
        public static bool IsBeginningOfGlobalStatementContext(this SyntaxToken token)
        {
            // cases:
            // }
            // |

            // ...;
            // |

            // extern alias Goo;
            // using System;
            // |

            // [assembly: Goo]
            // |

            if (token.Kind() == SyntaxKind.CloseBraceToken)
            {
                var memberDeclaration = token.GetAncestor <MemberDeclarationSyntax>();
                if (memberDeclaration != null && memberDeclaration.GetLastToken(includeZeroWidth: true) == token &&
                    memberDeclaration.IsParentKind(SyntaxKind.CompilationUnit))
                {
                    return(true);
                }
            }

            if (token.Kind() == SyntaxKind.SemicolonToken)
            {
                var globalStatement = token.GetAncestor <GlobalStatementSyntax>();
                if (globalStatement != null && globalStatement.GetLastToken(includeZeroWidth: true) == token)
                {
                    return(true);
                }

                if (token.Parent is FileScopedNamespaceDeclarationSyntax namespaceDeclaration && namespaceDeclaration.SemicolonToken == token)
                {
                    return(true);
                }

                var memberDeclaration = token.GetAncestor <MemberDeclarationSyntax>();
                if (memberDeclaration != null && memberDeclaration.GetLastToken(includeZeroWidth: true) == token &&
                    memberDeclaration.IsParentKind(SyntaxKind.CompilationUnit))
                {
                    return(true);
                }

                var compUnit = token.GetAncestor <CompilationUnitSyntax>();
                if (compUnit != null)
                {
                    if (compUnit.Usings.Count > 0 && compUnit.Usings.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }

                    if (compUnit.Externs.Count > 0 && compUnit.Externs.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }
                }
            }

            if (token.Kind() == SyntaxKind.CloseBracketToken)
            {
                var compUnit = token.GetAncestor <CompilationUnitSyntax>();
                if (compUnit != null)
                {
                    if (compUnit.AttributeLists.Count > 0 && compUnit.AttributeLists.Last().GetLastToken(includeZeroWidth: true) == token)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        private static SyntaxNode GetExpansionTarget(SyntaxToken token)
        {
            // get the directly enclosing statement
            var enclosingStatement = token.GetAncestors(n => n is StatementSyntax).FirstOrDefault();

            // System.Func<int, int> myFunc = arg => X;
            SyntaxNode possibleLambdaExpression = enclosingStatement == null
                ? token.GetAncestors(n => n is SimpleLambdaExpressionSyntax || n is ParenthesizedLambdaExpressionSyntax).FirstOrDefault()
                : null;
            if (possibleLambdaExpression != null)
            {
                var lambdaExpression = ((LambdaExpressionSyntax)possibleLambdaExpression);
                if (lambdaExpression.Body is ExpressionSyntax)
                {
                    return lambdaExpression.Body;
                }
            }

            // int M() => X;
            var possibleArrowExpressionClause = enclosingStatement == null
                ? token.GetAncestors<ArrowExpressionClauseSyntax>().FirstOrDefault()
                : null;
            if (possibleArrowExpressionClause != null)
            {
                return possibleArrowExpressionClause.Expression;
            }

            var enclosingNameMemberCrefOrnull = token.GetAncestors(n => n is NameMemberCrefSyntax).LastOrDefault();
            if (enclosingNameMemberCrefOrnull != null)
            {
                if (token.Parent is TypeSyntax && token.Parent.Parent is TypeSyntax)
                {
                    enclosingNameMemberCrefOrnull = null;
                }
            }

            var enclosingXmlNameAttr = token.GetAncestors(n => n is XmlNameAttributeSyntax).FirstOrDefault();
            if (enclosingXmlNameAttr != null)
            {
                return null;
            }

            var enclosingInitializer = token.GetAncestors<EqualsValueClauseSyntax>().FirstOrDefault();
            if (enclosingStatement == null && enclosingInitializer != null && enclosingInitializer.Parent is VariableDeclaratorSyntax)
            {
                return enclosingInitializer.Value;
            }

            var attributeSyntax = token.GetAncestor<AttributeSyntax>();
            if (attributeSyntax != null)
            {
                return attributeSyntax;
            }

            // there seems to be no statement above this one. Let's see if we can at least get an SimpleNameSyntax
            return enclosingStatement ?? enclosingNameMemberCrefOrnull ?? token.GetAncestors(n => n is SimpleNameSyntax).FirstOrDefault();
        }
        private IEnumerable <CompletionItem> GetTagsForMethod(IMethodSymbol symbol, TextSpan itemSpan, DocumentationCommentTriviaSyntax trivia, SyntaxToken token)
        {
            var items = new List <CompletionItem>();

            var parameters     = symbol.GetParameters().Select(p => p.Name).ToSet();
            var typeParameters = symbol.TypeParameters.Select(t => t.Name).ToSet();

            // User is trying to write a name, try to suggest only names.
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) ||
                (token.Parent.IsKind(SyntaxKind.IdentifierName) && token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute)))
            {
                string parentElementName = null;

                var emptyElement = token.GetAncestor <XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    parentElementName = emptyElement.Name.LocalName.Text;
                }

                // We're writing the name of a paramref or typeparamref
                if (parentElementName == ParamRefTagName)
                {
                    items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, p)));
                }
                else if (parentElementName == TypeParamRefTagName)
                {
                    items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, t)));
                }

                return(items);
            }

            RemoveExistingTags(trivia, parameters, x => AttributeSelector(x, ParamTagName));
            RemoveExistingTags(trivia, typeParameters, x => AttributeSelector(x, TypeParamTagName));

            items.AddRange(parameters.Select(p => CreateCompletionItem(itemSpan, FormatParameter(ParamTagName, p))));
            items.AddRange(typeParameters.Select(t => CreateCompletionItem(itemSpan, FormatParameter(TypeParamTagName, t))));

            // Provide a return completion item in case the function returns something
            var returns = true;

            foreach (var node in trivia.Content)
            {
                var element = node as XmlElementSyntax;
                if (element != null && !element.StartTag.IsMissing && !element.EndTag.IsMissing)
                {
                    var startTag = element.StartTag;

                    if (startTag.Name.LocalName.ValueText == ReturnsTagName)
                    {
                        returns = false;
                        break;
                    }
                }
            }

            if (returns && !symbol.ReturnsVoid)
            {
                items.Add(CreateCompletionItem(itemSpan, ReturnsTagName));
            }

            return(items);
        }