diff --git a/src/CodeStyle/Core/Analyzers/FormattingAnalyzerHelper.cs b/src/CodeStyle/Core/Analyzers/FormattingAnalyzerHelper.cs index a93aeac0c796d1158cd31996a3d56f5473067752..6c2920177bd229009f00376bc0c01d760423555e 100644 --- a/src/CodeStyle/Core/Analyzers/FormattingAnalyzerHelper.cs +++ b/src/CodeStyle/Core/Analyzers/FormattingAnalyzerHelper.cs @@ -2,20 +2,26 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; +#if CODE_STYLE +using FormatterState = Microsoft.CodeAnalysis.Formatting.ISyntaxFormattingService; +#else +using Microsoft.CodeAnalysis.Options; +using FormatterState = Microsoft.CodeAnalysis.Workspace; +#endif + namespace Microsoft.CodeAnalysis.CodeStyle { internal static class FormattingAnalyzerHelper { - internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, ISyntaxFormattingService syntaxFormattingService, DiagnosticDescriptor descriptor, OptionSet options) + internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, FormatterState formatterState, DiagnosticDescriptor descriptor, OptionSet options) { var tree = context.Tree; var cancellationToken = context.CancellationToken; var oldText = tree.GetText(cancellationToken); - var formattingChanges = Formatter.GetFormattedTextChanges(tree.GetRoot(cancellationToken), syntaxFormattingService, options, cancellationToken); + var formattingChanges = Formatter.GetFormattedTextChanges(tree.GetRoot(cancellationToken), formatterState, 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 diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs index abc6e20f25f55ebb54020d4fa6ab313809a96c03..84384bc2c84df7ef3cdbd96d7eca85cb2260e9ad 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs @@ -1,18 +1,27 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#if CODE_STYLE +extern alias CodeStyle; +#endif + using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Text; +#if CODE_STYLE +using Formatter = CodeStyle::Microsoft.CodeAnalysis.Formatting.Formatter; +using FormatterState = Microsoft.CodeAnalysis.Formatting.ISyntaxFormattingService; +#else +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using FormatterState = Microsoft.CodeAnalysis.Workspace; +#endif + namespace Microsoft.CodeAnalysis { - extern alias CodeStyle; - using Formatter = CodeStyle::Microsoft.CodeAnalysis.Formatting.Formatter; - internal static class FormattingCodeFixHelper { - internal static async Task FixOneAsync(SyntaxTree syntaxTree, ISyntaxFormattingService syntaxFormattingService, OptionSet options, Diagnostic diagnostic, CancellationToken cancellationToken) + internal static async Task 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); @@ -22,7 +31,14 @@ internal static async Task FixOneAsync(SyntaxTree syntaxTree, ISynta text.Lines[diagnosticLinePositionSpan.Start.Line].Start, text.Lines[diagnosticLinePositionSpan.End.Line].End); - return await Formatter.FormatAsync(syntaxTree, syntaxFormattingService, spanToFormat, options, cancellationToken).ConfigureAwait(false); + 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 = await Formatter.FormatAsync(root, spanToFormat, formatterState, options, cancellationToken).ConfigureAwait(false); +#endif + + return syntaxTree.WithRootAndOptions(formattedRoot, syntaxTree.Options); } } } diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 5cfdaaa90a031fcea6ab0492a8762c061bb6f1aa..da95993062fdbd30075763cd925cc0662b2cf283 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -7,6 +7,7 @@ Library Microsoft.CodeAnalysis netstandard1.3 + $(DefineConstants),CODE_STYLE diff --git a/src/Features/Core/Portable/Formatting/FormattingAnalyzerHelper.cs b/src/Features/Core/Portable/Formatting/FormattingAnalyzerHelper.cs deleted file mode 100644 index 46b0002c6547a2605da7f170abdb860878c8f338..0000000000000000000000000000000000000000 --- a/src/Features/Core/Portable/Formatting/FormattingAnalyzerHelper.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Text; - -namespace Microsoft.CodeAnalysis.CodeStyle -{ - internal static class FormattingAnalyzerHelper - { - internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, DiagnosticDescriptor descriptor, Workspace workspace, OptionSet options) - { - var tree = context.Tree; - var cancellationToken = context.CancellationToken; - - var oldText = tree.GetText(cancellationToken); - var formattingChanges = Formatter.GetFormattedTextChanges(tree.GetRoot(cancellationToken), workspace, 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)); - } - } - } -} diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixHelper.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixHelper.cs deleted file mode 100644 index ded0aa6661f3b1ca48a133fda5b5923173416ea8..0000000000000000000000000000000000000000 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixHelper.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Text; - -namespace Microsoft.CodeAnalysis -{ - internal static class FormattingCodeFixHelper - { - internal static async Task FixOneAsync(Document document, OptionSet options, Diagnostic diagnostic, CancellationToken cancellationToken) - { - var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - - // The span to format is the full line(s) containing the diagnostic - var text = await document.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); - - return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); - } - } -} diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index e9efa3d8873269c0870f28951be57fea970e479a..06474b8512c149031afc0e39c5ec4e82d0a45adb 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -34,7 +34,9 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) private static async Task FixOneAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) { var options = await context.Document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return await FormattingCodeFixHelper.FixOneAsync(context.Document, options, diagnostic, cancellationToken).ConfigureAwait(false); + var tree = await context.Document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var formattedTree = await FormattingCodeFixHelper.FixOneAsync(tree, context.Document.Project.Solution.Workspace, options, diagnostic, cancellationToken).ConfigureAwait(false); + return context.Document.WithSyntaxRoot(await formattedTree.GetRootAsync(cancellationToken).ConfigureAwait(false)); } protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs index e213bd8b4f9b89b4a14a9c53de30e4419f8491a5..9c094df504e8d9f01ab1233fcaf4a2441a4900bc 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -43,7 +43,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) } var workspace = workspaceAnalyzerOptions.Services.Workspace; - FormattingAnalyzerHelper.AnalyzeSyntaxTree(context, Descriptor, workspace, options); + FormattingAnalyzerHelper.AnalyzeSyntaxTree(context, workspace, Descriptor, options); } } } diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 71fb0d44bffc933948dc88967ae81233f87de748..9db357747f8e7af5029180822c94e1f2ca282017 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -97,6 +97,8 @@ + + Shared\Utilities\DesktopShim.cs