public override async Task <Document> RemoveUnnecessaryImportsAsync( Document document, Func <SyntaxNode, bool> predicate, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) { predicate ??= Functions <SyntaxNode> .True; using (Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_CSharp, cancellationToken)) { var unnecessaryImports = await GetCommonUnnecessaryImportsOfAllContextAsync( document, predicate, cancellationToken).ConfigureAwait(false); if (unnecessaryImports == null || unnecessaryImports.Any(import => import.OverlapsHiddenPosition(cancellationToken))) { return(document); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var oldRoot = (CompilationUnitSyntax)root; var newRoot = (CompilationUnitSyntax) new Rewriter(document, unnecessaryImports, cancellationToken).Visit(oldRoot); cancellationToken.ThrowIfCancellationRequested(); #if CODE_STYLE var provider = GetSyntaxFormatting(); #else var provider = document.Project.Solution.Workspace.Services; #endif var spans = new List <TextSpan>(); AddFormattingSpans(newRoot, spans, cancellationToken); var formattedRoot = Formatter.Format(newRoot, spans, provider, formattingOptions, rules: null, cancellationToken); return(document.WithSyntaxRoot(formattedRoot)); } }
protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken) { var formattingOptions = await GetOptionsAsync(document, cancellationToken).ConfigureAwait(false); var updatedRoot = Formatter.Format(editor.OriginalRoot, SyntaxFormatting, formattingOptions, cancellationToken); editor.ReplaceNode(editor.OriginalRoot, updatedRoot); }
public sealed override FixAllProvider GetFixAllProvider() => FixAllProvider.Create(async(context, document, diagnostics) => { var cancellationToken = context.CancellationToken; var options = await GetOptionsAsync(document, cancellationToken).ConfigureAwait(false); var syntaxRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var updatedSyntaxRoot = Formatter.Format(syntaxRoot, this.SyntaxFormatting, options, cancellationToken); return(document.WithSyntaxRoot(updatedSyntaxRoot)); });
protected override async Task <SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray <Diagnostic> diagnostics) { var options = await GetOptionsAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); var updatedSyntaxRoot = Formatter.Format(syntaxRoot, _formattingCodeFixProvider.SyntaxFormattingService, options, fixAllContext.CancellationToken); return(updatedSyntaxRoot); }
internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, FormattingProvider formattingProvider, DiagnosticDescriptor descriptor, SyntaxFormattingOptions options) { var tree = context.Tree; var cancellationToken = context.CancellationToken; var oldText = tree.GetText(cancellationToken); var formattingChanges = Formatter.GetFormattedTextChanges(tree.GetRoot(cancellationToken), formattingProvider, options, cancellationToken); // formattingChanges could include changes that impact a larger section of the original document than // necessary. Before reporting diagnostics, process the changes to minimize the span of individual // diagnostics. foreach (var formattingChange in formattingChanges) { var change = formattingChange; if (change.NewText.Length > 0 && !change.Span.IsEmpty) { // Handle cases where the change is a substring removal from the beginning. In these cases, we want // the diagnostic span to cover the unwanted leading characters (which should be removed), and // nothing more. var offset = change.Span.Length - change.NewText.Length; if (offset >= 0) { if (oldText.GetSubText(new TextSpan(change.Span.Start + offset, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) { change = new TextChange(new TextSpan(change.Span.Start, offset), ""); } else { // Handle cases where the change is a substring removal from the end. In these cases, we want // the diagnostic span to cover the unwanted trailing characters (which should be removed), and // nothing more. if (oldText.GetSubText(new TextSpan(change.Span.Start, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) { change = new TextChange(new TextSpan(change.Span.Start + change.NewText.Length, offset), ""); } } } } if (change.NewText.Length == 0 && change.Span.IsEmpty) { // No actual change (allows for the formatter to report a NOP change without triggering a // diagnostic that can't be fixed). continue; } var location = Location.Create(tree, change.Span); context.ReportDiagnostic(Diagnostic.Create( descriptor, location, additionalLocations: null, properties: null)); } }
internal static async Task <SyntaxTree> FixOneAsync(SyntaxTree syntaxTree, FormattingProvider formattingProvider, SyntaxFormattingOptions options, Diagnostic diagnostic, CancellationToken cancellationToken) { // The span to format is the full line(s) containing the diagnostic var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var diagnosticLinePositionSpan = text.Lines.GetLinePositionSpan(diagnosticSpan); var spanToFormat = TextSpan.FromBounds( text.Lines[diagnosticLinePositionSpan.Start.Line].Start, text.Lines[diagnosticLinePositionSpan.End.Line].End); var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var formattedRoot = Formatter.Format(root, spanToFormat, formattingProvider, options, cancellationToken); return(syntaxTree.WithRootAndOptions(formattedRoot, syntaxTree.Options)); }
protected override async Task FixAllAsync( Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // Defer to our callback to actually make the edits for each diagnostic. In turn, it // will return 'true' if it made a multi-line conditional expression. In that case, // we'll need to explicitly format this node so we can get our special multi-line // formatting in VB and C#. var nestedEditor = document.GetSyntaxEditor(root); foreach (var diagnostic in diagnostics) { await FixOneAsync( document, diagnostic, nestedEditor, fallbackOptions, cancellationToken).ConfigureAwait(false); } var changedRoot = nestedEditor.GetChangedRoot(); // Get the language specific rule for formatting this construct and call into the // formatted to explicitly format things. Note: all we will format is the new // conditional expression as that's the only node that has the appropriate // annotation on it. var rules = new List <AbstractFormattingRule> { GetMultiLineFormattingRule() }; #if CODE_STYLE var provider = GetSyntaxFormatting(); #else var provider = document.Project.Solution.Services; #endif var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var formattingOptions = options.GetFormattingOptions(GetSyntaxFormatting()); var formattedRoot = Formatter.Format(changedRoot, SpecializedFormattingAnnotation, provider, formattingOptions, rules, cancellationToken); changedRoot = formattedRoot; editor.ReplaceNode(root, changedRoot); }
internal static async Task <SyntaxTree> FixOneAsync( SyntaxTree syntaxTree, FormatterState formatterState, OptionSet options, Diagnostic diagnostic, CancellationToken cancellationToken ) { // The span to format is the full line(s) containing the diagnostic var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var diagnosticLinePositionSpan = text.Lines.GetLinePositionSpan(diagnosticSpan); var spanToFormat = TextSpan.FromBounds( text.Lines[diagnosticLinePositionSpan.Start.Line].Start, text.Lines[diagnosticLinePositionSpan.End.Line].End ); var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); #if CODE_STYLE var formattedRoot = Formatter.Format( root, formatterState, new[] { spanToFormat }, options, Formatter.GetDefaultFormattingRules(formatterState), cancellationToken ); #else var formattedRoot = Formatter.Format( root, spanToFormat, formatterState, options, cancellationToken ); #endif return(syntaxTree.WithRootAndOptions(formattedRoot, syntaxTree.Options)); }