From 864e9372f6b5f8debdee407857fe9c7b54cc1c6b Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 27 Jul 2018 11:10:13 -0500 Subject: [PATCH 01/25] Implement a formatting analyzer --- .../Formatting/FormattingAnalyzerTests.cs | 58 ++++++++++ .../PredefinedCodeFixProviderNames.cs | 1 + .../Diagnostics/Analyzers/IDEDiagnosticIds.cs | 2 + .../Portable/FeaturesResources.Designer.cs | 27 +++++ .../Core/Portable/FeaturesResources.resx | 9 ++ .../Formatting/FormattingCodeFixProvider.cs | 69 ++++++++++++ .../FormattingDiagnosticAnalyzer.cs | 101 ++++++++++++++++++ .../Portable/xlf/FeaturesResources.cs.xlf | 15 +++ .../Portable/xlf/FeaturesResources.de.xlf | 15 +++ .../Portable/xlf/FeaturesResources.es.xlf | 15 +++ .../Portable/xlf/FeaturesResources.fr.xlf | 15 +++ .../Portable/xlf/FeaturesResources.it.xlf | 15 +++ .../Portable/xlf/FeaturesResources.ja.xlf | 15 +++ .../Portable/xlf/FeaturesResources.ko.xlf | 15 +++ .../Portable/xlf/FeaturesResources.pl.xlf | 15 +++ .../Portable/xlf/FeaturesResources.pt-BR.xlf | 15 +++ .../Portable/xlf/FeaturesResources.ru.xlf | 15 +++ .../Portable/xlf/FeaturesResources.tr.xlf | 15 +++ .../xlf/FeaturesResources.zh-Hans.xlf | 15 +++ .../xlf/FeaturesResources.zh-Hant.xlf | 15 +++ .../Formatting/Engine/AbstractFormatEngine.cs | 10 +- .../Core/Portable/Formatting/Formatter.cs | 9 +- .../Portable/Formatting/FormattingOptions.cs | 1 + 23 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs create mode 100644 src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs create mode 100644 src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs new file mode 100644 index 0000000000000..922b8884ce8c7 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs @@ -0,0 +1,58 @@ +// 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; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting +{ + public class FormattingAnalyzerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest + { + internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) + => (new FormattingDiagnosticAnalyzer(), new FormattingCodeFixProvider()); + + [Fact, Trait(Traits.Feature, Traits.Features.Formatting)] + public async Task TrailingWhitespace() + { + var testCode = + "class X[| |]" + Environment.NewLine + + "{" + Environment.NewLine + + "}" + Environment.NewLine; + var expected = + "class X" + Environment.NewLine + + "{" + Environment.NewLine + + "}" + Environment.NewLine; + await TestInRegularAndScriptAsync(testCode, expected); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Formatting)] + public async Task TestMissingSpace() + { + var testCode = @" +class TypeName +{ + void Method() + { + if$$(true)return; + } +} +"; + var expected = @" +class TypeName +{ + void Method() + { + if (true)return; + } +} +"; + + await TestInRegularAndScriptAsync(testCode, expected); + } + } +} diff --git a/src/Features/Core/Portable/CodeFixes/PredefinedCodeFixProviderNames.cs b/src/Features/Core/Portable/CodeFixes/PredefinedCodeFixProviderNames.cs index 9744103ff5f0a..e62a530915c85 100644 --- a/src/Features/Core/Portable/CodeFixes/PredefinedCodeFixProviderNames.cs +++ b/src/Features/Core/Portable/CodeFixes/PredefinedCodeFixProviderNames.cs @@ -21,6 +21,7 @@ internal static class PredefinedCodeFixProviderNames public const string AddMissingReference = nameof(AddMissingReference); public const string AddImport = nameof(AddImport); public const string FullyQualify = nameof(FullyQualify); + public const string FixFormatting = nameof(FixFormatting); public const string FixIncorrectFunctionReturnType = nameof(FixIncorrectFunctionReturnType); public const string FixIncorrectExitContinue = nameof(FixIncorrectExitContinue); public const string GenerateConstructor = nameof(GenerateConstructor); diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs index 0c64254603829..e4c9a43d68e5d 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs @@ -84,6 +84,8 @@ internal static class IDEDiagnosticIds public const string UseExpressionBodyForLambdaExpressionsDiagnosticId = "IDE0053"; + public const string FormattingDiagnosticId = "IDE0054"; + // Analyzer error Ids public const string AnalyzerChangedId = "IDE1001"; public const string AnalyzerDependencyConflictId = "IDE1002"; diff --git a/src/Features/Core/Portable/FeaturesResources.Designer.cs b/src/Features/Core/Portable/FeaturesResources.Designer.cs index 215b6e91a65a9..73d0f87558e99 100644 --- a/src/Features/Core/Portable/FeaturesResources.Designer.cs +++ b/src/Features/Core/Portable/FeaturesResources.Designer.cs @@ -1369,6 +1369,33 @@ internal static string Format_string_contains_invalid_placeholder { } } + /// + /// Looks up a localized string similar to Fix formatting. + /// + internal static string Formatting_analyzer_code_fix { + get { + return ResourceManager.GetString("Formatting_analyzer_code_fix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fix formatting. + /// + internal static string Formatting_analyzer_message { + get { + return ResourceManager.GetString("Formatting_analyzer_message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fix formatting. + /// + internal static string Formatting_analyzer_title { + get { + return ResourceManager.GetString("Formatting_analyzer_title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Formatting document. /// diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 6b374a45bfc19..b5e03eb48f124 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -1430,4 +1430,13 @@ This version used in: {2} Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read. + + Fix formatting + + + Fix formatting + + + Fix formatting + \ No newline at end of file diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs new file mode 100644 index 0000000000000..f43831e23dee2 --- /dev/null +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -0,0 +1,69 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.Formatting +{ + [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = PredefinedCodeFixProviderNames.FixFormatting)] + [Shared] + internal class FormattingCodeFixProvider : SyntaxEditorBasedCodeFixProvider + { + public override ImmutableArray FixableDiagnosticIds + => ImmutableArray.Create(IDEDiagnosticIds.FormattingDiagnosticId); + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + context.RegisterCodeFix( + new MyCodeAction(c => FixOneAsync(context.Document, context.Diagnostics, c)), + context.Diagnostics); + + return Task.CompletedTask; + } + + protected async Task FixOneAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + { + var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var changes = new List(); + foreach (var diagnostic in diagnostics) + { + if (!tree.Equals(diagnostic.Location.SourceTree) + || !diagnostic.Properties.TryGetValue(FormattingDiagnosticAnalyzer.ReplaceTextKey, out var replacement)) + { + continue; + } + + changes.Add(new TextChange(diagnostic.Location.SourceSpan, replacement)); + } + + changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); + + return document.WithText(text.WithChanges(changes)); + } + + protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) + { + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var updatedDocument = await Formatter.FormatAsync(document, options, cancellationToken).ConfigureAwait(false); + editor.ReplaceNode(editor.OriginalRoot, await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false)); + } + + private sealed class MyCodeAction : CodeAction.DocumentChangeAction + { + public MyCodeAction(Func> createChangedDocument) + : base(FeaturesResources.Formatting_analyzer_code_fix, createChangedDocument, FeaturesResources.Formatting_analyzer_code_fix) + { + } + } + } +} diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000..1f19d8f55a289 --- /dev/null +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -0,0 +1,101 @@ +// 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.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.Formatting +{ + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + internal class FormattingDiagnosticAnalyzer + : AbstractCodeStyleDiagnosticAnalyzer + { + public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); + + public static readonly ImmutableDictionary RemoveTextProperties = + ImmutableDictionary.Create().Add(ReplaceTextKey, ""); + + public FormattingDiagnosticAnalyzer() + : base( + IDEDiagnosticIds.FormattingDiagnosticId, + new LocalizableResourceString(nameof(FeaturesResources.Formatting_analyzer_title), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Formatting_analyzer_message), FeaturesResources.ResourceManager, typeof(FeaturesResources))) + { + } + + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() + => DiagnosticAnalyzerCategory.SyntaxAnalysis; + + public override bool OpenFileOnly(Workspace workspace) + => false; + + protected override void InitializeWorker(AnalysisContext context) + => context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree); + + private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) + { + if (!(context.Options is WorkspaceAnalyzerOptions workspaceAnalyzerOptions)) + { + return; + } + + var options = context.Options.GetDocumentOptionSetAsync(context.Tree, context.CancellationToken).GetAwaiter().GetResult(); + if (options == null) + { + return; + } + + var workspace = workspaceAnalyzerOptions.Services.Workspace; + var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, context.CancellationToken); + foreach (var formattingChange in formattingChanges) + { + var change = formattingChange; + if (change.NewText.Length > 0 && !change.Span.IsEmpty) + { + var oldText = context.Tree.GetText(context.CancellationToken); + + // Handle cases where the change is a substring removal from the beginning + var offset = change.Span.Length - change.NewText.Length; + if (offset >= 0 && 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 + if (change.NewText.Length < change.Span.Length + && 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, change.Span.Length - change.NewText.Length), ""); + } + } + } + + if (change.NewText.Length == 0 && change.Span.IsEmpty) + { + // No actual change + continue; + } + + ImmutableDictionary properties; + if (change.NewText.Length == 0) + { + properties = RemoveTextProperties; + } + else + { + properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); + } + + var location = Location.Create(context.Tree, change.Span); + context.ReportDiagnostic(DiagnosticHelper.Create( + Descriptor, + location, + ReportDiagnostic.Default, + additionalLocations: null, + properties)); + } + } + } +} diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 089dfd5fee28c..c895ec2a0b8d1 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -62,6 +62,21 @@ Opravit překlep {0} + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Formátuje se dokument. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index 77a5b454eb105..0da8017d26d35 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -62,6 +62,21 @@ Tippfehler "{0}" korrigieren + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Dokument wird formatiert diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index aaa7bd169fb10..d8f88c6205ff1 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -62,6 +62,21 @@ Corregir error de escritura "{0}" + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Aplicando formato al documento diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 4fd55ad860bf5..887c572e7570d 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -62,6 +62,21 @@ Corriger la faute de frappe '{0}' + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Mise en forme du document diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index 9aed9dc638808..378965d4eefa5 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -62,6 +62,21 @@ Correggere l'errore di ortografia '{0}' + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Formattazione del documento diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 8009b5e33d199..f150d1b8bd771 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -62,6 +62,21 @@ '{0}' の入力ミスを修正します + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document ドキュメントの書式設定 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index b03ab463232e8..9519547453e87 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -62,6 +62,21 @@ 오타 '{0}' 수정 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document 문서 서식 지정 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index d6a2615bef8c9..2bfd6534ac630 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -62,6 +62,21 @@ Popraw błąd pisowni „{0}” + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Formatowanie dokumentu diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 7c3d9aed55c5a..fa3a51336e90f 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -62,6 +62,21 @@ Corrigir erro de digitação '{0}' + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Formatando documento diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index 7dd2e43c518ab..16b87ab4fa3db 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -62,6 +62,21 @@ Исправьте опечатку "{0}" + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Форматирование документа diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index b4d87e6f3451c..ccd4f7a40db45 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -62,6 +62,21 @@ '{0}' yazım hatasını düzeltin + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document Belge biçimlendiriliyor diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index c729b2e2d6915..a1233d9f88429 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -62,6 +62,21 @@ 修正笔误“{0}” + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document 设置文档格式 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 1c99e47d20968..17400e64cba51 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -62,6 +62,21 @@ 修正錯字 '{0}' + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + Formatting document 正在將文件格式化 diff --git a/src/Workspaces/Core/Portable/Formatting/Engine/AbstractFormatEngine.cs b/src/Workspaces/Core/Portable/Formatting/Engine/AbstractFormatEngine.cs index 482fc7a0488fa..c5e158c672c63 100644 --- a/src/Workspaces/Core/Portable/Formatting/Engine/AbstractFormatEngine.cs +++ b/src/Workspaces/Core/Portable/Formatting/Engine/AbstractFormatEngine.cs @@ -92,9 +92,13 @@ internal AbstractFormatEngine( _language = token1.Language; } - // set synchronous task executor if it is debug mode or if there is not many things to format - this.TaskExecutor = optionSet.GetOption(FormattingOptions.DebugMode, _language) ? TaskExecutor.Synchronous : - (SpanToFormat.Length < ConcurrentThreshold) ? TaskExecutor.Synchronous : executor; + // set synchronous task executor if it is enabled (explicitly or as part of debug mode) or if there is not + // many things to format + var synchronousExecutorAllowed = + !optionSet.GetOption(FormattingOptions.AllowConcurrent) + || optionSet.GetOption(FormattingOptions.DebugMode, _language); + var useSynchronousExecutor = synchronousExecutorAllowed || SpanToFormat.Length < ConcurrentThreshold; + TaskExecutor = useSynchronousExecutor ? TaskExecutor.Synchronous : executor; } protected abstract AbstractTriviaDataFactory CreateTriviaFactory(); diff --git a/src/Workspaces/Core/Portable/Formatting/Formatter.cs b/src/Workspaces/Core/Portable/Formatting/Formatter.cs index 2a26fe9af4a6a..3fd8709197113 100644 --- a/src/Workspaces/Core/Portable/Formatting/Formatter.cs +++ b/src/Workspaces/Core/Portable/Formatting/Formatter.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -281,7 +282,13 @@ internal static Task GetFormattingResult(SyntaxNode node, IEn /// An optional cancellation token. /// The changes necessary to format the tree. public static IList GetFormattedTextChanges(SyntaxNode node, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => GetFormattedTextChangesAsync(node, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = GetFormattedTextChangesAsync(node, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task> GetFormattedTextChangesAsync(SyntaxNode node, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => GetFormattedTextChangesAsync(node, SpecializedCollections.SingletonEnumerable(node.FullSpan), workspace, options, rules: null, cancellationToken: cancellationToken); diff --git a/src/Workspaces/Core/Portable/Formatting/FormattingOptions.cs b/src/Workspaces/Core/Portable/Formatting/FormattingOptions.cs index a56a7b233f8be..2686547d2322c 100644 --- a/src/Workspaces/Core/Portable/Formatting/FormattingOptions.cs +++ b/src/Workspaces/Core/Portable/Formatting/FormattingOptions.cs @@ -45,6 +45,7 @@ private static Optional ParseEditorConfigEndOfLine(string endOfLineValue } internal static PerLanguageOption DebugMode { get; } = new PerLanguageOption(nameof(FormattingOptions), nameof(DebugMode), defaultValue: false); + internal static Option AllowConcurrent { get; } = new Option(nameof(FormattingOptions), nameof(AllowConcurrent), defaultValue: true); internal static Option AllowDisjointSpanMerging { get; } = new Option(nameof(FormattingOptions), nameof(AllowDisjointSpanMerging), defaultValue: false); From ba0f5e1240f0e08527ef7cefc6c91677047161a7 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 28 Aug 2018 20:52:11 -0500 Subject: [PATCH 02/25] Implement a copy of the formatting analyzer in the CodeStyle layer --- .../CodeFixes/CSharpFormattingAnalyzer.cs | 30 +++ .../AbstractCodeStyleDiagnosticAnalyzer.cs | 106 ++++++++ .../Analyzers/CodeStyleResources.Designer.cs | 26 +- .../Core/Analyzers/CodeStyleResources.resx | 11 +- .../Core/Analyzers/DiagnosticHelper.cs | 248 ++++++++++++++++++ .../Analyzers/xlf/CodeStyleResources.cs.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.de.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.es.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.fr.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.it.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.ja.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.ko.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.pl.xlf | 18 +- .../xlf/CodeStyleResources.pt-BR.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.ru.xlf | 18 +- .../Analyzers/xlf/CodeStyleResources.tr.xlf | 18 +- .../xlf/CodeStyleResources.zh-Hans.xlf | 18 +- .../xlf/CodeStyleResources.zh-Hant.xlf | 18 +- .../CodeFixes/AbstractFormattingAnalyzer.cs | 101 +++++++ ...rosoft.CodeAnalysis.CodeStyle.Fixes.csproj | 3 + 20 files changed, 700 insertions(+), 59 deletions(-) create mode 100644 src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs create mode 100644 src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs create mode 100644 src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs create mode 100644 src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs diff --git a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs new file mode 100644 index 0000000000000..0a4d45d5bbffe --- /dev/null +++ b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs @@ -0,0 +1,30 @@ +// 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.CSharp.Formatting; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.CodingConventions; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + internal class CSharpFormattingAnalyzer + : AbstractFormattingAnalyzer + { + protected override OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext) + { + return optionSet.WithChangedOption(CSharpFormattingOptions.IndentBlock, GetBoolOrDefault(codingConventionContext.CurrentConventions, "csharp_indent_block_contents", CSharpFormattingOptions.IndentBlock.DefaultValue)); + } + + private bool GetBoolOrDefault(ICodingConventionsSnapshot currentConventions, string key, bool defaultValue) + { + if (currentConventions.TryGetConventionValue(key, out string rawValue) + && bool.TryParse(rawValue, out var value)) + { + return value; + } + + return defaultValue; + } + } +} diff --git a/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs b/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000..2e75356691068 --- /dev/null +++ b/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs @@ -0,0 +1,106 @@ +// 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.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis.Diagnostics; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer + { + protected readonly string DescriptorId; + + protected readonly DiagnosticDescriptor Descriptor; + + /// + /// Diagnostic descriptor for code you want to fade out *and* want to have a smart-tag + /// appear for. This is the common descriptor for code that is being faded out + /// + protected readonly DiagnosticDescriptor UnnecessaryWithSuggestionDescriptor; + + /// + /// Diagnostic descriptor for code you want to fade out and do *not* want to have a smart-tag + /// appear for. This is uncommon but useful in some cases. For example, if you are fading + /// out pieces of code before/after another piece of code *on the same line*, then you will + /// only want one usage of and multiple + /// usages of . + /// + /// That's because if you use for all the + /// faded out code then that will mean the user will see multiple code actions to fix the + /// same issue when they bring up the code action on that line. Using these two descriptors + /// helps ensure that there will not be useless code-action overload. + /// + protected readonly DiagnosticDescriptor UnnecessaryWithoutSuggestionDescriptor; + + protected readonly LocalizableString _localizableTitle; + protected readonly LocalizableString _localizableMessageFormat; + + private readonly bool _configurable; + + protected AbstractCodeStyleDiagnosticAnalyzer( + string descriptorId, LocalizableString title, + LocalizableString messageFormat = null, + bool configurable = true) + { + DescriptorId = descriptorId; + _localizableTitle = title; + _localizableMessageFormat = messageFormat ?? title; + _configurable = configurable; + + Descriptor = CreateDescriptor(); + UnnecessaryWithSuggestionDescriptor = CreateUnnecessaryDescriptor(); + UnnecessaryWithoutSuggestionDescriptor = CreateUnnecessaryDescriptor(descriptorId + "WithoutSuggestion"); + + SupportedDiagnostics = ImmutableArray.Create( + Descriptor, UnnecessaryWithoutSuggestionDescriptor, UnnecessaryWithSuggestionDescriptor); + } + + protected DiagnosticDescriptor CreateUnnecessaryDescriptor() + => CreateUnnecessaryDescriptor(DescriptorId); + + protected DiagnosticDescriptor CreateUnnecessaryDescriptor(string descriptorId) + => CreateDescriptorWithId( + descriptorId, _localizableTitle, _localizableMessageFormat, + WellKnownDiagnosticTags.Unnecessary, WellKnownDiagnosticTags.Telemetry); + + public override ImmutableArray SupportedDiagnostics + { + get; + } + + protected DiagnosticDescriptor CreateDescriptor(params string[] customTags) + => CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, customTags); + + protected DiagnosticDescriptor CreateDescriptorWithTitle(LocalizableString title, params string[] customTags) + => CreateDescriptorWithId(DescriptorId, title, title, customTags); + + protected DiagnosticDescriptor CreateDescriptorWithId( + string id, LocalizableString title, LocalizableString messageFormat, + params string[] customTags) + { + if (!_configurable) + { + customTags = customTags.Concat(new[] { WellKnownDiagnosticTags.NotConfigurable }).ToArray(); + } + + return new DiagnosticDescriptor( + id, title, messageFormat, + CodeStyleResources.Style, + DiagnosticSeverity.Hidden, + isEnabledByDefault: true, + customTags: customTags); + } + + public sealed override void Initialize(AnalysisContext context) + { + // Code style analyzers should not run on generated code. + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + + InitializeWorker(context); + } + + protected abstract void InitializeWorker(AnalysisContext context); + } +} diff --git a/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs b/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs index a7f72ab263830..25f6951d7c33d 100644 --- a/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs +++ b/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CodeStyleResources { @@ -62,11 +62,29 @@ internal CodeStyleResources() { } /// - /// Looks up a localized string similar to Remove this value when another is added.. + /// Looks up a localized string similar to Fix formatting. /// - internal static string EmptyResource { + internal static string Formatting_analyzer_message { get { - return ResourceManager.GetString("EmptyResource", resourceCulture); + return ResourceManager.GetString("Formatting_analyzer_message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fix formatting. + /// + internal static string Formatting_analyzer_title { + get { + return ResourceManager.GetString("Formatting_analyzer_title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Style. + /// + internal static string Style { + get { + return ResourceManager.GetString("Style", resourceCulture); } } } diff --git a/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx b/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx index 14ed010cf9ebb..110991e6a6ef1 100644 --- a/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx +++ b/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx @@ -117,8 +117,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Remove this value when another is added. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + + + Fix formatting + + + Style \ No newline at end of file diff --git a/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs b/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs new file mode 100644 index 0000000000000..b8b959dfd98a5 --- /dev/null +++ b/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs @@ -0,0 +1,248 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal static class DiagnosticHelper + { + /// + /// Creates a instance. + /// + /// A describing the diagnostic. + /// An optional primary location of the diagnostic. If null, will return . + /// Effective severity of the diagnostic. + /// + /// An optional set of additional locations related to the diagnostic. + /// Typically, these are locations of other items referenced in the message. + /// If null, will return an empty list. + /// + /// + /// An optional set of name-value pairs by means of which the analyzer that creates the diagnostic + /// can convey more detailed information to the fixer. If null, will return + /// . + /// + /// Arguments to the message of the diagnostic. + /// The instance. + public static Diagnostic Create( + DiagnosticDescriptor descriptor, + Location location, + ReportDiagnostic effectiveSeverity, + IEnumerable additionalLocations, + ImmutableDictionary properties, + params object[] messageArgs) + { + if (descriptor == null) + { + throw new ArgumentNullException(nameof(descriptor)); + } + + LocalizableString message; + if (messageArgs == null || messageArgs.Length == 0) + { + message = descriptor.MessageFormat; + } + else + { + message = new LocalizableStringWithArguments(descriptor.MessageFormat, messageArgs); + } + + var warningLevel = effectiveSeverity.ToDiagnosticSeverity() ?? descriptor.DefaultSeverity; + return Diagnostic.Create( + descriptor.Id, + descriptor.Category, + message, + effectiveSeverity.ToDiagnosticSeverity() ?? descriptor.DefaultSeverity, + descriptor.DefaultSeverity, + descriptor.IsEnabledByDefault, + warningLevel: effectiveSeverity.WithDefaultSeverity(descriptor.DefaultSeverity) == ReportDiagnostic.Error ? 0 : 1, + effectiveSeverity == ReportDiagnostic.Suppress, + descriptor.Title, + descriptor.Description, + descriptor.HelpLinkUri, + location, + additionalLocations, + descriptor.CustomTags, + properties); + } + + /// + /// Returns the equivalent for a value. + /// + /// The value. + /// + /// The equivalent for a value; otherwise, + /// if does not contain a direct equivalent for + /// . + /// + /// + /// If is not one of the expected values. + /// + private static DiagnosticSeverity? ToDiagnosticSeverity(this ReportDiagnostic reportDiagnostic) + { + switch (reportDiagnostic) + { + case ReportDiagnostic.Error: + return DiagnosticSeverity.Error; + + case ReportDiagnostic.Warn: + return DiagnosticSeverity.Warning; + + case ReportDiagnostic.Info: + return DiagnosticSeverity.Info; + + case ReportDiagnostic.Hidden: + return DiagnosticSeverity.Hidden; + + case ReportDiagnostic.Suppress: + case ReportDiagnostic.Default: + return null; + + default: + var o = reportDiagnostic; + var output = $"Unexpected value '{o}' of type '{o.GetType().FullName}'"; + throw new InvalidOperationException(output); + } + } + + /// + /// Applies a default severity to a value. + /// + /// The value. + /// The default severity. + /// + /// If is , returns + /// . + /// -or- + /// Otherwise, returns if it has a non-default value. + /// + private static ReportDiagnostic WithDefaultSeverity(this ReportDiagnostic reportDiagnostic, DiagnosticSeverity defaultSeverity) + { + if (reportDiagnostic != ReportDiagnostic.Default) + { + return reportDiagnostic; + } + + return defaultSeverity.ToReportDiagnostic(); + } + + /// + /// Returns the equivalent for a value. + /// + /// The value. + /// + /// The equivalent for the value. + /// + /// + /// If is not one of the expected values. + /// + private static ReportDiagnostic ToReportDiagnostic(this DiagnosticSeverity diagnosticSeverity) + { + switch (diagnosticSeverity) + { + case DiagnosticSeverity.Hidden: + return ReportDiagnostic.Hidden; + + case DiagnosticSeverity.Info: + return ReportDiagnostic.Info; + + case DiagnosticSeverity.Warning: + return ReportDiagnostic.Warn; + + case DiagnosticSeverity.Error: + return ReportDiagnostic.Error; + + default: + var o = diagnosticSeverity; + var output = $"Unexpected value '{o}' of type '{o.GetType().FullName}'"; + throw new InvalidOperationException(output); + } + } + + public sealed class LocalizableStringWithArguments : LocalizableString + { + private readonly LocalizableString _messageFormat; + private readonly string[] _formatArguments; + + public LocalizableStringWithArguments(LocalizableString messageFormat, params object[] formatArguments) + { + if (messageFormat == null) + { + throw new ArgumentNullException(nameof(messageFormat)); + } + + if (formatArguments == null) + { + throw new ArgumentNullException(nameof(formatArguments)); + } + + _messageFormat = messageFormat; + _formatArguments = new string[formatArguments.Length]; + for (var i = 0; i < formatArguments.Length; i++) + { + _formatArguments[i] = $"{formatArguments[i]}"; + } + } + + protected override string GetText(IFormatProvider formatProvider) + { + var messageFormat = _messageFormat.ToString(formatProvider); + return messageFormat != null ? + (_formatArguments.Length > 0 ? string.Format(formatProvider, messageFormat, _formatArguments) : messageFormat) : + string.Empty; + } + + protected override bool AreEqual(object other) + { + var otherResourceString = other as LocalizableStringWithArguments; + return otherResourceString != null && + _messageFormat.Equals(otherResourceString._messageFormat) && + SequenceEqual(_formatArguments, otherResourceString._formatArguments, (a, b) => a == b); + } + + protected override int GetHash() + { + // TODO: include values in hash + return _messageFormat.GetHashCode(); + } + + // TODO: unify definitions + public static bool SequenceEqual(IEnumerable first, IEnumerable second, Func comparer) + { + Debug.Assert(comparer != null); + + if (first == second) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + using (var enumerator = first.GetEnumerator()) + using (var enumerator2 = second.GetEnumerator()) + { + while (enumerator.MoveNext()) + { + if (!enumerator2.MoveNext() || !comparer(enumerator.Current, enumerator2.Current)) + { + return false; + } + } + + if (enumerator2.MoveNext()) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf index 6a6de2bb84ebf..4faac554d413d 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Odebrat tuto hodnotu, když se přidá jiná - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf index b44844bd0a41e..4ab91eee54c79 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Dieser Wert wird entfernt, wenn ein anderer hinzugefügt wird. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf index 7ed4ea2bc5105..464a5df4adf46 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Quite este valor cuando se agregue otro. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf index d91224ebf40dc..87c658fb8d7e6 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Supprimer cette valeur quand une autre est ajoutée. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf index 647758371b62a..5bf1ccac11d41 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Rimuovere questo valore quando ne viene aggiunto un altro. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf index 915450972d71f..d9675791e119c 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - 別の値が追加されたら、この値を削除します。 - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf index 14f22f49ebb93..cf577ccccefc2 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - 다른 값을 추가할 때 이 값을 제거하세요. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf index 343925dce71d7..13d6a44471a8e 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Usuń tę wartość, gdy dodawana jest kolejna. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf index eecaaac55c344..3b04a8d5a786b 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Remover este valor quando outro for adicionado. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf index 9d02b6f1aeaf7..6e63f0704c86a 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Удалите это значение при добавлении другого значения. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf index 30011bdc0ed44..290b0366e6390 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - Başka bir değer eklendiğinde bu değeri kaldırın. - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf index 50b21cbe874b8..d128257c7354d 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - 在添加其他值时删除此值。 - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf index fc6b9e1668a0c..4d03802436edb 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf @@ -2,10 +2,20 @@ - - Remove this value when another is added. - 當新增另一個值時移除此值。 - https://github.com/Microsoft/msbuild/issues/1661 + + Fix formatting + Fix formatting + + + + Fix formatting + Fix formatting + + + + Style + Style + diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs new file mode 100644 index 0000000000000..370a36e51d078 --- /dev/null +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -0,0 +1,101 @@ +// 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.Collections.Immutable; +using System.IO; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.CodingConventions; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal abstract class AbstractFormattingAnalyzer + : AbstractCodeStyleDiagnosticAnalyzer + { + private const string FormattingDiagnosticId = "IDE0051"; + + public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); + + public static readonly ImmutableDictionary RemoveTextProperties = + ImmutableDictionary.Create().Add(ReplaceTextKey, ""); + + protected AbstractFormattingAnalyzer() + : base( + FormattingDiagnosticId, + new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_title), CodeStyleResources.ResourceManager, typeof(CodeStyleResources)), + new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_message), CodeStyleResources.ResourceManager, typeof(CodeStyleResources))) + { + } + + protected abstract OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext); + + protected override void InitializeWorker(AnalysisContext context) + { + var workspace = new AdhocWorkspace(); + var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(); + + context.RegisterSyntaxTreeAction(c => AnalyzeSyntaxTree(c, workspace, codingConventionsManager)); + } + + private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace workspace, ICodingConventionsManager codingConventionsManager) + { + var options = workspace.Options; + if (File.Exists(context.Tree.FilePath)) + { + var codingConventionContext = codingConventionsManager.GetConventionContextAsync(context.Tree.FilePath, context.CancellationToken).GetAwaiter().GetResult(); + options = ApplyFormattingOptions(options, codingConventionContext); + } + + var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, context.CancellationToken); + foreach (var formattingChange in formattingChanges) + { + var change = formattingChange; + if (change.NewText.Length > 0 && !change.Span.IsEmpty) + { + var oldText = context.Tree.GetText(context.CancellationToken); + + // Handle cases where the change is a substring removal from the beginning + var offset = change.Span.Length - change.NewText.Length; + if (offset >= 0 && 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 + if (change.NewText.Length < change.Span.Length + && 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, change.Span.Length - change.NewText.Length), ""); + } + } + } + + if (change.NewText.Length == 0 && change.Span.IsEmpty) + { + // No actual change + continue; + } + + ImmutableDictionary properties; + if (change.NewText.Length == 0) + { + properties = RemoveTextProperties; + } + else + { + properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); + } + + var location = Location.Create(context.Tree, change.Span); + context.ReportDiagnostic(DiagnosticHelper.Create( + Descriptor, + location, + ReportDiagnostic.Default, + additionalLocations: null, + properties)); + } + } + } +} diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 3aef9dc298060..9d06f8c9f8018 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -8,6 +8,9 @@ Microsoft.CodeAnalysis netstandard1.3 + + + From 83c76f7afc804f42c96a735eb1de6b526d4e1769 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 29 Aug 2018 05:06:32 -0500 Subject: [PATCH 03/25] Update the CodeStyle layer to reference the 2.8.2 release --- .../Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj | 5 +++-- .../Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj | 7 +++---- ...icrosoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj | 4 ---- .../Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj | 4 ++-- .../Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj | 3 +-- .../Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj | 2 -- .../Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj | 5 +++-- ...crosoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj | 7 +++---- ...oft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj | 4 ---- 9 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj b/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj index d49af664d7971..99b4e2450ec5a 100644 --- a/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj +++ b/src/CodeStyle/CSharp/Analyzers/Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj @@ -8,9 +8,10 @@ Microsoft.CodeAnalysis.CSharp netstandard1.3 + + + - - diff --git a/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj b/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj index 37bf117b0a9a8..2e50d3f5a0191 100644 --- a/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj @@ -32,11 +32,10 @@ + + + - - - - diff --git a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj index 87b7328fea1bc..43877728d7d13 100644 --- a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj +++ b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj @@ -10,10 +10,6 @@ UnitTestPortable - - - - diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj index 1c02779e52327..0e874d635bff2 100644 --- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj +++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj @@ -8,8 +8,8 @@ Microsoft.CodeAnalysis netstandard1.3 - - + + diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 9d06f8c9f8018..3618c25635f36 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -9,11 +9,10 @@ netstandard1.3 + - - diff --git a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj index 58cf8a36f915b..95106d2f214b5 100644 --- a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj +++ b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj @@ -10,8 +10,6 @@ UnitTestPortable - - diff --git a/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj b/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj index 117c7d75700ec..b5b59051716c1 100644 --- a/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj +++ b/src/CodeStyle/VisualBasic/Analyzers/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj @@ -8,9 +8,10 @@ netstandard1.3 + + + - - diff --git a/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj b/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj index 7c83e925f4e7f..0176ecb84fd88 100644 --- a/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj +++ b/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj @@ -32,11 +32,10 @@ + + + - - - - diff --git a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj index 3ec6ba2000a25..5ea9987e59597 100644 --- a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj +++ b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj @@ -10,10 +10,6 @@ - - - - From 0c4f65518f9c3c6acaccdf207b60adc25b242791 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 29 Aug 2018 05:07:38 -0500 Subject: [PATCH 04/25] Work around lack of Workspaces layer during command line builds --- .../CodeFixes/CSharpFormattingAnalyzer.cs | 22 +---- .../CodeFixes/CSharpFormattingAnalyzerImpl.cs | 32 ++++++ ...CodeAnalysis.CSharp.CodeStyle.Fixes.csproj | 17 +++- ...Analysis.CSharp.CodeStyle.UnitTests.csproj | 4 +- .../CodeFixes/AbstractFormattingAnalyzer.cs | 90 ++++------------- .../AbstractFormattingAnalyzerImpl.cs | 97 +++++++++++++++++++ ...rosoft.CodeAnalysis.CodeStyle.Fixes.csproj | 2 +- ...ft.CodeAnalysis.CodeStyle.UnitTests.csproj | 4 +- ...nalysis.VisualBasic.CodeStyle.Fixes.vbproj | 2 +- ...sis.VisualBasic.CodeStyle.UnitTests.vbproj | 4 +- 10 files changed, 178 insertions(+), 96 deletions(-) create mode 100644 src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzerImpl.cs create mode 100644 src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs diff --git a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs index 0a4d45d5bbffe..28382affc38ed 100644 --- a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs +++ b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs @@ -1,30 +1,16 @@ // 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.CSharp.Formatting; +using System; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Options; -using Microsoft.VisualStudio.CodingConventions; namespace Microsoft.CodeAnalysis.CodeStyle { [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpFormattingAnalyzer - : AbstractFormattingAnalyzer + internal class CSharpFormattingAnalyzer : AbstractFormattingAnalyzer { - protected override OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext) + protected override Type GetAnalyzerImplType() { - return optionSet.WithChangedOption(CSharpFormattingOptions.IndentBlock, GetBoolOrDefault(codingConventionContext.CurrentConventions, "csharp_indent_block_contents", CSharpFormattingOptions.IndentBlock.DefaultValue)); - } - - private bool GetBoolOrDefault(ICodingConventionsSnapshot currentConventions, string key, bool defaultValue) - { - if (currentConventions.TryGetConventionValue(key, out string rawValue) - && bool.TryParse(rawValue, out var value)) - { - return value; - } - - return defaultValue; + return typeof(CSharpFormattingAnalyzerImpl); } } } diff --git a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzerImpl.cs b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzerImpl.cs new file mode 100644 index 0000000000000..92d411b294f15 --- /dev/null +++ b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzerImpl.cs @@ -0,0 +1,32 @@ +// 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.CSharp.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.CodingConventions; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal class CSharpFormattingAnalyzerImpl : AbstractFormattingAnalyzerImpl + { + public CSharpFormattingAnalyzerImpl(DiagnosticDescriptor descriptor) + : base(descriptor) + { + } + + protected override OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext) + { + return optionSet.WithChangedOption(CSharpFormattingOptions.IndentBlock, GetBoolOrDefault(codingConventionContext.CurrentConventions, "csharp_indent_block_contents", CSharpFormattingOptions.IndentBlock.DefaultValue)); + } + + private bool GetBoolOrDefault(ICodingConventionsSnapshot currentConventions, string key, bool defaultValue) + { + if (currentConventions.TryGetConventionValue(key, out string rawValue) + && bool.TryParse(rawValue, out var value)) + { + return value; + } + + return defaultValue; + } + } +} diff --git a/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj b/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj index 2e50d3f5a0191..91f1e3a908edf 100644 --- a/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/CSharp/CodeFixes/Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj @@ -6,7 +6,8 @@ AnyCPU Library Microsoft.CodeAnalysis.CSharp - netstandard1.3 + net46 + true true @@ -29,7 +30,21 @@ <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CodeStyle\**\Microsoft.CodeAnalysis.CodeStyle.resources.dll"/> <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CodeStyle.Fixes\**\Microsoft.CodeAnalysis.CodeStyle.Fixes.resources.dll"/> + + <_WorkspaceFile Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\Microsoft.VisualStudio.CodingConventions.dll"/> + <_WorkspaceFile Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\Microsoft.CodeAnalysis.Workspaces.dll"/> + <_WorkspaceFile Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\**\Microsoft.CodeAnalysis.Workspaces.resources.dll"/> + <_WorkspaceFile Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\Microsoft.CodeAnalysis.CSharp.Workspaces.dll"/> + <_WorkspaceFile Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\**\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll"/> + + + <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\System.Composition.AttributedModel.dll"/> + <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\System.Composition.Hosting.dll"/> + <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\System.Composition.Runtime.dll"/> + <_File Include="$(ArtifactsConfigurationDir)Dlls\Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes\System.Composition.TypedParts.dll"/> + + diff --git a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj index 43877728d7d13..bd65099ee1525 100644 --- a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj +++ b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj @@ -6,8 +6,8 @@ AnyCPU Library Microsoft.CodeAnalysis.CSharp - $(RoslynPortableTargetFrameworks) - UnitTestPortable + net46 + UnitTest diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs index 370a36e51d078..017c7c67d43e1 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -1,12 +1,11 @@ // 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.Collections.Immutable; +using System; +using System.Diagnostics; using System.IO; +using System.Linq; +using System.Reflection; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Text; -using Microsoft.VisualStudio.CodingConventions; namespace Microsoft.CodeAnalysis.CodeStyle { @@ -15,10 +14,10 @@ internal abstract class AbstractFormattingAnalyzer { private const string FormattingDiagnosticId = "IDE0051"; - public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); - - public static readonly ImmutableDictionary RemoveTextProperties = - ImmutableDictionary.Create().Add(ReplaceTextKey, ""); + static AbstractFormattingAnalyzer() + { + AppDomain.CurrentDomain.AssemblyResolve += HandleAssemblyResolve; + } protected AbstractFormattingAnalyzer() : base( @@ -28,73 +27,26 @@ protected AbstractFormattingAnalyzer() { } - protected abstract OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext); + protected abstract Type GetAnalyzerImplType(); protected override void InitializeWorker(AnalysisContext context) { - var workspace = new AdhocWorkspace(); - var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(); - - context.RegisterSyntaxTreeAction(c => AnalyzeSyntaxTree(c, workspace, codingConventionsManager)); + var analyzer = (AbstractFormattingAnalyzerImpl)Activator.CreateInstance(GetAnalyzerImplType(), Descriptor); + analyzer.InitializeWorker(context); } - private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace workspace, ICodingConventionsManager codingConventionsManager) + private static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args) { - var options = workspace.Options; - if (File.Exists(context.Tree.FilePath)) + switch (new AssemblyName(args.Name).Name) { - var codingConventionContext = codingConventionsManager.GetConventionContextAsync(context.Tree.FilePath, context.CancellationToken).GetAwaiter().GetResult(); - options = ApplyFormattingOptions(options, codingConventionContext); - } - - var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, context.CancellationToken); - foreach (var formattingChange in formattingChanges) - { - var change = formattingChange; - if (change.NewText.Length > 0 && !change.Span.IsEmpty) - { - var oldText = context.Tree.GetText(context.CancellationToken); - - // Handle cases where the change is a substring removal from the beginning - var offset = change.Span.Length - change.NewText.Length; - if (offset >= 0 && 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 - if (change.NewText.Length < change.Span.Length - && 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, change.Span.Length - change.NewText.Length), ""); - } - } - } - - if (change.NewText.Length == 0 && change.Span.IsEmpty) - { - // No actual change - continue; - } - - ImmutableDictionary properties; - if (change.NewText.Length == 0) - { - properties = RemoveTextProperties; - } - else - { - properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); - } - - var location = Location.Create(context.Tree, change.Span); - context.ReportDiagnostic(DiagnosticHelper.Create( - Descriptor, - location, - ReportDiagnostic.Default, - additionalLocations: null, - properties)); + case "Microsoft.CodeAnalysis.Workspaces": + case "Microsoft.CodeAnalysis.CSharp.Workspaces": + case "Microsoft.VisualStudio.CodingConventions": + var result = Assembly.LoadFrom(Path.Combine(Path.GetDirectoryName(typeof(AbstractFormattingAnalyzer).Assembly.Location), "..\\workspaces", new AssemblyName(args.Name).Name + ".dll")); + return result; + + default: + return null; } } } diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs new file mode 100644 index 0000000000000..cb5663df52703 --- /dev/null +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs @@ -0,0 +1,97 @@ +// 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.Collections.Immutable; +using System.IO; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.CodingConventions; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal abstract class AbstractFormattingAnalyzerImpl + { + public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); + + public static readonly ImmutableDictionary RemoveTextProperties = + ImmutableDictionary.Create().Add(ReplaceTextKey, ""); + + private readonly DiagnosticDescriptor _descriptor; + + protected AbstractFormattingAnalyzerImpl(DiagnosticDescriptor descriptor) + { + _descriptor = descriptor; + } + + internal void InitializeWorker(AnalysisContext context) + { + var workspace = new AdhocWorkspace(); + var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(); + + context.RegisterSyntaxTreeAction(c => AnalyzeSyntaxTree(c, workspace, codingConventionsManager)); + } + + protected abstract OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext); + + private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace workspace, ICodingConventionsManager codingConventionsManager) + { + var options = workspace.Options; + if (File.Exists(context.Tree.FilePath)) + { + var codingConventionContext = codingConventionsManager.GetConventionContextAsync(context.Tree.FilePath, context.CancellationToken).GetAwaiter().GetResult(); + options = ApplyFormattingOptions(options, codingConventionContext); + } + + var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, context.CancellationToken); + foreach (var formattingChange in formattingChanges) + { + var change = formattingChange; + if (change.NewText.Length > 0 && !change.Span.IsEmpty) + { + var oldText = context.Tree.GetText(context.CancellationToken); + + // Handle cases where the change is a substring removal from the beginning + var offset = change.Span.Length - change.NewText.Length; + if (offset >= 0 && 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 + if (change.NewText.Length < change.Span.Length + && 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, change.Span.Length - change.NewText.Length), ""); + } + } + } + + if (change.NewText.Length == 0 && change.Span.IsEmpty) + { + // No actual change + continue; + } + + ImmutableDictionary properties; + if (change.NewText.Length == 0) + { + properties = RemoveTextProperties; + } + else + { + properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); + } + + var location = Location.Create(context.Tree, change.Span); + context.ReportDiagnostic(DiagnosticHelper.Create( + _descriptor, + location, + ReportDiagnostic.Default, + additionalLocations: null, + properties)); + } + } + } +} diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 3618c25635f36..d6b750235c43c 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -6,7 +6,7 @@ AnyCPU Library Microsoft.CodeAnalysis - netstandard1.3 + net46 diff --git a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj index 95106d2f214b5..bd9b5023efde6 100644 --- a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj +++ b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTests.csproj @@ -6,8 +6,8 @@ AnyCPU Library Microsoft.CodeAnalysis - $(RoslynPortableTargetFrameworks) - UnitTestPortable + net46 + UnitTest diff --git a/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj b/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj index 0176ecb84fd88..d787e3c9ff9c5 100644 --- a/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj +++ b/src/CodeStyle/VisualBasic/CodeFixes/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj @@ -5,7 +5,7 @@ AnyCPU AnyCPU Library - netstandard1.3 + net46 diff --git a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj index 5ea9987e59597..52109b7e42831 100644 --- a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj +++ b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj @@ -5,8 +5,8 @@ AnyCPU AnyCPU Library - $(RoslynPortableTargetFrameworks) - UnitTestPortable + net46 + UnitTest From 0dc9b966ac6e16f8eabf601777d537f132c39df1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 29 Aug 2018 05:12:26 -0500 Subject: [PATCH 05/25] Move version reference to Packages.props --- build/Targets/Packages.props | 6 ++++++ .../Microsoft.CodeAnalysis.CSharp.CodeStyle.csproj | 2 +- .../Microsoft.CodeAnalysis.CSharp.CodeStyle.Fixes.csproj | 2 +- .../Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj | 2 +- .../CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj | 2 +- .../Microsoft.CodeAnalysis.VisualBasic.CodeStyle.vbproj | 2 +- ...icrosoft.CodeAnalysis.VisualBasic.CodeStyle.Fixes.vbproj | 2 +- 7 files changed, 12 insertions(+), 6 deletions(-) diff --git a/build/Targets/Packages.props b/build/Targets/Packages.props index a259bb5285e6e..a07f70aa7ec10 100644 --- a/build/Targets/Packages.props +++ b/build/Targets/Packages.props @@ -258,6 +258,12 @@ 2.4.1-pre.build.4059 1.0.51 2.4.1-pre.build.4059 + + + 2.8.2 2.8.2 + $(CodeStyleLayerCodeAnalysisVersion) + $(CodeStyleLayerCodeAnalysisVersion) + $(CodeStyleLayerCodeAnalysisVersion) + $(CodeStyleLayerCodeAnalysisVersion) + $(CodeStyleLayerCodeAnalysisVersion) + $(CodeStyleLayerCodeAnalysisVersion) - + 2.6.2-beta2 + 2.8.2 + 1.0.0-beta1-63310-01 0.9.3 0.11.0 @@ -47,8 +49,10 @@ 15.1.0-preview-000458-02 $(RoslynDiagnosticsNugetPackageVersion) 2.0.0-rc2-61102-09 + $(MicrosoftCodeAnalysisTestingVersion) 0.10.6 2.0.12 + $(MicrosoftCodeAnalysisTestingVersion) $(RoslynDiagnosticsNugetPackageVersion) 1.0.31 4.3.0 @@ -263,7 +267,6 @@ The CodeStyle layer depends on a prior stable release of the CodeAnalysis assemblies so the NuGet packages produced by the build can be installed in projects building with those older releases. --> - 2.8.2 $(CodeStyleLayerCodeAnalysisVersion) $(CodeStyleLayerCodeAnalysisVersion) $(CodeStyleLayerCodeAnalysisVersion) diff --git a/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs new file mode 100644 index 0000000000000..a14943e72f323 --- /dev/null +++ b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs @@ -0,0 +1,169 @@ +// 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.Tasks; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; +using Xunit; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + using Verify = CSharpCodeFixVerifier; + + public class FormattingAnalyzerTests + { + [Fact] + public async Task TestAlreadyFormatted() + { + var testCode = @" +class MyClass +{ + void MyMethod() + { + } +} +"; + + await Verify.VerifyAnalyzerAsync(testCode); + } + + [Fact] + public async Task TestNeedsIndentation() + { + var testCode = @" +class MyClass +{ + $$void MyMethod() + $${ + $$} +} +"; + var fixedCode = @" +class MyClass +{ + void MyMethod() + { + } +} +"; + + await Verify.VerifyCodeFixAsync(testCode, fixedCode); + } + + [Fact] + public async Task TestWhitespaceBetweenMethods1() + { + var testCode = @" +class MyClass +{ + void MyMethod1() + { + } +[| |] + void MyMethod2() + { + } +} +"; + var fixedCode = @" +class MyClass +{ + void MyMethod1() + { + } + + void MyMethod2() + { + } +} +"; + + await Verify.VerifyCodeFixAsync(testCode, fixedCode); + } + + [Fact] + public async Task TestWhitespaceBetweenMethods2() + { + var testCode = @" +class MyClass +{ + void MyMethod1() + { + }[| |] + + void MyMethod2() + { + } +} +"; + var fixedCode = @" +class MyClass +{ + void MyMethod1() + { + } + + void MyMethod2() + { + } +} +"; + + await Verify.VerifyCodeFixAsync(testCode, fixedCode); + } + + [Fact] + public async Task TestWhitespaceBetweenMethods3() + { + // This example has trailing whitespace on both lines preceding MyMethod2 + var testCode = @" +class MyClass +{ + void MyMethod1() + { + }[| + + |]void MyMethod2() + { + } +} +"; + var fixedCode = @" +class MyClass +{ + void MyMethod1() + { + } + + void MyMethod2() + { + } +} +"; + + await Verify.VerifyCodeFixAsync(testCode, fixedCode); + } + + [Fact] + public async Task TestOverIndentation() + { + var testCode = @" +class MyClass +{ + [| |]void MyMethod() + [| |]{ + [| |]} +} +"; + var fixedCode = @" +class MyClass +{ + void MyMethod() + { + } +} +"; + + await Verify.VerifyCodeFixAsync(testCode, fixedCode); + } + } +} diff --git a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj index c699d66859fbc..b2b5f5702fcf1 100644 --- a/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj +++ b/src/CodeStyle/CSharp/Tests/Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj @@ -9,6 +9,10 @@ net46 UnitTest + + + + diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs index db9c759cb34a8..3729c0e6c32bc 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -1,6 +1,7 @@ // 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; +using System.Collections.Immutable; using System.IO; using System.Reflection; using Microsoft.CodeAnalysis.Diagnostics; @@ -25,6 +26,9 @@ protected AbstractFormattingAnalyzer() { } + public override ImmutableArray SupportedDiagnostics + => ImmutableArray.Create(Descriptor); + protected abstract Type GetAnalyzerImplType(); protected override void InitializeWorker(AnalysisContext context) diff --git a/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb b/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb new file mode 100644 index 0000000000000..55caaf9117aa9 --- /dev/null +++ b/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb @@ -0,0 +1,25 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Xunit +Imports VerifyVB = Microsoft.CodeAnalysis.VisualBasic.Testing.VisualBasicCodeFixVerifier( + Of Microsoft.CodeAnalysis.CodeStyle.VisualBasicFormattingAnalyzer, + Microsoft.CodeAnalysis.CodeStyle.FormattingCodeFixProvider, + Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier) + +Namespace Microsoft.CodeAnalysis.CodeStyle + Public Class FormattingAnalyzerTests + + Public Async Function TestCaseCorrection() As Task + Dim testCode = " +class TestClass + public Sub MyMethod() + End Sub +end class +" + + ' Currently the analyzer and code fix rely on Formatter.FormatAsync, which does not normalize the casing of + ' keywords in Visual Basic. + Await VerifyVB.VerifyAnalyzerAsync(testCode) + End Function + End Class +End Namespace diff --git a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj index bbc7a1478b9ce..998e80b375107 100644 --- a/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj +++ b/src/CodeStyle/VisualBasic/Tests/Microsoft.CodeAnalysis.VisualBasic.CodeStyle.UnitTests.vbproj @@ -9,6 +9,10 @@ UnitTest + + + + From 75c90a04abb0acb5c760d5cc9e8fcb34fb8151ef Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 19 Sep 2018 16:19:05 -0500 Subject: [PATCH 11/25] Code cleanup based on review feedback --- .../AbstractFormattingAnalyzerImpl.cs | 47 ++++++++++++------- .../CodeFixes/FormattingCodeFixProvider.cs | 3 +- .../Formatting/FormattingCodeFixProvider.cs | 3 +- .../FormattingDiagnosticAnalyzer.cs | 45 +++++++++++------- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs index cb5663df52703..449a74c8915bb 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs @@ -1,5 +1,6 @@ // 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; using System.Collections.Immutable; using System.IO; using Microsoft.CodeAnalysis.Diagnostics; @@ -36,34 +37,46 @@ internal void InitializeWorker(AnalysisContext context) private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace workspace, ICodingConventionsManager codingConventionsManager) { + var tree = context.Tree; + var cancellationToken = context.CancellationToken; + var options = workspace.Options; - if (File.Exists(context.Tree.FilePath)) + if (File.Exists(tree.FilePath)) { - var codingConventionContext = codingConventionsManager.GetConventionContextAsync(context.Tree.FilePath, context.CancellationToken).GetAwaiter().GetResult(); + var codingConventionContext = codingConventionsManager.GetConventionContextAsync(tree.FilePath, cancellationToken).GetAwaiter().GetResult(); options = ApplyFormattingOptions(options, codingConventionContext); } - var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, 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) { - var oldText = context.Tree.GetText(context.CancellationToken); - - // Handle cases where the change is a substring removal from the beginning + // 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 && oldText.GetSubText(new TextSpan(change.Span.Start + offset, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) + if (offset >= 0) { - change = new TextChange(new TextSpan(change.Span.Start, offset), ""); - } - else - { - // Handle cases where the change is a substring removal from the end - if (change.NewText.Length < change.Span.Length - && oldText.GetSubText(new TextSpan(change.Span.Start, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) + 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 { - change = new TextChange(new TextSpan(change.Span.Start + change.NewText.Length, change.Span.Length - change.NewText.Length), ""); + // 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), ""); + } } } } @@ -71,7 +84,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace work if (change.NewText.Length == 0 && change.Span.IsEmpty) { // No actual change - continue; + throw new InvalidOperationException("This program location is thought to be unreachable."); } ImmutableDictionary properties; @@ -84,7 +97,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace work properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); } - var location = Location.Create(context.Tree, change.Span); + var location = Location.Create(tree, change.Span); context.ReportDiagnostic(DiagnosticHelper.Create( _descriptor, location, diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index d0b7ebae5e40e..cb590426280fa 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -43,8 +43,7 @@ protected async Task FixOneAsync(Document document, ImmutableArray(); foreach (var diagnostic in diagnostics) { - if (!tree.Equals(diagnostic.Location.SourceTree) - || !diagnostic.Properties.TryGetValue(AbstractFormattingAnalyzerImpl.ReplaceTextKey, out var replacement)) + if (!diagnostic.Properties.TryGetValue(AbstractFormattingAnalyzerImpl.ReplaceTextKey, out var replacement)) { continue; } diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index f43831e23dee2..2772fffc7172c 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -37,8 +37,7 @@ protected async Task FixOneAsync(Document document, ImmutableArray(); foreach (var diagnostic in diagnostics) { - if (!tree.Equals(diagnostic.Location.SourceTree) - || !diagnostic.Properties.TryGetValue(FormattingDiagnosticAnalyzer.ReplaceTextKey, out var replacement)) + if (!diagnostic.Properties.TryGetValue(FormattingDiagnosticAnalyzer.ReplaceTextKey, out var replacement)) { continue; } diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs index 1f19d8f55a289..7475f5b2471ad 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Formatting { @@ -40,34 +41,46 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) return; } - var options = context.Options.GetDocumentOptionSetAsync(context.Tree, context.CancellationToken).GetAwaiter().GetResult(); + var tree = context.Tree; + var cancellationToken = context.CancellationToken; + + var options = context.Options.GetDocumentOptionSetAsync(tree, cancellationToken).GetAwaiter().GetResult(); if (options == null) { return; } var workspace = workspaceAnalyzerOptions.Services.Workspace; - var formattingChanges = Formatter.GetFormattedTextChanges(context.Tree.GetRoot(context.CancellationToken), workspace, options, 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) { - var oldText = context.Tree.GetText(context.CancellationToken); - - // Handle cases where the change is a substring removal from the beginning + // 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 && oldText.GetSubText(new TextSpan(change.Span.Start + offset, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) + if (offset >= 0) { - change = new TextChange(new TextSpan(change.Span.Start, offset), ""); - } - else - { - // Handle cases where the change is a substring removal from the end - if (change.NewText.Length < change.Span.Length - && oldText.GetSubText(new TextSpan(change.Span.Start, change.NewText.Length)).ContentEquals(SourceText.From(change.NewText))) + 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 { - change = new TextChange(new TextSpan(change.Span.Start + change.NewText.Length, change.Span.Length - change.NewText.Length), ""); + // 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), ""); + } } } } @@ -75,7 +88,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) if (change.NewText.Length == 0 && change.Span.IsEmpty) { // No actual change - continue; + throw ExceptionUtilities.Unreachable; } ImmutableDictionary properties; @@ -88,7 +101,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); } - var location = Location.Create(context.Tree, change.Span); + var location = Location.Create(tree, change.Span); context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, location, From 1124126a863e106c4577c457cf3301f5dca1ec9c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 19 Sep 2018 16:41:59 -0500 Subject: [PATCH 12/25] Avoid storing code fixes in the diagnostic property bags --- .../CSharp/Tests/FormattingAnalyzerTests.cs | 29 ++++++++++++++ .../AbstractFormattingAnalyzerImpl.cs | 18 +-------- .../CodeFixes/FormattingCodeFixProvider.cs | 39 +++++++++---------- .../Formatting/FormattingCodeFixProvider.cs | 33 ++++++++-------- .../FormattingDiagnosticAnalyzer.cs | 18 +-------- 5 files changed, 66 insertions(+), 71 deletions(-) diff --git a/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs index a14943e72f323..a966e5fd6e421 100644 --- a/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs +++ b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs @@ -165,5 +165,34 @@ void MyMethod() await Verify.VerifyCodeFixAsync(testCode, fixedCode); } + + [Fact] + public async Task TestIncrementalFixesFullLine() + { + var testCode = @" +class MyClass +{ + int Property1$${$$get;$$set;$$} + int Property2$${$$get;$$} +} +"; + var fixedCode = @" +class MyClass +{ + int Property1 { get; set; } + int Property2 { get; } +} +"; + + await new CSharpCodeFixTest + { + TestCode = testCode, + FixedCode = fixedCode, + + // Each application of a single code fix covers all diagnostics on the same line. In total, two lines + // require changes so the number of incremental iterations is exactly 2. + NumberOfIncrementalIterations = 2, + }.RunAsync(); + } } } diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs index 449a74c8915bb..98d5127490517 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs @@ -1,7 +1,6 @@ // 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; -using System.Collections.Immutable; using System.IO; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; @@ -13,11 +12,6 @@ namespace Microsoft.CodeAnalysis.CodeStyle { internal abstract class AbstractFormattingAnalyzerImpl { - public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); - - public static readonly ImmutableDictionary RemoveTextProperties = - ImmutableDictionary.Create().Add(ReplaceTextKey, ""); - private readonly DiagnosticDescriptor _descriptor; protected AbstractFormattingAnalyzerImpl(DiagnosticDescriptor descriptor) @@ -87,23 +81,13 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace work throw new InvalidOperationException("This program location is thought to be unreachable."); } - ImmutableDictionary properties; - if (change.NewText.Length == 0) - { - properties = RemoveTextProperties; - } - else - { - properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); - } - var location = Location.Create(tree, change.Span); context.ReportDiagnostic(DiagnosticHelper.Create( _descriptor, location, ReportDiagnostic.Default, additionalLocations: null, - properties)); + properties: null)); } } } diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index cb590426280fa..9e32e87655ba2 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -1,6 +1,5 @@ // 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.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Threading; @@ -26,34 +25,34 @@ public override FixAllProvider GetFixAllProvider() public override Task RegisterCodeFixesAsync(CodeFixContext context) { - context.RegisterCodeFix( - CodeAction.Create( - CodeStyleFixesResources.Formatting_analyzer_code_fix, - c => FixOneAsync(context.Document, context.Diagnostics, c), - nameof(FormattingCodeFixProvider)), - context.Diagnostics); + foreach (var diagnostic in context.Diagnostics) + { + context.RegisterCodeFix( + CodeAction.Create( + CodeStyleFixesResources.Formatting_analyzer_code_fix, + c => FixOneAsync(context.Document, diagnostic, c), + nameof(FormattingCodeFixProvider)), + diagnostic); + } return Task.CompletedTask; } - protected async Task FixOneAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + protected async Task FixOneAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var changes = new List(); - foreach (var diagnostic in diagnostics) - { - if (!diagnostic.Properties.TryGetValue(AbstractFormattingAnalyzerImpl.ReplaceTextKey, out var replacement)) - { - continue; - } - changes.Add(new TextChange(diagnostic.Location.SourceSpan, replacement)); - } + // 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); - changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); - return document.WithText(text.WithChanges(changes)); + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); } private class FixAll : DocumentBasedFixAllProvider diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index 2772fffc7172c..86ad51e084c5a 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -1,7 +1,6 @@ // 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; -using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Threading; @@ -23,31 +22,31 @@ public override ImmutableArray FixableDiagnosticIds public override Task RegisterCodeFixesAsync(CodeFixContext context) { - context.RegisterCodeFix( - new MyCodeAction(c => FixOneAsync(context.Document, context.Diagnostics, c)), - context.Diagnostics); + foreach (var diagnostic in context.Diagnostics) + { + context.RegisterCodeFix( + new MyCodeAction(c => FixOneAsync(context.Document, diagnostic, c)), + diagnostic); + } return Task.CompletedTask; } - protected async Task FixOneAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + protected async Task FixOneAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var changes = new List(); - foreach (var diagnostic in diagnostics) - { - if (!diagnostic.Properties.TryGetValue(FormattingDiagnosticAnalyzer.ReplaceTextKey, out var replacement)) - { - continue; - } - changes.Add(new TextChange(diagnostic.Location.SourceSpan, replacement)); - } + // 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); - changes.Sort((left, right) => left.Span.Start.CompareTo(right.Span.Start)); - return document.WithText(text.WithChanges(changes)); + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + return await Formatter.FormatAsync(document, spanToFormat, options, 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 7475f5b2471ad..217c53270becc 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -1,6 +1,5 @@ // 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.Collections.Immutable; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; @@ -12,11 +11,6 @@ namespace Microsoft.CodeAnalysis.Formatting internal class FormattingDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer { - public static readonly string ReplaceTextKey = nameof(ReplaceTextKey); - - public static readonly ImmutableDictionary RemoveTextProperties = - ImmutableDictionary.Create().Add(ReplaceTextKey, ""); - public FormattingDiagnosticAnalyzer() : base( IDEDiagnosticIds.FormattingDiagnosticId, @@ -91,23 +85,13 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) throw ExceptionUtilities.Unreachable; } - ImmutableDictionary properties; - if (change.NewText.Length == 0) - { - properties = RemoveTextProperties; - } - else - { - properties = ImmutableDictionary.Create().Add(ReplaceTextKey, change.NewText); - } - var location = Location.Create(tree, change.Span); context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, location, ReportDiagnostic.Default, additionalLocations: null, - properties)); + properties: null)); } } } From 14d31d01116791ec7beaba13e2f95c2d2b0ffde9 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 3 Oct 2018 23:44:27 -0500 Subject: [PATCH 13/25] Updates from code review feedback --- .../CodeFixes/AbstractFormattingAnalyzer.cs | 8 +++ .../AbstractFormattingAnalyzerImpl.cs | 3 +- .../Core/Portable/Formatting/Formatter.cs | 64 ++++++++++++++++--- 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs index 3729c0e6c32bc..97db0294a9551 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -8,6 +8,12 @@ namespace Microsoft.CodeAnalysis.CodeStyle { + /// + /// This analyzer implements , but wraps the true formatting analyzer + /// implementations. Since the compiler doesn't provide the use of workspace-layer APIs for analyzers, we need to + /// provide our own copy of the workspace assemblies and load them using reflection if they are not already loaded + /// in the current process. + /// internal abstract class AbstractFormattingAnalyzer : AbstractCodeStyleDiagnosticAnalyzer { @@ -33,6 +39,8 @@ public override ImmutableArray SupportedDiagnostics protected override void InitializeWorker(AnalysisContext context) { + // Create an instance of the true formatting analyzer (which depends on workspace-layer APIs) only after the + // custom assembly resolver is in place to provide the assemblies if necessary. var analyzer = (AbstractFormattingAnalyzerImpl)Activator.CreateInstance(GetAnalyzerImplType(), Descriptor); analyzer.InitializeWorker(context); } diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs index 98d5127490517..f536a4bc11997 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs @@ -82,10 +82,9 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace work } var location = Location.Create(tree, change.Span); - context.ReportDiagnostic(DiagnosticHelper.Create( + context.ReportDiagnostic(Diagnostic.Create( _descriptor, location, - ReportDiagnostic.Default, additionalLocations: null, properties: null)); } diff --git a/src/Workspaces/Core/Portable/Formatting/Formatter.cs b/src/Workspaces/Core/Portable/Formatting/Formatter.cs index 3fd8709197113..8d88a6553819d 100644 --- a/src/Workspaces/Core/Portable/Formatting/Formatter.cs +++ b/src/Workspaces/Core/Portable/Formatting/Formatter.cs @@ -159,7 +159,13 @@ internal static async Task FormatAsync(Document document, SyntaxAnnota /// An optional cancellation token. /// The formatted tree's root node. public static SyntaxNode Format(SyntaxNode node, SyntaxAnnotation annotation, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => FormatAsync(node, annotation, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = FormatAsync(node, annotation, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task FormatAsync(SyntaxNode node, SyntaxAnnotation annotation, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => FormatAsync(node, annotation, workspace, options, rules: null, cancellationToken: cancellationToken); @@ -197,7 +203,13 @@ internal static Task FormatAsync(SyntaxNode node, SyntaxAnnotation a /// An optional cancellation token. /// The formatted tree's root node. public static SyntaxNode Format(SyntaxNode node, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => FormatAsync(node, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = FormatAsync(node, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task FormatAsync(SyntaxNode node, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => FormatAsync(node, SpecializedCollections.SingletonEnumerable(node.FullSpan), workspace, options, rules: null, cancellationToken: cancellationToken); @@ -212,7 +224,13 @@ internal static Task FormatAsync(SyntaxNode node, Workspace workspac /// An optional cancellation token. /// The formatted tree's root node. public static SyntaxNode Format(SyntaxNode node, TextSpan span, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => FormatAsync(node, span, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = FormatAsync(node, span, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task FormatAsync(SyntaxNode node, TextSpan span, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => FormatAsync(node, SpecializedCollections.SingletonEnumerable(span), workspace, options, rules: null, cancellationToken: cancellationToken); @@ -227,13 +245,25 @@ internal static Task FormatAsync(SyntaxNode node, TextSpan span, Wor /// An optional cancellation token. /// The formatted tree's root node. public static SyntaxNode Format(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => FormatAsync(node, spans, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = FormatAsync(node, spans, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task FormatAsync(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => FormatAsync(node, spans, workspace, options, rules: null, cancellationToken: cancellationToken); internal static SyntaxNode Format(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options, IEnumerable rules, CancellationToken cancellationToken) - => FormatAsync(node, spans, workspace, options, rules, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = FormatAsync(node, spans, workspace, options, rules, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static async Task FormatAsync(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options, IEnumerable rules, CancellationToken cancellationToken) { @@ -303,7 +333,13 @@ internal static Task> GetFormattedTextChangesAsync(SyntaxNode /// An optional cancellation token. /// The changes necessary to format the tree. public static IList GetFormattedTextChanges(SyntaxNode node, TextSpan span, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => GetFormattedTextChangesAsync(node, span, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = GetFormattedTextChangesAsync(node, span, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task> GetFormattedTextChangesAsync(SyntaxNode node, TextSpan span, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => GetFormattedTextChangesAsync(node, SpecializedCollections.SingletonEnumerable(span), workspace, options, rules: null, cancellationToken: cancellationToken); @@ -318,13 +354,25 @@ internal static Task> GetFormattedTextChangesAsync(SyntaxNode /// An optional cancellation token. /// The changes necessary to format the tree. public static IList GetFormattedTextChanges(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) - => GetFormattedTextChangesAsync(node, spans, workspace, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = GetFormattedTextChangesAsync(node, spans, workspace, options, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } internal static Task> GetFormattedTextChangesAsync(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options = null, CancellationToken cancellationToken = default) => GetFormattedTextChangesAsync(node, spans, workspace, options, rules: null, cancellationToken: cancellationToken); internal static IList GetFormattedTextChanges(SyntaxNode node, IEnumerable spans, Workspace workspace, OptionSet options, IEnumerable rules, CancellationToken cancellationToken) - => GetFormattedTextChangesAsync(node, spans, workspace, options, rules, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); + { + options = options ?? workspace.Options; + options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); + var resultTask = GetFormattedTextChangesAsync(node, spans, workspace, options, rules, cancellationToken); + Debug.Assert(resultTask.IsCompleted); + return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); + } private static IEnumerable GetAnnotatedSpans(SyntaxNode node, SyntaxAnnotation annotation) { From dc1bfbafb2b55237c2cda69d0d0460c3a9aa784a Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 4 Oct 2018 09:23:41 -0500 Subject: [PATCH 14/25] Disable VerifyAllSymbolEndActionsExecuted See #30309 --- .../Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs | 2 -- .../AnalyzerManager.AnalyzerExecutionContext.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs index adebac6893588..f8ac1ef9be714 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs @@ -436,13 +436,11 @@ private async Task ExecutePrimaryAnalysisTaskAsync(AnalysisScope analysisScope, await ProcessCompilationEventsAsync(analysisScope, analysisStateOpt, usingPrePopulatedEventQueue, cancellationToken).ConfigureAwait(false); -#if DEBUG // If not using pre-populated event queue (batch mode), then verify all symbol end actions were processed. if (!usingPrePopulatedEventQueue) { AnalyzerManager.VerifyAllSymbolEndActionsExecuted(); } -#endif } } diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs index fcbaa362fb8f2..8ba38149cf0fa 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs @@ -339,7 +339,7 @@ private void MarkSymbolEndAnalysisPending_NoLock(ISymbol symbol, ImmutableArray< _lazyPendingSymbolEndActionsOpt[symbol] = (symbolEndActions, symbolDeclaredEvent); } - [Conditional("DEBUG")] + [Conditional("DEBUG_ISSUE_30309")] public void VerifyAllSymbolEndActionsExecuted() { lock (_gate) From e05b2d56a5ca605ac26f208a9871089fcea17910 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 8 Oct 2018 20:26:32 -0500 Subject: [PATCH 15/25] Share code in implementation of AbstractCodeStyleDiagnosticAnalyzer --- .../AbstractCodeStyleDiagnosticAnalyzer.cs | 9 +- .../Core/Analyzers/DiagnosticCategory.cs | 9 ++ .../Microsoft.CodeAnalysis.CodeStyle.csproj | 3 + .../CSharpAddBracesDiagnosticAnalyzer.cs | 2 +- .../CSharpTypeStyleDiagnosticAnalyzerBase.cs | 2 +- ...harpInlineDeclarationDiagnosticAnalyzer.cs | 2 +- ...keDelegateWithConditionalAccessAnalyzer.cs | 2 +- ...RemoveUnreachableCodeDiagnosticAnalyzer.cs | 2 +- ...harpUseDeconstructionDiagnosticAnalyzer.cs | 2 +- ...harpUseDefaultLiteralDiagnosticAnalyzer.cs | 2 +- .../UseExpressionBodyDiagnosticAnalyzer.cs | 2 +- ...pressionBodyForLambdaDiagnosticAnalyzer.cs | 2 +- ...stAndEqualityOperatorDiagnosticAnalyzer.cs | 2 +- ...SharpUseLocalFunctionDiagnosticAnalyzer.cs | 2 +- .../CSharpAsAndNullCheckDiagnosticAnalyzer.cs | 2 +- .../CSharpIsAndCastCheckDiagnosticAnalyzer.cs | 2 +- ...dCastCheckWithoutNameDiagnosticAnalyzer.cs | 2 +- .../AbstractParenthesesDiagnosticAnalyzer.cs | 2 +- ...ccessibilityModifiersDiagnosticAnalyzer.cs | 2 +- ...tractBuiltInCodeStyleDiagnosticAnalyzer.cs | 20 ++++ .../AbstractCodeStyleDiagnosticAnalyzer.cs | 107 ------------------ ...tAnonymousTypeToTupleDiagnosticAnalyzer.cs | 2 +- .../NamingStyleDiagnosticAnalyzerBase.cs | 2 +- ...veUnnecessaryCastDiagnosticAnalyzerBase.cs | 2 +- ...tractEmbeddedLanguageDiagnosticAnalyzer.cs | 4 +- .../IEmbeddedLanguageFeatures.cs | 2 +- .../RegexDiagnosticAnalyzer.cs | 2 +- .../RegexEmbeddedLanguageFeatures.cs | 2 +- .../FormattingDiagnosticAnalyzer.cs | 2 +- .../MakeFieldReadonlyDiagnosticAnalyzer.cs | 2 +- .../Microsoft.CodeAnalysis.Features.csproj | 1 + ...bstractOrderModifiersDiagnosticAnalyzer.cs | 2 +- .../PopulateSwitchDiagnosticAnalyzer.cs | 2 +- ...eferFrameworkTypeDiagnosticAnalyzerBase.cs | 2 +- ...ctQualifyMemberAccessDiagnosticAnalyzer.cs | 2 +- ...tractSimplifyThisOrMeDiagnosticAnalyzer.cs | 2 +- .../AbstractUseAutoPropertyAnalyzer.cs | 2 +- ...UseCoalesceExpressionDiagnosticAnalyzer.cs | 2 +- ...ExpressionForNullableDiagnosticAnalyzer.cs | 2 +- ...CollectionInitializerDiagnosticAnalyzer.cs | 2 +- ...ConditionalExpressionDiagnosticAnalyzer.cs | 2 +- .../UseExplicitTupleNameDiagnosticAnalyzer.cs | 2 +- ...UseInferredMemberNameDiagnosticAnalyzer.cs | 2 +- ...ullForReferenceEqualsDiagnosticAnalyzer.cs | 2 +- ...actUseNullPropagationDiagnosticAnalyzer.cs | 2 +- ...tUseObjectInitializerDiagnosticAnalyzer.cs | 2 +- ...actUseThrowExpressionDiagnosticAnalyzer.cs | 2 +- 47 files changed, 78 insertions(+), 155 deletions(-) create mode 100644 src/CodeStyle/Core/Analyzers/DiagnosticCategory.cs create mode 100644 src/Features/Core/Portable/CodeStyle/AbstractBuiltInCodeStyleDiagnosticAnalyzer.cs delete mode 100644 src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs diff --git a/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs b/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs index 2e75356691068..802af3845b315 100644 --- a/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs +++ b/src/CodeStyle/Core/Analyzers/AbstractCodeStyleDiagnosticAnalyzer.cs @@ -62,12 +62,9 @@ protected DiagnosticDescriptor CreateUnnecessaryDescriptor() protected DiagnosticDescriptor CreateUnnecessaryDescriptor(string descriptorId) => CreateDescriptorWithId( descriptorId, _localizableTitle, _localizableMessageFormat, - WellKnownDiagnosticTags.Unnecessary, WellKnownDiagnosticTags.Telemetry); + DiagnosticCustomTags.Unnecessary); - public override ImmutableArray SupportedDiagnostics - { - get; - } + public override ImmutableArray SupportedDiagnostics { get; } protected DiagnosticDescriptor CreateDescriptor(params string[] customTags) => CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, customTags); @@ -86,7 +83,7 @@ protected DiagnosticDescriptor CreateDescriptorWithId( return new DiagnosticDescriptor( id, title, messageFormat, - CodeStyleResources.Style, + DiagnosticCategory.Style, DiagnosticSeverity.Hidden, isEnabledByDefault: true, customTags: customTags); diff --git a/src/CodeStyle/Core/Analyzers/DiagnosticCategory.cs b/src/CodeStyle/Core/Analyzers/DiagnosticCategory.cs new file mode 100644 index 0000000000000..febeb5f4af02f --- /dev/null +++ b/src/CodeStyle/Core/Analyzers/DiagnosticCategory.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal static class DiagnosticCategory + { + public static readonly string Style = CodeStyleResources.Style; + } +} diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj index e1ab823c31256..580a9301d9ced 100644 --- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj +++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj @@ -23,6 +23,9 @@ + + + True diff --git a/src/Features/CSharp/Portable/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs index 9fc2b42e9bc5a..797a7db6eca68 100644 --- a/src/Features/CSharp/Portable/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.AddBraces { [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class CSharpAddBracesDiagnosticAnalyzer : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer { public CSharpAddBracesDiagnosticAnalyzer() : base(IDEDiagnosticIds.AddBracesDiagnosticId, diff --git a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpTypeStyleDiagnosticAnalyzerBase.cs b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpTypeStyleDiagnosticAnalyzerBase.cs index 6157dabd9daa7..86cae3c108020 100644 --- a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpTypeStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpTypeStyleDiagnosticAnalyzerBase.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle { internal abstract partial class CSharpTypeStyleDiagnosticAnalyzerBase : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer { protected abstract CSharpTypeStyleHelper Helper { get; } diff --git a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs index dce3d8c4466e4..76bf38872e2b4 100644 --- a/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs @@ -26,7 +26,7 @@ namespace Microsoft.CodeAnalysis.CSharp.InlineDeclaration /// /// [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpInlineDeclarationDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpInlineDeclarationDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private const string CS0165 = nameof(CS0165); // Use of unassigned local variable 's' diff --git a/src/Features/CSharp/Portable/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs b/src/Features/CSharp/Portable/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs index 3625ebf1f2aeb..de88cb4a07612 100644 --- a/src/Features/CSharp/Portable/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs +++ b/src/Features/CSharp/Portable/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs @@ -18,7 +18,7 @@ internal static class Constants } [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class InvokeDelegateWithConditionalAccessAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class InvokeDelegateWithConditionalAccessAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public InvokeDelegateWithConditionalAccessAnalyzer() : base(IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId, diff --git a/src/Features/CSharp/Portable/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs index bb1ca3206d873..aeec3629a0a67 100644 --- a/src/Features/CSharp/Portable/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.CSharp.RemoveUnreachableCode { [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpRemoveUnreachableCodeDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpRemoveUnreachableCodeDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private const string CS0162 = nameof(CS0162); // Unreachable code detected diff --git a/src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs index 78fbbf6491ec4..c3adaad05d2cc 100644 --- a/src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseDeconstruction { [DiagnosticAnalyzer(LanguageNames.CSharp), Shared] - internal class CSharpUseDeconstructionDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpUseDeconstructionDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public CSharpUseDeconstructionDiagnosticAnalyzer() : base(IDEDiagnosticIds.UseDeconstructionDiagnosticId, diff --git a/src/Features/CSharp/Portable/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs index f0871e9eb677a..0bbd83ae0fa39 100644 --- a/src/Features/CSharp/Portable/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseDefaultLiteral { [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpUseDefaultLiteralDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpUseDefaultLiteralDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public CSharpUseDefaultLiteralDiagnosticAnalyzer() : base(IDEDiagnosticIds.UseDefaultLiteralDiagnosticId, diff --git a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs index 29de2121b21e8..e17fdf640f05a 100644 --- a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody { [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class UseExpressionBodyDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class UseExpressionBodyDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public const string FixesError = nameof(FixesError); diff --git a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaDiagnosticAnalyzer.cs index d915d6678b3f3..ca73906f90c7c 100644 --- a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaDiagnosticAnalyzer.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBodyForLambda using static UseExpressionBodyForLambdaHelpers; [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal sealed class UseExpressionBodyForLambdaDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal sealed class UseExpressionBodyForLambdaDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public const string FixesError = nameof(FixesError); diff --git a/src/Features/CSharp/Portable/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs index 1b4e4a0b029dd..8ed3ef23c7a30 100644 --- a/src/Features/CSharp/Portable/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseIsNullCheck { [DiagnosticAnalyzer(LanguageNames.CSharp)] internal class CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private static readonly ImmutableDictionary s_properties = ImmutableDictionary.Empty.Add(UseIsNullConstants.Kind, UseIsNullConstants.CastAndEqualityKey); diff --git a/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs index 8e11b63c363d8..1ba7f6d8b8be5 100644 --- a/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs @@ -38,7 +38,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseLocalFunction /// } /// [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpUseLocalFunctionDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpUseLocalFunctionDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public override bool OpenFileOnly(Workspace workspace) => false; diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs index 3815986ec1672..5ba85f77a90d3 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs @@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching /// /// [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal partial class CSharpAsAndNullCheckDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal partial class CSharpAsAndNullCheckDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public override bool OpenFileOnly(Workspace workspace) => false; diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs index c8fd608b5e3c6..73efa32fd9f1d 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs @@ -27,7 +27,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching /// } /// [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpIsAndCastCheckDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpIsAndCastCheckDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public static readonly CSharpIsAndCastCheckDiagnosticAnalyzer Instance = new CSharpIsAndCastCheckDiagnosticAnalyzer(); diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs index 1549a165003d2..86dc64ee41219 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs @@ -30,7 +30,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching // we will re-enable it once the issue is addressed. // https://devdiv.visualstudio.com/DevDiv/_workitems?id=504089&_a=edit&triage=true // [DiagnosticAnalyzer(LanguageNames.CSharp), Shared] - internal class CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private const string CS0165 = nameof(CS0165); // Use of unassigned local variable 's' private static readonly SyntaxAnnotation s_referenceAnnotation = new SyntaxAnnotation(); diff --git a/src/Features/Core/Portable/AbstractParenthesesDiagnosticAnalyzer.cs b/src/Features/Core/Portable/AbstractParenthesesDiagnosticAnalyzer.cs index 6ef0f7bbebca0..f296f59b2adb0 100644 --- a/src/Features/Core/Portable/AbstractParenthesesDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/AbstractParenthesesDiagnosticAnalyzer.cs @@ -6,7 +6,7 @@ namespace Microsoft.CodeAnalysis.RemoveUnnecessaryParentheses { - internal abstract class AbstractParenthesesDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal abstract class AbstractParenthesesDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { protected AbstractParenthesesDiagnosticAnalyzer( string descriptorId, LocalizableString title, LocalizableString message) diff --git a/src/Features/Core/Portable/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs b/src/Features/Core/Portable/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs index 48f0ab95074d6..b1ec01e1ff8b9 100644 --- a/src/Features/Core/Portable/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.AddAccessibilityModifiers { internal abstract class AbstractAddAccessibilityModifiersDiagnosticAnalyzer - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TCompilationUnitSyntax : SyntaxNode { protected AbstractAddAccessibilityModifiersDiagnosticAnalyzer() diff --git a/src/Features/Core/Portable/CodeStyle/AbstractBuiltInCodeStyleDiagnosticAnalyzer.cs b/src/Features/Core/Portable/CodeStyle/AbstractBuiltInCodeStyleDiagnosticAnalyzer.cs new file mode 100644 index 0000000000000..66c1a8472e141 --- /dev/null +++ b/src/Features/Core/Portable/CodeStyle/AbstractBuiltInCodeStyleDiagnosticAnalyzer.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + internal abstract class AbstractBuiltInCodeStyleDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer + { + protected AbstractBuiltInCodeStyleDiagnosticAnalyzer( + string descriptorId, LocalizableString title, + LocalizableString messageFormat = null, + bool configurable = true) + : base(descriptorId, title, messageFormat, configurable) + { + } + + public abstract DiagnosticAnalyzerCategory GetAnalyzerCategory(); + public abstract bool OpenFileOnly(Workspace workspace); + } +} diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs deleted file mode 100644 index 1e176056b6119..0000000000000 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleDiagnosticAnalyzer.cs +++ /dev/null @@ -1,107 +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; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis.Diagnostics; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.CodeStyle -{ - internal abstract class AbstractCodeStyleDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer - { - protected readonly string DescriptorId; - - protected readonly DiagnosticDescriptor Descriptor; - - /// - /// Diagnostic descriptor for code you want to fade out *and* want to have a smart-tag - /// appear for. This is the common descriptor for code that is being faded out - /// - protected readonly DiagnosticDescriptor UnnecessaryWithSuggestionDescriptor; - - /// - /// Diagnostic descriptor for code you want to fade out and do *not* want to have a smart-tag - /// appear for. This is uncommon but useful in some cases. For example, if you are fading - /// out pieces of code before/after another piece of code *on the same line*, then you will - /// only want one usage of and multiple - /// usages of . - /// - /// That's because if you use for all the - /// faded out code then that will mean the user will see multiple code actions to fix the - /// same issue when they bring up the code action on that line. Using these two descriptors - /// helps ensure that there will not be useless code-action overload. - /// - protected readonly DiagnosticDescriptor UnnecessaryWithoutSuggestionDescriptor; - - protected readonly LocalizableString _localizableTitle; - protected readonly LocalizableString _localizableMessageFormat; - - private readonly bool _configurable; - - protected AbstractCodeStyleDiagnosticAnalyzer( - string descriptorId, LocalizableString title, - LocalizableString messageFormat = null, - bool configurable = true) - { - DescriptorId = descriptorId; - _localizableTitle = title; - _localizableMessageFormat = messageFormat ?? title; - _configurable = configurable; - - Descriptor = CreateDescriptor(); - UnnecessaryWithSuggestionDescriptor = CreateUnnecessaryDescriptor(); - UnnecessaryWithoutSuggestionDescriptor = CreateUnnecessaryDescriptor(descriptorId + "WithoutSuggestion"); - - SupportedDiagnostics = ImmutableArray.Create( - Descriptor, UnnecessaryWithoutSuggestionDescriptor, UnnecessaryWithSuggestionDescriptor); - } - - protected DiagnosticDescriptor CreateUnnecessaryDescriptor() - => CreateUnnecessaryDescriptor(DescriptorId); - - protected DiagnosticDescriptor CreateUnnecessaryDescriptor(string descriptorId) - => CreateDescriptorWithId( - descriptorId, _localizableTitle, _localizableMessageFormat, - DiagnosticCustomTags.Unnecessary); - - public override ImmutableArray SupportedDiagnostics { get; } - - protected DiagnosticDescriptor CreateDescriptor(params string[] customTags) - => CreateDescriptorWithId(DescriptorId, _localizableTitle, _localizableMessageFormat, customTags); - - protected DiagnosticDescriptor CreateDescriptorWithTitle(LocalizableString title, params string[] customTags) - => CreateDescriptorWithId(DescriptorId, title, title, customTags); - - protected DiagnosticDescriptor CreateDescriptorWithId( - string id, LocalizableString title, LocalizableString messageFormat, - params string[] customTags) - { - if (!_configurable) - { - customTags = customTags.Concat(WellKnownDiagnosticTags.NotConfigurable).ToArray(); - } - - return new DiagnosticDescriptor( - id, title, messageFormat, - DiagnosticCategory.Style, - DiagnosticSeverity.Hidden, - isEnabledByDefault: true, - customTags: customTags); - } - - public sealed override void Initialize(AnalysisContext context) - { - // Code style analyzers should not run on generated code. - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - context.EnableConcurrentExecution(); - - InitializeWorker(context); - } - - protected abstract void InitializeWorker(AnalysisContext context); - - public abstract DiagnosticAnalyzerCategory GetAnalyzerCategory(); - public abstract bool OpenFileOnly(Workspace workspace); - } -} diff --git a/src/Features/Core/Portable/ConvertAnonymousTypeToTuple/AbstractConvertAnonymousTypeToTupleDiagnosticAnalyzer.cs b/src/Features/Core/Portable/ConvertAnonymousTypeToTuple/AbstractConvertAnonymousTypeToTupleDiagnosticAnalyzer.cs index 34697e8462905..d064d2211b074 100644 --- a/src/Features/Core/Portable/ConvertAnonymousTypeToTuple/AbstractConvertAnonymousTypeToTupleDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/ConvertAnonymousTypeToTuple/AbstractConvertAnonymousTypeToTupleDiagnosticAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.ConvertAnonymousTypeToTuple internal abstract class AbstractConvertAnonymousTypeToTupleDiagnosticAnalyzer< TSyntaxKind, TAnonymousObjectCreationExpressionSyntax> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TAnonymousObjectCreationExpressionSyntax : SyntaxNode { diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs index c4f8c28c8510f..ec6327d450db0 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { internal abstract class NamingStyleDiagnosticAnalyzerBase : - AbstractCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct + AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct { private static readonly LocalizableString s_localizableMessageFormat = new LocalizableResourceString(nameof(FeaturesResources.Naming_rule_violation_0), FeaturesResources.ResourceManager, typeof(FeaturesResources)); private static readonly LocalizableString s_localizableTitleNamingStyle = new LocalizableResourceString(nameof(FeaturesResources.Naming_Styles), FeaturesResources.ResourceManager, typeof(FeaturesResources)); diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs index 6704628018463..35c5aee4db5a5 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.RemoveUnnecessaryCast { internal abstract class RemoveUnnecessaryCastDiagnosticAnalyzerBase< TLanguageKindEnum, - TCastExpression> : AbstractCodeStyleDiagnosticAnalyzer + TCastExpression> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TCastExpression : SyntaxNode { diff --git a/src/Features/Core/Portable/EmbeddedLanguages/AbstractEmbeddedLanguageDiagnosticAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/AbstractEmbeddedLanguageDiagnosticAnalyzer.cs index 07f7a9fcf7c9c..47f820797cac1 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/AbstractEmbeddedLanguageDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/AbstractEmbeddedLanguageDiagnosticAnalyzer.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages { internal abstract class AbstractEmbeddedLanguageDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer { - private readonly ImmutableArray _analyzers; + private readonly ImmutableArray _analyzers; private readonly DiagnosticAnalyzerCategory _category; public override ImmutableArray SupportedDiagnostics { get; } @@ -22,7 +22,7 @@ protected AbstractEmbeddedLanguageDiagnosticAnalyzer( { var supportedDiagnostics = ArrayBuilder.GetInstance(); - var analyzers = ArrayBuilder.GetInstance(); + var analyzers = ArrayBuilder.GetInstance(); var category = default(DiagnosticAnalyzerCategory?); Debug.Assert(languagesProvider.Languages.Length > 0); diff --git a/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs b/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs index 6f5b318a39a59..4b5793af00ba5 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs @@ -21,6 +21,6 @@ internal interface IEmbeddedLanguageFeatures : IEmbeddedLanguage /// /// An optional analyzer that produces diagnostics for an embedded language string. /// - AbstractCodeStyleDiagnosticAnalyzer DiagnosticAnalyzer { get; } + AbstractBuiltInCodeStyleDiagnosticAnalyzer DiagnosticAnalyzer { get; } } } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexDiagnosticAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexDiagnosticAnalyzer.cs index 9e1f724560240..2fbe087686174 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexDiagnosticAnalyzer.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions /// /// Analyzer that reports diagnostics in strings that we know are regex text. /// - internal sealed class RegexDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal sealed class RegexDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public const string DiagnosticId = "RE0001"; diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexEmbeddedLanguageFeatures.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexEmbeddedLanguageFeatures.cs index 6f51d1e12f811..1a3bb43ce329a 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexEmbeddedLanguageFeatures.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexEmbeddedLanguageFeatures.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions internal class RegexEmbeddedLanguageFeatures : RegexEmbeddedLanguage, IEmbeddedLanguageFeatures { public IDocumentHighlightsService DocumentHighlightsService { get; } - public AbstractCodeStyleDiagnosticAnalyzer DiagnosticAnalyzer { get; } + public AbstractBuiltInCodeStyleDiagnosticAnalyzer DiagnosticAnalyzer { get; } public RegexEmbeddedLanguageFeatures(EmbeddedLanguageInfo info) : base(info) { diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs index 217c53270becc..66682d10c5ab5 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.Formatting { [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] internal class FormattingDiagnosticAnalyzer - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public FormattingDiagnosticAnalyzer() : base( diff --git a/src/Features/Core/Portable/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs b/src/Features/Core/Portable/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs index 5b50c4a57f820..6e2b3f631272a 100644 --- a/src/Features/Core/Portable/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.MakeFieldReadonly { [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] internal sealed class MakeFieldReadonlyDiagnosticAnalyzer - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public MakeFieldReadonlyDiagnosticAnalyzer() : base( diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index c879b52d9f723..8dd669c7c340e 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -96,6 +96,7 @@ + Shared\Utilities\DesktopShim.cs diff --git a/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs b/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs index 9a003a6888169..84d0f7d541d0e 100644 --- a/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.OrderModifiers { - internal abstract class AbstractOrderModifiersDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal abstract class AbstractOrderModifiersDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private readonly ISyntaxFactsService _syntaxFacts; private readonly Option> _option; diff --git a/src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs b/src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs index 291de778c530a..8e941a0350081 100644 --- a/src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.PopulateSwitch { [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] internal sealed class PopulateSwitchDiagnosticAnalyzer : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer { private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(FeaturesResources.Add_missing_cases), FeaturesResources.ResourceManager, typeof(FeaturesResources)); private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(WorkspacesResources.Populate_switch), WorkspacesResources.ResourceManager, typeof(WorkspacesResources)); diff --git a/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs index b208be1d2ef15..55f7c872a960e 100644 --- a/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.PreferFrameworkType { internal abstract class PreferFrameworkTypeDiagnosticAnalyzerBase : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TPredefinedTypeSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs b/src/Features/Core/Portable/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs index c610cf9208ea1..f3cfc60f9f511 100644 --- a/src/Features/Core/Portable/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs @@ -12,7 +12,7 @@ internal abstract class AbstractQualifyMemberAccessDiagnosticAnalyzer< TLanguageKindEnum, TExpressionSyntax, TSimpleNameSyntax> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TSimpleNameSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs index ba6ec9510d49f..d40878304a95e 100644 --- a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs @@ -17,7 +17,7 @@ internal abstract class AbstractSimplifyThisOrMeDiagnosticAnalyzer< TExpressionSyntax, TThisExpressionSyntax, TMemberAccessExpressionSyntax> : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TThisExpressionSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs b/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs index 23f57d9f05fa3..6a18f6b187a61 100644 --- a/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs +++ b/src/Features/Core/Portable/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.UseAutoProperty { internal abstract class AbstractUseAutoPropertyAnalyzer< - TPropertyDeclaration, TFieldDeclaration, TVariableDeclarator, TExpression> : AbstractCodeStyleDiagnosticAnalyzer + TPropertyDeclaration, TFieldDeclaration, TVariableDeclarator, TExpression> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TPropertyDeclaration : SyntaxNode where TFieldDeclaration : SyntaxNode where TVariableDeclarator : SyntaxNode diff --git a/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs index be2037018d999..6be17fa7dab53 100644 --- a/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs @@ -14,7 +14,7 @@ internal abstract class AbstractUseCoalesceExpressionDiagnosticAnalyzer< TSyntaxKind, TExpressionSyntax, TConditionalExpressionSyntax, - TBinaryExpressionSyntax> : AbstractCodeStyleDiagnosticAnalyzer + TBinaryExpressionSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TConditionalExpressionSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs index ad395f516eaab..1ffa4c82830ea 100644 --- a/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs @@ -14,7 +14,7 @@ internal abstract class AbstractUseCoalesceExpressionForNullableDiagnosticAnalyz TConditionalExpressionSyntax, TBinaryExpressionSyntax, TMemberAccessExpression, - TPrefixUnaryExpressionSyntax> : AbstractCodeStyleDiagnosticAnalyzer + TPrefixUnaryExpressionSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TConditionalExpressionSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs index 2342235c76b67..ae518cc01f125 100644 --- a/src/Features/Core/Portable/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs @@ -20,7 +20,7 @@ internal abstract partial class AbstractUseCollectionInitializerDiagnosticAnalyz TInvocationExpressionSyntax, TExpressionStatementSyntax, TVariableDeclaratorSyntax> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TStatementSyntax : SyntaxNode diff --git a/src/Features/Core/Portable/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs index 6d0c2ff1faebc..cb2e66b6aed49 100644 --- a/src/Features/Core/Portable/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.UseConditionalExpression { internal abstract class AbstractUseConditionalExpressionDiagnosticAnalyzer< TIfStatementSyntax> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TIfStatementSyntax : SyntaxNode { private readonly PerLanguageOption> _option; diff --git a/src/Features/Core/Portable/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs index 79a82b7aee86f..c4d446a172b14 100644 --- a/src/Features/Core/Portable/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.UseExplicitTupleName { [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] - internal class UseExplicitTupleNameDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal class UseExplicitTupleNameDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { public const string ElementName = nameof(ElementName); diff --git a/src/Features/Core/Portable/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs index 850b3d0523c31..31d25275c615f 100644 --- a/src/Features/Core/Portable/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs @@ -6,7 +6,7 @@ namespace Microsoft.CodeAnalysis.UseInferredMemberName { - internal abstract class AbstractUseInferredMemberNameDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer + internal abstract class AbstractUseInferredMemberNameDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { abstract protected void LanguageSpecificAnalyzeSyntax(SyntaxNodeAnalysisContext context, SyntaxTree syntaxTree, OptionSet optionSet); diff --git a/src/Features/Core/Portable/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs index 5028e4eed37d9..27d08def4ac4b 100644 --- a/src/Features/Core/Portable/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.UseIsNullCheck { internal abstract class AbstractUseIsNullCheckForReferenceEqualsDiagnosticAnalyzer< TLanguageKindEnum> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct { protected AbstractUseIsNullCheckForReferenceEqualsDiagnosticAnalyzer(LocalizableString title) diff --git a/src/Features/Core/Portable/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs index 92bf0042cf6cd..1a83f340d5ad2 100644 --- a/src/Features/Core/Portable/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs @@ -22,7 +22,7 @@ internal abstract class AbstractUseNullPropagationDiagnosticAnalyzer< TInvocationExpression, TMemberAccessExpression, TConditionalAccessExpression, - TElementAccessExpression> : AbstractCodeStyleDiagnosticAnalyzer + TElementAccessExpression> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TConditionalExpressionSyntax : TExpressionSyntax diff --git a/src/Features/Core/Portable/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs index f5f620352b6f3..01de989309201 100644 --- a/src/Features/Core/Portable/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs @@ -18,7 +18,7 @@ internal abstract partial class AbstractUseObjectInitializerDiagnosticAnalyzer< TMemberAccessExpressionSyntax, TAssignmentStatementSyntax, TVariableDeclaratorSyntax> - : AbstractCodeStyleDiagnosticAnalyzer + : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TSyntaxKind : struct where TExpressionSyntax : SyntaxNode where TStatementSyntax : SyntaxNode diff --git a/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs index 8703e5d2cc4b0..9802db8d63de5 100644 --- a/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs @@ -33,7 +33,7 @@ namespace Microsoft.CodeAnalysis.UseThrowExpression /// expressions as well. /// internal abstract class AbstractUseThrowExpressionDiagnosticAnalyzer : - AbstractCodeStyleDiagnosticAnalyzer + AbstractBuiltInCodeStyleDiagnosticAnalyzer { protected AbstractUseThrowExpressionDiagnosticAnalyzer() : base(IDEDiagnosticIds.UseThrowExpressionDiagnosticId, From 9ce3c05a72516c17ed44e2464d19a1af80807b13 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 8 Oct 2018 20:28:50 -0500 Subject: [PATCH 16/25] Code cleanup from review feedback --- .../CodeFixes/EditorConfigOptionsApplier.cs | 4 +- .../Core/Analyzers/DiagnosticHelper.cs | 248 ------------------ .../Microsoft.CodeAnalysis.CodeStyle.csproj | 1 + .../CodeFixes/AbstractFormattingAnalyzer.cs | 4 +- .../CodeFixes/FormattingCodeFixProvider.cs | 9 +- 5 files changed, 11 insertions(+), 255 deletions(-) delete mode 100644 src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs diff --git a/src/CodeStyle/CSharp/CodeFixes/EditorConfigOptionsApplier.cs b/src/CodeStyle/CSharp/CodeFixes/EditorConfigOptionsApplier.cs index 77b9fd6c85322..83838233283ce 100644 --- a/src/CodeStyle/CSharp/CodeFixes/EditorConfigOptionsApplier.cs +++ b/src/CodeStyle/CSharp/CodeFixes/EditorConfigOptionsApplier.cs @@ -1,11 +1,11 @@ // 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.Options; -using Microsoft.VisualStudio.CodingConventions; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.CodingConventions; namespace Microsoft.CodeAnalysis.CodeStyle { diff --git a/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs b/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs deleted file mode 100644 index b8b959dfd98a5..0000000000000 --- a/src/CodeStyle/Core/Analyzers/DiagnosticHelper.cs +++ /dev/null @@ -1,248 +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; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; - -namespace Microsoft.CodeAnalysis.CodeStyle -{ - internal static class DiagnosticHelper - { - /// - /// Creates a instance. - /// - /// A describing the diagnostic. - /// An optional primary location of the diagnostic. If null, will return . - /// Effective severity of the diagnostic. - /// - /// An optional set of additional locations related to the diagnostic. - /// Typically, these are locations of other items referenced in the message. - /// If null, will return an empty list. - /// - /// - /// An optional set of name-value pairs by means of which the analyzer that creates the diagnostic - /// can convey more detailed information to the fixer. If null, will return - /// . - /// - /// Arguments to the message of the diagnostic. - /// The instance. - public static Diagnostic Create( - DiagnosticDescriptor descriptor, - Location location, - ReportDiagnostic effectiveSeverity, - IEnumerable additionalLocations, - ImmutableDictionary properties, - params object[] messageArgs) - { - if (descriptor == null) - { - throw new ArgumentNullException(nameof(descriptor)); - } - - LocalizableString message; - if (messageArgs == null || messageArgs.Length == 0) - { - message = descriptor.MessageFormat; - } - else - { - message = new LocalizableStringWithArguments(descriptor.MessageFormat, messageArgs); - } - - var warningLevel = effectiveSeverity.ToDiagnosticSeverity() ?? descriptor.DefaultSeverity; - return Diagnostic.Create( - descriptor.Id, - descriptor.Category, - message, - effectiveSeverity.ToDiagnosticSeverity() ?? descriptor.DefaultSeverity, - descriptor.DefaultSeverity, - descriptor.IsEnabledByDefault, - warningLevel: effectiveSeverity.WithDefaultSeverity(descriptor.DefaultSeverity) == ReportDiagnostic.Error ? 0 : 1, - effectiveSeverity == ReportDiagnostic.Suppress, - descriptor.Title, - descriptor.Description, - descriptor.HelpLinkUri, - location, - additionalLocations, - descriptor.CustomTags, - properties); - } - - /// - /// Returns the equivalent for a value. - /// - /// The value. - /// - /// The equivalent for a value; otherwise, - /// if does not contain a direct equivalent for - /// . - /// - /// - /// If is not one of the expected values. - /// - private static DiagnosticSeverity? ToDiagnosticSeverity(this ReportDiagnostic reportDiagnostic) - { - switch (reportDiagnostic) - { - case ReportDiagnostic.Error: - return DiagnosticSeverity.Error; - - case ReportDiagnostic.Warn: - return DiagnosticSeverity.Warning; - - case ReportDiagnostic.Info: - return DiagnosticSeverity.Info; - - case ReportDiagnostic.Hidden: - return DiagnosticSeverity.Hidden; - - case ReportDiagnostic.Suppress: - case ReportDiagnostic.Default: - return null; - - default: - var o = reportDiagnostic; - var output = $"Unexpected value '{o}' of type '{o.GetType().FullName}'"; - throw new InvalidOperationException(output); - } - } - - /// - /// Applies a default severity to a value. - /// - /// The value. - /// The default severity. - /// - /// If is , returns - /// . - /// -or- - /// Otherwise, returns if it has a non-default value. - /// - private static ReportDiagnostic WithDefaultSeverity(this ReportDiagnostic reportDiagnostic, DiagnosticSeverity defaultSeverity) - { - if (reportDiagnostic != ReportDiagnostic.Default) - { - return reportDiagnostic; - } - - return defaultSeverity.ToReportDiagnostic(); - } - - /// - /// Returns the equivalent for a value. - /// - /// The value. - /// - /// The equivalent for the value. - /// - /// - /// If is not one of the expected values. - /// - private static ReportDiagnostic ToReportDiagnostic(this DiagnosticSeverity diagnosticSeverity) - { - switch (diagnosticSeverity) - { - case DiagnosticSeverity.Hidden: - return ReportDiagnostic.Hidden; - - case DiagnosticSeverity.Info: - return ReportDiagnostic.Info; - - case DiagnosticSeverity.Warning: - return ReportDiagnostic.Warn; - - case DiagnosticSeverity.Error: - return ReportDiagnostic.Error; - - default: - var o = diagnosticSeverity; - var output = $"Unexpected value '{o}' of type '{o.GetType().FullName}'"; - throw new InvalidOperationException(output); - } - } - - public sealed class LocalizableStringWithArguments : LocalizableString - { - private readonly LocalizableString _messageFormat; - private readonly string[] _formatArguments; - - public LocalizableStringWithArguments(LocalizableString messageFormat, params object[] formatArguments) - { - if (messageFormat == null) - { - throw new ArgumentNullException(nameof(messageFormat)); - } - - if (formatArguments == null) - { - throw new ArgumentNullException(nameof(formatArguments)); - } - - _messageFormat = messageFormat; - _formatArguments = new string[formatArguments.Length]; - for (var i = 0; i < formatArguments.Length; i++) - { - _formatArguments[i] = $"{formatArguments[i]}"; - } - } - - protected override string GetText(IFormatProvider formatProvider) - { - var messageFormat = _messageFormat.ToString(formatProvider); - return messageFormat != null ? - (_formatArguments.Length > 0 ? string.Format(formatProvider, messageFormat, _formatArguments) : messageFormat) : - string.Empty; - } - - protected override bool AreEqual(object other) - { - var otherResourceString = other as LocalizableStringWithArguments; - return otherResourceString != null && - _messageFormat.Equals(otherResourceString._messageFormat) && - SequenceEqual(_formatArguments, otherResourceString._formatArguments, (a, b) => a == b); - } - - protected override int GetHash() - { - // TODO: include values in hash - return _messageFormat.GetHashCode(); - } - - // TODO: unify definitions - public static bool SequenceEqual(IEnumerable first, IEnumerable second, Func comparer) - { - Debug.Assert(comparer != null); - - if (first == second) - { - return true; - } - - if (first == null || second == null) - { - return false; - } - - using (var enumerator = first.GetEnumerator()) - using (var enumerator2 = second.GetEnumerator()) - { - while (enumerator.MoveNext()) - { - if (!enumerator2.MoveNext() || !comparer(enumerator.Current, enumerator2.Current)) - { - return false; - } - } - - if (enumerator2.MoveNext()) - { - return false; - } - } - - return true; - } - } - } -} diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj index 580a9301d9ced..25d74ea6f72d9 100644 --- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj +++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj @@ -24,6 +24,7 @@ + diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs index 97db0294a9551..98685ec0cc4a0 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -17,8 +17,6 @@ namespace Microsoft.CodeAnalysis.CodeStyle internal abstract class AbstractFormattingAnalyzer : AbstractCodeStyleDiagnosticAnalyzer { - internal const string FormattingDiagnosticId = "IDE0054"; - static AbstractFormattingAnalyzer() { AppDomain.CurrentDomain.AssemblyResolve += HandleAssemblyResolve; @@ -26,7 +24,7 @@ static AbstractFormattingAnalyzer() protected AbstractFormattingAnalyzer() : base( - FormattingDiagnosticId, + IDEDiagnosticIds.FormattingDiagnosticId, new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_title), CodeStyleResources.ResourceManager, typeof(CodeStyleResources)), new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_message), CodeStyleResources.ResourceManager, typeof(CodeStyleResources))) { diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index 9e32e87655ba2..6e4d5449cda6a 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Text; @@ -16,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CodeStyle internal class FormattingCodeFixProvider : CodeFixProvider { public override ImmutableArray FixableDiagnosticIds - => ImmutableArray.Create(AbstractFormattingAnalyzer.FormattingDiagnosticId); + => ImmutableArray.Create(IDEDiagnosticIds.FormattingDiagnosticId); public override FixAllProvider GetFixAllProvider() { @@ -50,11 +51,15 @@ protected async Task FixOneAsync(Document document, Diagnostic diagnos text.Lines[diagnosticLinePositionSpan.Start.Line].Start, text.Lines[diagnosticLinePositionSpan.End.Line].End); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); } + /// + /// Provide an optimized Fix All implementation that runs + /// on the document(s) + /// included in the Fix All scope. + /// private class FixAll : DocumentBasedFixAllProvider { protected override string CodeActionTitle => CodeStyleFixesResources.Formatting_analyzer_code_fix; From 1b402fb4043864be163804aeaedec8536ac84488 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 8 Oct 2018 20:49:45 -0500 Subject: [PATCH 17/25] Share code in FixAllContextHelper and FixAllContext.DiagnosticProvider --- .../CodeFixes/DocumentBasedFixAllProvider.cs | 4 +- .../Core/CodeFixes/FixAllContextHelper.cs | 52 +++---- ...rosoft.CodeAnalysis.CodeStyle.Fixes.csproj | 3 + .../FixAllContext.DiagnosticProvider.cs | 127 +----------------- .../Microsoft.CodeAnalysis.Workspaces.csproj | 1 + 5 files changed, 39 insertions(+), 148 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/DocumentBasedFixAllProvider.cs b/src/CodeStyle/Core/CodeFixes/DocumentBasedFixAllProvider.cs index c3c3f264d7265..c928ac25eeea8 100644 --- a/src/CodeStyle/Core/CodeFixes/DocumentBasedFixAllProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/DocumentBasedFixAllProvider.cs @@ -69,7 +69,7 @@ public override Task GetFixAsync(FixAllContext fixAllContext) private async Task GetDocumentFixesAsync(FixAllContext fixAllContext) { - var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false); + var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext, progressTrackerOpt: null, (document, cancellationToken) => false).ConfigureAwait(false); if (!documentDiagnosticsToFix.TryGetValue(fixAllContext.Document, out var diagnostics)) { return fixAllContext.Document; @@ -86,7 +86,7 @@ private async Task GetDocumentFixesAsync(FixAllContext fixAllContext) private async Task GetSolutionFixesAsync(FixAllContext fixAllContext, ImmutableArray documents) { - var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext).ConfigureAwait(false); + var documentDiagnosticsToFix = await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync(fixAllContext, progressTrackerOpt: null, (document, cancellationToken) => false).ConfigureAwait(false); var solution = fixAllContext.Solution; var newDocuments = new List>(documents.Length); diff --git a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs index ca89026b37e8d..0039ea6abb04c 100644 --- a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs @@ -1,18 +1,25 @@ // 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; using System.Collections.Concurrent; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.CodeStyle { internal static class FixAllContextHelper { - public static async Task>> GetDocumentDiagnosticsToFixAsync(FixAllContext fixAllContext) + public static async Task>> GetDocumentDiagnosticsToFixAsync( + FixAllContext fixAllContext, + IProgressTracker progressTrackerOpt, + Func isGeneratedCode) { + var cancellationToken = fixAllContext.CancellationToken; + var allDiagnostics = ImmutableArray.Empty; var projectsToFix = ImmutableArray.Empty; @@ -22,7 +29,7 @@ public static async Task>.Empty.SetItem(document, documentDiagnostics); @@ -32,7 +39,7 @@ public static async Task p.Language == project.Language) .ToImmutableArray(); - var diagnostics = new ConcurrentDictionary>(); + progressTrackerOpt?.AddItems(projectsToFix.Length); + + var diagnostics = new ConcurrentBag(); var tasks = new Task[projectsToFix.Length]; for (var i = 0; i < projectsToFix.Length; i++) { - fixAllContext.CancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); var projectToFix = projectsToFix[i]; - tasks[i] = Task.Run( - async () => + tasks[i] = Task.Run(async () => + { + var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false); + foreach (var diagnostic in projectDiagnostics) { - var projectDiagnostics = await GetAllDiagnosticsAsync(fixAllContext, projectToFix).ConfigureAwait(false); - diagnostics.TryAdd(projectToFix.Id, projectDiagnostics); - }, fixAllContext.CancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + diagnostics.Add(diagnostic); + } + + progressTrackerOpt?.ItemCompleted(); + }, cancellationToken); } await Task.WhenAll(tasks).ConfigureAwait(false); - allDiagnostics = allDiagnostics.AddRange(diagnostics.SelectMany(i => i.Value.Where(x => fixAllContext.DiagnosticIds.Contains(x.Id)))); + allDiagnostics = allDiagnostics.AddRange(diagnostics); break; } @@ -64,20 +78,8 @@ public static async Task>.Empty; } - return await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false); - } - - /// - /// Gets all instances within a specific which are relevant to a - /// . - /// - /// The context for the Fix All operation. - /// The project. - /// A representing the asynchronous operation. When the task completes - /// successfully, the will contain the requested diagnostics. - private static async Task> GetAllDiagnosticsAsync(FixAllContext fixAllContext, Project project) - { - return await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false); + return await GetDocumentDiagnosticsToFixAsync( + allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false); } private static async Task>> GetDocumentDiagnosticsToFixAsync( diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 21fb840d96780..0363470f5a036 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -8,6 +8,9 @@ Microsoft.CodeAnalysis net46 + + + diff --git a/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllContext.DiagnosticProvider.cs b/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllContext.DiagnosticProvider.cs index 66e164a34f6e2..575aa06366a4f 100644 --- a/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllContext.DiagnosticProvider.cs +++ b/src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllContext.DiagnosticProvider.cs @@ -1,13 +1,11 @@ // 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; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.GeneratedCodeRecognition; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -54,129 +52,16 @@ internal async Task>> G internal virtual async Task>> GetDocumentDiagnosticsToFixWorkerAsync( FixAllContext fixAllContext) { - var cancellationToken = fixAllContext.CancellationToken; - using (Logger.LogBlock( FunctionId.CodeFixes_FixAllOccurrencesComputation_Document_Diagnostics, FixAllLogger.CreateCorrelationLogMessage(fixAllContext.State.CorrelationId), - cancellationToken)) - { - var allDiagnostics = ImmutableArray.Empty; - var projectsToFix = ImmutableArray.Empty; - - var document = fixAllContext.Document; - var project = fixAllContext.Project; - - switch (fixAllContext.Scope) - { - case FixAllScope.Document: - if (document != null && !document.IsGeneratedCode(cancellationToken)) - { - var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); - var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePairUtil.Create(document, documentDiagnostics)); - return ImmutableDictionary.CreateRange(kvp); - } - - break; - - case FixAllScope.Project: - projectsToFix = ImmutableArray.Create(project); - allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false); - break; - - case FixAllScope.Solution: - projectsToFix = project.Solution.Projects - .Where(p => p.Language == project.Language) - .ToImmutableArray(); - - var progressTracker = fixAllContext.ProgressTracker; - progressTracker.AddItems(projectsToFix.Length); - - var diagnostics = new ConcurrentBag(); - var tasks = new Task[projectsToFix.Length]; - for (int i = 0; i < projectsToFix.Length; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - var projectToFix = projectsToFix[i]; - tasks[i] = Task.Run(async () => - { - var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false); - foreach (var diagnostic in projectDiagnostics) - { - cancellationToken.ThrowIfCancellationRequested(); - diagnostics.Add(diagnostic); - } - - progressTracker.ItemCompleted(); - }, cancellationToken); - } - - await Task.WhenAll(tasks).ConfigureAwait(false); - allDiagnostics = allDiagnostics.AddRange(diagnostics); - break; - } - - if (allDiagnostics.IsEmpty) - { - return ImmutableDictionary>.Empty; - } - - return await GetDocumentDiagnosticsToFixAsync( - allDiagnostics, projectsToFix, fixAllContext.CancellationToken).ConfigureAwait(false); - } - } - - private async static Task>> GetDocumentDiagnosticsToFixAsync( - ImmutableArray diagnostics, - ImmutableArray projects, - CancellationToken cancellationToken) - { - var treeToDocumentMap = await GetTreeToDocumentMapAsync(projects, cancellationToken).ConfigureAwait(false); - - var builder = ImmutableDictionary.CreateBuilder>(); - foreach (var documentAndDiagnostics in diagnostics.GroupBy(d => GetReportedDocument(d, treeToDocumentMap))) - { - cancellationToken.ThrowIfCancellationRequested(); - var document = documentAndDiagnostics.Key; - if (!document.IsGeneratedCode(cancellationToken)) - { - var diagnosticsForDocument = documentAndDiagnostics.ToImmutableArray(); - builder.Add(document, diagnosticsForDocument); - } - } - - return builder.ToImmutable(); - } - - private static async Task> GetTreeToDocumentMapAsync(ImmutableArray projects, CancellationToken cancellationToken) - { - var builder = ImmutableDictionary.CreateBuilder(); - foreach (var project in projects) - { - cancellationToken.ThrowIfCancellationRequested(); - foreach (var document in project.Documents) - { - cancellationToken.ThrowIfCancellationRequested(); - var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - builder.Add(tree, document); - } - } - - return builder.ToImmutable(); - } - - private static Document GetReportedDocument(Diagnostic diagnostic, ImmutableDictionary treeToDocumentsMap) - { - var tree = diagnostic.Location.SourceTree; - if (tree != null) + fixAllContext.CancellationToken)) { - if (treeToDocumentsMap.TryGetValue(tree, out var document)) - { - return document; - } + return await FixAllContextHelper.GetDocumentDiagnosticsToFixAsync( + fixAllContext, + fixAllContext.ProgressTracker, + (document, cancellationToken) => document.IsGeneratedCode(cancellationToken)); } - - return null; } internal virtual async Task>> GetProjectDiagnosticsToFixAsync( diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 6a6606c1bd32a..2db5781219185 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -28,6 +28,7 @@ + Collections\ArrayBuilderExtensions.cs From 24da46e673f3e7da439fc7d55600d757d6670d8b Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 8 Oct 2018 20:58:43 -0500 Subject: [PATCH 18/25] Reduce contention in GetDocumentDiagnosticsToFixAsync --- src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs index 0039ea6abb04c..83f4662c6da83 100644 --- a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs @@ -49,7 +49,7 @@ public static async Task(); + var diagnostics = new ConcurrentDictionary>(); var tasks = new Task[projectsToFix.Length]; for (var i = 0; i < projectsToFix.Length; i++) { @@ -58,18 +58,13 @@ public static async Task { var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false); - foreach (var diagnostic in projectDiagnostics) - { - cancellationToken.ThrowIfCancellationRequested(); - diagnostics.Add(diagnostic); - } - + diagnostics.TryAdd(projectToFix.Id, projectDiagnostics); progressTrackerOpt?.ItemCompleted(); }, cancellationToken); } await Task.WhenAll(tasks).ConfigureAwait(false); - allDiagnostics = allDiagnostics.AddRange(diagnostics); + allDiagnostics = allDiagnostics.AddRange(diagnostics.SelectMany(i => i.Value)); break; } From c539707271e3f4d7944f3860d41ed79f7d93f79a Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 9 Oct 2018 05:47:11 -0500 Subject: [PATCH 19/25] Fix expected test output following behavior change in 1124126 --- .../CSharpTest/Formatting/FormattingAnalyzerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs index 922b8884ce8c7..ffd4061f016c1 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingAnalyzerTests.cs @@ -47,7 +47,7 @@ class TypeName { void Method() { - if (true)return; + if (true) return; } } "; From 7edc55398f95392a9500f216744fe079eef934c4 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 9 Oct 2018 06:30:01 -0500 Subject: [PATCH 20/25] Share code in formatting analyzer and code fix --- .../AbstractFormattingAnalyzerImpl.cs | 51 +------------- .../CodeFixes/FormattingAnalyzerHelper.cs | 67 +++++++++++++++++++ .../Core/CodeFixes/FormattingCodeFixHelper.cs | 28 ++++++++ .../CodeFixes/FormattingCodeFixProvider.cs | 21 +----- ...rosoft.CodeAnalysis.CodeStyle.Fixes.csproj | 1 + .../Formatting/FormattingCodeFixProvider.cs | 20 +----- .../FormattingDiagnosticAnalyzer.cs | 51 +------------- .../Microsoft.CodeAnalysis.Features.csproj | 2 + 8 files changed, 103 insertions(+), 138 deletions(-) create mode 100644 src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs create mode 100644 src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs index f536a4bc11997..08267edc0fbf0 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzerImpl.cs @@ -1,11 +1,8 @@ // 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; using System.IO; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.CodingConventions; namespace Microsoft.CodeAnalysis.CodeStyle @@ -41,53 +38,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Workspace work options = ApplyFormattingOptions(options, codingConventionContext); } - 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 - throw new InvalidOperationException("This program location is thought to be unreachable."); - } - - var location = Location.Create(tree, change.Span); - context.ReportDiagnostic(Diagnostic.Create( - _descriptor, - location, - additionalLocations: null, - properties: null)); - } + FormattingAnalyzerHelper.AnalyzeSyntaxTree(context, _descriptor, workspace, options); } } } diff --git a/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs b/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs new file mode 100644 index 0000000000000..68d51b354013c --- /dev/null +++ b/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs @@ -0,0 +1,67 @@ +// 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; +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 + throw new InvalidOperationException("This program location is thought to be unreachable."); + } + + var location = Location.Create(tree, change.Span); + context.ReportDiagnostic(Diagnostic.Create( + descriptor, + location, + additionalLocations: null, + properties: null)); + } + } + } +} diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs new file mode 100644 index 0000000000000..9b500c1b00d5e --- /dev/null +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs @@ -0,0 +1,28 @@ +// 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.Text; + +namespace Microsoft.CodeAnalysis +{ + internal static class FormattingCodeFixHelper + { + internal static async Task FixOneAsync(Document document, 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); + + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index 6e4d5449cda6a..e3bae555381fd 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -8,11 +8,10 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CodeStyle { - [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = "FixFormatting")] + [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = PredefinedCodeFixProviderNames.FixFormatting)] [Shared] internal class FormattingCodeFixProvider : CodeFixProvider { @@ -31,7 +30,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( CodeStyleFixesResources.Formatting_analyzer_code_fix, - c => FixOneAsync(context.Document, diagnostic, c), + c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c), nameof(FormattingCodeFixProvider)), diagnostic); } @@ -39,22 +38,6 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) return Task.CompletedTask; } - protected async Task FixOneAsync(Document document, 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); - - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); - } - /// /// Provide an optimized Fix All implementation that runs /// on the document(s) diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index 0363470f5a036..12fd987fea4d8 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -9,6 +9,7 @@ net46 + diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index 86ad51e084c5a..8432f85b18b9a 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Formatting { @@ -25,30 +24,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) foreach (var diagnostic in context.Diagnostics) { context.RegisterCodeFix( - new MyCodeAction(c => FixOneAsync(context.Document, diagnostic, c)), + new MyCodeAction(c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c)), diagnostic); } return Task.CompletedTask; } - protected async Task FixOneAsync(Document document, 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); - - - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); - } - protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs index 66682d10c5ab5..c881a766f3ffd 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -2,8 +2,6 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Formatting { @@ -45,54 +43,7 @@ private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) } var workspace = workspaceAnalyzerOptions.Services.Workspace; - 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 - throw ExceptionUtilities.Unreachable; - } - - var location = Location.Create(tree, change.Span); - context.ReportDiagnostic(DiagnosticHelper.Create( - Descriptor, - location, - ReportDiagnostic.Default, - additionalLocations: null, - properties: null)); - } + FormattingAnalyzerHelper.AnalyzeSyntaxTree(context, Descriptor, workspace, options); } } } diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 8dd669c7c340e..bee1a75581690 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 From 031cd695031feab5d388bc8a15e297fb19a584d0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 11 Oct 2018 10:25:25 -0500 Subject: [PATCH 21/25] Fix resource string names for style consistency --- .../Analyzers/CodeStyleResources.Designer.cs | 13 ++----- .../Core/Analyzers/CodeStyleResources.resx | 5 +-- .../Analyzers/xlf/CodeStyleResources.cs.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.de.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.es.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.fr.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.it.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.ja.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.ko.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.pl.xlf | 7 +--- .../xlf/CodeStyleResources.pt-BR.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.ru.xlf | 7 +--- .../Analyzers/xlf/CodeStyleResources.tr.xlf | 7 +--- .../xlf/CodeStyleResources.zh-Hans.xlf | 7 +--- .../xlf/CodeStyleResources.zh-Hant.xlf | 7 +--- .../CodeFixes/AbstractFormattingAnalyzer.cs | 4 +-- .../CodeStyleFixesResources.Designer.cs | 11 +++--- .../CodeFixes/CodeStyleFixesResources.resx | 5 +-- .../CodeFixes/FormattingCodeFixProvider.cs | 4 +-- .../xlf/CodeStyleFixesResources.cs.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.de.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.es.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.fr.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.it.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.ja.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.ko.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.pl.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.pt-BR.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.ru.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.tr.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.zh-Hans.xlf | 8 ++--- .../xlf/CodeStyleFixesResources.zh-Hant.xlf | 8 ++--- .../Portable/FeaturesResources.Designer.cs | 36 +++++-------------- .../Core/Portable/FeaturesResources.resx | 8 +---- .../Formatting/FormattingCodeFixProvider.cs | 2 +- .../FormattingDiagnosticAnalyzer.cs | 4 +-- .../Portable/xlf/FeaturesResources.cs.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.de.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.es.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.fr.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.it.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.ja.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.ko.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.pl.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.pt-BR.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.ru.xlf | 18 +++------- .../Portable/xlf/FeaturesResources.tr.xlf | 18 +++------- .../xlf/FeaturesResources.zh-Hans.xlf | 18 +++------- .../xlf/FeaturesResources.zh-Hant.xlf | 18 +++------- 49 files changed, 146 insertions(+), 375 deletions(-) diff --git a/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs b/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs index 25f6951d7c33d..7626e9e6c7ef2 100644 --- a/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs +++ b/src/CodeStyle/Core/Analyzers/CodeStyleResources.Designer.cs @@ -64,18 +64,9 @@ internal CodeStyleResources() { /// /// Looks up a localized string similar to Fix formatting. /// - internal static string Formatting_analyzer_message { + internal static string Fix_formatting { get { - return ResourceManager.GetString("Formatting_analyzer_message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Fix formatting. - /// - internal static string Formatting_analyzer_title { - get { - return ResourceManager.GetString("Formatting_analyzer_title", resourceCulture); + return ResourceManager.GetString("Fix_formatting", resourceCulture); } } diff --git a/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx b/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx index 110991e6a6ef1..e712a05d5ceac 100644 --- a/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx +++ b/src/CodeStyle/Core/Analyzers/CodeStyleResources.resx @@ -117,10 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Fix formatting - - + Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf index 4faac554d413d..9dd0acb61cfac 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.cs.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf index 4ab91eee54c79..1b836706e2169 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.de.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf index 464a5df4adf46..21ac829ef7bf2 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.es.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf index 87c658fb8d7e6..14834a720d54b 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.fr.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf index 5bf1ccac11d41..a3b752066289d 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.it.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf index d9675791e119c..b69e1dd6782ea 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ja.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf index cf577ccccefc2..515f08afb075e 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ko.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf index 13d6a44471a8e..28f66bc8c37a8 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pl.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf index 3b04a8d5a786b..359fe32f863e5 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.pt-BR.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf index 6e63f0704c86a..d5f00ae95545f 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.ru.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf index 290b0366e6390..ff68faaf8e5c1 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.tr.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf index d128257c7354d..4c13d820f47a1 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hans.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf index 4d03802436edb..a6c3db6be0f4b 100644 --- a/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf +++ b/src/CodeStyle/Core/Analyzers/xlf/CodeStyleResources.zh-Hant.xlf @@ -2,12 +2,7 @@ - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting diff --git a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs index 98685ec0cc4a0..c287efe105696 100644 --- a/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs +++ b/src/CodeStyle/Core/CodeFixes/AbstractFormattingAnalyzer.cs @@ -25,8 +25,8 @@ static AbstractFormattingAnalyzer() protected AbstractFormattingAnalyzer() : base( IDEDiagnosticIds.FormattingDiagnosticId, - new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_title), CodeStyleResources.ResourceManager, typeof(CodeStyleResources)), - new LocalizableResourceString(nameof(CodeStyleResources.Formatting_analyzer_message), CodeStyleResources.ResourceManager, typeof(CodeStyleResources))) + new LocalizableResourceString(nameof(CodeStyleResources.Fix_formatting), CodeStyleResources.ResourceManager, typeof(CodeStyleResources)), + new LocalizableResourceString(nameof(CodeStyleResources.Fix_formatting), CodeStyleResources.ResourceManager, typeof(CodeStyleResources))) { } diff --git a/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.Designer.cs b/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.Designer.cs index c8425920241e5..b9e6d374a23ff 100644 --- a/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.Designer.cs +++ b/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.Designer.cs @@ -10,6 +10,7 @@ namespace Microsoft.CodeAnalysis { using System; + using System.Reflection; /// @@ -19,7 +20,7 @@ namespace Microsoft.CodeAnalysis { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CodeStyleFixesResources { @@ -39,7 +40,7 @@ internal CodeStyleFixesResources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CodeAnalysis.CodeStyleFixesResources", typeof(CodeStyleFixesResources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CodeAnalysis.CodeStyleFixesResources", typeof(CodeStyleFixesResources).GetTypeInfo().Assembly); resourceMan = temp; } return resourceMan; @@ -61,11 +62,11 @@ internal CodeStyleFixesResources() { } /// - /// Looks up a localized string similar to Fix formatting. + /// Looks up a localized string similar to Remove this value when another is added.. /// - internal static string Formatting_analyzer_code_fix { + internal static string EmptyResource { get { - return ResourceManager.GetString("Formatting_analyzer_code_fix", resourceCulture); + return ResourceManager.GetString("EmptyResource", resourceCulture); } } } diff --git a/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.resx b/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.resx index eb5e3ea02d4c7..14ed010cf9ebb 100644 --- a/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.resx +++ b/src/CodeStyle/Core/CodeFixes/CodeStyleFixesResources.resx @@ -117,7 +117,8 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Fix formatting + + Remove this value when another is added. + https://github.com/Microsoft/msbuild/issues/1661 \ No newline at end of file diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index e3bae555381fd..a13f8a76989e4 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -29,7 +29,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) { context.RegisterCodeFix( CodeAction.Create( - CodeStyleFixesResources.Formatting_analyzer_code_fix, + CodeStyleResources.Fix_formatting, c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c), nameof(FormattingCodeFixProvider)), diagnostic); @@ -45,7 +45,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) /// private class FixAll : DocumentBasedFixAllProvider { - protected override string CodeActionTitle => CodeStyleFixesResources.Formatting_analyzer_code_fix; + protected override string CodeActionTitle => CodeStyleResources.Fix_formatting; protected override async Task FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray diagnostics) { diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.cs.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.cs.xlf index 9a45dba1e3fdb..559726ff639c6 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.cs.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.cs.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Odebrat tuto hodnotu, když se přidá jiná + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.de.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.de.xlf index 5fe29967bab93..d5a6d6aaca6f7 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.de.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.de.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Dieser Wert wird entfernt, wenn ein anderer hinzugefügt wird. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.es.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.es.xlf index 821d4829d9879..2d94e4f72ae08 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.es.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.es.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Quite este valor cuando se agregue otro. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.fr.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.fr.xlf index aa82e329e8355..d090cec024319 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.fr.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.fr.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Supprimer cette valeur quand une autre est ajoutée. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.it.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.it.xlf index 796a86f18bb04..39117266e3829 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.it.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.it.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Rimuovere questo valore quando ne viene aggiunto un altro. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ja.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ja.xlf index c7c2f19f44255..c6f9b412ca04e 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ja.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ja.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + 別の値が追加されたら、この値を削除します。 + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ko.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ko.xlf index 83590b8f6c63f..2fdb94976762d 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ko.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ko.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + 다른 값을 추가할 때 이 값을 제거하세요. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pl.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pl.xlf index f3d462a4a349b..676ecc024083f 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pl.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pl.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Usuń tę wartość, gdy dodawana jest kolejna. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pt-BR.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pt-BR.xlf index d69e139face3e..4b35061ad6e5c 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pt-BR.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.pt-BR.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Remover este valor quando outro for adicionado. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ru.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ru.xlf index 6b9e9cb284fd5..a5527cc1adace 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ru.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.ru.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Удалите это значение при добавлении другого значения. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.tr.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.tr.xlf index 25dcfcdfc9b0c..65ac78f824b91 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.tr.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.tr.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + Başka bir değer eklendiğinde bu değeri kaldırın. + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hans.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hans.xlf index 9bdc32333b818..1a6295ceca776 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hans.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hans.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + 在添加其他值时删除此值。 + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hant.xlf b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hant.xlf index 87d085048997c..47e57451acb6b 100644 --- a/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hant.xlf +++ b/src/CodeStyle/Core/CodeFixes/xlf/CodeStyleFixesResources.zh-Hant.xlf @@ -2,10 +2,10 @@ - - Fix formatting - Fix formatting - + + Remove this value when another is added. + 當新增另一個值時移除此值。 + https://github.com/Microsoft/msbuild/issues/1661 diff --git a/src/Features/Core/Portable/FeaturesResources.Designer.cs b/src/Features/Core/Portable/FeaturesResources.Designer.cs index 69191d98ff7f7..7fe5c6760314d 100644 --- a/src/Features/Core/Portable/FeaturesResources.Designer.cs +++ b/src/Features/Core/Portable/FeaturesResources.Designer.cs @@ -1351,6 +1351,15 @@ internal static string Fix_all_occurrences { } } + /// + /// Looks up a localized string similar to Fix formatting. + /// + internal static string Fix_formatting { + get { + return ResourceManager.GetString("Fix_formatting", resourceCulture); + } + } + /// /// Looks up a localized string similar to Fix Name Violation: {0}. /// @@ -1378,33 +1387,6 @@ internal static string Format_string_contains_invalid_placeholder { } } - /// - /// Looks up a localized string similar to Fix formatting. - /// - internal static string Formatting_analyzer_code_fix { - get { - return ResourceManager.GetString("Formatting_analyzer_code_fix", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Fix formatting. - /// - internal static string Formatting_analyzer_message { - get { - return ResourceManager.GetString("Formatting_analyzer_message", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Fix formatting. - /// - internal static string Formatting_analyzer_title { - get { - return ResourceManager.GetString("Formatting_analyzer_title", resourceCulture); - } - } - /// /// Looks up a localized string similar to Formatting document. /// diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index e8a17929831d5..30ed47076dc45 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -1439,13 +1439,7 @@ This version used in: {2} Modifying source file {0} will prevent the debug session from continuing due to internal error: {1}. - - Fix formatting - - - Fix formatting - - + Fix formatting \ No newline at end of file diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index 8432f85b18b9a..f6bdc1627df1d 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -41,7 +41,7 @@ protected override async Task FixAllAsync(Document document, ImmutableArray> createChangedDocument) - : base(FeaturesResources.Formatting_analyzer_code_fix, createChangedDocument, FeaturesResources.Formatting_analyzer_code_fix) + : base(FeaturesResources.Fix_formatting, createChangedDocument, FeaturesResources.Fix_formatting) { } } diff --git a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs index c881a766f3ffd..e213bd8b4f9b8 100644 --- a/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/Formatting/FormattingDiagnosticAnalyzer.cs @@ -12,8 +12,8 @@ internal class FormattingDiagnosticAnalyzer public FormattingDiagnosticAnalyzer() : base( IDEDiagnosticIds.FormattingDiagnosticId, - new LocalizableResourceString(nameof(FeaturesResources.Formatting_analyzer_title), FeaturesResources.ResourceManager, typeof(FeaturesResources)), - new LocalizableResourceString(nameof(FeaturesResources.Formatting_analyzer_message), FeaturesResources.ResourceManager, typeof(FeaturesResources))) + new LocalizableResourceString(nameof(FeaturesResources.Fix_formatting), FeaturesResources.ResourceManager, typeof(FeaturesResources)), + new LocalizableResourceString(nameof(FeaturesResources.Fix_formatting), FeaturesResources.ResourceManager, typeof(FeaturesResources))) { } diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index f5973f1797b37..9282ad587edec 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Opravit překlep {0} - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Opravit překlep {0} diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index b37064f863f32..d80e24e6481b4 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Tippfehler "{0}" korrigieren - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Tippfehler "{0}" korrigieren diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index bca6f8b185b9c..a150752f913df 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Corregir error de escritura "{0}" - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Corregir error de escritura "{0}" diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index ed1ccc25a5146..08e338a053efb 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Corriger la faute de frappe '{0}' - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Corriger la faute de frappe '{0}' diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index a7ab930c44081..4b516689bfb00 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Correggere l'errore di ortografia '{0}' - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Correggere l'errore di ortografia '{0}' diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 423665a5d3702..5aca432883116 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - '{0}' の入力ミスを修正します - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + '{0}' の入力ミスを修正します diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 40ca19267d746..fe74ef427e085 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - 오타 '{0}' 수정 - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + 오타 '{0}' 수정 diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 1e903e9b52c79..4d74a11be9f79 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Popraw błąd pisowni „{0}” - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Popraw błąd pisowni „{0}” diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 3839cffab2eb0..e231212d7df89 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Corrigir erro de digitação '{0}' - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Corrigir erro de digitação '{0}' diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index dc8e1e4a22904..d0de1fb6567e5 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - Исправьте опечатку "{0}" - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + Исправьте опечатку "{0}" diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index 79dc6b59e830b..7200b0b03aecf 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - '{0}' yazım hatasını düzeltin - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + '{0}' yazım hatasını düzeltin diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 81a69c2ab0ab2..423e5a5427edd 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - 修正笔误“{0}” - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + 修正笔误“{0}” diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 8796891d596a2..4c42179abb67f 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -62,24 +62,14 @@ Convert to tuple - - Fix typo '{0}' - 修正錯字 '{0}' - - - - Fix formatting - Fix formatting - - - + Fix formatting Fix formatting - - Fix formatting - Fix formatting + + Fix typo '{0}' + 修正錯字 '{0}' From 45877d34bb864678318a2153646ab06f3a7719a2 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 11 Oct 2018 12:00:19 -0500 Subject: [PATCH 22/25] Remove workaround for #30309 since it was fixed separately --- .../AnalyzerManager.AnalyzerExecutionContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs index 6e57d59330198..2ebdcd7e78b30 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs @@ -359,7 +359,7 @@ private void MarkSymbolEndAnalysisPending_NoLock(ISymbol symbol, ImmutableArray< _lazyPendingSymbolEndActionsOpt[symbol] = (symbolEndActions, symbolDeclaredEvent); } - [Conditional("DEBUG_ISSUE_30309")] + [Conditional("DEBUG")] public void VerifyAllSymbolEndActionsExecuted() { lock (_gate) From 8a88bc9790257eed30d1270bdfca580507a48346 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 11 Oct 2018 14:09:14 -0500 Subject: [PATCH 23/25] Add test for formatting code fix relying on .editorconfig --- .../CSharpFormattingCodeFixProvider.cs | 21 ++++++++ .../CSharp/Tests/FormattingAnalyzerTests.cs | 50 ++++++++++++++++- .../Core/CodeFixes/FormattingCodeFixHelper.cs | 4 +- .../CodeFixes/FormattingCodeFixProvider.cs | 53 +++++++++++++++---- .../VisualBasicFormattingCodeFixProvider.vb | 19 +++++++ .../Tests/FormattingAnalyzerTests.vb | 2 +- .../Formatting/FormattingCodeFixProvider.cs | 8 ++- 7 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 src/CodeStyle/CSharp/CodeFixes/CSharpFormattingCodeFixProvider.cs create mode 100644 src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingCodeFixProvider.vb diff --git a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingCodeFixProvider.cs b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingCodeFixProvider.cs new file mode 100644 index 0000000000000..79622d72acf28 --- /dev/null +++ b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingCodeFixProvider.cs @@ -0,0 +1,21 @@ +// 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.Composition; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.CodingConventions; + +namespace Microsoft.CodeAnalysis.CodeStyle +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.FixFormatting)] + [Shared] + internal class CSharpFormattingCodeFixProvider : AbstractFormattingCodeFixProvider + { + private readonly EditorConfigOptionsApplier _editorConfigOptionsApplier = new EditorConfigOptionsApplier(); + + protected override OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext) + { + return _editorConfigOptionsApplier.ApplyConventions(optionSet, codingConventionContext.CurrentConventions, LanguageNames.CSharp); + } + } +} diff --git a/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs index a966e5fd6e421..c9abd0249e025 100644 --- a/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs +++ b/src/CodeStyle/CSharp/Tests/FormattingAnalyzerTests.cs @@ -1,5 +1,6 @@ // 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.IO; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; @@ -7,7 +8,7 @@ namespace Microsoft.CodeAnalysis.CodeStyle { - using Verify = CSharpCodeFixVerifier; + using Verify = CSharpCodeFixVerifier; public class FormattingAnalyzerTests { @@ -184,7 +185,7 @@ class MyClass } "; - await new CSharpCodeFixTest + await new CSharpCodeFixTest { TestCode = testCode, FixedCode = fixedCode, @@ -194,5 +195,50 @@ class MyClass NumberOfIncrementalIterations = 2, }.RunAsync(); } + + [Fact] + public async Task TestEditorConfigUsed() + { + var testCode = @" +class MyClass { + void MyMethod()[| |]{ + } +} +"; + var fixedCode = @" +class MyClass { + void MyMethod() + { + } +} +"; + var editorConfig = @" +root = true + +[*.cs] +csharp_new_line_before_open_brace = methods +"; + + var testDirectoryName = Path.GetRandomFileName(); + Directory.CreateDirectory(testDirectoryName); + try + { + File.WriteAllText(Path.Combine(testDirectoryName, ".editorconfig"), editorConfig); + + // The contents of this file are ignored, but the coding conventions library checks for existence before + // .editorconfig is used. + File.WriteAllText(Path.Combine(testDirectoryName, "Test0.cs"), string.Empty); + + await new CSharpCodeFixTest + { + TestState = { Sources = { (Path.GetFullPath(Path.Combine(testDirectoryName, "Test0.cs")), testCode) } }, + FixedState = { Sources = { (Path.GetFullPath(Path.Combine(testDirectoryName, "Test0.cs")), fixedCode) } }, + }.RunAsync(); + } + finally + { + Directory.Delete(testDirectoryName, true); + } + } } } diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs index 9b500c1b00d5e..ded0aa6661f3b 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixHelper.cs @@ -3,13 +3,14 @@ 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, Diagnostic diagnostic, CancellationToken cancellationToken) + internal static async Task FixOneAsync(Document document, OptionSet options, Diagnostic diagnostic, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); @@ -21,7 +22,6 @@ internal static async Task FixOneAsync(Document document, Diagnostic d text.Lines[diagnosticLinePositionSpan.Start.Line].Start, text.Lines[diagnosticLinePositionSpan.End.Line].End); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); return await Formatter.FormatAsync(document, spanToFormat, options, cancellationToken).ConfigureAwait(false); } } diff --git a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs index a13f8a76989e4..19a9d088f0680 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingCodeFixProvider.cs @@ -1,43 +1,67 @@ // 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.Collections.Immutable; -using System.Composition; +using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.VisualStudio.CodingConventions; namespace Microsoft.CodeAnalysis.CodeStyle { - [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = PredefinedCodeFixProviderNames.FixFormatting)] - [Shared] - internal class FormattingCodeFixProvider : CodeFixProvider + internal abstract class AbstractFormattingCodeFixProvider : CodeFixProvider { - public override ImmutableArray FixableDiagnosticIds + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(IDEDiagnosticIds.FormattingDiagnosticId); - public override FixAllProvider GetFixAllProvider() + public sealed override FixAllProvider GetFixAllProvider() { - return new FixAll(); + return new FixAll(this); } - public override Task RegisterCodeFixesAsync(CodeFixContext context) + public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { context.RegisterCodeFix( CodeAction.Create( CodeStyleResources.Fix_formatting, - c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c), - nameof(FormattingCodeFixProvider)), + c => FixOneAsync(context, diagnostic, c), + nameof(AbstractFormattingCodeFixProvider)), diagnostic); } return Task.CompletedTask; } + protected abstract OptionSet ApplyFormattingOptions(OptionSet optionSet, ICodingConventionContext codingConventionContext); + + private async Task FixOneAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) + { + var options = await GetOptionsAsync(context.Document, cancellationToken).ConfigureAwait(false); + return await FormattingCodeFixHelper.FixOneAsync(context.Document, options, diagnostic, cancellationToken).ConfigureAwait(false); + } + + private async Task GetOptionsAsync(Document document, CancellationToken cancellationToken) + { + OptionSet options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + + // The in-IDE workspace supports .editorconfig without special handling. However, the AdhocWorkspace used + // in testing requires manual handling of .editorconfig. + if (document.Project.Solution.Workspace is AdhocWorkspace && File.Exists(document.FilePath ?? document.Name)) + { + var codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(); + var codingConventionContext = await codingConventionsManager.GetConventionContextAsync(document.FilePath ?? document.Name, cancellationToken).ConfigureAwait(false); + options = ApplyFormattingOptions(options, codingConventionContext); + } + + return options; + } + /// /// Provide an optimized Fix All implementation that runs /// on the document(s) @@ -45,11 +69,18 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) /// private class FixAll : DocumentBasedFixAllProvider { + private readonly AbstractFormattingCodeFixProvider _formattingCodeFixProvider; + + public FixAll(AbstractFormattingCodeFixProvider formattingCodeFixProvider) + { + _formattingCodeFixProvider = formattingCodeFixProvider; + } + protected override string CodeActionTitle => CodeStyleResources.Fix_formatting; protected override async Task FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray diagnostics) { - var options = await document.GetOptionsAsync(fixAllContext.CancellationToken).ConfigureAwait(false); + var options = await _formattingCodeFixProvider.GetOptionsAsync(document, fixAllContext.CancellationToken).ConfigureAwait(false); var updatedDocument = await Formatter.FormatAsync(document, options, fixAllContext.CancellationToken).ConfigureAwait(false); return await updatedDocument.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false); } diff --git a/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingCodeFixProvider.vb b/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingCodeFixProvider.vb new file mode 100644 index 0000000000000..8726cfa1da728 --- /dev/null +++ b/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingCodeFixProvider.vb @@ -0,0 +1,19 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Composition +Imports Microsoft.CodeAnalysis.CodeFixes +Imports Microsoft.CodeAnalysis.Options +Imports Microsoft.VisualStudio.CodingConventions + +Namespace Microsoft.CodeAnalysis.CodeStyle + + <[Shared]> + Friend Class VisualBasicFormattingCodeFixProvider + Inherits AbstractFormattingCodeFixProvider + + Protected Overrides Function ApplyFormattingOptions(optionSet As OptionSet, codingConventionContext As ICodingConventionContext) As OptionSet + Return optionSet + End Function + End Class +End Namespace + diff --git a/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb b/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb index 55caaf9117aa9..f9838a32cd41e 100644 --- a/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb +++ b/src/CodeStyle/VisualBasic/Tests/FormattingAnalyzerTests.vb @@ -3,7 +3,7 @@ Imports Xunit Imports VerifyVB = Microsoft.CodeAnalysis.VisualBasic.Testing.VisualBasicCodeFixVerifier( Of Microsoft.CodeAnalysis.CodeStyle.VisualBasicFormattingAnalyzer, - Microsoft.CodeAnalysis.CodeStyle.FormattingCodeFixProvider, + Microsoft.CodeAnalysis.CodeStyle.VisualBasicFormattingCodeFixProvider, Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier) Namespace Microsoft.CodeAnalysis.CodeStyle diff --git a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs index f6bdc1627df1d..e9efa3d887326 100644 --- a/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs +++ b/src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs @@ -24,13 +24,19 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) foreach (var diagnostic in context.Diagnostics) { context.RegisterCodeFix( - new MyCodeAction(c => FormattingCodeFixHelper.FixOneAsync(context.Document, diagnostic, c)), + new MyCodeAction(c => FixOneAsync(context, diagnostic, c)), diagnostic); } return Task.CompletedTask; } + 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); + } + protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); From 2ccd3022a03e816f2663e348025781c71982f6d6 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 11 Oct 2018 15:58:15 -0500 Subject: [PATCH 24/25] Allow the formatter to report NOP text changes --- src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs b/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs index 68d51b354013c..46b0002c6547a 100644 --- a/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FormattingAnalyzerHelper.cs @@ -1,6 +1,5 @@ // 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; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -51,8 +50,9 @@ internal static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context, Diagno if (change.NewText.Length == 0 && change.Span.IsEmpty) { - // No actual change - throw new InvalidOperationException("This program location is thought to be unreachable."); + // 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); From a4a1961828c180ef059f79d9b2d610720b8fb6bb Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 12 Oct 2018 14:39:48 -0500 Subject: [PATCH 25/25] Document reflection load pattern in derived types --- src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs | 1 + .../VisualBasic/CodeFixes/VisualBasicFormattingAnalyzer.vb | 1 + 2 files changed, 2 insertions(+) diff --git a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs index 28382affc38ed..67c09862fad39 100644 --- a/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs +++ b/src/CodeStyle/CSharp/CodeFixes/CSharpFormattingAnalyzer.cs @@ -10,6 +10,7 @@ internal class CSharpFormattingAnalyzer : AbstractFormattingAnalyzer { protected override Type GetAnalyzerImplType() { + // Explained at the call site in the base class return typeof(CSharpFormattingAnalyzerImpl); } } diff --git a/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingAnalyzer.vb b/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingAnalyzer.vb index 44da0efdec50f..048a9b1a463ab 100644 --- a/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingAnalyzer.vb +++ b/src/CodeStyle/VisualBasic/CodeFixes/VisualBasicFormattingAnalyzer.vb @@ -8,6 +8,7 @@ Namespace Microsoft.CodeAnalysis.CodeStyle Inherits AbstractFormattingAnalyzer Protected Overrides Function GetAnalyzerImplType() As Type + ' Explained at the call site in the base class Return GetType(VisualBasicFormattingAnalyzerImpl) End Function End Class