internal static TNode RemoveSingleLineDocumentationComment <TNode>(TNode node, DocumentationCommentTriviaSyntax documentationComment) where TNode : SyntaxNode { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (!documentationComment.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) { throw new ArgumentException($"Documentation comment's kind must be '{nameof(SyntaxKind.SingleLineDocumentationCommentTrivia)}'.", nameof(documentationComment)); } SyntaxTrivia trivia = documentationComment.ParentTrivia; SyntaxToken token = trivia.Token; SyntaxTriviaList leadingTrivia = token.LeadingTrivia; int index = leadingTrivia.IndexOf(trivia); if (index >= 0 && index < leadingTrivia.Count - 1 && leadingTrivia[index + 1].IsWhitespaceTrivia()) { SyntaxTriviaList newLeadingTrivia = leadingTrivia.RemoveRange(index, 2); SyntaxToken newToken = token.WithLeadingTrivia(newLeadingTrivia); return(node.ReplaceToken(token, newToken)); } return(node.RemoveNode(documentationComment, SyntaxRemoveOptions.KeepNoTrivia)); }
public static Task <Document> RemoveEmptyLinesBeforeAsync( Document document, SyntaxToken token, CancellationToken cancellationToken = default) { SyntaxTriviaList leadingTrivia = token.LeadingTrivia; int count = 0; SyntaxTriviaList.Enumerator en = leadingTrivia.GetEnumerator(); while (en.MoveNext()) { if (en.Current.IsWhitespaceTrivia()) { if (!en.MoveNext()) { break; } if (!en.Current.IsEndOfLineTrivia()) { break; } count += 2; } else if (en.Current.IsEndOfLineTrivia()) { count++; } else { break; } } SyntaxToken newToken = token.WithLeadingTrivia(leadingTrivia.RemoveRange(0, count)); return(document.ReplaceTokenAsync(token, newToken, cancellationToken)); }
private static SyntaxNode AddHeader(Document document, SyntaxNode root, string name, StyleCopSettings settings) { string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var newLineTrivia = SyntaxFactory.EndOfLine(newLineText); var newTrivia = CreateNewHeader("//", name, settings, newLineText).Add(newLineTrivia).Add(newLineTrivia); // Skip blank lines already at the beginning of the document, since we add our own SyntaxTriviaList leadingTrivia = root.GetLeadingTrivia(); int skipCount = 0; for (int i = 0; i < leadingTrivia.Count; i++) { bool done = false; switch (leadingTrivia[i].Kind()) { case SyntaxKind.WhitespaceTrivia: break; case SyntaxKind.EndOfLineTrivia: skipCount = i + 1; break; default: done = true; break; } if (done) { break; } } newTrivia = newTrivia.AddRange(leadingTrivia.RemoveRange(0, skipCount)); return(root.WithLeadingTrivia(newTrivia)); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out CompilationUnitSyntax compilationUnit)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; switch (diagnostic.Id) { case DiagnosticIdentifiers.NormalizeWhitespaceAtBeginningOfFile: { SyntaxToken token = compilationUnit.EndOfFileToken; if (token.FullSpan.Start > 0) { token = compilationUnit.GetFirstToken(); } SyntaxTriviaList leading = token.LeadingTrivia; string title; if (leading[0].IsWhitespaceTrivia() && (leading.Count == 1 || leading[1].IsEndOfLineTrivia())) { title = "Remove whitespace"; } else { title = CodeFixTitles.RemoveNewLine; } CodeAction codeAction = CodeAction.Create( title, ct => { SyntaxToken token = compilationUnit.EndOfFileToken; if (token.FullSpan.Start > 0) { token = compilationUnit.GetFirstToken(); } SyntaxTriviaList leading = token.LeadingTrivia; int count = leading.TakeWhile(f => f.IsWhitespaceOrEndOfLineTrivia()).Count(); SyntaxToken newToken = token.WithLeadingTrivia(leading.RemoveRange(0, count)); return(document.ReplaceTokenAsync(token, newToken, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out CompilationUnitSyntax compilationUnit)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; switch (diagnostic.Id) { case DiagnosticIdentifiers.NormalizeWhitespaceAtEndOfFile: { bool preferNewLineAtEndOfFile = document.GetConfigOptions(compilationUnit.SyntaxTree).PreferNewLineAtEndOfFile() ?? false; CodeAction codeAction = CodeAction.Create( (preferNewLineAtEndOfFile) ? CodeFixTitles.AddNewLine : CodeFixTitles.RemoveNewLine, ct => { SyntaxToken endOfFile = compilationUnit.EndOfFileToken; SyntaxTriviaList leading = endOfFile.LeadingTrivia; SyntaxToken oldToken; SyntaxToken newToken; if (!preferNewLineAtEndOfFile) { if (leading.Any()) { SyntaxTrivia last = leading.Last(); if (last.GetStructure() is DirectiveTriviaSyntax directive) { SyntaxTriviaList trailing = directive.GetTrailingTrivia(); DirectiveTriviaSyntax newDirective = directive.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1)); return(document.ReplaceNodeAsync(directive, newDirective, ct)); } else { oldToken = endOfFile; int index = leading.Count - 1; for (int i = leading.Count - 2; i >= 0; i--) { if (leading[i].IsWhitespaceOrEndOfLineTrivia()) { index--; } } newToken = oldToken.WithLeadingTrivia(leading.RemoveRange(index, leading.Count - index)); } } else { oldToken = endOfFile.GetPreviousToken(); SyntaxTriviaList trailing = oldToken.TrailingTrivia; newToken = oldToken.WithTrailingTrivia(trailing.RemoveAt(trailing.Count - 1)); } } else if (leading.Any()) { oldToken = endOfFile; if (leading.Span.Start == 0 && leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { newToken = oldToken.WithoutLeadingTrivia(); } else { newToken = oldToken.AppendEndOfLineToLeadingTrivia(); } } else { oldToken = endOfFile.GetPreviousToken(); newToken = oldToken.AppendEndOfLineToTrailingTrivia(); } return(document.ReplaceTokenAsync(oldToken, newToken, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } }