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); }
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);
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); }
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)); }