private static bool IsBeforeOrAfterNodeOnSameLine(
            SourceText text,
            SyntaxNode root,
            SyntaxNode member,
            int position
            )
        {
            var token = root.FindToken(position);

            if (
                token == member.GetFirstToken() &&
                position <= token.SpanStart &&
                text.AreOnSameLine(position, token.SpanStart)
                )
            {
                return(true);
            }

            if (
                token == member.GetLastToken() &&
                position >= token.Span.End &&
                text.AreOnSameLine(position, token.Span.End)
                )
            {
                return(true);
            }

            return(false);
        }
Exemple #2
0
            internal (CodeAction action, TextSpan renameSpan) TryGetCodeAction(
                Document document, SourceText text, TextSpan userSpan,
                IEnumerable <IRefactorNotifyService> refactorNotifyServices,
                ITextUndoHistoryRegistry undoHistoryRegistry,
                CancellationToken cancellationToken)
            {
                try
                {
                    // This can be called on a background thread. We are being asked whether a
                    // lightbulb should be shown for the given document, but we only know about the
                    // current state of the buffer. Compare the text to see if we should bail early.
                    // Even if the text is the same, the buffer may change on the UI thread during this
                    // method. If it does, we may give an incorrect response, but the diagnostics
                    // engine will know that the document changed and not display the lightbulb anyway.

                    if (Buffer.AsTextContainer().CurrentText == text &&
                        CanInvokeRename(out var trackingSession, waitForResult: true, cancellationToken: cancellationToken))
                    {
                        var snapshotSpan = trackingSession.TrackingSpan.GetSpan(Buffer.CurrentSnapshot);

                        // user needs to be on the same line as the diagnostic location.
                        if (text.AreOnSameLine(userSpan.Start, snapshotSpan.Start))
                        {
                            var title = string.Format(
                                EditorFeaturesResources.Rename_0_to_1,
                                trackingSession.OriginalName,
                                snapshotSpan.GetText());

                            return(new RenameTrackingCodeAction(ThreadingContext, document, title, refactorNotifyServices, undoHistoryRegistry, GlobalOptions),
                                   snapshotSpan.Span.ToTextSpan());
                        }
                    }

                    return(default);
Exemple #3
0
        private static SyntaxNode?TryGetDeclaration(
            UseExpressionBodyHelper helper,
            SourceText text,
            SyntaxNode node,
            int position
            )
        {
            var declaration = GetDeclaration(node, helper);

            if (declaration == null)
            {
                return(null);
            }

            if (position < declaration.SpanStart)
            {
                // The user is allowed to be before the starting point of this node, as long as
                // they're only between the start of the node and the start of the same line the
                // node starts on.  This prevents unnecessarily showing this feature in areas like
                // the comment of a method.
                if (!text.AreOnSameLine(position, declaration.SpanStart))
                {
                    return(null);
                }
            }

            return(declaration);
        }
Exemple #4
0
        protected override IfStatementSyntax UpdateIf(
            SourceText sourceText,
            IfStatementSyntax ifNode,
            SyntaxNode condition,
            StatementSyntax trueStatement,
            StatementSyntax falseStatementOpt = null
            )
        {
            var isSingleLine = sourceText.AreOnSameLine(
                ifNode.GetFirstToken(),
                ifNode.GetLastToken()
                );

            if (isSingleLine && falseStatementOpt != null)
            {
                // If statement is on a single line, and we're swapping the true/false parts.
                // In that case, try to swap the trailing trivia between the true/false parts.
                // That way the trailing comments/newlines at the end of hte 'if' stay there,
                // and the spaces after the true-part stay where they are.

                (trueStatement, falseStatementOpt) = (
                    trueStatement.WithTrailingTrivia(falseStatementOpt.GetTrailingTrivia()),
                    falseStatementOpt.WithTrailingTrivia(trueStatement.GetTrailingTrivia())
                    );
            }

            var updatedIf = ifNode
                            .WithCondition((ExpressionSyntax)condition)
                            .WithStatement(
                trueStatement is IfStatementSyntax
                      ? SyntaxFactory.Block(trueStatement)
                      : trueStatement
                );

            if (falseStatementOpt != null)
            {
                var elseClause =
                    updatedIf.Else != null
                        ? updatedIf.Else.WithStatement(falseStatementOpt)
                        : SyntaxFactory.ElseClause(falseStatementOpt);

                updatedIf = updatedIf.WithElse(elseClause);
            }

            // If this is multiline, format things after we swap around the if/else.  Because
            // of all the different types of rewriting, we may need indentation fixed up and
            // whatnot.  Don't do this with single-line because we want to ensure as closely
            // as possible that we've kept things on that single line.
            return(isSingleLine
              ? updatedIf
              : updatedIf.WithAdditionalAnnotations(Formatter.Annotation));
        }
        /// <summary>
        /// Returns all of the trivia to the left of this token up to the previous token (concatenates
        /// the previous token's trailing trivia and this token's leading trivia).
        /// </summary>
        public static IEnumerable <SyntaxTrivia> GetAllPrecedingTriviaToPreviousToken(
            this SyntaxToken token, SourceText sourceText           = null,
            bool includePreviousTokenTrailingTriviaOnlyIfOnSameLine = false)
        {
            var prevToken = token.GetPreviousToken(includeSkipped: true);

            if (prevToken.Kind() == SyntaxKind.None)
            {
                return(token.LeadingTrivia);
            }

            if (includePreviousTokenTrailingTriviaOnlyIfOnSameLine &&
                !sourceText.AreOnSameLine(prevToken, token))
            {
                return(token.LeadingTrivia);
            }

            return(prevToken.TrailingTrivia.Concat(token.LeadingTrivia));
        }