diff --git a/eng/Versions.props b/eng/Versions.props index 46e3a8b7dab53..06c66a342b9d4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -21,7 +21,7 @@ 3.3.3-beta1.21105.3 6.0.0-rc1.21366.2 - 1.1.1-beta1.22081.4 + 1.1.2-beta1.22122.4 0.1.127-beta 4.0.1 diff --git a/global.json b/global.json index ee7e263ef19f1..8b4d21042c9d0 100644 --- a/global.json +++ b/global.json @@ -12,7 +12,7 @@ "xcopy-msbuild": "16.10.0-preview2" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22117.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22117.2" + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22080.1", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22080.1" } } diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs index 4efaffbe9927e..27d4df2cb6859 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs @@ -40,7 +40,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) { - var fadeCode = context.GetIdeOptions().FadeOutUnreachableCode; + var fadeCode = context.Options.GetIdeOptions().FadeOutUnreachableCode; var semanticModel = context.SemanticModel; var cancellationToken = context.CancellationToken; diff --git a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerHelper.cs b/src/Analyzers/Core/Analyzers/Helpers/AnalyzerHelper.cs index 78fc8b8477c4a..b2232b2c2aace 100644 --- a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerHelper.cs +++ b/src/Analyzers/Core/Analyzers/Helpers/AnalyzerHelper.cs @@ -14,46 +14,44 @@ namespace Microsoft.CodeAnalysis.Diagnostics { internal readonly record struct IdeAnalyzerOptions( - bool FadeOutUnusedImports, - bool FadeOutUnreachableCode, - bool ReportInvalidPlaceholdersInStringDotFormatCalls, - bool ReportInvalidRegexPatterns) + bool FadeOutUnusedImports = true, + bool FadeOutUnreachableCode = true, + bool ReportInvalidPlaceholdersInStringDotFormatCalls = true, + bool ReportInvalidRegexPatterns = true) { + public IdeAnalyzerOptions() + : this(FadeOutUnusedImports: true) + { + } + + public static readonly IdeAnalyzerOptions Default = new(); + public static readonly IdeAnalyzerOptions CodeStyleDefault = new( FadeOutUnusedImports: false, FadeOutUnreachableCode: false, ReportInvalidPlaceholdersInStringDotFormatCalls: true, ReportInvalidRegexPatterns: true); - } - - internal static partial class AnalyzerHelper - { - public static IdeAnalyzerOptions GetIdeOptions(this SyntaxTreeAnalysisContext context) -#if CODE_STYLE - => IdeAnalyzerOptions.CodeStyleDefault; -#else - => (context.Options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.GetIdeOptions(context.Tree.Options.Language) : IdeAnalyzerOptions.CodeStyleDefault; -#endif - public static IdeAnalyzerOptions GetIdeOptions(this OperationAnalysisContext context) -#if CODE_STYLE - => IdeAnalyzerOptions.CodeStyleDefault; -#else - => (context.Options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.GetIdeOptions(context.Operation.Language) : IdeAnalyzerOptions.CodeStyleDefault; -#endif +#if !CODE_STYLE + public static IdeAnalyzerOptions FromProject(Project project) + => From(project.Solution.Options, project.Language); - public static IdeAnalyzerOptions GetIdeOptions(this SyntaxNodeAnalysisContext context) -#if CODE_STYLE - => IdeAnalyzerOptions.CodeStyleDefault; -#else - => (context.Options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.GetIdeOptions(context.Node.Language) : IdeAnalyzerOptions.CodeStyleDefault; + public static IdeAnalyzerOptions From(OptionSet options, string language) + => new( + FadeOutUnusedImports: options.GetOption(Microsoft.CodeAnalysis.Fading.FadingOptions.Metadata.FadeOutUnusedImports, language), + FadeOutUnreachableCode: options.GetOption(Microsoft.CodeAnalysis.Fading.FadingOptions.Metadata.FadeOutUnreachableCode, language), + ReportInvalidPlaceholdersInStringDotFormatCalls: options.GetOption(Microsoft.CodeAnalysis.ValidateFormatString.ValidateFormatStringOption.ReportInvalidPlaceholdersInStringDotFormatCalls, language), + ReportInvalidRegexPatterns: options.GetOption(Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.LanguageServices.RegularExpressionsOptions.ReportInvalidRegexPatterns, language)); #endif + } - public static IdeAnalyzerOptions GetIdeOptions(this SemanticModelAnalysisContext context) + internal static partial class AnalyzerHelper + { + public static IdeAnalyzerOptions GetIdeOptions(this AnalyzerOptions options) #if CODE_STYLE => IdeAnalyzerOptions.CodeStyleDefault; #else - => (context.Options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.GetIdeOptions(context.SemanticModel.Language) : IdeAnalyzerOptions.CodeStyleDefault; + => (options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.IdeOptions : IdeAnalyzerOptions.CodeStyleDefault; #endif public static T GetOption(this SemanticModelAnalysisContext context, Option2 option) diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs index 816dcb501398a..7bc38692f1e06 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs @@ -142,7 +142,7 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) // for us appropriately. unnecessaryImports = MergeImports(unnecessaryImports); - var fadeOut = context.GetIdeOptions().FadeOutUnusedImports; + var fadeOut = context.Options.GetIdeOptions().FadeOutUnusedImports; DiagnosticDescriptor descriptor; if (GeneratedCodeUtilities.IsGeneratedCode(tree, IsRegularCommentOrDocComment, cancellationToken)) diff --git a/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs index 8a9da43afd2dd..8e06aa10dd658 100644 --- a/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs @@ -96,7 +96,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol for return; } - if (!context.GetIdeOptions().ReportInvalidPlaceholdersInStringDotFormatCalls) + if (!context.Options.GetIdeOptions().ReportInvalidPlaceholdersInStringDotFormatCalls) { return; } diff --git a/src/Analyzers/Core/Analyzers/ValidateFormatString/ValidateFormatStringOption.cs b/src/Analyzers/Core/Analyzers/ValidateFormatString/ValidateFormatStringOption.cs index cf5153efb20b5..57fc450317da5 100644 --- a/src/Analyzers/Core/Analyzers/ValidateFormatString/ValidateFormatStringOption.cs +++ b/src/Analyzers/Core/Analyzers/ValidateFormatString/ValidateFormatStringOption.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.ValidateFormatString @@ -12,7 +13,7 @@ internal class ValidateFormatStringOption new( nameof(ValidateFormatStringOption), nameof(ReportInvalidPlaceholdersInStringDotFormatCalls), - defaultValue: true, + IdeAnalyzerOptions.Default.ReportInvalidPlaceholdersInStringDotFormatCalls, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.WarnOnInvalidStringDotFormatCalls")); } } diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs index 2022170660e07..d6624d0d75a81 100644 --- a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs @@ -5,6 +5,7 @@ #nullable disable using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; @@ -1468,6 +1469,11 @@ class T : A [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestWithGroupingOff1() { + var options = CodeActionOptions.Default with + { + ImplementTypeOptions = new ImplementTypeOptions(InsertionBehavior: ImplementTypeInsertionBehavior.AtTheEnd) + }; + await TestInRegularAndScriptAsync( @"abstract class Base { @@ -1488,7 +1494,7 @@ class Derived : Base void Goo() { } public override int Prop => throw new System.NotImplementedException(); -}", options: Option(ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd)); +}", codeActionOptions: options); } [WorkItem(17274, "https://github.com/dotnet/roslyn/issues/17274")] @@ -1641,6 +1647,11 @@ public override void M2(T? i = null) [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] public async Task TestAutoProperties() { + var options = CodeActionOptions.Default with + { + ImplementTypeOptions = new ImplementTypeOptions(PropertyGenerationBehavior: ImplementTypePropertyGenerationBehavior.PreferAutoProperties) + }; + await TestInRegularAndScript1Async( @"abstract class AbstractClass { @@ -1664,9 +1675,7 @@ class C : AbstractClass public override int ReadOnlyProp { get; } public override int ReadWriteProp { get; set; } public override int WriteOnlyProp { set => throw new System.NotImplementedException(); } -}", parameters: new TestParameters(options: Option( - ImplementTypeOptions.Metadata.PropertyGenerationBehavior, - ImplementTypePropertyGenerationBehavior.PreferAutoProperties))); +}", parameters: new TestParameters(codeActionOptions: options)); } [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementAbstractClass)] diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs index f072bdc5b8417..093dd5c8b8500 100644 --- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; @@ -7286,10 +7287,10 @@ void M() { } public int Prop => throw new System.NotImplementedException(); }", - Options = + CodeActionOptions = CodeActionOptions.Default with { - { ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd }, - }, + ImplementTypeOptions = new ImplementTypeOptions(InsertionBehavior: ImplementTypeInsertionBehavior.AtTheEnd) + } }.RunAsync(); } @@ -7461,10 +7462,10 @@ class Class : IInterface public int ReadWriteProp { get; set; } public int WriteOnlyProp { set => throw new System.NotImplementedException(); } }", - Options = + CodeActionOptions = CodeActionOptions.Default with { - { ImplementTypeOptions.Metadata.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties }, - }, + ImplementTypeOptions = new ImplementTypeOptions(PropertyGenerationBehavior: ImplementTypePropertyGenerationBehavior.PreferAutoProperties) + } }.RunAsync(); } diff --git a/src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs b/src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs index 55b01386e6e7f..bc8bccac358ba 100644 --- a/src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs +++ b/src/EditorFeatures/CSharpTest/Wrapping/AbstractWrappingTests.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.SymbolSearch; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Wrapping @@ -19,7 +20,9 @@ protected sealed override ImmutableArray MassageActions(ImmutableArr => FlattenActions(actions); private protected static CodeActionOptions GetIndentionColumn(int column) - => new(SymbolSearchOptions.Default, WrappingColumn: column); + => new(SymbolSearchOptions.Default, + ImplementTypeOptions.Default, + WrappingColumn: column); protected Task TestAllWrappingCasesAsync( string input, diff --git a/src/EditorFeatures/Core/ImplementType/ImplementTypeOptionsStorage.cs b/src/EditorFeatures/Core/ImplementType/ImplementTypeOptionsStorage.cs new file mode 100644 index 0000000000000..139acd773f8a2 --- /dev/null +++ b/src/EditorFeatures/Core/ImplementType/ImplementTypeOptionsStorage.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.ImplementType +{ + internal static class ImplementTypeOptionsStorage + { + public static ImplementTypeOptions GetImplementTypeOptions(this IGlobalOptionService globalOptions, string language) + => new( + InsertionBehavior: globalOptions.GetOption(InsertionBehavior, language), + PropertyGenerationBehavior: globalOptions.GetOption(PropertyGenerationBehavior, language)); + + private const string FeatureName = "ImplementTypeOptions"; + + public static readonly PerLanguageOption2 InsertionBehavior = + new(FeatureName, + "InsertionBehavior", + defaultValue: ImplementTypeOptions.Default.InsertionBehavior, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.ImplementTypeOptions.InsertionBehavior")); + + public static readonly PerLanguageOption2 PropertyGenerationBehavior = + new(FeatureName, + "PropertyGenerationBehavior", + defaultValue: ImplementTypeOptions.Default.PropertyGenerationBehavior, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.ImplementTypeOptions.PropertyGenerationBehavior")); + } +} diff --git a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionOptionsStorage.cs b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionOptionsStorage.cs index c4a5784c02f94..602b692419fdd 100644 --- a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionOptionsStorage.cs +++ b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionOptionsStorage.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.SymbolSearch; @@ -20,6 +21,7 @@ internal static CodeActionOptions GetBlockingCodeActionOptions(this IGlobalOptio private static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, string language, bool isBlocking) => new( SearchOptions: globalOptions.GetSymbolSearchOptions(language), + ImplementTypeOptions: globalOptions.GetImplementTypeOptions(language), HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, language), IsBlocking: isBlocking); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index aa218035e8803..7997a06582b08 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -376,6 +376,7 @@ internal Task TestInRegularAndScriptAsync( CodeActionPriority? priority = null, CompilationOptions compilationOptions = null, OptionsCollection options = null, + CodeActionOptions? codeActionOptions = null, object fixProviderData = null, ParseOptions parseOptions = null, string title = null, @@ -383,7 +384,7 @@ internal Task TestInRegularAndScriptAsync( { return TestInRegularAndScript1Async( initialMarkup, expectedMarkup, index, - new TestParameters(parseOptions, compilationOptions, options, CodeActionOptions.Default, fixProviderData, index, priority, title: title, testHost: testHost)); + new TestParameters(parseOptions, compilationOptions, options, codeActionOptions ?? CodeActionOptions.Default, fixProviderData, index, priority, title: title, testHost: testHost)); } internal Task TestInRegularAndScript1Async( diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs index a53c5d8cfd2c0..1aa10174c9630 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -16,6 +16,8 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Text; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.Shared.Utilities; #if !CODE_STYLE using Roslyn.Utilities; @@ -73,6 +75,13 @@ public Test() /// internal OptionsCollection Options => _sharedState.Options; +#if !CODE_STYLE + internal CodeActionOptions CodeActionOptions + { + get => _sharedState.CodeActionOptions; + set => _sharedState.CodeActionOptions = value; + } +#endif /// public string? EditorConfig { @@ -97,7 +106,31 @@ protected override async Task RunImplAsync(CancellationToken cancellationToken = #if !CODE_STYLE protected override AnalyzerOptions GetAnalyzerOptions(Project project) - => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project); + + protected override CodeFixContext CreateCodeFixContext(Document document, TextSpan span, ImmutableArray diagnostics, Action> registerCodeFix, CancellationToken cancellationToken) + => new(document, span, diagnostics, registerCodeFix, _sharedState.CodeActionOptions, cancellationToken); + + protected override FixAllContext CreateFixAllContext( + Document? document, + Project project, + CodeFixProvider codeFixProvider, + FixAllScope scope, + string? codeActionEquivalenceKey, + IEnumerable diagnosticIds, + FixAllContext.DiagnosticProvider fixAllDiagnosticProvider, + CancellationToken cancellationToken) + => new(new FixAllState( + fixAllProvider: null, + document, + project, + codeFixProvider, + scope, + codeActionEquivalenceKey, + diagnosticIds, + fixAllDiagnosticProvider, + _ => _sharedState.CodeActionOptions), + new ProgressTracker(), cancellationToken); #endif protected override Diagnostic? TrySelectDiagnosticToFix(ImmutableArray fixableDiagnostics) diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeRefactoringVerifier`1+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeRefactoringVerifier`1+Test.cs index 8012ac3db1bef..4218e06bae0d7 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeRefactoringVerifier`1+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeRefactoringVerifier`1+Test.cs @@ -102,7 +102,7 @@ protected override ImmutableArray FilterCodeActions(ImmutableArray new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project); /// /// The we want this test to run in. Defaults to if unspecified. diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs index c8679afa8e11c..b5229719dac52 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Testing.Verifiers; #if !CODE_STYLE +using Microsoft.CodeAnalysis.CodeActions; using Roslyn.Utilities; #endif @@ -45,6 +46,9 @@ public SharedVerifierState(AnalyzerTest test, string defaultFileE /// internal OptionsCollection Options { get; } +#if !CODE_STYLE + internal CodeActionOptions CodeActionOptions { get; set; } +#endif internal void Apply() { var (analyzerConfigSource, remainingOptions) = CodeFixVerifierHelper.ConvertOptionsToAnalyzerConfig(_defaultFileExt, EditorConfig, Options); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs index 1ec477ed7b4a6..35e6c68133148 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -88,7 +88,7 @@ protected override async Task RunImplAsync(CancellationToken cancellationToken = #if !CODE_STYLE protected override AnalyzerOptions GetAnalyzerOptions(Project project) - => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project); #endif protected override Diagnostic? TrySelectDiagnosticToFix(ImmutableArray fixableDiagnostics) diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeRefactoringVerifier`1+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeRefactoringVerifier`1+Test.cs index 727be29d9a845..c27d8f86a8a86 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeRefactoringVerifier`1+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeRefactoringVerifier`1+Test.cs @@ -76,7 +76,7 @@ protected override async Task RunImplAsync(CancellationToken cancellationToken) #if !CODE_STYLE protected override AnalyzerOptions GetAnalyzerOptions(Project project) - => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution); + => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project); #endif } } diff --git a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs index 9ad9af6c9bc95..3903bebbb08e5 100644 --- a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs +++ b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs @@ -266,9 +266,9 @@ public void TestPreviewWorkspaceDoesNotLeakSolution() private static void ExecuteAnalyzers(PreviewWorkspace previewWorkspace, ImmutableArray analyzers) { var analyzerOptions = new AnalyzerOptions(additionalFiles: ImmutableArray.Empty); - var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(analyzerOptions, previewWorkspace.CurrentSolution); - var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(workspaceAnalyzerOptions, onAnalyzerException: null, concurrentAnalysis: false, logAnalyzerExecutionTime: false); var project = previewWorkspace.CurrentSolution.Projects.Single(); + var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(analyzerOptions, project); + var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(workspaceAnalyzerOptions, onAnalyzerException: null, concurrentAnalysis: false, logAnalyzerExecutionTime: false); var compilation = project.GetRequiredCompilationAsync(CancellationToken.None).Result; var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, compilationWithAnalyzersOptions); var result = compilationWithAnalyzers.GetAnalysisResultAsync(CancellationToken.None).Result; diff --git a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb index 3c7167f549ea6..1a179ce52af3a 100644 --- a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb @@ -163,7 +163,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers Return False End If - Dim options = ImplementTypeOptions.From(document.Project) + Dim options = _globalOptions.GetImplementTypeOptions(document.Project.Language) Dim newDocument = TryGetNewDocument(document, options, identifier, cancellationToken) If newDocument Is Nothing Then diff --git a/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb b/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb index 74bd618c3f1b0..0d19bbdab8213 100644 --- a/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb +++ b/src/EditorFeatures/VisualBasicTest/ImplementAbstractClass/ImplementAbstractClassTests.vb @@ -2,10 +2,12 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics Imports Microsoft.CodeAnalysis.ImplementType +Imports Microsoft.CodeAnalysis.SymbolSearch Imports Microsoft.CodeAnalysis.VisualBasic.ImplementAbstractClass Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ImplementAbstractClass @@ -630,9 +632,9 @@ Class C Throw New System.NotImplementedException() End Set End Property -End Class", parameters:=New TestParameters(options:=[Option]( - ImplementTypeOptions.Metadata.PropertyGenerationBehavior, - ImplementTypePropertyGenerationBehavior.PreferAutoProperties))) +End Class", parameters:=New TestParameters(codeActionOptions:=New CodeActionOptions( + SearchOptions:=SymbolSearchOptions.Default, + ImplementTypeOptions:=New ImplementTypeOptions(PropertyGenerationBehavior:=ImplementTypePropertyGenerationBehavior.PreferAutoProperties)))) End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb b/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb index f915762663037..31bd6cd863b48 100644 --- a/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb @@ -2,10 +2,12 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics Imports Microsoft.CodeAnalysis.ImplementType +Imports Microsoft.CodeAnalysis.SymbolSearch Imports Microsoft.CodeAnalysis.VisualBasic.ImplementInterface Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ImplementInterface @@ -4646,9 +4648,9 @@ class Class Throw New System.NotImplementedException() End Set End Property -end class", parameters:=New TestParameters(options:=[Option]( - ImplementTypeOptions.Metadata.PropertyGenerationBehavior, - ImplementTypePropertyGenerationBehavior.PreferAutoProperties))) +end class", parameters:=New TestParameters(codeActionOptions:=New CodeActionOptions( + SearchOptions:=SymbolSearchOptions.Default, + ImplementTypeOptions:=New ImplementTypeOptions(PropertyGenerationBehavior:=ImplementTypePropertyGenerationBehavior.PreferAutoProperties)))) End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb b/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb index 01c9887ad6705..0bd73c3c86d56 100644 --- a/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb @@ -6,6 +6,7 @@ Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings +Imports Microsoft.CodeAnalysis.ImplementType Imports Microsoft.CodeAnalysis.SymbolSearch Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping @@ -17,7 +18,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping End Function Private Protected Shared Function GetIndentionColumn(column As Integer) As CodeActionOptions - Return New CodeActionOptions(SymbolSearchOptions.Default, WrappingColumn:=column) + Return New CodeActionOptions( + SymbolSearchOptions.Default, + ImplementTypeOptions.Default, + WrappingColumn:=column) End Function Protected Function TestAllWrappingCasesAsync( diff --git a/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs b/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs index ffaa2974eb11c..34e68a1f1bd02 100644 --- a/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs @@ -51,11 +51,10 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var service = document.GetRequiredLanguageService(); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var options = ImplementTypeOptions.From(document.Project); var actions = token.Parent.GetAncestorsOrThis() .Where(_interfaceName) - .Select(n => service.GetCodeActions(document, options, model, n, cancellationToken)) + .Select(n => service.GetCodeActions(document, context.Options.ImplementTypeOptions, model, n, cancellationToken)) .FirstOrDefault(a => !a.IsEmpty); if (actions.IsDefaultOrEmpty) diff --git a/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs b/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs index fb06d30cab4e1..d25f30c640d95 100644 --- a/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs +++ b/src/Features/Core/Portable/Diagnostics/AnalyzerHelper.cs @@ -266,7 +266,7 @@ public static IEnumerable ToAnalyzerPerformanceInfo(thi // in IDE, we always set concurrentAnalysis == false otherwise, we can get into thread starvation due to // async being used with synchronous blocking concurrency. var analyzerOptions = new CompilationWithAnalyzersOptions( - options: new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution), + options: new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project), onAnalyzerException: null, analyzerExceptionFilter: GetAnalyzerExceptionFilter(), concurrentAnalysis: false, diff --git a/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs b/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs index 180f99a8a86d7..f2d85b9126ebc 100644 --- a/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs +++ b/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs @@ -21,26 +21,19 @@ internal sealed class WorkspaceAnalyzerOptions : AnalyzerOptions { private readonly Solution _solution; - // IDE options for each encountered language - private ImmutableDictionary _ideOptionsCache; + public IdeAnalyzerOptions IdeOptions { get; } - public WorkspaceAnalyzerOptions(AnalyzerOptions options, Solution solution) + public WorkspaceAnalyzerOptions(AnalyzerOptions options, Solution solution, IdeAnalyzerOptions ideOptions) : base(options.AdditionalFiles, options.AnalyzerConfigOptionsProvider) { _solution = solution; - _ideOptionsCache = ImmutableDictionary.Empty; + IdeOptions = ideOptions; } - public IdeAnalyzerOptions GetIdeOptions(string language) - => ImmutableInterlocked.GetOrAdd( - ref _ideOptionsCache, - language, - static (language, solution) => new IdeAnalyzerOptions( - FadeOutUnusedImports: solution.Options.GetOption(Fading.FadingOptions.Metadata.FadeOutUnusedImports, language), - FadeOutUnreachableCode: solution.Options.GetOption(Fading.FadingOptions.Metadata.FadeOutUnreachableCode, language), - ReportInvalidPlaceholdersInStringDotFormatCalls: solution.Options.GetOption(ValidateFormatString.ValidateFormatStringOption.ReportInvalidPlaceholdersInStringDotFormatCalls, language), - ReportInvalidRegexPatterns: solution.Options.GetOption(Features.EmbeddedLanguages.RegularExpressions.LanguageServices.RegularExpressionsOptions.ReportInvalidRegexPatterns, language)), - _solution); + public WorkspaceAnalyzerOptions(AnalyzerOptions options, Project project) + : this(options, project.Solution, IdeAnalyzerOptions.FromProject(project)) + { + } public HostWorkspaceServices Services => _solution.Workspace.Services; diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs index 9dc30d83f5350..6c792f00bea7e 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs @@ -43,7 +43,7 @@ public void Analyze(SemanticModelAnalysisContext context) var syntaxTree = semanticModel.SyntaxTree; var cancellationToken = context.CancellationToken; - var option = context.GetIdeOptions().ReportInvalidRegexPatterns; + var option = context.Options.GetIdeOptions().ReportInvalidRegexPatterns; if (!option) return; diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegularExpressionsOptions.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegularExpressionsOptions.cs index b95e2f02834d9..6285a663b2816 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegularExpressionsOptions.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegularExpressionsOptions.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using System.Composition; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options.Providers; @@ -17,7 +18,7 @@ internal class RegularExpressionsOptions new( nameof(RegularExpressionsOptions), nameof(ReportInvalidRegexPatterns), - defaultValue: true, + IdeAnalyzerOptions.Default.ReportInvalidRegexPatterns, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ReportInvalidRegexPatterns")); public static PerLanguageOption2 HighlightRelatedRegexComponentsUnderCursor = diff --git a/src/Features/Core/Portable/Fading/FadingOptions.cs b/src/Features/Core/Portable/Fading/FadingOptions.cs index 152f0217ad468..9349c606b1bd4 100644 --- a/src/Features/Core/Portable/Fading/FadingOptions.cs +++ b/src/Features/Core/Portable/Fading/FadingOptions.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using System.Composition; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options.Providers; @@ -29,11 +30,11 @@ public Metadata() private const string FeatureName = "FadingOptions"; public static readonly PerLanguageOption2 FadeOutUnusedImports = new( - FeatureName, "FadeOutUnusedImports", defaultValue: true, + FeatureName, "FadeOutUnusedImports", IdeAnalyzerOptions.Default.FadeOutUnusedImports, storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.FadeOutUnusedImports")); public static readonly PerLanguageOption2 FadeOutUnreachableCode = new( - FeatureName, "FadeOutUnreachableCode", defaultValue: true, + FeatureName, "FadeOutUnreachableCode", IdeAnalyzerOptions.Default.FadeOutUnreachableCode, storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.FadeOutUnreachableCode")); } } diff --git a/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs b/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs index 6295abf449ee6..7ced21bcb6e74 100644 --- a/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs +++ b/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs @@ -41,9 +41,8 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) if (classNode == null) return; - var options = ImplementTypeOptions.From(document.Project); var data = await ImplementAbstractClassData.TryGetDataAsync( - document, classNode, GetClassIdentifier(classNode), options, cancellationToken).ConfigureAwait(false); + document, classNode, GetClassIdentifier(classNode), context.Options.ImplementTypeOptions, cancellationToken).ConfigureAwait(false); if (data == null) return; diff --git a/src/Features/Core/Portable/ImplementType/ImplementTypeOptions.cs b/src/Features/Core/Portable/ImplementType/ImplementTypeOptions.cs deleted file mode 100644 index 2a543b075ce87..0000000000000 --- a/src/Features/Core/Portable/ImplementType/ImplementTypeOptions.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Composition; -using System.Collections.Immutable; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options.Providers; - -namespace Microsoft.CodeAnalysis.ImplementType -{ - internal readonly record struct ImplementTypeOptions( - ImplementTypeInsertionBehavior InsertionBehavior, - ImplementTypePropertyGenerationBehavior PropertyGenerationBehavior) - { - public static ImplementTypeOptions From(Project project) - => From(project.Solution.Options, project.Language); - - public static ImplementTypeOptions From(OptionSet options, string language) - => new( - InsertionBehavior: options.GetOption(Metadata.InsertionBehavior, language), - PropertyGenerationBehavior: options.GetOption(Metadata.PropertyGenerationBehavior, language)); - - [ExportSolutionOptionProvider, Shared] - internal sealed class Metadata : IOptionProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public Metadata() - { - } - - public ImmutableArray Options { get; } = ImmutableArray.Create( - InsertionBehavior, - PropertyGenerationBehavior); - - private const string FeatureName = "ImplementTypeOptions"; - - public static readonly PerLanguageOption2 InsertionBehavior = - new(FeatureName, - "InsertionBehavior", - defaultValue: ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.ImplementTypeOptions.InsertionBehavior")); - - public static readonly PerLanguageOption2 PropertyGenerationBehavior = - new(FeatureName, - "PropertyGenerationBehavior", - defaultValue: ImplementTypePropertyGenerationBehavior.PreferThrowingProperties, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.ImplementTypeOptions.PropertyGenerationBehavior")); - } - } -} diff --git a/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb b/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb index 4d4081405d9db..07412631d3d9c 100644 --- a/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb @@ -58,11 +58,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ImplementInterface Return End If - Dim options = ImplementTypeOptions.From(document.Project) Dim service = document.GetLanguageService(Of IImplementInterfaceService)() Dim actions = service.GetCodeActions( document, - options, + context.Options.ImplementTypeOptions, Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False), typeNode, cancellationToken) diff --git a/src/Tools/AnalyzerRunner/DiagnosticAnalyzerRunner.cs b/src/Tools/AnalyzerRunner/DiagnosticAnalyzerRunner.cs index 2cc06bb7721bf..2c5720ee8f2a8 100644 --- a/src/Tools/AnalyzerRunner/DiagnosticAnalyzerRunner.cs +++ b/src/Tools/AnalyzerRunner/DiagnosticAnalyzerRunner.cs @@ -186,7 +186,7 @@ private static async Task TestDocumentPerformanceAs var stopwatch = PerformanceTracker.StartNew(); for (int i = 0; i < analyzerOptionsInternal.TestDocumentIterations; i++) { - var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution); + var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project); CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(languageAnalyzers, new CompilationWithAnalyzersOptions(workspaceAnalyzerOptions, null, analyzerOptionsInternal.RunConcurrent, logAnalyzerExecutionTime: true, reportSuppressedDiagnostics: analyzerOptionsInternal.ReportSuppressedDiagnostics)); SyntaxTree tree = await project.GetDocument(documentId).GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); @@ -393,7 +393,7 @@ private static async Task GetProjectAnalysisResultAsync( Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var newCompilation = compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(compilation.SyntaxTrees); - var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution); + var workspaceAnalyzerOptions = new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project); CompilationWithAnalyzers compilationWithAnalyzers = newCompilation.WithAnalyzers(analyzers, new CompilationWithAnalyzersOptions(workspaceAnalyzerOptions, null, analyzerOptionsInternal.RunConcurrent, logAnalyzerExecutionTime: true, reportSuppressedDiagnostics: analyzerOptionsInternal.ReportSuppressedDiagnostics)); var analystResult = await compilationWithAnalyzers.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false); return analystResult; diff --git a/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs new file mode 100644 index 0000000000000..f507e20d2587c --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs @@ -0,0 +1,134 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CSharp.Formatting +{ + internal enum OmniSharpLabelPositionOptions + { + LeftMost = LabelPositionOptions.LeftMost, + OneLess = LabelPositionOptions.OneLess, + NoIndent = LabelPositionOptions.NoIndent + } + + internal enum OmniSharpBinaryOperatorSpacingOptions + { + Single = BinaryOperatorSpacingOptions.Single, + Ignore = BinaryOperatorSpacingOptions.Ignore, + Remove = BinaryOperatorSpacingOptions.Remove + } + + internal static class OmniSharpSyntaxFormattingOptionsFactory + { + public static OmniSharpSyntaxFormattingOptionsWrapper Create( + bool useTabs, + int tabSize, + int indentationSize, + string newLine, + bool separateImportDirectiveGroups, + bool spacingAfterMethodDeclarationName, + bool spaceWithinMethodDeclarationParenthesis, + bool spaceBetweenEmptyMethodDeclarationParentheses, + bool spaceAfterMethodCallName, + bool spaceWithinMethodCallParentheses, + bool spaceBetweenEmptyMethodCallParentheses, + bool spaceAfterControlFlowStatementKeyword, + bool spaceWithinExpressionParentheses, + bool spaceWithinCastParentheses, + bool spaceWithinOtherParentheses, + bool spaceAfterCast, + bool spaceBeforeOpenSquareBracket, + bool spaceBetweenEmptySquareBrackets, + bool spaceWithinSquareBrackets, + bool spaceAfterColonInBaseTypeDeclaration, + bool spaceAfterComma, + bool spaceAfterDot, + bool spaceAfterSemicolonsInForStatement, + bool spaceBeforeColonInBaseTypeDeclaration, + bool spaceBeforeComma, + bool spaceBeforeDot, + bool spaceBeforeSemicolonsInForStatement, + OmniSharpBinaryOperatorSpacingOptions spacingAroundBinaryOperator, + bool indentBraces, + bool indentBlock, + bool indentSwitchSection, + bool indentSwitchCaseSection, + bool indentSwitchCaseSectionWhenBlock, + OmniSharpLabelPositionOptions labelPositioning, + bool wrappingPreserveSingleLine, + bool wrappingKeepStatementsOnSingleLine, + bool newLinesForBracesInTypes, + bool newLinesForBracesInMethods, + bool newLinesForBracesInProperties, + bool newLinesForBracesInAccessors, + bool newLinesForBracesInAnonymousMethods, + bool newLinesForBracesInControlBlocks, + bool newLinesForBracesInAnonymousTypes, + bool newLinesForBracesInObjectCollectionArrayInitializers, + bool newLinesForBracesInLambdaExpressionBody, + bool newLineForElse, + bool newLineForCatch, + bool newLineForFinally, + bool newLineForMembersInObjectInit, + bool newLineForMembersInAnonymousTypes, + bool newLineForClausesInQuery) + => new(new CSharpSyntaxFormattingOptions( + useTabs: useTabs, + tabSize: tabSize, + indentationSize: indentationSize, + newLine: newLine, + separateImportDirectiveGroups: separateImportDirectiveGroups, + spacing: + (spacingAfterMethodDeclarationName ? SpacePlacement.AfterMethodDeclarationName : 0) | + (spaceBetweenEmptyMethodDeclarationParentheses ? SpacePlacement.BetweenEmptyMethodDeclarationParentheses : 0) | + (spaceWithinMethodDeclarationParenthesis ? SpacePlacement.WithinMethodDeclarationParenthesis : 0) | + (spaceAfterMethodCallName ? SpacePlacement.AfterMethodCallName : 0) | + (spaceBetweenEmptyMethodCallParentheses ? SpacePlacement.BetweenEmptyMethodCallParentheses : 0) | + (spaceWithinMethodCallParentheses ? SpacePlacement.WithinMethodCallParentheses : 0) | + (spaceAfterControlFlowStatementKeyword ? SpacePlacement.AfterControlFlowStatementKeyword : 0) | + (spaceWithinExpressionParentheses ? SpacePlacement.WithinExpressionParentheses : 0) | + (spaceWithinCastParentheses ? SpacePlacement.WithinCastParentheses : 0) | + (spaceBeforeSemicolonsInForStatement ? SpacePlacement.BeforeSemicolonsInForStatement : 0) | + (spaceAfterSemicolonsInForStatement ? SpacePlacement.AfterSemicolonsInForStatement : 0) | + (spaceWithinOtherParentheses ? SpacePlacement.WithinOtherParentheses : 0) | + (spaceAfterCast ? SpacePlacement.AfterCast : 0) | + (spaceBeforeOpenSquareBracket ? SpacePlacement.BeforeOpenSquareBracket : 0) | + (spaceBetweenEmptySquareBrackets ? SpacePlacement.BetweenEmptySquareBrackets : 0) | + (spaceWithinSquareBrackets ? SpacePlacement.WithinSquareBrackets : 0) | + (spaceAfterColonInBaseTypeDeclaration ? SpacePlacement.AfterColonInBaseTypeDeclaration : 0) | + (spaceBeforeColonInBaseTypeDeclaration ? SpacePlacement.BeforeColonInBaseTypeDeclaration : 0) | + (spaceAfterComma ? SpacePlacement.AfterComma : 0) | + (spaceBeforeComma ? SpacePlacement.BeforeComma : 0) | + (spaceAfterDot ? SpacePlacement.AfterDot : 0) | + (spaceBeforeDot ? SpacePlacement.BeforeDot : 0), + spacingAroundBinaryOperator: (BinaryOperatorSpacingOptions)spacingAroundBinaryOperator, + newLines: + (newLineForMembersInObjectInit ? NewLinePlacement.BeforeMembersInObjectInitializers : 0) | + (newLineForMembersInAnonymousTypes ? NewLinePlacement.BeforeMembersInAnonymousTypes : 0) | + (newLineForElse ? NewLinePlacement.BeforeElse : 0) | + (newLineForCatch ? NewLinePlacement.BeforeCatch : 0) | + (newLineForFinally ? NewLinePlacement.BeforeFinally : 0) | + (newLinesForBracesInTypes ? NewLinePlacement.BeforeOpenBraceInTypes : 0) | + (newLinesForBracesInAnonymousTypes ? NewLinePlacement.BeforeOpenBraceInAnonymousTypes : 0) | + (newLinesForBracesInObjectCollectionArrayInitializers ? NewLinePlacement.BeforeOpenBraceInObjectCollectionArrayInitializers : 0) | + (newLinesForBracesInProperties ? NewLinePlacement.BeforeOpenBraceInProperties : 0) | + (newLinesForBracesInMethods ? NewLinePlacement.BeforeOpenBraceInMethods : 0) | + (newLinesForBracesInAccessors ? NewLinePlacement.BeforeOpenBraceInAccessors : 0) | + (newLinesForBracesInAnonymousMethods ? NewLinePlacement.BeforeOpenBraceInAnonymousMethods : 0) | + (newLinesForBracesInLambdaExpressionBody ? NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody : 0) | + (newLinesForBracesInControlBlocks ? NewLinePlacement.BeforeOpenBraceInControlBlocks : 0) | + (newLineForClausesInQuery ? NewLinePlacement.BetweenQueryExpressionClauses : 0), + labelPositioning: (LabelPositionOptions)labelPositioning, + indentation: + (indentBraces ? IndentationPlacement.Braces : 0) | + (indentBlock ? IndentationPlacement.BlockContents : 0) | + (indentSwitchCaseSection ? IndentationPlacement.SwitchCaseContents : 0) | + (indentSwitchCaseSectionWhenBlock ? IndentationPlacement.SwitchCaseContentsWhenBlock : 0) | + (indentSwitchSection ? IndentationPlacement.SwitchSection : 0), + wrappingKeepStatementsOnSingleLine: wrappingKeepStatementsOnSingleLine, + wrappingPreserveSingleLine: wrappingPreserveSingleLine)); + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/Analyzers/OmniSharpWorkspaceAnalyzerOptionsFactory.cs b/src/Tools/ExternalAccess/OmniSharp/Analyzers/OmniSharpWorkspaceAnalyzerOptionsFactory.cs new file mode 100644 index 0000000000000..bf6932ceaea87 --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/Analyzers/OmniSharpWorkspaceAnalyzerOptionsFactory.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Analyzers +{ + internal static class OmniSharpWorkspaceAnalyzerOptionsFactory + { + public static AnalyzerOptions Create(Solution solution, AnalyzerOptions options) + => new WorkspaceAnalyzerOptions(options, solution, IdeAnalyzerOptions.Default); + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs new file mode 100644 index 0000000000000..b4f31dd36f8ba --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Immutable; +using System.Threading; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.ImplementType; +using Microsoft.CodeAnalysis.ImplementType; +using Microsoft.CodeAnalysis.SymbolSearch; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CodeActions +{ + internal static class OmniSharpCodeFixContextFactory + { + public static CodeFixContext Create( + Document document, + TextSpan span, + ImmutableArray diagnostics, + Action> registerCodeFix, + OmniSharpImplementTypeOptions implementTypeOptions, + CancellationToken cancellationToken) + => new(document, span, diagnostics, registerCodeFix, GetCodeActionOptions(implementTypeOptions), cancellationToken); + + private static CodeActionOptions GetCodeActionOptions(OmniSharpImplementTypeOptions implementTypeOptions) + => new( + SymbolSearchOptions.Default, + new ImplementTypeOptions( + InsertionBehavior: (ImplementTypeInsertionBehavior)implementTypeOptions.InsertionBehavior, + PropertyGenerationBehavior: (ImplementTypePropertyGenerationBehavior)implementTypeOptions.PropertyGenerationBehavior)); + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs new file mode 100644 index 0000000000000..29cd5c5a935a4 --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.DocumentationComments; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.DocumentationComments +{ + internal readonly struct OmniSharpDocumentationCommentOptionsWrapper + { + internal readonly DocumentationCommentOptions UnderlyingObject; + + internal OmniSharpDocumentationCommentOptionsWrapper(DocumentationCommentOptions underlyingObject) + => UnderlyingObject = underlyingObject; + + public OmniSharpDocumentationCommentOptionsWrapper( + bool autoXmlDocCommentGeneration, + int tabSize, + bool useTabs, + string newLine) + : this(new(autoXmlDocCommentGeneration, tabSize, useTabs, newLine)) + { + } + + public static async ValueTask FromDocumentAsync( + Document document, + bool autoXmlDocCommentGeneration, + CancellationToken cancellationToken) + { + var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + return new(DocumentationCommentOptions.From(documentOptions) with { AutoXmlDocCommentGeneration = autoXmlDocCommentGeneration }); + } + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentSnippet.cs b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentSnippet.cs new file mode 100644 index 0000000000000..8f1080792120a --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentSnippet.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.DocumentationComments +{ + internal sealed class OmniSharpDocumentationCommentSnippet + { + /// + /// The span in the original text that should be replaced with the documentation comment. + /// + public TextSpan SpanToReplace { get; } + + /// + /// The documentation comment text to replace the span with + /// + public string SnippetText { get; } + + /// + /// The offset within where the caret should be positioned after replacement + /// + public int CaretOffset { get; } + + internal OmniSharpDocumentationCommentSnippet(TextSpan spanToReplace, string snippetText, int caretOffset) + { + SpanToReplace = spanToReplace; + SnippetText = snippetText; + CaretOffset = caretOffset; + } + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentsSnippetService.cs b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentsSnippetService.cs index cd74c914f1153..33c5570262629 100644 --- a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentsSnippetService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentsSnippetService.cs @@ -5,7 +5,6 @@ using System.Threading; using Microsoft.CodeAnalysis.DocumentationComments; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -18,25 +17,11 @@ internal static class OmniSharpDocumentationCommentsSnippetService SyntaxTree syntaxTree, SourceText text, int position, - DocumentOptionSet options, + OmniSharpDocumentationCommentOptionsWrapper options, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); - var docCommentOptions = DocumentationCommentOptions.From(options); - return Translate(service.GetDocumentationCommentSnippetOnCharacterTyped(syntaxTree, text, position, docCommentOptions, cancellationToken)); - } - - public static OmniSharpDocumentationCommentSnippet? GetDocumentationCommentSnippetOnCommandInvoke( - Document document, - SyntaxTree syntaxTree, - SourceText text, - int position, - DocumentOptionSet options, - CancellationToken cancellationToken) - { - var service = document.GetRequiredLanguageService(); - var docCommentOptions = DocumentationCommentOptions.From(options); - return Translate(service.GetDocumentationCommentSnippetOnCommandInvoke(syntaxTree, text, position, docCommentOptions, cancellationToken)); + return Translate(service.GetDocumentationCommentSnippetOnCharacterTyped(syntaxTree, text, position, options.UnderlyingObject, cancellationToken)); } public static OmniSharpDocumentationCommentSnippet? GetDocumentationCommentSnippetOnEnterTyped( @@ -44,51 +29,14 @@ internal static class OmniSharpDocumentationCommentsSnippetService SyntaxTree syntaxTree, SourceText text, int position, - DocumentOptionSet options, + OmniSharpDocumentationCommentOptionsWrapper options, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); - var docCommentOptions = DocumentationCommentOptions.From(options); - return Translate(service.GetDocumentationCommentSnippetOnEnterTyped(syntaxTree, text, position, docCommentOptions, cancellationToken)); - } - - public static OmniSharpDocumentationCommentSnippet? GetDocumentationCommentSnippetFromPreviousLine( - Document document, - DocumentOptionSet options, - TextLine currentLine, - TextLine previousLine) - { - var service = document.GetRequiredLanguageService(); - var docCommentOptions = DocumentationCommentOptions.From(options); - return Translate(service.GetDocumentationCommentSnippetFromPreviousLine(docCommentOptions, currentLine, previousLine)); + return Translate(service.GetDocumentationCommentSnippetOnEnterTyped(syntaxTree, text, position, options.UnderlyingObject, cancellationToken)); } private static OmniSharpDocumentationCommentSnippet? Translate(DocumentationCommentSnippet? result) => result == null ? null : new(result.SpanToReplace, result.SnippetText, result.CaretOffset); } - - internal sealed class OmniSharpDocumentationCommentSnippet - { - /// - /// The span in the original text that should be replaced with the documentation comment. - /// - public TextSpan SpanToReplace { get; } - - /// - /// The documentation comment text to replace the span with - /// - public string SnippetText { get; } - - /// - /// The offset within where the caret should be positioned after replacement - /// - public int CaretOffset { get; } - - internal OmniSharpDocumentationCommentSnippet(TextSpan spanToReplace, string snippetText, int caretOffset) - { - SpanToReplace = spanToReplace; - SnippetText = snippetText; - CaretOffset = caretOffset; - } - } } diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs new file mode 100644 index 0000000000000..cadbac84be4ea --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.OrganizeImports; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting +{ + internal static class OmniSharpFormatter + { + public static Task FormatAsync(Document document, IEnumerable? spans, OmniSharpSyntaxFormattingOptionsWrapper options, CancellationToken cancellationToken) + => Formatter.FormatAsync(document, spans, options.UnderlyingObject, rules: null, cancellationToken); + + public static async Task OrganizeImportsAsync(Document document, OmniSharpOrganizeImportsOptionsWrapper options, CancellationToken cancellationToken) + { + var organizeImportsService = document.GetLanguageService(); + if (organizeImportsService is null) + { + return document; + } + + return await organizeImportsService.OrganizeImportsAsync(document, options.UnderlyingObject, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs new file mode 100644 index 0000000000000..e6721fffbdcd7 --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.OrganizeImports; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting +{ + internal readonly struct OmniSharpOrganizeImportsOptionsWrapper + { + internal readonly OrganizeImportsOptions UnderlyingObject; + + private OmniSharpOrganizeImportsOptionsWrapper(OrganizeImportsOptions underlyingObject) + { + UnderlyingObject = underlyingObject; + } + + public OmniSharpOrganizeImportsOptionsWrapper( + bool placeSystemNamespaceFirst, + bool separateImportDirectiveGroups, + string newLine) : this(new OrganizeImportsOptions( + placeSystemNamespaceFirst, + separateImportDirectiveGroups, + newLine)) + { + } + + public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) + => new(await OrganizeImportsOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false)); + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs new file mode 100644 index 0000000000000..5ff2ccf0b9e0f --- /dev/null +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Formatting; + +namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting +{ + internal readonly record struct OmniSharpSyntaxFormattingOptionsWrapper + { + internal readonly SyntaxFormattingOptions UnderlyingObject; + + internal OmniSharpSyntaxFormattingOptionsWrapper(SyntaxFormattingOptions underlyingObject) + => UnderlyingObject = underlyingObject; + + public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) + { + var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + return new OmniSharpSyntaxFormattingOptionsWrapper(options); + } + } +} diff --git a/src/Tools/ExternalAccess/OmniSharp/ImplementType/OmniSharpImplementTypeOptions.cs b/src/Tools/ExternalAccess/OmniSharp/ImplementType/OmniSharpImplementTypeOptions.cs index 6a7c48179da23..9d4b8ab5cad31 100644 --- a/src/Tools/ExternalAccess/OmniSharp/ImplementType/OmniSharpImplementTypeOptions.cs +++ b/src/Tools/ExternalAccess/OmniSharp/ImplementType/OmniSharpImplementTypeOptions.cs @@ -3,24 +3,12 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.ImplementType; -using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.ImplementType { - internal static class OmniSharpImplementTypeOptions - { - public static OmniSharpImplementTypeInsertionBehavior GetInsertionBehavior(OptionSet options, string language) - => (OmniSharpImplementTypeInsertionBehavior)options.GetOption(ImplementTypeOptions.Metadata.InsertionBehavior, language); - - public static OptionSet SetInsertionBehavior(OptionSet options, string language, OmniSharpImplementTypeInsertionBehavior value) - => options.WithChangedOption(ImplementTypeOptions.Metadata.InsertionBehavior, language, (ImplementTypeInsertionBehavior)value); - - public static OmniSharpImplementTypePropertyGenerationBehavior GetPropertyGenerationBehavior(OptionSet options, string language) - => (OmniSharpImplementTypePropertyGenerationBehavior)options.GetOption(ImplementTypeOptions.Metadata.PropertyGenerationBehavior, language); - - public static OptionSet SetPropertyGenerationBehavior(OptionSet options, string language, OmniSharpImplementTypePropertyGenerationBehavior value) - => options.WithChangedOption(ImplementTypeOptions.Metadata.PropertyGenerationBehavior, language, (ImplementTypePropertyGenerationBehavior)value); - } + internal readonly record struct OmniSharpImplementTypeOptions( + OmniSharpImplementTypeInsertionBehavior InsertionBehavior, + OmniSharpImplementTypePropertyGenerationBehavior PropertyGenerationBehavior); internal enum OmniSharpImplementTypeInsertionBehavior { diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs index fbc2016f006c2..d21c61cedf71f 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs @@ -117,11 +117,11 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(DontPutOutOrRefOnStruct, ExtractMethodOptions.Metadata.DontPutOutOrRefOnStruct, LanguageNames.CSharp); - BindToOption(with_other_members_of_the_same_kind, ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, LanguageNames.CSharp); - BindToOption(at_the_end, ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd, LanguageNames.CSharp); + BindToOption(with_other_members_of_the_same_kind, ImplementTypeOptionsStorage.InsertionBehavior, ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, LanguageNames.CSharp); + BindToOption(at_the_end, ImplementTypeOptionsStorage.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd, LanguageNames.CSharp); - BindToOption(prefer_throwing_properties, ImplementTypeOptions.Metadata.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferThrowingProperties, LanguageNames.CSharp); - BindToOption(prefer_auto_properties, ImplementTypeOptions.Metadata.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties, LanguageNames.CSharp); + BindToOption(prefer_throwing_properties, ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferThrowingProperties, LanguageNames.CSharp); + BindToOption(prefer_auto_properties, ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties, LanguageNames.CSharp); BindToOption(Report_invalid_placeholders_in_string_dot_format_calls, ValidateFormatStringOption.ReportInvalidPlaceholdersInStringDotFormatCalls, LanguageNames.CSharp); diff --git a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs index ae55dec64f47b..71012b803c84f 100644 --- a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs @@ -162,7 +162,7 @@ void Method() var compilationWithAnalyzers = (await project.GetCompilationAsync()).WithAnalyzers( analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(), - new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution)); + new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project)); // no result for open file only analyzer unless forced var result = await runner.AnalyzeProjectAsync(project, compilationWithAnalyzers, forceExecuteAllAnalyzers: false, logPerformanceInfo: false, getTelemetryInfo: false, cancellationToken: CancellationToken.None); @@ -204,7 +204,7 @@ void Method() var analyzers = analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(); var compilationWithAnalyzers = (await project.GetCompilationAsync()) - .WithAnalyzers(analyzers, new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution)); + .WithAnalyzers(analyzers, new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project)); var result = await runner.AnalyzeProjectAsync(project, compilationWithAnalyzers, forceExecuteAllAnalyzers: false, logPerformanceInfo: false, getTelemetryInfo: false, cancellationToken: CancellationToken.None); @@ -229,7 +229,7 @@ private static async Task AnalyzeAsync(TestWorkspace w var analyzerDriver = (await project.GetCompilationAsync()).WithAnalyzers( analyzerReference.GetAnalyzers(project.Language).Where(a => a.GetType() == analyzerType).ToImmutableArray(), - new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution)); + new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project)); var result = await executor.AnalyzeProjectAsync(project, analyzerDriver, forceExecuteAllAnalyzers: true, logPerformanceInfo: false, getTelemetryInfo: false, cancellationToken); diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb index 59c1f2df469c8..3286c99c8c72c 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb +++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb @@ -137,11 +137,11 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options BindToOption(DontPutOutOrRefOnStruct, ExtractMethodOptions.Metadata.DontPutOutOrRefOnStruct, LanguageNames.VisualBasic) ' Implement Interface or Abstract Class - BindToOption(with_other_members_of_the_same_kind, ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, LanguageNames.VisualBasic) - BindToOption(at_the_end, ImplementTypeOptions.Metadata.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd, LanguageNames.VisualBasic) + BindToOption(with_other_members_of_the_same_kind, ImplementTypeOptionsStorage.InsertionBehavior, ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, LanguageNames.VisualBasic) + BindToOption(at_the_end, ImplementTypeOptionsStorage.InsertionBehavior, ImplementTypeInsertionBehavior.AtTheEnd, LanguageNames.VisualBasic) - BindToOption(prefer_throwing_properties, ImplementTypeOptions.Metadata.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferThrowingProperties, LanguageNames.VisualBasic) - BindToOption(prefer_auto_properties, ImplementTypeOptions.Metadata.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties, LanguageNames.VisualBasic) + BindToOption(prefer_throwing_properties, ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferThrowingProperties, LanguageNames.VisualBasic) + BindToOption(prefer_auto_properties, ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties, LanguageNames.VisualBasic) ' Inline hints BindToOption(DisplayAllHintsWhilePressingAltF1, InlineHintsViewOptions.DisplayAllHintsWhilePressingAltF1) diff --git a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs index 79a4fd226ad64..a3fdda566823b 100644 --- a/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs +++ b/src/VisualStudio/Xaml/Impl/Features/OrganizeImports/XamlOrganizeImportsService.cs @@ -28,11 +28,9 @@ public XamlOrganizeImportsService(IXamlOrganizeNamespacesService organizeService _organizeService = organizeService; } - public async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken) + public async Task OrganizeImportsAsync(Document document, OrganizeImportsOptions options, CancellationToken cancellationToken) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst); - return await _organizeService.OrganizeNamespacesAsync(document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false) ?? document; + return await _organizeService.OrganizeNamespacesAsync(document, options.PlaceSystemNamespaceFirst, cancellationToken).ConfigureAwait(false) ?? document; } public string SortImportsDisplayStringWithAccelerator diff --git a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj index 24fc04129f356..fb0483f25a55e 100644 --- a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj +++ b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj @@ -46,6 +46,7 @@ + diff --git a/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.Rewriter.cs b/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.Rewriter.cs index 1b71495259de6..c9d1bc1adb201 100644 --- a/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.Rewriter.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -13,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CSharp.OrganizeImports { internal partial class CSharpOrganizeImportsService { - private class Rewriter : CSharpSyntaxRewriter + private sealed class Rewriter : CSharpSyntaxRewriter { private readonly bool _placeSystemNamespaceFirst; private readonly bool _separateGroups; @@ -21,13 +23,11 @@ private class Rewriter : CSharpSyntaxRewriter public readonly IList TextChanges = new List(); - public Rewriter(bool placeSystemNamespaceFirst, - bool separateGroups, - SyntaxTrivia newLineTrivia) + public Rewriter(OrganizeImportsOptions options) { - _placeSystemNamespaceFirst = placeSystemNamespaceFirst; - _separateGroups = separateGroups; - _newLineTrivia = newLineTrivia; + _placeSystemNamespaceFirst = options.PlaceSystemNamespaceFirst; + _separateGroups = options.SeparateImportDirectiveGroups; + _newLineTrivia = CSharpSyntaxGeneratorInternal.Instance.EndOfLine(options.NewLine); } public override SyntaxNode VisitCompilationUnit(CompilationUnitSyntax node) diff --git a/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs b/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs index d659b6b46b022..e7fc05da2fca2 100644 --- a/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs +++ b/src/Workspaces/CSharp/Portable/OrganizeImports/CSharpOrganizeImportsService.cs @@ -25,16 +25,11 @@ public CSharpOrganizeImportsService() { } - public async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken) + public async Task OrganizeImportsAsync(Document document, OrganizeImportsOptions options, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst); - var blankLineBetweenGroups = options.GetOption(GenerationOptions.SeparateImportDirectiveGroups); - var newLineTrivia = CSharpSyntaxGeneratorInternal.Instance.EndOfLine(options.GetOption(FormattingOptions2.NewLine)); - - var rewriter = new Rewriter(placeSystemNamespaceFirst, blankLineBetweenGroups, newLineTrivia); + var rewriter = new Rewriter(options); var newRoot = rewriter.Visit(root); return document.WithSyntaxRoot(newRoot); diff --git a/src/Workspaces/Core/Portable/Formatting/Formatter.cs b/src/Workspaces/Core/Portable/Formatting/Formatter.cs index 95327a7f3fbe5..5574dc9dd9fb9 100644 --- a/src/Workspaces/Core/Portable/Formatting/Formatter.cs +++ b/src/Workspaces/Core/Portable/Formatting/Formatter.cs @@ -310,15 +310,16 @@ internal static IList GetFormattedTextChanges(SyntaxNode node, IEnum /// The document to organize. /// The cancellation token that the operation will observe. /// The document with organized imports. If the language does not support organizing imports, or if no changes were made, this method returns . - public static Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken = default) + public static async Task OrganizeImportsAsync(Document document, CancellationToken cancellationToken = default) { var organizeImportsService = document.GetLanguageService(); if (organizeImportsService is null) { - return Task.FromResult(document); + return document; } - return organizeImportsService.OrganizeImportsAsync(document, cancellationToken); + var options = await OrganizeImportsOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + return await organizeImportsService.OrganizeImportsAsync(document, options, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/Core/Portable/ImplementType/ImplementTypeInsertionBehavior.cs b/src/Workspaces/Core/Portable/ImplementType/ImplementTypeInsertionBehavior.cs similarity index 100% rename from src/Features/Core/Portable/ImplementType/ImplementTypeInsertionBehavior.cs rename to src/Workspaces/Core/Portable/ImplementType/ImplementTypeInsertionBehavior.cs diff --git a/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs b/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs new file mode 100644 index 0000000000000..307a8ffc66f5b --- /dev/null +++ b/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.Serialization; + +namespace Microsoft.CodeAnalysis.ImplementType +{ + [DataContract] + internal readonly record struct ImplementTypeOptions( + [property: DataMember(Order = 0)] ImplementTypeInsertionBehavior InsertionBehavior = ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, + [property: DataMember(Order = 1)] ImplementTypePropertyGenerationBehavior PropertyGenerationBehavior = ImplementTypePropertyGenerationBehavior.PreferThrowingProperties) + { + public ImplementTypeOptions() + : this(InsertionBehavior: ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind) + { + } + + public static readonly ImplementTypeOptions Default = new(); + } +} diff --git a/src/Features/Core/Portable/ImplementType/ImplementTypePropertyGenerationBehavior.cs b/src/Workspaces/Core/Portable/ImplementType/ImplementTypePropertyGenerationBehavior.cs similarity index 100% rename from src/Features/Core/Portable/ImplementType/ImplementTypePropertyGenerationBehavior.cs rename to src/Workspaces/Core/Portable/ImplementType/ImplementTypePropertyGenerationBehavior.cs diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 69768a3e7c101..161653267be59 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -44,6 +44,7 @@ + @@ -80,7 +81,7 @@ - +