From 2b1fbd8d580b275efce5748fb6a7d963bcb0f28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Thu, 14 Apr 2022 14:22:05 -0700 Subject: [PATCH] Simplifier options (#60174) * SimplifierOptions * Public option tests * Serializability * Fallback simplifier options for analyzers * Null annotate * Fallback simplifier options for code actions * Document extension * Avoid calling Reducer APIs that take OptionSet; CodeCleanupOptions * Revert project change * Remove GlobalIdeOptionsProvider * Formatting * Make IsApplicable abstract --- eng/config/BannedSymbols.txt | 4 + .../Analyzers/CSharpAnalyzers.projitems | 1 + ...rpQualifyMemberAccessDiagnosticAnalyzer.cs | 6 +- .../CSharpSimplifierOptionsFactory.cs | 18 ++ ...mplicitObjectCreationDiagnosticAnalyzer.cs | 15 +- .../CSharpTypeStyleDiagnosticAnalyzerBase.cs | 7 +- ...MisplacedUsingDirectivesCodeFixProvider.cs | 42 ++-- .../Helpers/AnalyzerOptionsExtensions.cs | 9 +- ...ctQualifyMemberAccessDiagnosticAnalyzer.cs | 38 ++-- ...derCodeFixProvider.CustomFixAllProvider.cs | 8 +- ...geNamespaceToMatchFolderCodeFixProvider.cs | 17 +- ...icQualifyMemberAccessDiagnosticAnalyzer.vb | 7 +- .../VisualBasicSimplifierOptionsFactory.vb | 19 ++ .../Analyzers/VisualBasicAnalyzers.projitems | 1 + .../EncapsulateFieldCommandHandler.cs | 4 +- ...EventHookupCommandHandler_TabKeyCommand.cs | 3 +- .../CSharpSimplifierOptionsStorage.cs | 43 ++++ .../MoveToNamespace/MoveToNamespaceTests.cs | 2 + .../AbstractSnippetExpansionClient.cs | 14 +- .../CSharpSnippets/SnippetCommandHandler.cs | 2 +- .../CSharpSnippets/SnippetExpansionClient.cs | 5 +- .../SnippetFunctionGenerateSwitchCases.cs | 3 +- .../SnippetFunctionSimpleTypeName.cs | 3 +- .../Core.Wpf/Peek/DefinitionPeekableItem.cs | 2 +- .../AbstractAddImportsPasteCommandHandler.cs | 7 +- .../CodeActions/CodeActionOptionsStorage.cs | 28 +-- .../DefinitionContextTracker.cs | 2 +- .../AbstractEncapsulateFieldCommandHandler.cs | 13 +- .../References/FindUsagesLSPContext.cs | 2 +- .../AbstractCodeActionOrUserDiagnosticTest.cs | 1 - .../AbstractMoveToNamespaceTests.cs | 2 + .../AbstractCodeGenerationTests.cs | 4 +- .../CodeGeneration/CodeGenerationTests.cs | 5 +- .../Test2/Expansion/AbstractExpansionTest.vb | 7 +- .../Test2/NavigationBar/TestHelpers.vb | 2 +- .../AbstractSimplificationTests.vb | 2 + .../ParameterSimplificationTests.vb | 4 +- .../Simplification/SimplifierAPITests.vb | 154 -------------- ...stractNewDocumentFormattingServiceTests.cs | 5 +- .../EncapsulateFieldCommandHandler.vb | 4 +- .../VisualBasic/LineCommit/CommitFormatter.vb | 7 +- ...sualBasicEditorNavigationBarItemService.vb | 6 +- ...NavigationBarItemService_CodeGeneration.vb | 14 +- .../VisualBasicSimplifierOptionsStorage.vb | 40 ++++ ...tAbstractClassOrInterfaceCommandHandler.vb | 3 +- .../CaseCorrectionServiceTests.vb | 5 +- .../EncapsulateFieldCommandHandlerTests.vb | 2 + .../EncapsulateFieldTestState.vb | 1 + .../AbstractParameterWrappingTests.vb | 9 +- .../AbstractUseTypeCodeRefactoringProvider.cs | 9 +- .../UseExplicitTypeCodeRefactoringProvider.cs | 5 +- .../UseImplicitTypeCodeRefactoringProvider.cs | 6 +- ...harpSimplifyTypeNamesDiagnosticAnalyzer.cs | 18 +- .../Analyzers/TypeSyntaxSimplifierWalker.cs | 9 +- ...yModifiersNewDocumentFormattingProvider.cs | 3 +- ...eclarationNewDocumentFormattingProvider.cs | 5 +- ...nizeUsingsNewDocumentFormattingProvider.cs | 18 +- ...rogramMainNewDocumentFormattingProvider.cs | 7 +- ...CSharpImplementInterfaceCodeFixProvider.cs | 2 +- ...SharpSimplifyThisOrMeDiagnosticAnalyzer.cs | 13 +- .../SimplifyTypeNamesCodeFixProvider.cs | 3 +- ...FileBannerNewDocumentFormattingProvider.cs | 5 +- .../AbstractAddImportCodeFixProvider.cs | 9 +- .../AbstractAddImportFeatureService.cs | 5 +- .../AddImport/IAddImportFeatureService.cs | 5 +- .../AddImport/References/AssemblyReference.cs | 3 +- .../References/MetadataSymbolReference.cs | 3 +- .../AddImport/References/PackageReference.cs | 3 +- .../References/ProjectSymbolReference.cs | 3 +- .../AddImport/References/Reference.cs | 10 +- .../AddImport/References/SymbolReference.cs | 13 +- .../AbstractAddPackageCodeFixProvider.cs | 2 +- .../AbstractChangeSignatureService.cs | 11 +- ...r.GlobalSuppressMessageFixAllCodeAction.cs | 7 +- ...AbstractAddMissingImportsFeatureService.cs | 4 +- ...actAddMissingImportsRefactoringProvider.cs | 12 +- .../IAddMissingImportsFeatureService.cs | 7 +- ...actExtractMethodCodeRefactoringProvider.cs | 2 +- .../AbstractChangeNamespaceService.cs | 36 ++-- ...actSyncNamespaceCodeRefactoringProvider.cs | 2 +- ...stractMemberInsertingCompletionProvider.cs | 19 +- .../AbstractEncapsulateFieldService.cs | 56 +++-- .../EncapsulateFieldOptions.cs | 12 ++ .../EncapsulateFieldRefactoringProvider.cs | 6 +- .../IRemoteEncapsulateFieldService.cs | 1 + .../AbstractExtractInterfaceService.cs | 4 +- .../ExtractMethod/ExtractMethodResult.cs | 8 +- .../AbstractNewDocumentFormattingService.cs | 5 +- .../INewDocumentFormattingProvider.cs | 5 +- .../INewDocumentFormattingService.cs | 3 +- .../AbstractFullyQualifyCodeFixProvider.cs | 2 +- .../AbstractGenerateTypeService.Editor.cs | 5 +- ...ctImplementAbstractClassCodeFixProvider.cs | 2 +- ...ice.AbstractIntroduceVariableCodeAction.cs | 3 +- ...ntroduceVariableAllOccurrenceCodeAction.cs | 4 +- .../AbstractMetadataAsSourceService.cs | 23 ++- ...compilationMetadataAsSourceFileProvider.cs | 4 +- .../IMetadataAsSourceService.cs | 3 +- .../MetadataAsSourceOptions.cs | 5 +- ...deAction.MoveItemsToNamespaceCodeAction.cs | 6 +- ...odeAction.MoveTypeToNamespaceCodeAction.cs | 6 +- .../AbstractMoveToNamespaceCodeAction.cs | 12 +- .../AbstractMoveToNamespaceService.cs | 16 +- .../MoveToNamespaceCodeActionProvider.cs | 3 +- .../Shared/Utilities/ExtractTypeHelpers.cs | 9 +- ...tractSimplifyThisOrMeDiagnosticAnalyzer.cs | 18 +- ...bstractSimplifyTypeNamesCodeFixProvider.cs | 25 +-- ...SimplifyTypeNamesDiagnosticAnalyzerBase.cs | 30 +-- .../Snippets/SnippetFunctionService.cs | 15 +- .../AbstractSpellCheckCodeFixProvider.cs | 2 +- ...AbstractWrappingCodeRefactoringProvider.cs | 2 +- .../DefaultDiagnosticAnalyzerService.cs | 2 +- ...cIncrementalAnalyzer.CompilationManager.cs | 2 +- ...osticIncrementalAnalyzer_GetDiagnostics.cs | 2 +- ...crementalAnalyzer_GetDiagnosticsForSpan.cs | 2 +- ...IncrementalAnalyzer_IncrementalAnalyzer.cs | 2 +- .../Options/AutoFormattingOptionsStorage.cs | 2 - .../Options/BlockStructureOptionsStorage.cs | 103 +++++----- .../Options/ClassificationOptionsStorage.cs | 35 ++-- .../Options/CompletionOptionsStorage.cs | 191 +++++++++--------- .../DocumentationCommentOptionsStorage.cs | 2 - .../Options/ExtractMethodOptionsStorage.cs | 1 - .../Options/HighlightingOptionsStorage.cs | 1 - .../Options/IdeAnalyzerOptionsStorage.cs | 17 +- .../Options/IndentationOptionsStorage.cs | 1 - .../Options/InternalDiagnosticsOptions.cs | 11 +- .../Options/MetadataAsSourceOptionsStorage.cs | 35 ++-- .../Options/SignatureHelpOptionsStorage.cs | 13 +- .../Options/SimplifierOptionsStorage.cs | 24 +++ .../Options/SolutionCrawlerOptionsStorage.cs | 77 ++++--- .../WorkspaceConfigurationOptionsStorage.cs | 83 ++++---- .../Options/WorkspaceConfigurationService.cs | 33 ++- .../AbstractGoToDefinitionHandler.cs | 2 +- .../InlineCompletionsHandler.cs | 20 +- .../XmlSnippetParser.ParsedXmlSnippet.cs | 5 +- ...odeAnalysis.LanguageServer.Protocol.csproj | 3 +- .../Analyzers/TypeSyntaxSimplifierWalker.vb | 9 +- ...asicSimplifyTypeNamesDiagnosticAnalyzer.vb | 17 +- ...nizeUsingsNewDocumentFormattingProvider.vb | 3 +- ...lBasicImplementInterfaceCodeFixProvider.vb | 2 +- ...BasicSimplifyThisOrMeDiagnosticAnalyzer.vb | 12 +- .../SimplifyTypeNamesCodeFixProvider.vb | 3 +- ...OmniSharpSyntaxFormattingOptionsFactory.cs | 114 ++++++----- .../CodeActions/OmniSharpCodeActionOptions.cs | 8 +- .../OmniSharpCodeFixContextFactory.cs | 2 +- .../Formatting/OmniSharpFormatter.cs | 2 +- ...OmniSharpSyntaxFormattingOptionsWrapper.cs | 17 +- .../OmniSharpMetadataAsSourceService.cs | 8 +- .../CodeCleanup/AbstractCodeCleanUpFixer.cs | 6 +- .../Implementation/AbstractEditorFactory.cs | 11 +- .../AbstractSnippetExpansionClient.cs | 2 +- .../SnippetFunctionGenerateSwitchCases.cs | 5 +- .../SnippetFunctionSimpleTypeName.cs | 6 +- .../VisualStudioSuppressionFixService.cs | 10 +- .../Def/Venus/ContainedLanguageCodeSupport.cs | 8 +- .../VisualStudioSymbolNavigationService.cs | 2 +- .../CodeModel/AbstractCodeModelService.cs | 12 +- .../Core/Impl/CodeModel/FileCodeModel.cs | 7 +- ...alStudioDiagnosticAnalyzerExecutorTests.cs | 39 ++-- .../Definitions/GoToDefinitionHandler.cs | 2 +- ...nService.NodesAndTokensToReduceComputer.cs | 2 +- .../CSharpSimplificationService.cs | 19 +- ...CSharpReducer.AbstractReductionRewriter.cs | 50 +++-- .../Reducers/AbstractCSharpReducer.cs | 5 + .../Reducers/CSharpCastReducer.cs | 9 +- ...CSharpDefaultExpressionReducer.Rewriter.cs | 7 +- .../CSharpDefaultExpressionReducer.cs | 3 + .../Reducers/CSharpEscapingReducer.cs | 7 +- .../Reducers/CSharpExtensionMethodReducer.cs | 7 +- ...SharpInferredMemberNameReducer.Rewriter.cs | 9 +- .../CSharpInferredMemberNameReducer.cs | 3 + .../Reducers/CSharpMiscellaneousReducer.cs | 19 +- .../Reducers/CSharpNameReducer.cs | 11 +- .../CSharpNullableAnnotationReducer.cs | 8 +- .../CSharpParenthesizedExpressionReducer.cs | 7 +- .../CSharpParenthesizedPatternReducer.cs | 7 +- .../Reducers/CSharpVarReducer.Rewriter.cs | 2 +- .../Reducers/CSharpVarReducer.cs | 10 +- .../Simplifiers/AbstractCSharpSimplifier.cs | 8 +- .../Simplifiers/ExpressionSimplifier.cs | 16 +- .../Simplifiers/NameSimplifier.cs | 10 +- .../Simplifiers/QualifiedCrefSimplifier.cs | 5 +- .../CodeGeneration/AddImportsTests.cs | 5 +- .../CodeGeneration/SymbolEditorTests.cs | 3 +- .../ChangeNamespace/ChangeNamespaceOptions.cs | 47 +++++ .../IChangeNamespaceService.cs | 5 +- .../Core/Portable/CodeActions/CodeAction.cs | 21 +- .../CodeCleanup/AbstractCodeCleanerService.cs | 4 +- .../Core/Portable/CodeCleanup/CodeCleaner.cs | 4 +- .../CodeCleanup/CodeCleanupOptions.cs | 28 +++ .../CodeCleanup/ICodeCleanerService.cs | 2 +- .../Providers/FormatCodeCleanupProvider.cs | 4 +- .../Providers/ICodeCleanupProvider.cs | 2 +- .../SimplificationCodeCleanupProvider.cs | 4 +- .../Core/Portable/CodeFixes/CodeFixContext.cs | 2 +- .../CodeRefactoringContext.cs | 2 +- .../Core/Portable/Editing/SyntaxGenerator.cs | 3 +- .../Portable/Options/IGlobalOptionService.cs | 9 +- .../ConflictEngine/RenamedSpansTracker.cs | 3 +- .../Core/Portable/Rename/RenameOptions.cs | 2 + .../Renamer.SyncNamespaceDocumentAction.cs | 10 +- .../Core/Portable/Rename/Renamer.cs | 21 +- .../AbstractReducer.IExpressionRewriter.cs | 3 +- .../Simplification/AbstractReducer.cs | 3 +- .../AbstractSimplificationService.cs | 54 +++-- .../Simplification/ISimplificationService.cs | 15 +- .../Portable/Simplification/Simplifier.cs | 44 +++- .../Simplifiers/AbstractSimplifier.cs | 6 +- .../CodeCleanup/MockCodeCleanupProvider.cs | 6 +- .../CoreTest/Remote/ServiceDescriptorTests.cs | 14 ++ .../CoreTest/Simplifier/SimplifierTests.cs | 159 +++++++++++++++ .../Serialization/MessagePackFormatters.cs | 14 +- ...vertTupleToStructCodeRefactoringService.cs | 8 +- .../RemoteEncapsulateFieldService.cs | 3 +- .../CSharp/CSharpCompilerExtensions.projitems | 1 + .../Formatting/CSharpSyntaxFormatting.cs | 3 + .../Simplification/CSharpSimplifierOptions.cs | 90 +++++++++ .../TypeStyle/CSharpTypeStyleHelper.State.cs | 9 +- .../TypeStyle/CSharpTypeStyleHelper.cs | 20 +- .../TypeStyle/CSharpUseExplicitTypeHelper.cs | 9 +- .../TypeStyle/CSharpUseImplicitTypeHelper.cs | 11 +- .../Core/CodeStyle/CodeStyleOption2`1.cs | 17 +- .../Core/CodeStyle/CodeStyleOptions2.cs | 1 + .../Core/CompilerExtensions.projitems | 1 + .../AnalyzerConfigOptionsExtensions.cs | 14 +- .../AbstractSyntaxFormattingService.cs | 1 + .../Core/Formatting/ISyntaxFormatting.cs | 2 + .../Core/Simplification/SimplifierOptions.cs | 81 ++++++++ .../VisualBasicSimplifierOptions.vb | 52 +++++ .../VisualBasicCompilerExtensions.projitems | 1 + ...olExtensions.TypeSyntaxGeneratorVisitor.cs | 3 +- .../Core/CodeFixes/CodeActionOptions.cs | 47 +++-- .../AddImports/IAddImportsService.cs | 13 +- .../SimplificationHelpers.cs | 24 +-- .../Core/WorkspaceExtensions.projitems | 2 +- .../AbstractTokensCodeCleanupProvider.vb | 2 +- .../CaseCorrectionCodeCleanupProvider.vb | 2 +- ...ModifiersOrOperatorsCodeCleanupProvider.vb | 4 +- ...saryLineContinuationCodeCleanupProvider.vb | 4 +- .../Formatting/VisualBasicSyntaxFormatting.vb | 6 + ...lBasicReducer.AbstractReductionRewriter.vb | 21 +- .../Reducers/AbstractVisualBasicReducer.vb | 10 +- .../Reducers/VisualBasicCallReducer.vb | 8 +- .../Reducers/VisualBasicCastReducer.vb | 13 +- .../Reducers/VisualBasicEscapingReducer.vb | 6 +- .../VisualBasicExtensionMethodReducer.vb | 8 +- ...BasicInferredMemberNameReducer.Rewriter.vb | 9 +- .../VisualBasicInferredMemberNameReducer.vb | 4 + .../VisualBasicMiscellaneousReducer.vb | 16 +- .../Reducers/VisualBasicNameReducer.vb | 10 +- .../Reducers/VisualBasicParenthesesReducer.vb | 4 + .../VisualBasicVariableDeclaratorReducer.vb | 8 +- .../AbstractVisualBasicSimplifier.vb | 6 +- .../Simplifiers/ExpressionSimplifier.vb | 20 +- .../Simplifiers/NameSimplifier.vb | 10 +- .../VisualBasicSimplificationService.vb | 11 + .../CodeGeneration/AddImportsTests.vb | 4 +- 257 files changed, 2178 insertions(+), 1276 deletions(-) create mode 100644 src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs create mode 100644 src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb create mode 100644 src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs delete mode 100644 src/EditorFeatures/Test2/Simplification/SimplifierAPITests.vb create mode 100644 src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb create mode 100644 src/Features/Core/Portable/EncapsulateField/EncapsulateFieldOptions.cs rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/AutoFormattingOptionsStorage.cs (98%) rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/DocumentationCommentOptionsStorage.cs (98%) rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/ExtractMethodOptionsStorage.cs (97%) rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/HighlightingOptionsStorage.cs (98%) rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/IdeAnalyzerOptionsStorage.cs (88%) rename src/Features/{Core/Portable => LanguageServer/Protocol/Features}/Options/IndentationOptionsStorage.cs (97%) create mode 100644 src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs create mode 100644 src/Workspaces/Core/Portable/ChangeNamespace/ChangeNamespaceOptions.cs rename src/Workspaces/Core/Portable/{Rename => ChangeNamespace}/IChangeNamespaceService.cs (93%) create mode 100644 src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs create mode 100644 src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs create mode 100644 src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs create mode 100644 src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs create mode 100644 src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb rename src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/{Helpers => Simplification}/SimplificationHelpers.cs (78%) diff --git a/eng/config/BannedSymbols.txt b/eng/config/BannedSymbols.txt index b3f5e5f9afcd1..8a51cac5d9646 100644 --- a/eng/config/BannedSymbols.txt +++ b/eng/config/BannedSymbols.txt @@ -25,3 +25,7 @@ M:Microsoft.CodeAnalysis.Formatting.Formatter.Format(Microsoft.CodeAnalysis.Synt M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,Microsoft.CodeAnalysis.Text.TextSpan,Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead M:Microsoft.CodeAnalysis.Formatting.Formatter.GetFormattedTextChanges(Microsoft.CodeAnalysis.SyntaxNode,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.Text.TextSpan},Microsoft.CodeAnalysis.Workspace,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead +M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions +M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.SyntaxAnnotation,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions +M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Text.TextSpan,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions +M:Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(Microsoft.CodeAnalysis.Document,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.Text.TextSpan},Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload that takes SimplifierOptions diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems index 716f188b5bf96..60ed46390e5cd 100644 --- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems +++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems @@ -60,6 +60,7 @@ + diff --git a/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs index 1cadc95164172..e180a2c800faa 100644 --- a/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs @@ -4,6 +4,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.QualifyMemberAccess; @@ -13,11 +14,14 @@ namespace Microsoft.CodeAnalysis.CSharp.QualifyMemberAccess { [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class CSharpQualifyMemberAccessDiagnosticAnalyzer - : AbstractQualifyMemberAccessDiagnosticAnalyzer + : AbstractQualifyMemberAccessDiagnosticAnalyzer { protected override string GetLanguageName() => LanguageNames.CSharp; + protected override CSharpSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree) + => options.GetCSharpSimplifierOptions(syntaxTree); + protected override bool IsAlreadyQualifiedMemberAccess(ExpressionSyntax node) => node.IsKind(SyntaxKind.ThisExpression); diff --git a/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs b/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs new file mode 100644 index 0000000000000..a065e1ea4bbfc --- /dev/null +++ b/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs @@ -0,0 +1,18 @@ +// 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.CSharp.Simplification; + +internal static class CSharpSimplifierOptionsFactory +{ + internal static CSharpSimplifierOptions GetCSharpSimplifierOptions(this AnalyzerOptions options, SyntaxTree syntaxTree) + { + var configOptions = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); + var ideOptions = options.GetIdeOptions(); + + return CSharpSimplifierOptions.Create(configOptions, (CSharpSimplifierOptions?)ideOptions.SimplifierOptions); + } +} diff --git a/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs index 246184e9a442f..71af8d9bad828 100644 --- a/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs @@ -6,11 +6,13 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.UseImplicitObjectCreation { @@ -44,7 +46,6 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) if (syntaxTree.Options.LanguageVersion() < LanguageVersion.CSharp9) return; - var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); var styleOption = options.GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, syntaxTree, cancellationToken); if (!styleOption.Value) { @@ -73,11 +74,15 @@ objectCreation.Parent.Parent.Parent is VariableDeclarationSyntax variableDeclara typeNode = variableDeclaration.Type; var helper = CSharpUseImplicitTypeHelper.Instance; - if (helper.ShouldAnalyzeVariableDeclaration(variableDeclaration, cancellationToken) && - helper.AnalyzeTypeName(typeNode, semanticModel, optionSet, cancellationToken).IsStylePreferred) + if (helper.ShouldAnalyzeVariableDeclaration(variableDeclaration, cancellationToken)) { - // this is a case where the user would prefer 'var'. don't offer to use an implicit object here. - return; + var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); + + if (helper.AnalyzeTypeName(typeNode, semanticModel, simplifierOptions, cancellationToken).IsStylePreferred) + { + // this is a case where the user would prefer 'var'. don't offer to use an implicit object here. + return; + } } } else if (objectCreation.Parent.IsKind(SyntaxKind.ArrowExpressionClause)) diff --git a/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs b/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs index 26a0f557e3371..fb2439791a12f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs +++ b/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; @@ -52,10 +53,8 @@ protected override void InitializeWorker(AnalysisContext context) private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) { var declarationStatement = context.Node; - var options = context.Options; var syntaxTree = context.Node.SyntaxTree; var cancellationToken = context.CancellationToken; - var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); var semanticModel = context.SemanticModel; var declaredType = Helper.FindAnalyzableType(declarationStatement, semanticModel, cancellationToken); @@ -64,8 +63,10 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) return; } + var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); + var typeStyle = Helper.AnalyzeTypeName( - declaredType, semanticModel, optionSet, cancellationToken); + declaredType, semanticModel, simplifierOptions, cancellationToken); if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert()) { return; diff --git a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs index 540a1a2521913..eade815ae34f3 100644 --- a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; @@ -65,14 +66,17 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) #if CODE_STYLE var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(syntaxRoot.SyntaxTree, cancellationToken); + var simplifierOptions = CSharpSimplifierOptions.Create(options, fallbackOptions: null); #else var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: context.Options(document.Project.LanguageServices).SimplifierOptions, cancellationToken).ConfigureAwait(false); #endif + var codeStyleOption = options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement); // Read the preferred placement option and verify if it can be applied to this code file. // There are cases where we will not be able to fix the diagnostic and the user will need to resolve // it manually. - var (placement, preferPreservation) = DeterminePlacement(compilationUnit, options); + var (placement, preferPreservation) = DeterminePlacement(compilationUnit, codeStyleOption); if (preferPreservation) return; @@ -81,24 +85,22 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( CSharpAnalyzersResources.Move_misplaced_using_directives, - token => GetTransformedDocumentAsync(document, compilationUnit, GetAllUsingDirectives(compilationUnit), placement, token), + token => GetTransformedDocumentAsync(document, compilationUnit, GetAllUsingDirectives(compilationUnit), placement, simplifierOptions, token), nameof(CSharpAnalyzersResources.Move_misplaced_using_directives)), diagnostic); } } - internal static async Task TransformDocumentIfRequiredAsync(Document document, CancellationToken cancellationToken) + internal static async Task TransformDocumentIfRequiredAsync( + Document document, + SimplifierOptions simplifierOptions, + CodeStyleOption2 importPlacementStyleOption, + CancellationToken cancellationToken) { var syntaxRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var compilationUnit = (CompilationUnitSyntax)syntaxRoot; -#if CODE_STYLE - var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(syntaxRoot.SyntaxTree, cancellationToken); -#else - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif - - var (placement, preferPreservation) = DeterminePlacement(compilationUnit, options); + var (placement, preferPreservation) = DeterminePlacement(compilationUnit, importPlacementStyleOption); if (preferPreservation) { return document; @@ -112,7 +114,7 @@ internal static async Task TransformDocumentIfRequiredAsync(Document d return document; } - return await GetTransformedDocumentAsync(document, compilationUnit, allUsingDirectives, placement, cancellationToken).ConfigureAwait(false); + return await GetTransformedDocumentAsync(document, compilationUnit, allUsingDirectives, placement, simplifierOptions, cancellationToken).ConfigureAwait(false); } private static ImmutableList GetAllUsingDirectives(CompilationUnitSyntax compilationUnit) @@ -127,6 +129,7 @@ private static async Task GetTransformedDocumentAsync( CompilationUnitSyntax compilationUnit, IEnumerable allUsingDirectives, AddImportPlacement placement, + SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { var bannerService = document.GetRequiredLanguageService(); @@ -149,8 +152,13 @@ private static async Task GetTransformedDocumentAsync( var newDocument = document.WithSyntaxRoot(newCompilationUnitWithHeader); // Simplify usings now that they have been moved and are in the proper context. - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, options, cancellationToken).ConfigureAwait(false); +#if CODE_STYLE +#pragma warning disable RS0030 // Do not used banned APIs + return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false); +#pragma warning restore +#else + return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, simplifierOptions, cancellationToken).ConfigureAwait(false); +#endif } private static async Task ExpandUsingDirectivesAsync(Document document, CompilationUnitSyntax containerNode, IEnumerable allUsingDirectives, CancellationToken cancellationToken) @@ -360,12 +368,10 @@ private static TSyntaxNode EnsureLeadingBlankLineBeforeFirstMember( return node.ReplaceNode(firstMember, newFirstMember); } - private static (AddImportPlacement placement, bool preferPreservation) DeterminePlacement(CompilationUnitSyntax compilationUnit, OptionSet options) + private static (AddImportPlacement placement, bool preferPreservation) DeterminePlacement(CompilationUnitSyntax compilationUnit, CodeStyleOption2 styleOption) { - var codeStyleOption = options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement); - - var placement = codeStyleOption.Value; - var preferPreservation = codeStyleOption.Notification == NotificationOption2.None; + var placement = styleOption.Value; + var preferPreservation = styleOption.Notification == NotificationOption2.None; if (preferPreservation || placement == AddImportPlacement.OutsideNamespace) return (placement, preferPreservation); diff --git a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs b/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs index 7e76442dbfdfc..c81c069ede0ee 100644 --- a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs +++ b/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs @@ -4,12 +4,8 @@ using System.Runtime.Serialization; using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; using Microsoft.CodeAnalysis.Options; -using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Simplification; #if CODE_STYLE using TOption = Microsoft.CodeAnalysis.Options.IOption2; @@ -27,7 +23,8 @@ internal readonly record struct IdeAnalyzerOptions( [property: DataMember(Order = 3)] bool ReportInvalidPlaceholdersInStringDotFormatCalls = true, [property: DataMember(Order = 4)] bool ReportInvalidRegexPatterns = true, [property: DataMember(Order = 5)] bool ReportInvalidJsonPatterns = true, - [property: DataMember(Order = 6)] bool DetectAndOfferEditorFeaturesForProbableJsonStrings = true) + [property: DataMember(Order = 6)] bool DetectAndOfferEditorFeaturesForProbableJsonStrings = true, + [property: DataMember(Order = 7)] SimplifierOptions? SimplifierOptions = null) { public IdeAnalyzerOptions() : this(CrashOnAnalyzerException: false) diff --git a/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs index 5274b582473cd..307649bb6f946 100644 --- a/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; #if CODE_STYLE @@ -18,11 +19,13 @@ namespace Microsoft.CodeAnalysis.QualifyMemberAccess internal abstract class AbstractQualifyMemberAccessDiagnosticAnalyzer< TLanguageKindEnum, TExpressionSyntax, - TSimpleNameSyntax> + TSimpleNameSyntax, + TSimplifierOptions> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TSimpleNameSyntax : TExpressionSyntax + where TSimplifierOptions : SimplifierOptions { protected AbstractQualifyMemberAccessDiagnosticAnalyzer() : base(IDEDiagnosticIds.AddQualificationDiagnosticId, @@ -62,6 +65,7 @@ protected override void InitializeWorker(AnalysisContext context) => context.RegisterOperationAction(AnalyzeOperation, OperationKind.FieldReference, OperationKind.PropertyReference, OperationKind.MethodReference, OperationKind.Invocation); protected abstract Location GetLocation(IOperation operation); + protected abstract TSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree); public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -117,8 +121,15 @@ private void AnalyzeOperation(OperationAnalysisContext context, IOperation opera if (instanceOperation.Syntax is not TSimpleNameSyntax simpleName) return; - var applicableOption = QualifyMembersHelpers.GetApplicableOptionFromSymbolKind(operation); - var optionValue = context.GetOption(applicableOption, context.Operation.Syntax.Language); + var symbolKind = operation switch + { + IMemberReferenceOperation memberReferenceOperation => memberReferenceOperation.Member.Kind, + IInvocationOperation invocationOperation => invocationOperation.TargetMethod.Kind, + _ => throw ExceptionUtilities.UnexpectedValue(operation), + }; + + var simplifierOptions = GetSimplifierOptions(context.Options, context.Operation.Syntax.SyntaxTree); + var optionValue = simplifierOptions.QualifyMemberAccess(symbolKind); var shouldOptionBePresent = optionValue.Value; var severity = optionValue.Notification.Severity; @@ -153,25 +164,4 @@ static bool IsStaticMemberOrIsLocalFunctionHelper(ISymbol symbol) } } } - - internal static class QualifyMembersHelpers - { - public static PerLanguageOption2> GetApplicableOptionFromSymbolKind(SymbolKind symbolKind) - => symbolKind switch - { - SymbolKind.Field => CodeStyleOptions2.QualifyFieldAccess, - SymbolKind.Property => CodeStyleOptions2.QualifyPropertyAccess, - SymbolKind.Method => CodeStyleOptions2.QualifyMethodAccess, - SymbolKind.Event => CodeStyleOptions2.QualifyEventAccess, - _ => throw ExceptionUtilities.UnexpectedValue(symbolKind), - }; - - internal static PerLanguageOption2> GetApplicableOptionFromSymbolKind(IOperation operation) - => operation switch - { - IMemberReferenceOperation memberReferenceOperation => GetApplicableOptionFromSymbolKind(memberReferenceOperation.Member.Kind), - IInvocationOperation invocationOperation => GetApplicableOptionFromSymbolKind(invocationOperation.TargetMethod.Kind), - _ => throw ExceptionUtilities.UnexpectedValue(operation), - }; - } } diff --git a/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.CustomFixAllProvider.cs b/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.CustomFixAllProvider.cs index b7b8c464dcb15..f635a0ad40383 100644 --- a/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.CustomFixAllProvider.cs +++ b/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.CustomFixAllProvider.cs @@ -46,6 +46,11 @@ private class CustomFixAllProvider : FixAllProvider fixAllContext.Project.Solution, diagnostics, fixAllContext.GetProgressTracker(), +#if CODE_STYLE + options: _ => default, +#else + fixAllContext.State.CodeActionOptionsProvider, +#endif cancellationToken), title); @@ -67,6 +72,7 @@ private static async Task FixAllByDocumentAsync( Solution solution, ImmutableArray diagnostics, IProgressTracker progressTracker, + CodeActionOptionsProvider options, CancellationToken cancellationToken) { // Use documentId instead of tree here because the @@ -89,7 +95,7 @@ private static async Task FixAllByDocumentAsync( var document = newSolution.GetRequiredDocument(documentId); using var _ = progressTracker.ItemCompletedScope(document.Name); - newSolution = await FixAllInDocumentAsync(document, diagnosticsInTree, cancellationToken).ConfigureAwait(false); + newSolution = await FixAllInDocumentAsync(document, diagnosticsInTree, options, cancellationToken).ConfigureAwait(false); } return newSolution; diff --git a/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.cs index 408f4c464f7ef..1155e31fa0f53 100644 --- a/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/MatchFolderAndNamespace/AbstractChangeNamespaceToMatchFolderCodeFixProvider.cs @@ -8,12 +8,16 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.Analyzers.MatchFolderAndNamespace; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Rename; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CodeFixes.MatchFolderAndNamespace @@ -29,7 +33,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( AnalyzersResources.Change_namespace_to_match_folder_structure, - cancellationToken => FixAllInDocumentAsync(context.Document, context.Diagnostics, cancellationToken), + cancellationToken => FixAllInDocumentAsync(context.Document, context.Diagnostics, +#if CODE_STYLE + options: _ => default, +#else + context.Options, +#endif + cancellationToken), nameof(AnalyzersResources.Change_namespace_to_match_folder_structure)), context.Diagnostics); } @@ -37,7 +47,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) return Task.CompletedTask; } - private static async Task FixAllInDocumentAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + private static async Task FixAllInDocumentAsync(Document document, ImmutableArray diagnostics, CodeActionOptionsProvider options, CancellationToken cancellationToken) { // All the target namespaces should be the same for a given document Debug.Assert(diagnostics.Select(diagnostic => diagnostic.Properties[MatchFolderAndNamespaceConstants.TargetNamespace]).Distinct().Count() == 1); @@ -54,6 +64,9 @@ private static async Task FixAllInDocumentAsync(Document document, Imm var renameActionSet = await Renamer.RenameDocumentAsync( documentWithInvalidFolders, new DocumentRenameOptions(), +#if !CODE_STYLE + ChangeNamespaceOptions.CreateProvider(options), +#endif documentWithInvalidFolders.Name, newDocumentFolders: targetFolders, cancellationToken: cancellationToken).ConfigureAwait(false); diff --git a/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb index 2ee70fa172f2f..46aaf5e54f4c9 100644 --- a/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb @@ -5,16 +5,21 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.QualifyMemberAccess Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Namespace Microsoft.CodeAnalysis.VisualBasic.QualifyMemberAccess Friend NotInheritable Class VisualBasicQualifyMemberAccessDiagnosticAnalyzer - Inherits AbstractQualifyMemberAccessDiagnosticAnalyzer(Of SyntaxKind, ExpressionSyntax, SimpleNameSyntax) + Inherits AbstractQualifyMemberAccessDiagnosticAnalyzer(Of SyntaxKind, ExpressionSyntax, SimpleNameSyntax, VisualBasicSimplifierOptions) Protected Overrides Function GetLanguageName() As String Return LanguageNames.VisualBasic End Function + Protected Overrides Function GetSimplifierOptions(options As AnalyzerOptions, syntaxTree As SyntaxTree) As VisualBasicSimplifierOptions + Return options.GetVisualBasicSimplifierOptions(syntaxTree) + End Function + Protected Overrides Function IsAlreadyQualifiedMemberAccess(node As ExpressionSyntax) As Boolean Return node.IsKind(SyntaxKind.MeExpression) End Function diff --git a/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb b/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb new file mode 100644 index 0000000000000..2b402e2a29155 --- /dev/null +++ b/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb @@ -0,0 +1,19 @@ +' 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. + +Imports System.Runtime.CompilerServices +Imports Microsoft.CodeAnalysis.Diagnostics + +Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification + Friend Module VisualBasicSimplifierOptionsFactory + + Public Function GetVisualBasicSimplifierOptions(options As AnalyzerOptions, syntaxTree As SyntaxTree) As VisualBasicSimplifierOptions + Dim configOptions = options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree) + Dim ideOptions = options.GetIdeOptions() + + Return VisualBasicSimplifierOptions.Create(configOptions, DirectCast(ideOptions.SimplifierOptions, VisualBasicSimplifierOptions)) + End Function + End Module +End Namespace + diff --git a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems index 6665cce389e70..72e888f4bef43 100644 --- a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems +++ b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems @@ -36,6 +36,7 @@ + diff --git a/src/EditorFeatures/CSharp/EncapsulateField/EncapsulateFieldCommandHandler.cs b/src/EditorFeatures/CSharp/EncapsulateField/EncapsulateFieldCommandHandler.cs index 74af10b1f1e32..547aae4494c4c 100644 --- a/src/EditorFeatures/CSharp/EncapsulateField/EncapsulateFieldCommandHandler.cs +++ b/src/EditorFeatures/CSharp/EncapsulateField/EncapsulateFieldCommandHandler.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.EncapsulateField; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text.Operations; @@ -25,8 +26,9 @@ internal class EncapsulateFieldCommandHandler : AbstractEncapsulateFieldCommandH public EncapsulateFieldCommandHandler( IThreadingContext threadingContext, ITextBufferUndoManagerProvider undoManager, + IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider) - : base(threadingContext, undoManager, listenerProvider) + : base(threadingContext, undoManager, globalOptions, listenerProvider) { } } diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs index 89b9c9a95ef9e..6c66369c81fb8 100644 --- a/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs +++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs @@ -168,8 +168,9 @@ private Solution CreateSolutionWithEventHandler( } var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); + var simplifierOptions = document.GetSimplifierOptionsAsync(_globalOptions, cancellationToken).WaitAndGetResult(cancellationToken); - var simplifiedDocument = Simplifier.ReduceAsync(documentWithNameAndAnnotationsAdded.WithSyntaxRoot(updatedRoot), Simplifier.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); + var simplifiedDocument = Simplifier.ReduceAsync(documentWithNameAndAnnotationsAdded.WithSyntaxRoot(updatedRoot), Simplifier.Annotation, simplifierOptions, cancellationToken).WaitAndGetResult(cancellationToken); var formattedDocument = Formatter.FormatAsync(simplifiedDocument, Formatter.Annotation, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken); var newRoot = formattedDocument.GetSyntaxRootSynchronously(cancellationToken); diff --git a/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs new file mode 100644 index 0000000000000..1029a436c209b --- /dev/null +++ b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs @@ -0,0 +1,43 @@ +// 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 Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.CSharp.Simplification; + +internal static class CSharpSimplifierOptionsStorage +{ + [ExportLanguageService(typeof(ISimplifierOptionsStorage), LanguageNames.CSharp), Shared] + private sealed class Service : ISimplifierOptionsStorage + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public Service() + { + } + + public SimplifierOptions GetOptions(IGlobalOptionService globalOptions) + => GetCSharpSimplifierOptions(globalOptions); + } + + public static CSharpSimplifierOptions GetCSharpSimplifierOptions(this IGlobalOptionService globalOptions) + => new( + qualifyFieldAccess: globalOptions.GetOption(CodeStyleOptions2.QualifyFieldAccess, LanguageNames.CSharp), + qualifyPropertyAccess: globalOptions.GetOption(CodeStyleOptions2.QualifyPropertyAccess, LanguageNames.CSharp), + qualifyMethodAccess: globalOptions.GetOption(CodeStyleOptions2.QualifyMethodAccess, LanguageNames.CSharp), + qualifyEventAccess: globalOptions.GetOption(CodeStyleOptions2.QualifyEventAccess, LanguageNames.CSharp), + preferPredefinedTypeKeywordInMemberAccess: globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, LanguageNames.CSharp), + preferPredefinedTypeKeywordInDeclaration: globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, LanguageNames.CSharp), + varForBuiltInTypes: globalOptions.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes), + varWhenTypeIsApparent: globalOptions.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent), + varElsewhere: globalOptions.GetOption(CSharpCodeStyleOptions.VarElsewhere), + preferSimpleDefaultExpression: globalOptions.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression), + preferBraces: globalOptions.GetOption(CSharpCodeStyleOptions.PreferBraces)); +} diff --git a/src/EditorFeatures/CSharpTest/MoveToNamespace/MoveToNamespaceTests.cs b/src/EditorFeatures/CSharpTest/MoveToNamespace/MoveToNamespaceTests.cs index 01c56d4628746..b06ed35872de8 100644 --- a/src/EditorFeatures/CSharpTest/MoveToNamespace/MoveToNamespaceTests.cs +++ b/src/EditorFeatures/CSharpTest/MoveToNamespace/MoveToNamespaceTests.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -1174,6 +1175,7 @@ void Method() { } var actions = await testState.MoveToNamespaceService.GetCodeActionsAsync( testState.InvocationDocument, testState.TestInvocationDocument.SelectedSpans.Single(), + language => ChangeNamespaceOptions.GetDefault(testState.InvocationDocument.Project.LanguageServices), CancellationToken.None); Assert.Empty(actions); diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs b/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs index 705445b4258ec..512420104affc 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; @@ -30,18 +31,21 @@ internal abstract class AbstractSnippetExpansionClient : IExpansionClient protected readonly ITextView TextView; protected readonly ITextBuffer SubjectBuffer; + public readonly IGlobalOptionService GlobalOptions; + protected bool _indentCaretOnCommit; protected int _indentDepth; protected bool _earlyEndExpansionHappened; public IExpansionSession? ExpansionSession { get; private set; } - public AbstractSnippetExpansionClient(IContentType languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IExpansionServiceProvider expansionServiceProvider) + public AbstractSnippetExpansionClient(IContentType languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IExpansionServiceProvider expansionServiceProvider, IGlobalOptionService globalOptions) { - this.LanguageServiceGuid = languageServiceGuid; - this.TextView = textView; - this.SubjectBuffer = subjectBuffer; - this.ExpansionServiceProvider = expansionServiceProvider; + LanguageServiceGuid = languageServiceGuid; + TextView = textView; + SubjectBuffer = subjectBuffer; + ExpansionServiceProvider = expansionServiceProvider; + GlobalOptions = globalOptions; } public abstract IExpansionFunction? GetExpansionFunction(XElement xmlFunctionNode, string fieldName); diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetCommandHandler.cs b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetCommandHandler.cs index 5cc96ccbcfb70..eee35719dac32 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetCommandHandler.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetCommandHandler.cs @@ -84,7 +84,7 @@ protected override AbstractSnippetExpansionClient GetSnippetExpansionClient(ITex { if (!textView.Properties.TryGetProperty(typeof(AbstractSnippetExpansionClient), out AbstractSnippetExpansionClient expansionClient)) { - expansionClient = new SnippetExpansionClient(subjectBuffer.ContentType, textView, subjectBuffer, ExpansionServiceProvider); + expansionClient = new SnippetExpansionClient(subjectBuffer.ContentType, textView, subjectBuffer, ExpansionServiceProvider, GlobalOptions); textView.Properties.AddProperty(typeof(AbstractSnippetExpansionClient), expansionClient); } diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetExpansionClient.cs b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetExpansionClient.cs index 5254107f15e7c..6243391dd4f7c 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetExpansionClient.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetExpansionClient.cs @@ -5,6 +5,7 @@ using System; using System.Xml.Linq; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServices.CSharp.Snippets.SnippetFunctions; using Microsoft.VisualStudio.LanguageServices.Implementation.Snippets; using Microsoft.VisualStudio.Text; @@ -17,8 +18,8 @@ namespace Microsoft.VisualStudio.LanguageServices.CSharp.Snippets { internal sealed partial class SnippetExpansionClient : AbstractSnippetExpansionClient { - public SnippetExpansionClient(IContentType languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IExpansionServiceProvider expansionServiceProvider) - : base(languageServiceGuid, textView, subjectBuffer, expansionServiceProvider) + public SnippetExpansionClient(IContentType languageServiceGuid, ITextView textView, ITextBuffer subjectBuffer, IExpansionServiceProvider expansionServiceProvider, IGlobalOptionService globalOptions) + : base(languageServiceGuid, textView, subjectBuffer, expansionServiceProvider, globalOptions) { } diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs index c1344fe4e68af..d085206abfcd8 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs @@ -96,7 +96,8 @@ protected override bool TryGetSimplifiedTypeNameInCaseContext(Document document, var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation)); var documentWithAnnotations = documentWithCaseAdded.WithSyntaxRoot(updatedRoot); - var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).Result; + var simplifierOptions = document.GetSimplifierOptionsAsync(_snippetExpansionClient.GlobalOptions, cancellationToken).WaitAndGetResult(cancellationToken); + var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, simplifierOptions, cancellationToken).WaitAndGetResult(cancellationToken); simplifiedTypeName = simplifiedDocument.GetRequiredSyntaxRootSynchronously(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString(); return true; } diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs index bfa6bf753cd0e..460cbf48be81b 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/CSharpSnippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs @@ -37,7 +37,8 @@ protected override bool TryGetSimplifiedTypeName(Document documentWithFullyQuali var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation)); var documentWithAnnotations = documentWithFullyQualifiedTypeName.WithSyntaxRoot(updatedRoot); - var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); + var simplifierOptions = documentWithAnnotations.GetSimplifierOptionsAsync(_snippetExpansionClient.GlobalOptions, cancellationToken).WaitAndGetResult(cancellationToken); + var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, simplifierOptions, cancellationToken).WaitAndGetResult(cancellationToken); simplifiedTypeName = simplifiedDocument.GetRequiredSyntaxRootSynchronously(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString(); return true; } diff --git a/src/EditorFeatures/Core.Wpf/Peek/DefinitionPeekableItem.cs b/src/EditorFeatures/Core.Wpf/Peek/DefinitionPeekableItem.cs index 4b398e7df05c7..f3d7a685ac961 100644 --- a/src/EditorFeatures/Core.Wpf/Peek/DefinitionPeekableItem.cs +++ b/src/EditorFeatures/Core.Wpf/Peek/DefinitionPeekableItem.cs @@ -77,7 +77,7 @@ public void FindResults(string relationshipName, IPeekResultCollection resultCol if (!sourceLocations.Any()) { // It's a symbol from metadata, so we want to go produce it from metadata - var options = _peekableItem._globalOptions.GetMetadataAsSourceOptions(); + var options = _peekableItem._globalOptions.GetMetadataAsSourceOptions(project.LanguageServices); var declarationFile = _peekableItem._metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly: true, options, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken); var peekDisplayInfo = new PeekResultDisplayInfo(declarationFile.DocumentTitle, declarationFile.DocumentTitle, declarationFile.DocumentTitle, declarationFile.DocumentTitle); var identifierSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; diff --git a/src/EditorFeatures/Core/AddImports/AbstractAddImportsPasteCommandHandler.cs b/src/EditorFeatures/Core/AddImports/AbstractAddImportsPasteCommandHandler.cs index 115762c6da533..0ac259ae9afb6 100644 --- a/src/EditorFeatures/Core/AddImports/AbstractAddImportsPasteCommandHandler.cs +++ b/src/EditorFeatures/Core/AddImports/AbstractAddImportsPasteCommandHandler.cs @@ -4,6 +4,7 @@ using System; using Microsoft.CodeAnalysis.AddMissingImports; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Options; @@ -125,11 +126,11 @@ private void ExecuteCommandWorker( #pragma warning disable VSTHRD102 // Implement internal logic asynchronously var updatedDocument = _threadingContext.JoinableTaskFactory.Run(async () => { - var placement = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); var options = new AddMissingImportsOptions( - HideAdvancedMembers: _globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, document.Project.Language), - placement); + CleanupOptions: cleanupOptions, + HideAdvancedMembers: _globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, document.Project.Language)); return await addMissingImportsService.AddMissingImportsAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); }); diff --git a/src/EditorFeatures/Core/CodeActions/CodeActionOptionsStorage.cs b/src/EditorFeatures/Core/CodeActions/CodeActionOptionsStorage.cs index 3c453445d267d..7060d90303be5 100644 --- a/src/EditorFeatures/Core/CodeActions/CodeActionOptionsStorage.cs +++ b/src/EditorFeatures/Core/CodeActions/CodeActionOptionsStorage.cs @@ -4,39 +4,43 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.ExtractMethod; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.SymbolSearch; -using Microsoft.CodeAnalysis.ExtractMethod; namespace Microsoft.CodeAnalysis.CodeActions { internal static class CodeActionOptionsStorage { - internal static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, string language) - => GetCodeActionOptions(globalOptions, language, isBlocking: false); + internal static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) + => GetCodeActionOptions(globalOptions, languageServices, isBlocking: false); - internal static CodeActionOptions GetBlockingCodeActionOptions(this IGlobalOptionService globalOptions, string language) - => GetCodeActionOptions(globalOptions, language, isBlocking: true); + internal static CodeActionOptions GetBlockingCodeActionOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) + => GetCodeActionOptions(globalOptions, languageServices, isBlocking: true); - private static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, string language, bool isBlocking) + private static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices, bool isBlocking) => new( - SearchOptions: globalOptions.GetSymbolSearchOptions(language), - ImplementTypeOptions: globalOptions.GetImplementTypeOptions(language), - ExtractMethodOptions: globalOptions.GetExtractMethodOptions(language), - HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, language), + SearchOptions: globalOptions.GetSymbolSearchOptions(languageServices.Language), + ImplementTypeOptions: globalOptions.GetImplementTypeOptions(languageServices.Language), + ExtractMethodOptions: globalOptions.GetExtractMethodOptions(languageServices.Language), + SimplifierOptions: globalOptions.GetSimplifierOptions(languageServices), + HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, languageServices.Language), IsBlocking: isBlocking); internal static CodeActionOptionsProvider GetCodeActionOptionsProvider(this IGlobalOptionService globalOptions) { var cache = ImmutableDictionary.Empty; - return language => ImmutableInterlocked.GetOrAdd(ref cache, language, (language, options) => GetCodeActionOptions(options, language), globalOptions); + return languageService => ImmutableInterlocked.GetOrAdd(ref cache, languageService.Language, (_, options) => GetCodeActionOptions(options, languageService), globalOptions); } internal static CodeActionOptionsProvider GetBlockingCodeActionOptionsProvider(this IGlobalOptionService globalOptions) { var cache = ImmutableDictionary.Empty; - return language => ImmutableInterlocked.GetOrAdd(ref cache, language, (language, options) => GetBlockingCodeActionOptions(options, language), globalOptions); + return languageService => ImmutableInterlocked.GetOrAdd(ref cache, languageService.Language, (language, options) => GetBlockingCodeActionOptions(options, languageService), globalOptions); } } } diff --git a/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs b/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs index 02e8b5918d848..d5861917efa69 100644 --- a/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs +++ b/src/EditorFeatures/Core/CodeDefinitionWindow/DefinitionContextTracker.cs @@ -210,7 +210,7 @@ internal async Task> GetContextFrom } else if (_metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol)) { - var options = _globalOptions.GetMetadataAsSourceOptions(); + var options = _globalOptions.GetMetadataAsSourceOptions(document.Project.LanguageServices); var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, signaturesOnly: false, options, cancellationToken).ConfigureAwait(false); var identifierSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; return ImmutableArray.Create(new CodeDefinitionWindowLocation(symbol.ToDisplayString(), declarationFile.FilePath, identifierSpan.Start)); diff --git a/src/EditorFeatures/Core/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs b/src/EditorFeatures/Core/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs index 68847172ebd8b..12a9eba7e599f 100644 --- a/src/EditorFeatures/Core/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs +++ b/src/EditorFeatures/Core/EncapsulateField/AbstractEncapsulateFieldCommandHandler.cs @@ -9,8 +9,10 @@ using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; using Microsoft.VisualStudio.Text.Operations; @@ -23,6 +25,7 @@ internal abstract class AbstractEncapsulateFieldCommandHandler : ICommandHandler { private readonly IThreadingContext _threadingContext; private readonly ITextBufferUndoManagerProvider _undoManager; + private readonly IGlobalOptionService _globalOptions; private readonly IAsynchronousOperationListener _listener; public string DisplayName => EditorFeaturesResources.Encapsulate_Field; @@ -30,10 +33,12 @@ internal abstract class AbstractEncapsulateFieldCommandHandler : ICommandHandler public AbstractEncapsulateFieldCommandHandler( IThreadingContext threadingContext, ITextBufferUndoManagerProvider undoManager, + IGlobalOptionService globalOptions, IAsynchronousOperationListenerProvider listenerProvider) { _threadingContext = threadingContext; _undoManager = undoManager; + _globalOptions = globalOptions; _listener = listenerProvider.GetListener(FeatureAttribute.EncapsulateField); } @@ -65,7 +70,13 @@ private bool Execute(EncapsulateFieldCommandArgs args, IUIThreadOperationScope w var service = document.GetLanguageService(); - var result = service.EncapsulateFieldsInSpanAsync(document, spans.First().Span.ToTextSpan(), true, cancellationToken).WaitAndGetResult(cancellationToken); + // The formatting and simplification options are only applied within the given document (and all linked documents). + // We can therefore fetch all necessary options for the language now rather then lazily, + // which would be needed if we had to apply them to documents of different languages. + var fallbackOptions = new EncapsulateFieldOptions( + SimplifierOptions: _globalOptions.GetSimplifierOptions(document.Project.LanguageServices)); + + var result = service.EncapsulateFieldsInSpanAsync(document, spans.First().Span.ToTextSpan(), fallbackOptions, useDefaultBehavior: true, cancellationToken).WaitAndGetResult(cancellationToken); // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindUsagesLSPContext.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindUsagesLSPContext.cs index 64787cfc4819c..90912055ea1b1 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindUsagesLSPContext.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/References/FindUsagesLSPContext.cs @@ -244,7 +244,7 @@ public override async ValueTask OnReferenceFoundAsync(SourceReferenceItem refere return null; } - var options = _globalOptions.GetMetadataAsSourceOptions(); + var options = _globalOptions.GetMetadataAsSourceOptions(_document.Project.LanguageServices); var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync( _document.Project, symbol, signaturesOnly: true, options, cancellationToken).ConfigureAwait(false); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index 31d9a9bdefae0..4cff315e31f8d 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -196,7 +196,6 @@ protected TestWorkspace CreateWorkspaceFromOptions(string workspaceMarkupOrCode, #endif // we need to set global options since the tests are going thru incremental diagnostic analyzer that reads them from there: workspace.GlobalOptions.SetIdeAnalyzerOptions(GetLanguage(), parameters.ideAnalyzerOptions); - return workspace; } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs b/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs index eefb13e9583c9..509a5b87a1122 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -47,6 +48,7 @@ public async Task TestMoveToNamespaceAsync( var actions = await testState.MoveToNamespaceService.GetCodeActionsAsync( testState.InvocationDocument, testState.TestInvocationDocument.SelectedSpans.Single(), + language => ChangeNamespaceOptions.GetDefault(workspace.Services.GetLanguageServices(GetLanguage())), CancellationToken.None); var operationTasks = actions diff --git a/src/EditorFeatures/Test/CodeGeneration/AbstractCodeGenerationTests.cs b/src/EditorFeatures/Test/CodeGeneration/AbstractCodeGenerationTests.cs index 45ff92a6ef52f..096f9d9102285 100644 --- a/src/EditorFeatures/Test/CodeGeneration/AbstractCodeGenerationTests.cs +++ b/src/EditorFeatures/Test/CodeGeneration/AbstractCodeGenerationTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; @@ -38,7 +39,8 @@ private static SyntaxNode Simplify( var annotatedDocument = document.WithSyntaxRoot( root.WithAdditionalAnnotations(Simplifier.Annotation)); - var simplifiedDocument = Simplifier.ReduceAsync(annotatedDocument).Result; + var options = document.Project.LanguageServices.GetRequiredService().DefaultOptions; + var simplifiedDocument = Simplifier.ReduceAsync(annotatedDocument, options, CancellationToken.None).Result; var rootNode = simplifiedDocument.GetRequiredSyntaxRootAsync(default).AsTask().Result; diff --git a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs index 35174142febdc..97219f300c705 100644 --- a/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs +++ b/src/EditorFeatures/Test/CodeGeneration/CodeGenerationTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -22,6 +23,7 @@ using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic.Formatting; +using Microsoft.CodeAnalysis.VisualBasic.Simplification; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; @@ -885,8 +887,9 @@ public void Dispose() this.Document = this.Result; var formattingOptions = IsVisualBasic ? (SyntaxFormattingOptions)VisualBasicSyntaxFormattingOptions.Default : CSharpSyntaxFormattingOptions.Default; + var simplifierOptions = IsVisualBasic ? (SimplifierOptions)VisualBasicSimplifierOptions.Default : CSharpSimplifierOptions.Default; - var simplified = Simplifier.ReduceAsync(this.Document, Simplifier.Annotation).Result; + var simplified = Simplifier.ReduceAsync(this.Document, Simplifier.Annotation, simplifierOptions, CancellationToken.None).Result; var actual = Formatter.FormatAsync(simplified, Formatter.Annotation, formattingOptions, CancellationToken.None).Result.GetSyntaxRootAsync().Result.ToFullString(); Assert.Equal(_expected, actual); diff --git a/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb b/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb index 9ff69b2523c3d..58d14b0f784d7 100644 --- a/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb +++ b/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb @@ -27,6 +27,9 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Expansion Dim root = Await document.GetSyntaxRootAsync() + Dim formattingOptions = Await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None) + Dim simplifyOptions = Await SimplifierOptions.FromDocumentAsync(document, fallbackOptions:=Nothing, CancellationToken.None) + If (hostDocument.AnnotatedSpans.ContainsKey("Expand")) Then For Each span In hostDocument.AnnotatedSpans("Expand") Dim node = GetExpressionSyntaxWithSameSpan(root.FindToken(span.Start).Parent, span.End) @@ -37,13 +40,11 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Expansion Dim node = GetExpressionSyntaxWithSameSpan(root.FindToken(span.Start).Parent, span.End) root = root.ReplaceNode(node, Await Simplifier.ExpandAsync(node, document, expandInsideNode:=Nothing, expandParameter:=expandParameter)) document = document.WithSyntaxRoot(root) - document = Await Simplifier.ReduceAsync(document, Simplifier.Annotation) + document = Await Simplifier.ReduceAsync(document, Simplifier.Annotation, simplifyOptions, CancellationToken.None) root = Await document.GetSyntaxRootAsync() Next End If - Dim formattingOptions = Await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None) - document = document.WithSyntaxRoot(root) document = Await Formatter.FormatAsync(document, FormattingOptions, CancellationToken.None) diff --git a/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb b/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb index fc199dd1b1667..5de020bb74c8b 100644 --- a/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb +++ b/src/EditorFeatures/Test2/NavigationBar/TestHelpers.vb @@ -96,7 +96,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.NavigationBar Dim contextLocation = (Await document.GetSyntaxTreeAsync()).GetLocation(New TextSpan(0, 0)) Dim generateCodeItem = DirectCast(rightItem, WrappedNavigationBarItem).UnderlyingItem - Dim newDocument = Await VisualBasicEditorNavigationBarItemService.GetGeneratedDocumentAsync(document, generateCodeItem, CancellationToken.None) + Dim newDocument = Await VisualBasicEditorNavigationBarItemService.GetGeneratedDocumentAsync(document, generateCodeItem, workspace.GlobalOptions, CancellationToken.None) Dim actual = (Await newDocument.GetSyntaxRootAsync()).ToFullString().TrimEnd() Dim expected = expectedText.NormalizedValue.TrimEnd() diff --git a/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb index 4a23a6a4834a2..6e604bb4e1624 100644 --- a/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/AbstractSimplificationTests.vb @@ -114,12 +114,14 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification document = document.WithSyntaxRoot(root) +#Disable Warning RS0030 ' Do Not used banned APIs Dim simplifiedDocument As Document If Not explicitSpansToSimplifyWithin.IsDefaultOrEmpty Then simplifiedDocument = Await Simplifier.ReduceAsync(document, explicitSpansToSimplifyWithin, optionSet) Else simplifiedDocument = Await Simplifier.ReduceAsync(document, Simplifier.Annotation, optionSet) End If +#Enable Warning RS0030 Return simplifiedDocument End Function diff --git a/src/EditorFeatures/Test2/Simplification/ParameterSimplificationTests.vb b/src/EditorFeatures/Test2/Simplification/ParameterSimplificationTests.vb index 45bfae7c85aef..0c6aafb34c9e8 100644 --- a/src/EditorFeatures/Test2/Simplification/ParameterSimplificationTests.vb +++ b/src/EditorFeatures/Test2/Simplification/ParameterSimplificationTests.vb @@ -2,6 +2,8 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports System.Threading +Imports Microsoft.CodeAnalysis.CSharp.Simplification Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Text @@ -23,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification Dim annotatedDocument = document.WithSyntaxRoot( (Await document.GetSyntaxRootAsync()).WithAdditionalAnnotations(Simplifier.Annotation)) - Dim simplifiedDocument = Await Simplifier.ReduceAsync(annotatedDocument) + Dim simplifiedDocument = Await Simplifier.ReduceAsync(annotatedDocument, CSharpSimplifierOptions.Default, CancellationToken.None) Assert.Equal(expected, (Await simplifiedDocument.GetTextAsync()).ToString()) End Using diff --git a/src/EditorFeatures/Test2/Simplification/SimplifierAPITests.vb b/src/EditorFeatures/Test2/Simplification/SimplifierAPITests.vb deleted file mode 100644 index 7ec0fc594a4b4..0000000000000 --- a/src/EditorFeatures/Test2/Simplification/SimplifierAPITests.vb +++ /dev/null @@ -1,154 +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. - -Imports Microsoft.CodeAnalysis.CSharp -Imports Microsoft.CodeAnalysis.Simplification -Imports Microsoft.CodeAnalysis.Text - -Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification - - Public Class SimplifierAPITests - - - Public Async Function TestExpandAsync() As Task - Await Assert.ThrowsAsync(Of ArgumentNullException)("node", - Function() - Return Simplifier.ExpandAsync(Of SyntaxNode)(Nothing, Nothing) - End Function) - End Function - - - Public Async Function TestExpandAsync2() As Task - Dim node = GetSyntaxNode() - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() As Task - Return Simplifier.ExpandAsync(node, Nothing) - End Function) - End Function - - - Public Sub TestExpand() - Assert.Throws(Of ArgumentNullException)("node", - Sub() - Simplifier.Expand(Of SyntaxNode)(Nothing, Nothing, Nothing) - End Sub) - End Sub - - - Public Sub TestExpand2() - Dim node = GetSyntaxNode() - Assert.Throws(Of ArgumentNullException)("semanticModel", - Sub() - Simplifier.Expand(node, Nothing, Nothing) - End Sub) - End Sub - - - Public Sub TestExpand3() - Dim node = GetSyntaxNode() - Dim semanticModel = GetSemanticModel() - Assert.Throws(Of ArgumentNullException)("workspace", - Sub() - Simplifier.Expand(node, semanticModel, Nothing) - End Sub) - End Sub - - - Public Async Function TestTokenExpandAsync() As Task - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() - Return Simplifier.ExpandAsync(Nothing, Nothing) - End Function) - End Function - - - Public Sub TestTokenExpand() - Assert.Throws(Of ArgumentNullException)("semanticModel", - Sub() - Dim expandedNode = Simplifier.Expand(Nothing, Nothing, Nothing) - End Sub) - End Sub - - - Public Sub TestTokenExpand2() - Dim semanticModel = GetSemanticModel() - Assert.Throws(Of ArgumentNullException)("workspace", - Sub() - Dim expandedNode = Simplifier.Expand(Nothing, semanticModel, Nothing) - End Sub) - End Sub - - - Public Async Function TestReduceAsync() As Task - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() - Return Simplifier.ReduceAsync(Nothing) - End Function) - End Function - - - Public Async Function TestReduceAsync2() As Task - Dim syntaxAnnotation As SyntaxAnnotation = Nothing - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() - Return Simplifier.ReduceAsync(Nothing, syntaxAnnotation) - End Function) - End Function - - - Public Async Function TestReduceAsync3() As Task - Dim syntaxAnnotation As SyntaxAnnotation = Nothing - Dim document = GetDocument() - Await Assert.ThrowsAsync(Of ArgumentNullException)("annotation", - Function() - Return Simplifier.ReduceAsync(document, syntaxAnnotation) - End Function) - End Function - - - Public Async Function TestReduceAsync4() As Task - Dim textSpan As TextSpan = Nothing - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() - Return Simplifier.ReduceAsync(Nothing, textSpan) - End Function) - End Function - - - Public Async Function TestReduceAsync5() As Task - Dim spans As IEnumerable(Of TextSpan) = Nothing - Await Assert.ThrowsAsync(Of ArgumentNullException)("document", - Function() - Return Simplifier.ReduceAsync(Nothing, spans) - End Function) - End Function - - - Public Async Function TestReduceAsync6() As Task - Dim document = GetDocument() - Dim spans As IEnumerable(Of TextSpan) = Nothing - Await Assert.ThrowsAsync(Of ArgumentNullException)("spans", - Function() As Task - Return Simplifier.ReduceAsync(document, spans) - End Function) - End Function - - Private Shared Function GetDocument() As Document - Dim workspace = New AdhocWorkspace() - - Dim solution = workspace.CreateSolution(SolutionId.CreateNewId()) - Dim project = workspace.AddProject("CSharpTest", LanguageNames.CSharp) - - Return workspace.AddDocument(project.Id, "CSharpFile.cs", SourceText.From("class C { }")) - End Function - - Private Shared Function GetSemanticModel() As SemanticModel - Return GetDocument().GetSemanticModelAsync().Result - End Function - - Private Shared Function GetSyntaxNode() As SyntaxNode - Return SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Test")) - End Function - End Class -End Namespace diff --git a/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs b/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs index 432ae717e94cc..a4603c33d98cf 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -66,8 +67,8 @@ private async Task TestCoreAsync(string testCode, string expected, (OptionKey var document = workspace.CurrentSolution.Projects.First().Documents.First(); var formattingService = document.GetRequiredLanguageService(); - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None).ConfigureAwait(false); - var formattedDocument = await formattingService.FormatNewDocumentAsync(document, hintDocument: null, formattingOptions, CancellationToken.None); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, CancellationToken.None).ConfigureAwait(false); + var formattedDocument = await formattingService.FormatNewDocumentAsync(document, hintDocument: null, cleanupOptions, CancellationToken.None); var actual = await formattedDocument.GetTextAsync(); AssertEx.EqualOrDiff(expected, actual.ToString()); diff --git a/src/EditorFeatures/VisualBasic/EncapsulateField/EncapsulateFieldCommandHandler.vb b/src/EditorFeatures/VisualBasic/EncapsulateField/EncapsulateFieldCommandHandler.vb index 3deca66036fa7..692cfdb2df231 100644 --- a/src/EditorFeatures/VisualBasic/EncapsulateField/EncapsulateFieldCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/EncapsulateField/EncapsulateFieldCommandHandler.vb @@ -11,6 +11,7 @@ Imports Microsoft.CodeAnalysis.Shared.TestHooks Imports Microsoft.VisualStudio.Commanding Imports Microsoft.VisualStudio.Text.Operations Imports Microsoft.VisualStudio.Utilities +Imports Microsoft.CodeAnalysis.Options Namespace Microsoft.CodeAnalysis.VisualBasic.EncapsulateField @@ -24,8 +25,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.EncapsulateField Public Sub New(threadingContext As IThreadingContext, undoManager As ITextBufferUndoManagerProvider, + globalOptions As IGlobalOptionService, listenerProvider As IAsynchronousOperationListenerProvider) - MyBase.New(threadingContext, undoManager, listenerProvider) + MyBase.New(threadingContext, undoManager, globalOptions, listenerProvider) End Sub End Class End Namespace diff --git a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb index f5889434f3474..0d77f26a96de0 100644 --- a/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb +++ b/src/EditorFeatures/VisualBasic/LineCommit/CommitFormatter.vb @@ -5,6 +5,7 @@ Imports System.Collections.Immutable Imports System.ComponentModel.Composition Imports System.Threading +Imports Microsoft.CodeAnalysis.AddImport Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.CodeCleanup.Providers Imports Microsoft.CodeAnalysis.Formatting @@ -13,6 +14,7 @@ Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Indentation Imports Microsoft.CodeAnalysis.Internal.Log Imports Microsoft.CodeAnalysis.Options +Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Text Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor @@ -88,13 +90,16 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Concat(commitFormattingCleanup) Dim cleanupService = document.GetRequiredLanguageService(Of ICodeCleanerService) + Dim simplifierOptions = document.GetSimplifierOptionsAsync(_globalOptions, cancellationToken).WaitAndGetResult(cancellationToken) + Dim addImportOptions = AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken) + Dim cleanupOptions = New CodeCleanupOptions(formattingOptions, simplifierOptions, addImportOptions) Dim finalDocument As Document If useSemantics OrElse isExplicitFormat Then finalDocument = cleanupService.CleanupAsync( document, ImmutableArray.Create(textSpanToFormat), - formattingOptions, + cleanupOptions, codeCleanups, cancellationToken).WaitAndGetResult(cancellationToken) Else diff --git a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService.vb b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService.vb index 370bf1681bc55..29d1e8bb7edf6 100644 --- a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService.vb +++ b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService.vb @@ -9,6 +9,7 @@ Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.NavigationBar.RoslynNavigationBarItem +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor @@ -23,16 +24,19 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Private ReadOnly _editorOperationsFactoryService As IEditorOperationsFactoryService Private ReadOnly _textUndoHistoryRegistry As ITextUndoHistoryRegistry + Private ReadOnly _globalOptions As IGlobalOptionService Public Sub New( threadingContext As IThreadingContext, editorOperationsFactoryService As IEditorOperationsFactoryService, - textUndoHistoryRegistry As ITextUndoHistoryRegistry) + textUndoHistoryRegistry As ITextUndoHistoryRegistry, + globalOptions As IGlobalOptionService) MyBase.New(threadingContext) _editorOperationsFactoryService = editorOperationsFactoryService _textUndoHistoryRegistry = textUndoHistoryRegistry + _globalOptions = globalOptions End Sub Friend Overrides Async Function GetNavigationLocationAsync( diff --git a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb index 15e8944e24f20..41300ee881aba 100644 --- a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb +++ b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb @@ -13,6 +13,7 @@ Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Formatting.Rules Imports Microsoft.CodeAnalysis.NavigationBar Imports Microsoft.CodeAnalysis.NavigationBar.RoslynNavigationBarItem +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Text @@ -24,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Private Async Function GenerateCodeForItemAsync(document As Document, generateCodeItem As AbstractGenerateCodeItem, textView As ITextView, cancellationToken As CancellationToken) As Task ' We'll compute everything up front before we go mutate state Dim text = Await document.GetTextAsync(cancellationToken).ConfigureAwait(False) - Dim newDocument = Await GetGeneratedDocumentAsync(document, generateCodeItem, cancellationToken).ConfigureAwait(False) + Dim newDocument = Await GetGeneratedDocumentAsync(document, generateCodeItem, _globalOptions, cancellationToken).ConfigureAwait(False) Dim generatedTree = Await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Dim generatedNode = generatedTree.GetAnnotatedNodes(GeneratedSymbolAnnotation).Single().FirstAncestorOrSelf(Of MethodBlockBaseSyntax) @@ -48,7 +49,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar End Using End Function - Public Shared Async Function GetGeneratedDocumentAsync(document As Document, generateCodeItem As RoslynNavigationBarItem, cancellationToken As CancellationToken) As Task(Of Document) + Public Shared Async Function GetGeneratedDocumentAsync(document As Document, generateCodeItem As RoslynNavigationBarItem, globalOptions As IGlobalOptionService, cancellationToken As CancellationToken) As Task(Of Document) Dim syntaxTree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False) Dim contextLocation = syntaxTree.GetLocation(New TextSpan(0, 0)) @@ -59,19 +60,20 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Return document End If - newDocument = Await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, Nothing, cancellationToken).ConfigureAwait(False) + Dim simplifierOptions = Await newDocument.GetSimplifierOptionsAsync(globalOptions, cancellationToken).ConfigureAwait(False) + Dim formattingOptions = Await SyntaxFormattingOptions.FromDocumentAsync(newDocument, cancellationToken).ConfigureAwait(False) + + newDocument = Await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, simplifierOptions, cancellationToken).ConfigureAwait(False) Dim formatterRules = Formatter.GetDefaultFormattingRules(newDocument) If ShouldApplyLineAdjustmentFormattingRule(generateCodeItem) Then formatterRules = ImmutableArray.Create(Of AbstractFormattingRule)(LineAdjustmentFormattingRule.Instance).AddRange(formatterRules) End If - Dim documentOptions = Await document.GetOptionsAsync(cancellationToken).ConfigureAwait(False) - Return Await Formatter.FormatAsync( newDocument, Formatter.Annotation, - options:=documentOptions, + options:=formattingOptions, cancellationToken:=cancellationToken, rules:=formatterRules).ConfigureAwait(False) End Function diff --git a/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb b/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb new file mode 100644 index 0000000000000..6351689884e39 --- /dev/null +++ b/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb @@ -0,0 +1,40 @@ +' 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. + +Imports System.Composition +Imports System.Runtime.CompilerServices +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.Options +Imports Microsoft.CodeAnalysis.Simplification + +Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification + Friend Module VisualBasicSimplifierOptionsStorage + + + Private NotInheritable Class Service + Implements ISimplifierOptionsStorage + + + + Public Sub New() + End Sub + + Public Function GetOptions(globalOptions As IGlobalOptionService) As SimplifierOptions Implements ISimplifierOptionsStorage.GetOptions + Return GetVisualBasicSimplifierOptions(globalOptions) + End Function + End Class + + + Public Function GetVisualBasicSimplifierOptions(globalOptions As IGlobalOptionService) As VisualBasicSimplifierOptions + Return New VisualBasicSimplifierOptions( + qualifyFieldAccess:=globalOptions.GetOption(CodeStyleOptions2.QualifyFieldAccess, LanguageNames.VisualBasic), + qualifyPropertyAccess:=globalOptions.GetOption(CodeStyleOptions2.QualifyPropertyAccess, LanguageNames.VisualBasic), + qualifyMethodAccess:=globalOptions.GetOption(CodeStyleOptions2.QualifyMethodAccess, LanguageNames.VisualBasic), + qualifyEventAccess:=globalOptions.GetOption(CodeStyleOptions2.QualifyEventAccess, LanguageNames.VisualBasic), + preferPredefinedTypeKeywordInMemberAccess:=globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, LanguageNames.VisualBasic), + preferPredefinedTypeKeywordInDeclaration:=globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, LanguageNames.VisualBasic)) + End Function + End Module +End Namespace diff --git a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb index d2978febaf77b..d756e35ee6f72 100644 --- a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb @@ -171,8 +171,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers End If Dim formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(newDocument, cancellationToken).WaitAndGetResult(cancellationToken) + Dim simplifierOptions = newDocument.GetSimplifierOptionsAsync(_globalOptions, cancellationToken).WaitAndGetResult(cancellationToken) - newDocument = Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, Nothing, cancellationToken).WaitAndGetResult(cancellationToken) + newDocument = Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, simplifierOptions, cancellationToken).WaitAndGetResult(cancellationToken) newDocument = Formatter.FormatAsync(newDocument, Formatter.Annotation, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken) newDocument.Project.Solution.Workspace.ApplyDocumentChanges(newDocument, cancellationToken) diff --git a/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb b/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb index 3ef31c1fa05ec..c9c2de0f14ce7 100644 --- a/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb @@ -4,13 +4,11 @@ Imports System.Collections.Immutable Imports System.Threading -Imports System.Xml.Linq Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.CodeCleanup.Providers Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces -Imports Microsoft.CodeAnalysis.Formatting Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CaseCorrecting <[UseExportProvider]> @@ -34,7 +32,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CaseCorrecting Dim buffer = hostDocument.GetTextBuffer() Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id) Dim span = (Await document.GetSyntaxRootAsync()).FullSpan - Dim options = Await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None) + + Dim options = Await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions:=Nothing, CancellationToken.None) Dim service = document.GetLanguageService(Of ICodeCleanerService) Dim newDocument = Await service.CleanupAsync( diff --git a/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldCommandHandlerTests.vb b/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldCommandHandlerTests.vb index 30ea8abb4dfaf..25d5a68b0f56b 100644 --- a/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldCommandHandlerTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldCommandHandlerTests.vb @@ -6,6 +6,7 @@ Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities Imports Microsoft.CodeAnalysis.Editor.UnitTests Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Shared.TestHooks Imports Microsoft.CodeAnalysis.VisualBasic.EncapsulateField Imports Microsoft.VisualStudio.Text.Editor.Commanding.Commands @@ -154,6 +155,7 @@ End Class Dim handler = New EncapsulateFieldCommandHandler( workspace.GetService(Of IThreadingContext), workspace.GetService(Of ITextBufferUndoManagerProvider), + workspace.GlobalOptions, workspace.GetService(Of IAsynchronousOperationListenerProvider)()) Dim state = handler.GetCommandState(New EncapsulateFieldCommandArgs(textView, textView.TextBuffer)) diff --git a/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldTestState.vb b/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldTestState.vb index c5f187fa03b38..386325aca98d5 100644 --- a/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldTestState.vb +++ b/src/EditorFeatures/VisualBasicTest/EncapsulateField/EncapsulateFieldTestState.vb @@ -35,6 +35,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EncapsulateField Dim commandHandler = New EncapsulateFieldCommandHandler( Workspace.ExportProvider.GetExportedValue(Of IThreadingContext)(), Workspace.GetService(Of ITextBufferUndoManagerProvider)(), + Workspace.GlobalOptions, Workspace.ExportProvider.GetExportedValue(Of IAsynchronousOperationListenerProvider)) commandHandler.ExecuteCommand(args, TestCommandExecutionContext.Create()) End Sub diff --git a/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb b/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb index 356f108c1dc35..73cebdd9aaa55 100644 --- a/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Wrapping/AbstractParameterWrappingTests.vb @@ -6,9 +6,6 @@ Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings -Imports Microsoft.CodeAnalysis.ExtractMethod -Imports Microsoft.CodeAnalysis.ImplementType -Imports Microsoft.CodeAnalysis.SymbolSearch Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping Public MustInherit Class AbstractWrappingTests @@ -19,11 +16,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping End Function Private Protected Shared Function GetIndentionColumn(column As Integer) As CodeActionOptions - Return New CodeActionOptions( - SymbolSearchOptions.Default, - ImplementTypeOptions.Default, - ExtractMethodOptions.Default, - WrappingColumn:=column) + Return New CodeActionOptions(WrappingColumn:=column) End Function Protected Function TestAllWrappingCasesAsync( diff --git a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/AbstractUseTypeCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/AbstractUseTypeCodeRefactoringProvider.cs index 24be9b03fd663..dcc989931b350 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/AbstractUseTypeCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/AbstractUseTypeCodeRefactoringProvider.cs @@ -11,12 +11,14 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseType { @@ -25,7 +27,7 @@ internal abstract class AbstractUseTypeCodeRefactoringProvider : CodeRefactoring protected abstract string Title { get; } protected abstract Task HandleDeclarationAsync(Document document, SyntaxEditor editor, TypeSyntax type, CancellationToken cancellationToken); protected abstract TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken); - protected abstract TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken); + protected abstract TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, CSharpSimplifierOptions options, CancellationToken cancellationToken); public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { @@ -50,8 +52,9 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte return; } - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var typeStyle = AnalyzeTypeName(declaredType, semanticModel, optionSet, cancellationToken); + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + var simplifierOptions = CSharpSimplifierOptions.Create(configOptions, (CSharpSimplifierOptions)context.Options(document.Project.LanguageServices).SimplifierOptions); + var typeStyle = AnalyzeTypeName(declaredType, semanticModel, simplifierOptions, cancellationToken); if (typeStyle.IsStylePreferred && typeStyle.Severity != ReportDiagnostic.Suppress) { // the analyzer would handle this. So we do not. diff --git a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeCodeRefactoringProvider.cs index af6445056d210..f093ba1f6af8f 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseExplicitTypeCodeRefactoringProvider.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseType; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.TypeStyle; using Microsoft.CodeAnalysis.CSharp.Utilities; @@ -33,8 +34,8 @@ protected override string Title protected override TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) => CSharpUseExplicitTypeHelper.Instance.FindAnalyzableType(node, semanticModel, cancellationToken); - protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) - => CSharpUseExplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, optionSet, cancellationToken); + protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, CSharpSimplifierOptions options, CancellationToken cancellationToken) + => CSharpUseExplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, options, cancellationToken); protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, TypeSyntax node, CancellationToken cancellationToken) => UseExplicitTypeCodeFixProvider.HandleDeclarationAsync(document, editor, node, cancellationToken); diff --git a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeCodeRefactoringProvider.cs index dc35f8912897d..17f922876f708 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitOrImplicitType/UseImplicitTypeCodeRefactoringProvider.cs @@ -10,11 +10,11 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseType; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.TypeStyle; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseImplicitType { @@ -33,8 +33,8 @@ protected override string Title protected override TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) => CSharpUseImplicitTypeHelper.Instance.FindAnalyzableType(node, semanticModel, cancellationToken); - protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) - => CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, optionSet, cancellationToken); + protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, CSharpSimplifierOptions options, CancellationToken cancellationToken) + => CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, options, cancellationToken); protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, TypeSyntax type, CancellationToken cancellationToken) { diff --git a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs index d625cd68869d3..275d9240590c1 100644 --- a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs @@ -6,11 +6,13 @@ using System.Threading; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Collections; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.SimplifyTypeNames; using Microsoft.CodeAnalysis.Text; @@ -18,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames { [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class CSharpSimplifyTypeNamesDiagnosticAnalyzer - : SimplifyTypeNamesDiagnosticAnalyzerBase + : SimplifyTypeNamesDiagnosticAnalyzerBase { private static readonly ImmutableArray s_kindsOfInterest = ImmutableArray.Create( @@ -51,8 +53,8 @@ protected override ImmutableArray AnalyzeCodeBlock(CodeBlockAnalysis var cancellationToken = context.CancellationToken; var syntaxTree = semanticModel.SyntaxTree; - var optionSet = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); - var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, optionSet, ignoredSpans: null, cancellationToken); + var options = context.Options.GetCSharpSimplifierOptions(syntaxTree); + var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, options, ignoredSpans: null, cancellationToken); simplifier.Visit(context.CodeBlock); return simplifier.Diagnostics; } @@ -63,10 +65,10 @@ protected override ImmutableArray AnalyzeSemanticModel(SemanticModel var cancellationToken = context.CancellationToken; var syntaxTree = semanticModel.SyntaxTree; - var optionSet = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); + var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); var root = syntaxTree.GetRoot(cancellationToken); - var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, optionSet, ignoredSpans: codeBlockIntervalTree, cancellationToken); + var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, simplifierOptions, ignoredSpans: codeBlockIntervalTree, cancellationToken); simplifier.Visit(root); return simplifier.Diagnostics; } @@ -75,7 +77,7 @@ internal override bool IsCandidate(SyntaxNode node) => node != null && s_kindsOfInterest.Contains(node.Kind()); internal override bool CanSimplifyTypeNameExpression( - SemanticModel model, SyntaxNode node, OptionSet optionSet, + SemanticModel model, SyntaxNode node, CSharpSimplifierOptions options, out TextSpan issueSpan, out string diagnosticId, out bool inDeclaration, CancellationToken cancellationToken) { @@ -98,14 +100,14 @@ internal override bool CanSimplifyTypeNameExpression( SyntaxNode replacementSyntax; if (node.IsKind(SyntaxKind.QualifiedCref, out QualifiedCrefSyntax? crefSyntax)) { - if (!QualifiedCrefSimplifier.Instance.TrySimplify(crefSyntax, model, optionSet, out var replacement, out issueSpan, cancellationToken)) + if (!QualifiedCrefSimplifier.Instance.TrySimplify(crefSyntax, model, options, out var replacement, out issueSpan, cancellationToken)) return false; replacementSyntax = replacement; } else { - if (!ExpressionSimplifier.Instance.TrySimplify((ExpressionSyntax)node, model, optionSet, out var replacement, out issueSpan, cancellationToken)) + if (!ExpressionSimplifier.Instance.TrySimplify((ExpressionSyntax)node, model, options, out var replacement, out issueSpan, cancellationToken)) return false; replacementSyntax = replacement; diff --git a/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs b/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs index bb4ee748b1cac..f0eb6e638b222 100644 --- a/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs +++ b/src/Features/CSharp/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Collections; @@ -42,7 +43,7 @@ internal class TypeSyntaxSimplifierWalker : CSharpSyntaxWalker private readonly CSharpSimplifyTypeNamesDiagnosticAnalyzer _analyzer; private readonly SemanticModel _semanticModel; - private readonly OptionSet _optionSet; + private readonly CSharpSimplifierOptions _options; private readonly SimpleIntervalTree? _ignoredSpans; private readonly CancellationToken _cancellationToken; @@ -71,12 +72,12 @@ public ImmutableArray.Builder DiagnosticsBuilder } } - public TypeSyntaxSimplifierWalker(CSharpSimplifyTypeNamesDiagnosticAnalyzer analyzer, SemanticModel semanticModel, OptionSet optionSet, SimpleIntervalTree? ignoredSpans, CancellationToken cancellationToken) + public TypeSyntaxSimplifierWalker(CSharpSimplifyTypeNamesDiagnosticAnalyzer analyzer, SemanticModel semanticModel, CSharpSimplifierOptions options, SimpleIntervalTree? ignoredSpans, CancellationToken cancellationToken) : base(SyntaxWalkerDepth.StructuredTrivia) { _analyzer = analyzer; _semanticModel = semanticModel; - _optionSet = optionSet; + _options = options; _ignoredSpans = ignoredSpans; _cancellationToken = cancellationToken; @@ -276,7 +277,7 @@ public override void VisitQualifiedCref(QualifiedCrefSyntax node) /// private bool TrySimplify(SyntaxNode node) { - if (!_analyzer.TrySimplify(_semanticModel, node, out var diagnostic, _optionSet, _cancellationToken)) + if (!_analyzer.TrySimplify(_semanticModel, node, out var diagnostic, _options, _cancellationToken)) return false; DiagnosticsBuilder.Add(diagnostic); diff --git a/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs index ba53dbbc9a20f..2c6ac1de5ab38 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddAccessibilityModifiers; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.LanguageServices; using Microsoft.CodeAnalysis.Editing; @@ -26,7 +27,7 @@ public CSharpAccessibilityModifiersNewDocumentFormattingProvider() { } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var accessibilityPreferences = documentOptions.GetOption(CodeStyleOptions2.RequireAccessibilityModifiers, document.Project.Language); diff --git a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs index 050e3b16ed36a..428db28a1c04a 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CSharp.ConvertNamespace; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; @@ -27,7 +28,7 @@ public CSharpNamespaceDeclarationNewDocumentFormattingProvider() { } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); @@ -36,7 +37,7 @@ public async Task FormatNewDocumentAsync(Document document, Document? if (namespaces.Count != 1) return document; - return await ConvertNamespaceTransform.ConvertAsync(document, namespaces[0], options, cancellationToken).ConfigureAwait(false); + return await ConvertNamespaceTransform.ConvertAsync(document, namespaces[0], options.FormattingOptions, cancellationToken).ConfigureAwait(false); } private static IEnumerable GetNamespacesToReplace(Document document, CompilationUnitSyntax root, DocumentOptionSet optionSet) diff --git a/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs index ed370a01dd77a..4bfbf176acb6c 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs @@ -6,9 +6,14 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.MisplacedUsingDirectives; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.OrganizeImports; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.Formatting { @@ -21,10 +26,17 @@ public CSharpOrganizeUsingsNewDocumentFormattingProvider() { } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { - var organizedDocument = await Formatter.OrganizeImportsAsync(document, cancellationToken).ConfigureAwait(false); - return await MisplacedUsingDirectivesCodeFixProvider.TransformDocumentIfRequiredAsync(organizedDocument, cancellationToken).ConfigureAwait(false); + var organizeImportsService = document.GetRequiredLanguageService(); + + var organizeOptions = await OrganizeImportsOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var codeStyleOption = documentOptions.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement); + + var organizedDocument = await organizeImportsService.OrganizeImportsAsync(document, organizeOptions, cancellationToken).ConfigureAwait(false); + + return await MisplacedUsingDirectivesCodeFixProvider.TransformDocumentIfRequiredAsync(organizedDocument, options.SimplifierOptions, codeStyleOption, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs index a7cec74575b69..128f258cc56f6 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.ConvertProgram; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; @@ -22,13 +23,13 @@ public CSharpUseProgramMainNewDocumentFormattingProvider() { } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); // if the user prefers Program.Main style instead, then attempt to convert a template with // top-level-statements to that form. - var option = options.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); + var option = documentOptions.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); if (option.Value) return document; diff --git a/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs b/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs index 676af4f7ba025..1362d6a7fe76f 100644 --- a/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/ImplementInterface/CSharpImplementInterfaceCodeFixProvider.cs @@ -54,7 +54,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var actions = token.Parent.GetAncestorsOrThis() .Where(_interfaceName) - .Select(n => service.GetCodeActions(document, context.Options(document.Project.Language).ImplementTypeOptions, model, n, cancellationToken)) + .Select(n => service.GetCodeActions(document, context.Options(document.Project.LanguageServices).ImplementTypeOptions, model, n, cancellationToken)) .FirstOrDefault(a => !a.IsEmpty); if (actions.IsDefaultOrEmpty) diff --git a/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs index f572364f624b5..61355bddd70fc 100644 --- a/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs @@ -4,11 +4,12 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.LanguageServices; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.LanguageServices; -using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.SimplifyThisOrMe; using Microsoft.CodeAnalysis.Text; @@ -20,16 +21,20 @@ internal sealed class CSharpSimplifyThisOrMeDiagnosticAnalyzer SyntaxKind, ExpressionSyntax, ThisExpressionSyntax, - MemberAccessExpressionSyntax> + MemberAccessExpressionSyntax, + CSharpSimplifierOptions> { protected override ISyntaxFacts GetSyntaxFacts() => CSharpSyntaxFacts.Instance; + protected override CSharpSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree) + => options.GetCSharpSimplifierOptions(syntaxTree); + protected override bool CanSimplifyTypeNameExpression( - SemanticModel model, MemberAccessExpressionSyntax node, OptionSet optionSet, + SemanticModel model, MemberAccessExpressionSyntax node, CSharpSimplifierOptions options, out TextSpan issueSpan, CancellationToken cancellationToken) { - return ExpressionSimplifier.Instance.TrySimplify(node, model, optionSet, out _, out issueSpan, cancellationToken); + return ExpressionSimplifier.Instance.TrySimplify(node, model, options, out _, out issueSpan, cancellationToken); } } } diff --git a/src/Features/CSharp/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.cs b/src/Features/CSharp/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.cs index 0742e1a32f5e3..5a68a42614dbb 100644 --- a/src/Features/CSharp/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; @@ -19,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp.SimplifyTypeNames { [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.SimplifyNames), Shared] [ExtensionOrder(After = PredefinedCodeFixProviderNames.RemoveUnnecessaryCast)] - internal partial class SimplifyTypeNamesCodeFixProvider : AbstractSimplifyTypeNamesCodeFixProvider + internal partial class SimplifyTypeNamesCodeFixProvider : AbstractSimplifyTypeNamesCodeFixProvider { [ImportingConstructor] [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] diff --git a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs index 0e723e3457129..ef1f1a6f61d04 100644 --- a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs +++ b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.FileHeaders; @@ -19,7 +20,7 @@ internal abstract class AbstractAddFileBannerNewDocumentFormattingProvider : INe protected abstract SyntaxGeneratorInternal SyntaxGeneratorInternal { get; } protected abstract AbstractFileHeaderHelper FileHeaderHelper { get; } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { var rootToFormat = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); @@ -28,7 +29,7 @@ public async Task FormatNewDocumentAsync(Document document, Document? var fileHeaderTemplate = documentOptions.GetOption(CodeStyleOptions2.FileHeaderTemplate); if (!string.IsNullOrEmpty(fileHeaderTemplate)) { - var newLineTrivia = SyntaxGeneratorInternal.EndOfLine(options.NewLine); + var newLineTrivia = SyntaxGeneratorInternal.EndOfLine(options.FormattingOptions.NewLine); var rootWithFileHeader = await AbstractFileHeaderCodeFixProvider.GetTransformedSyntaxRootAsync( SyntaxGenerator.SyntaxFacts, FileHeaderHelper, diff --git a/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs b/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs index 2d12603c7e556..2f687a4e61786 100644 --- a/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs +++ b/src/Features/Core/Portable/AddImport/AbstractAddImportCodeFixProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Packaging; @@ -55,7 +56,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var addImportService = document.GetRequiredLanguageService(); var services = document.Project.Solution.Workspace.Services; - var searchOptions = context.Options(document.Project.Language).SearchOptions; + var searchOptions = context.Options(document.Project.LanguageServices).SearchOptions; var symbolSearchService = _symbolSearchService ?? services.GetRequiredService(); @@ -71,12 +72,12 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) searchOptions = searchOptions with { SearchNuGetPackages = false }; } - var placement = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); var addImportOptions = new AddImportOptions( searchOptions, - context.Options(document.Project.Language).HideAdvancedMembers, - placement); + cleanupOptions, + context.Options(document.Project.LanguageServices).HideAdvancedMembers); var fixesForDiagnostic = await addImportService.GetFixesForDiagnosticsAsync( document, span, diagnostics, MaxResults, symbolSearchService, addImportOptions, packageSources, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs b/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs index a6cb300bb006c..49bf94ea79a47 100644 --- a/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs +++ b/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs @@ -23,6 +23,7 @@ using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeCleanup; namespace Microsoft.CodeAnalysis.AddImport { @@ -94,7 +95,7 @@ private async Task> GetFixesInCurrentProcessAsy { if (!cancellationToken.IsCancellationRequested) { - if (CanAddImport(node, options.Placement.AllowInHiddenRegions, cancellationToken)) + if (CanAddImport(node, options.CleanupOptions.AddImportOptions.AllowInHiddenRegions, cancellationToken)) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var allSymbolReferences = await FindResultsAsync( @@ -106,7 +107,7 @@ private async Task> GetFixesInCurrentProcessAsy { cancellationToken.ThrowIfCancellationRequested(); - var fixData = await reference.TryGetFixDataAsync(document, node, options.Placement, cancellationToken).ConfigureAwait(false); + var fixData = await reference.TryGetFixDataAsync(document, node, options.CleanupOptions, cancellationToken).ConfigureAwait(false); result.AddIfNotNull(fixData); } } diff --git a/src/Features/Core/Portable/AddImport/IAddImportFeatureService.cs b/src/Features/Core/Portable/AddImport/IAddImportFeatureService.cs index 453c8a89cd5c8..2f856e4edc061 100644 --- a/src/Features/Core/Portable/AddImport/IAddImportFeatureService.cs +++ b/src/Features/Core/Portable/AddImport/IAddImportFeatureService.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.SymbolSearch; @@ -17,8 +18,8 @@ namespace Microsoft.CodeAnalysis.AddImport [DataContract] internal readonly record struct AddImportOptions( [property: DataMember(Order = 0)] SymbolSearchOptions SearchOptions, - [property: DataMember(Order = 1)] bool HideAdvancedMembers, - [property: DataMember(Order = 2)] AddImportPlacementOptions Placement); + [property: DataMember(Order = 1)] CodeCleanupOptions CleanupOptions, + [property: DataMember(Order = 2)] bool HideAdvancedMembers); internal interface IAddImportFeatureService : ILanguageService { diff --git a/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs b/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs index 680218405a222..4e5fecb1a9af9 100644 --- a/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs +++ b/src/Features/Core/Portable/AddImport/References/AssemblyReference.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.SymbolSearch; using Roslyn.Utilities; @@ -28,7 +29,7 @@ public AssemblyReference( } public override async Task TryGetFixDataAsync( - Document document, SyntaxNode node, AddImportPlacementOptions options, CancellationToken cancellationToken) + Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken) { var textChanges = await GetTextChangesAsync(document, node, options, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/AddImport/References/MetadataSymbolReference.cs b/src/Features/Core/Portable/AddImport/References/MetadataSymbolReference.cs index 1671105787b8a..bace3e619a3e3 100644 --- a/src/Features/Core/Portable/AddImport/References/MetadataSymbolReference.cs +++ b/src/Features/Core/Portable/AddImport/References/MetadataSymbolReference.cs @@ -9,6 +9,7 @@ using System.IO; using System.Threading; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Tags; using Microsoft.CodeAnalysis.Text; @@ -41,7 +42,7 @@ public MetadataSymbolReference( protected override bool ShouldAddWithExistingImport(Document document) => true; protected override (string description, bool hasExistingImport) GetDescription( - Document document, AddImportPlacementOptions options, SyntaxNode node, + Document document, CodeCleanupOptions options, SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { var (description, hasExistingImport) = base.GetDescription(document, options, node, semanticModel, cancellationToken); diff --git a/src/Features/Core/Portable/AddImport/References/PackageReference.cs b/src/Features/Core/Portable/AddImport/References/PackageReference.cs index 0168a9f3d3830..e790aa14aa0ef 100644 --- a/src/Features/Core/Portable/AddImport/References/PackageReference.cs +++ b/src/Features/Core/Portable/AddImport/References/PackageReference.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Roslyn.Utilities; @@ -33,7 +34,7 @@ public PackageReference( } public override async Task TryGetFixDataAsync( - Document document, SyntaxNode node, AddImportPlacementOptions options, CancellationToken cancellationToken) + Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken) { var textChanges = await GetTextChangesAsync( document, node, options, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/AddImport/References/ProjectSymbolReference.cs b/src/Features/Core/Portable/AddImport/References/ProjectSymbolReference.cs index 3f85b7457f2f8..aed38f3db4a81 100644 --- a/src/Features/Core/Portable/AddImport/References/ProjectSymbolReference.cs +++ b/src/Features/Core/Portable/AddImport/References/ProjectSymbolReference.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Tags; @@ -87,7 +88,7 @@ protected override AddImportFixData GetFixData( } protected override (string description, bool hasExistingImport) GetDescription( - Document document, AddImportPlacementOptions options, SyntaxNode node, + Document document, CodeCleanupOptions options, SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { var (description, hasExistingImport) = base.GetDescription(document, options, node, semanticModel, cancellationToken); diff --git a/src/Features/Core/Portable/AddImport/References/Reference.cs b/src/Features/Core/Portable/AddImport/References/Reference.cs index 98dbb57fa3853..a9080a50f67e6 100644 --- a/src/Features/Core/Portable/AddImport/References/Reference.cs +++ b/src/Features/Core/Portable/AddImport/References/Reference.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -102,10 +102,10 @@ public override int GetHashCode() } public abstract Task TryGetFixDataAsync( - Document document, SyntaxNode node, AddImportPlacementOptions options, CancellationToken cancellationToken); + Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken); protected async Task> GetTextChangesAsync( - Document document, SyntaxNode node, AddImportPlacementOptions options, CancellationToken cancellationToken) + Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken) { var originalDocument = document; @@ -113,10 +113,10 @@ protected async Task> GetTextChangesAsync( node, document, cancellationToken).ConfigureAwait(false); var newDocument = await provider.AddImportAsync( - node, SearchResult.NameParts, document, options, cancellationToken).ConfigureAwait(false); + node, SearchResult.NameParts, document, options.AddImportOptions, cancellationToken).ConfigureAwait(false); var cleanedDocument = await CodeAction.CleanupDocumentAsync( - newDocument, cancellationToken).ConfigureAwait(false); + newDocument, options, cancellationToken).ConfigureAwait(false); var textChanges = await cleanedDocument.GetTextChangesAsync( originalDocument, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/AddImport/References/SymbolReference.cs b/src/Features/Core/Portable/AddImport/References/SymbolReference.cs index 45f8cf54a43f6..2b8eb2c7f361e 100644 --- a/src/Features/Core/Portable/AddImport/References/SymbolReference.cs +++ b/src/Features/Core/Portable/AddImport/References/SymbolReference.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Tags; using Microsoft.CodeAnalysis.Text; @@ -52,7 +53,7 @@ public override int GetHashCode() private async Task> GetTextChangesAsync( Document document, SyntaxNode contextNode, - AddImportPlacementOptions options, bool hasExistingImport, + CodeCleanupOptions options, bool hasExistingImport, CancellationToken cancellationToken) { // Defer to the language to add the actual import/using. @@ -66,10 +67,10 @@ private async Task> GetTextChangesAsync( var updatedDocument = await provider.AddImportAsync( newContextNode, SymbolResult.Symbol, newDocument, - options, cancellationToken).ConfigureAwait(false); + options.AddImportOptions, cancellationToken).ConfigureAwait(false); var cleanedDocument = await CodeAction.CleanupDocumentAsync( - updatedDocument, cancellationToken).ConfigureAwait(false); + updatedDocument, options, cancellationToken).ConfigureAwait(false); var textChanges = await cleanedDocument.GetTextChangesAsync( document, cancellationToken).ConfigureAwait(false); @@ -79,7 +80,7 @@ private async Task> GetTextChangesAsync( public sealed override async Task TryGetFixDataAsync( Document document, SyntaxNode node, - AddImportPlacementOptions options, CancellationToken cancellationToken) + CodeCleanupOptions options, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var (description, hasExistingImport) = GetDescription(document, options, node, semanticModel, cancellationToken); @@ -127,11 +128,11 @@ protected abstract AddImportFixData GetFixData( protected abstract CodeActionPriority GetPriority(Document document); protected virtual (string description, bool hasExistingImport) GetDescription( - Document document, AddImportPlacementOptions options, SyntaxNode node, + Document document, CodeCleanupOptions options, SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { return provider.GetDescription( - document, options, SymbolResult.Symbol, semanticModel, node, cancellationToken); + document, options.AddImportOptions, SymbolResult.Symbol, semanticModel, node, cancellationToken); } } } diff --git a/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs b/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs index 94c8901b70553..9e543e09569ad 100644 --- a/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs +++ b/src/Features/Core/Portable/AddPackage/AbstractAddPackageCodeFixProvider.cs @@ -52,7 +52,7 @@ protected async Task> GetAddPackagesCodeActionsAsync( var codeActions = ArrayBuilder.GetInstance(); if (symbolSearchService != null && installerService != null && - context.Options(document.Project.Language).SearchOptions.SearchNuGetPackages && + context.Options(document.Project.LanguageServices).SearchOptions.SearchNuGetPackages && installerService.IsEnabled(document.Project.Id)) { var packageSources = PackageSourceHelper.GetPackageSources(installerService.TryGetPackageSources()); diff --git a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs index 48915313eab50..7f0bab1059332 100644 --- a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs +++ b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindSymbols.Finders; @@ -416,12 +416,11 @@ private static async Task> FindChangeSignatureR foreach (var docId in nodesToUpdate.Keys) { var updatedDoc = currentSolution.GetRequiredDocument(docId).WithSyntaxRoot(updatedRoots[docId]); - var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(updatedDoc, cancellationToken).ConfigureAwait(false); - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(updatedDoc, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(updatedDoc, fallbackOptions: null, cancellationToken).ConfigureAwait(false); - var docWithImports = await ImportAdder.AddImportsFromSymbolAnnotationAsync(updatedDoc, addImportOptions, cancellationToken).ConfigureAwait(false); - var reducedDoc = await Simplifier.ReduceAsync(docWithImports, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false); - var formattedDoc = await Formatter.FormatAsync(reducedDoc, SyntaxAnnotation.ElasticAnnotation, formattingOptions, cancellationToken).ConfigureAwait(false); + var docWithImports = await ImportAdder.AddImportsFromSymbolAnnotationAsync(updatedDoc, cleanupOptions.AddImportOptions, cancellationToken).ConfigureAwait(false); + var reducedDoc = await Simplifier.ReduceAsync(docWithImports, Simplifier.Annotation, cleanupOptions.SimplifierOptions, cancellationToken: cancellationToken).ConfigureAwait(false); + var formattedDoc = await Formatter.FormatAsync(reducedDoc, SyntaxAnnotation.ElasticAnnotation, cleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false); currentSolution = currentSolution.WithDocumentSyntaxRoot(docId, (await formattedDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false))!); } diff --git a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageFixAllCodeAction.cs b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageFixAllCodeAction.cs index 407042a49b2dd..f3373836744dd 100644 --- a/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageFixAllCodeAction.cs +++ b/src/Features/Core/Portable/CodeFixes/Suppression/AbstractSuppressionCodeFixProvider.GlobalSuppressMessageFixAllCodeAction.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Formatting; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.CodeCleanup; namespace Microsoft.CodeAnalysis.CodeFixes.Suppression { @@ -124,7 +125,7 @@ protected override async Task GetChangedSuppressionDocumentAsync(Cance var services = suppressionsDoc.Project.Solution.Workspace.Services; var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var addImportsService = suppressionsDoc.GetRequiredLanguageService(); - var options = await SyntaxFormattingOptions.FromDocumentAsync(suppressionsDoc, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(suppressionsDoc, fallbackOptions: null, cancellationToken).ConfigureAwait(false); foreach (var (targetSymbol, diagnostics) in _diagnosticsBySymbol) { @@ -133,12 +134,12 @@ protected override async Task GetChangedSuppressionDocumentAsync(Cance Contract.ThrowIfFalse(!diagnostic.IsSuppressed); suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute( suppressionsRoot, targetSymbol, _suppressMessageAttribute, diagnostic, - services, options, addImportsService, cancellationToken); + services, cleanupOptions.FormattingOptions, addImportsService, cancellationToken); } } var result = suppressionsDoc.WithSyntaxRoot(suppressionsRoot); - var final = await CleanupDocumentAsync(result, cancellationToken).ConfigureAwait(false); + var final = await CleanupDocumentAsync(result, cleanupOptions, cancellationToken).ConfigureAwait(false); return final; } diff --git a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs index 5c6001c3ddea6..17da6c72cc9d7 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs @@ -62,8 +62,8 @@ public async Task AnalyzeAsync(Document documen var addImportOptions = new AddImportOptions( SearchOptions: new(SearchReferenceAssemblies: true, SearchNuGetPackages: false), - HideAdvancedMembers: options.HideAdvancedMembers, - Placement: options.Placement); + CleanupOptions: options.CleanupOptions, + HideAdvancedMembers: options.HideAdvancedMembers); var unambiguousFixes = await addImportFeatureService.GetUniqueFixesAsync( document, textSpan, FixableDiagnosticIds, symbolSearchService, diff --git a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsRefactoringProvider.cs b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsRefactoringProvider.cs index df26d9b289e2b..a798c3084bbc8 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsRefactoringProvider.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsRefactoringProvider.cs @@ -7,14 +7,10 @@ using System; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeRefactorings; -using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.PasteTracking; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.AddMissingImports { @@ -39,8 +35,10 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte // Check pasted text span for missing imports var addMissingImportsService = document.GetLanguageService(); - var placement = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - var options = new AddMissingImportsOptions(context.Options(document.Project.Language).HideAdvancedMembers, placement); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var options = new AddMissingImportsOptions( + cleanupOptions, + context.Options(document.Project.LanguageServices).HideAdvancedMembers); var analysis = await addMissingImportsService.AnalyzeAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); if (!analysis.CanAddMissingImports) diff --git a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/IAddMissingImportsFeatureService.cs b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/IAddMissingImportsFeatureService.cs index 7cb68cf7d3cd9..aa84f876128a4 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/IAddMissingImportsFeatureService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/IAddMissingImportsFeatureService.cs @@ -5,8 +5,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Text; @@ -14,8 +13,8 @@ namespace Microsoft.CodeAnalysis.AddMissingImports { [DataContract] internal readonly record struct AddMissingImportsOptions( - [property: DataMember(Order = 0)] bool HideAdvancedMembers, - [property: DataMember(Order = 1)] AddImportPlacementOptions Placement); + [property: DataMember(Order = 0)] CodeCleanupOptions CleanupOptions, + [property: DataMember(Order = 1)] bool HideAdvancedMembers); internal interface IAddMissingImportsFeatureService : ILanguageService { diff --git a/src/Features/Core/Portable/CodeRefactorings/ExtractMethod/AbstractExtractMethodCodeRefactoringProvider.cs b/src/Features/Core/Portable/CodeRefactorings/ExtractMethod/AbstractExtractMethodCodeRefactoringProvider.cs index aae685a87be61..51aded52f3354 100644 --- a/src/Features/Core/Portable/CodeRefactorings/ExtractMethod/AbstractExtractMethodCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/CodeRefactorings/ExtractMethod/AbstractExtractMethodCodeRefactoringProvider.cs @@ -56,7 +56,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte return; } - var options = context.Options(document.Project.Language).ExtractMethodOptions; + var options = context.Options(document.Project.LanguageServices).ExtractMethodOptions; var actions = await GetCodeActionsAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); context.RegisterRefactorings(actions); } diff --git a/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractChangeNamespaceService.cs b/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractChangeNamespaceService.cs index 8e2fa98735110..1997d385a21f7 100644 --- a/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractChangeNamespaceService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractChangeNamespaceService.cs @@ -34,9 +34,9 @@ internal abstract class AbstractChangeNamespaceService : IChangeNamespaceService { public abstract Task CanChangeNamespaceAsync(Document document, SyntaxNode container, CancellationToken cancellationToken); - public abstract Task ChangeNamespaceAsync(Document document, SyntaxNode container, string targetNamespace, CancellationToken cancellationToken); + public abstract Task ChangeNamespaceAsync(Document document, SyntaxNode container, string targetNamespace, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); - public abstract Task TryChangeTopLevelNamespacesAsync(Document document, string targetNamespace, CancellationToken cancellationToken); + public abstract Task TryChangeTopLevelNamespacesAsync(Document document, string targetNamespace, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); /// /// Try to get a new node to replace given node, which is a reference to a top-level type declared inside the @@ -110,6 +110,7 @@ public override async Task CanChangeNamespaceAsync(Document document, Synt public override async Task TryChangeTopLevelNamespacesAsync( Document document, string targetNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService(); @@ -151,7 +152,7 @@ public override async Task CanChangeNamespaceAsync(Document document, Synt Debug.Assert(namespaces.Length == originalNamespaceDeclarations.Length); var namespaceToRename = namespaces[i]; - solution = await ChangeNamespaceAsync(document, namespaceToRename, targetNamespace, cancellationToken).ConfigureAwait(false); + solution = await ChangeNamespaceAsync(document, namespaceToRename, targetNamespace, options, cancellationToken).ConfigureAwait(false); document = solution.GetRequiredDocument(document.Id); } @@ -172,6 +173,7 @@ public override async Task ChangeNamespaceAsync( Document document, SyntaxNode container, string targetNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { // Make sure given namespace name is valid, "" means global namespace. @@ -220,7 +222,7 @@ public override async Task ChangeNamespaceAsync( foreach (var documentId in documentIds) { var (newSolution, refDocumentIds) = - await ChangeNamespaceInSingleDocumentAsync(solutionAfterNamespaceChange, documentId, declaredNamespace, targetNamespace, cancellationToken) + await ChangeNamespaceInSingleDocumentAsync(solutionAfterNamespaceChange, documentId, declaredNamespace, targetNamespace, options, cancellationToken) .ConfigureAwait(false); solutionAfterNamespaceChange = newSolution; referenceDocuments.AddRange(refDocumentIds); @@ -426,6 +428,7 @@ private static SyntaxNode CreateImport(SyntaxGenerator syntaxGenerator, string n DocumentId id, string oldNamespace, string newNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { var document = solution.GetRequiredDocument(id); @@ -462,7 +465,7 @@ private static SyntaxNode CreateImport(SyntaxGenerator syntaxGenerator, string n } } - var documentWithNewNamespace = await FixDeclarationDocumentAsync(document, refLocationsInCurrentDocument, oldNamespace, newNamespace, cancellationToken) + var documentWithNewNamespace = await FixDeclarationDocumentAsync(document, refLocationsInCurrentDocument, oldNamespace, newNamespace, options, cancellationToken) .ConfigureAwait(false); var solutionWithChangedNamespace = documentWithNewNamespace.Project.Solution; @@ -474,6 +477,7 @@ private static SyntaxNode CreateImport(SyntaxGenerator syntaxGenerator, string n solutionWithChangedNamespace.GetRequiredDocument(refInOneDocument.Key), refInOneDocument, newNamespace, + options, cancellationToken))).ConfigureAwait(false); var solutionWithFixedReferences = await MergeDocumentChangesAsync(solutionWithChangedNamespace, fixedDocuments, cancellationToken).ConfigureAwait(false); @@ -558,6 +562,7 @@ private async Task FixDeclarationDocumentAsync( IReadOnlyList refLocations, string oldNamespace, string newNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { Debug.Assert(newNamespace != null); @@ -606,15 +611,14 @@ private async Task FixDeclarationDocumentAsync( // references to the type inside it's new namespace var namesToImport = GetAllNamespaceImportsForDeclaringDocument(oldNamespace, newNamespace); - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var addImportsOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var documentOptions = await ChangeNamespaceOptions.FromDocumentAsync(document, options(document.Project.LanguageServices), cancellationToken).ConfigureAwait(false); var documentWithAddedImports = await AddImportsInContainersAsync( document, addImportService, containersToAddImports, namesToImport, - addImportsOptions, + documentOptions.AddImportOptions, cancellationToken).ConfigureAwait(false); var root = await documentWithAddedImports.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); @@ -624,18 +628,18 @@ private async Task FixDeclarationDocumentAsync( // Need to invoke formatter explicitly since we are doing the diff merge ourselves. var services = documentWithAddedImports.Project.Solution.Workspace.Services; - var formattingOptions = SyntaxFormattingOptions.Create(optionSet, services, root.Language); - root = Formatter.Format(root, Formatter.Annotation, services, formattingOptions, cancellationToken); + root = Formatter.Format(root, Formatter.Annotation, services, documentOptions.FormattingOptions, cancellationToken); root = root.WithAdditionalAnnotations(Simplifier.Annotation); var formattedDocument = documentWithAddedImports.WithSyntaxRoot(root); - return await Simplifier.ReduceAsync(formattedDocument, optionSet, cancellationToken).ConfigureAwait(false); + return await Simplifier.ReduceAsync(formattedDocument, documentOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); } private static async Task FixReferencingDocumentAsync( Document document, IEnumerable refLocations, string newNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { // 1. Fully qualify all simple references (i.e. not via an alias) with new namespace. @@ -651,23 +655,21 @@ private static async Task FixReferencingDocumentAsync( await FixReferencesAsync(document, changeNamespaceService, addImportService, refLocations, newNamespaceParts, cancellationToken) .ConfigureAwait(false); - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - var addImportsOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var documentOptions = await ChangeNamespaceOptions.FromDocumentAsync(document, options(document.Project.LanguageServices), cancellationToken).ConfigureAwait(false); var documentWithAdditionalImports = await AddImportsInContainersAsync( documentWithRefFixed, addImportService, containers, ImmutableArray.Create(newNamespace), - addImportsOptions, + documentOptions.AddImportOptions, cancellationToken).ConfigureAwait(false); // Need to invoke formatter explicitly since we are doing the diff merge ourselves. - var formattedDocument = await Formatter.FormatAsync(documentWithAdditionalImports, Formatter.Annotation, formattingOptions, cancellationToken) + var formattedDocument = await Formatter.FormatAsync(documentWithAdditionalImports, Formatter.Annotation, documentOptions.FormattingOptions, cancellationToken) .ConfigureAwait(false); - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return await Simplifier.ReduceAsync(formattedDocument, optionSet, cancellationToken).ConfigureAwait(false); + return await Simplifier.ReduceAsync(formattedDocument, documentOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); } /// diff --git a/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractSyncNamespaceCodeRefactoringProvider.cs b/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractSyncNamespaceCodeRefactoringProvider.cs index 95d0fb8d24e5e..678198a141e9c 100644 --- a/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractSyncNamespaceCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/CodeRefactorings/SyncNamespace/AbstractSyncNamespaceCodeRefactoringProvider.cs @@ -73,7 +73,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte state.TargetNamespace.Length == 0 ? FeaturesResources.Change_to_global_namespace : string.Format(FeaturesResources.Change_namespace_to_0, state.TargetNamespace), - token => service.ChangeNamespaceAsync(document, state.Container, state.TargetNamespace, token)); + token => service.ChangeNamespaceAsync(document, state.Container, state.TargetNamespace, ChangeNamespaceOptions.CreateProvider(context.Options), token)); context.RegisterRefactoring(solutionChangeAction, textSpan); } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs index 8e4c0d35092ae..fb0a718f0f008 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; @@ -85,9 +86,9 @@ private async Task DetermineNewDocumentAsync(Document document, Comple return document; } - var memberContainingDocumentFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - var insertionRoot = await GetTreeWithAddedSyntaxNodeRemovedAsync(memberContainingDocument, memberContainingDocumentFormattingOptions, cancellationToken).ConfigureAwait(false); - var insertionText = await GenerateInsertionTextAsync(memberContainingDocument, memberContainingDocumentFormattingOptions, cancellationToken).ConfigureAwait(false); + var memberContainingDocumentCleanupOptions = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var insertionRoot = await GetTreeWithAddedSyntaxNodeRemovedAsync(memberContainingDocument, memberContainingDocumentCleanupOptions, cancellationToken).ConfigureAwait(false); + var insertionText = await GenerateInsertionTextAsync(memberContainingDocument, memberContainingDocumentCleanupOptions, cancellationToken).ConfigureAwait(false); var destinationSpan = ComputeDestinationSpan(insertionRoot); @@ -179,21 +180,21 @@ private TextSpan ComputeDestinationSpan(SyntaxNode insertionRoot) } private async Task GenerateInsertionTextAsync( - Document memberContainingDocument, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + Document memberContainingDocument, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken) { - memberContainingDocument = await Simplifier.ReduceAsync(memberContainingDocument, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false); - memberContainingDocument = await Formatter.FormatAsync(memberContainingDocument, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); + memberContainingDocument = await Simplifier.ReduceAsync(memberContainingDocument, Simplifier.Annotation, cleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); + memberContainingDocument = await Formatter.FormatAsync(memberContainingDocument, Formatter.Annotation, cleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false); var root = await memberContainingDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return root.GetAnnotatedNodes(_annotation).Single().ToString().Trim(); } private async Task GetTreeWithAddedSyntaxNodeRemovedAsync( - Document document, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + Document document, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken) { // Added imports are annotated for simplification too. Therefore, we simplify the document // before removing added member node to preserve those imports in the document. - document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false); + document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var members = root.GetAnnotatedNodes(_annotation).AsImmutable(); @@ -203,7 +204,7 @@ private async Task GetTreeWithAddedSyntaxNodeRemovedAsync( var dismemberedDocument = document.WithSyntaxRoot(root); - dismemberedDocument = await Formatter.FormatAsync(dismemberedDocument, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); + dismemberedDocument = await Formatter.FormatAsync(dismemberedDocument, Formatter.Annotation, cleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false); return await dismemberedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); } diff --git a/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs b/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs index f7f7226721e08..5006dfb1f79df 100644 --- a/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs +++ b/src/Features/Core/Portable/EncapsulateField/AbstractEncapsulateFieldService.cs @@ -32,7 +32,7 @@ internal abstract partial class AbstractEncapsulateFieldService : ILanguageServi protected abstract Task RewriteFieldNameAndAccessibilityAsync(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CancellationToken cancellationToken); protected abstract Task> GetFieldsAsync(Document document, TextSpan span, CancellationToken cancellationToken); - public async Task EncapsulateFieldsInSpanAsync(Document document, TextSpan span, bool useDefaultBehavior, CancellationToken cancellationToken) + public async Task EncapsulateFieldsInSpanAsync(Document document, TextSpan span, EncapsulateFieldOptions fallbackOptions, bool useDefaultBehavior, CancellationToken cancellationToken) { var fields = await GetFieldsAsync(document, span, cancellationToken).ConfigureAwait(false); if (fields.IsDefaultOrEmpty) @@ -42,10 +42,10 @@ public async Task EncapsulateFieldsInSpanAsync(Document return new EncapsulateFieldResult( firstField.ToDisplayString(), firstField.GetGlyph(), - c => EncapsulateFieldsAsync(document, fields, useDefaultBehavior, c)); + c => EncapsulateFieldsAsync(document, fields, fallbackOptions, useDefaultBehavior, c)); } - public async Task> GetEncapsulateFieldCodeActionsAsync(Document document, TextSpan span, CancellationToken cancellationToken) + public async Task> GetEncapsulateFieldCodeActionsAsync(Document document, TextSpan span, EncapsulateFieldOptions fallbackOptions, CancellationToken cancellationToken) { var fields = await GetFieldsAsync(document, span, cancellationToken).ConfigureAwait(false); if (fields.IsDefaultOrEmpty) @@ -54,7 +54,7 @@ public async Task> GetEncapsulateFieldCodeActionsAsyn if (fields.Length == 1) { // there is only one field - return EncapsulateOneField(document, fields[0]); + return EncapsulateOneField(document, fields[0], fallbackOptions); } // there are multiple fields. @@ -64,38 +64,39 @@ public async Task> GetEncapsulateFieldCodeActionsAsyn { // if there is no selection, get action for each field + all of them. foreach (var field in fields) - builder.AddRange(EncapsulateOneField(document, field)); + builder.AddRange(EncapsulateOneField(document, field, fallbackOptions)); } - builder.AddRange(EncapsulateAllFields(document, fields)); + builder.AddRange(EncapsulateAllFields(document, fields, fallbackOptions)); return builder.ToImmutable(); } - private ImmutableArray EncapsulateAllFields(Document document, ImmutableArray fields) + private ImmutableArray EncapsulateAllFields(Document document, ImmutableArray fields, EncapsulateFieldOptions fallbackOptions) { return ImmutableArray.Create( new MyCodeAction( FeaturesResources.Encapsulate_fields_and_use_property, - c => EncapsulateFieldsAsync(document, fields, updateReferences: true, c)), + c => EncapsulateFieldsAsync(document, fields, fallbackOptions, updateReferences: true, c)), new MyCodeAction( FeaturesResources.Encapsulate_fields_but_still_use_field, - c => EncapsulateFieldsAsync(document, fields, updateReferences: false, c))); + c => EncapsulateFieldsAsync(document, fields, fallbackOptions, updateReferences: false, c))); } - private ImmutableArray EncapsulateOneField(Document document, IFieldSymbol field) + private ImmutableArray EncapsulateOneField(Document document, IFieldSymbol field, EncapsulateFieldOptions fallbackOptions) { var fields = ImmutableArray.Create(field); return ImmutableArray.Create( new MyCodeAction( string.Format(FeaturesResources.Encapsulate_field_colon_0_and_use_property, field.Name), - c => EncapsulateFieldsAsync(document, fields, updateReferences: true, c)), + c => EncapsulateFieldsAsync(document, fields, fallbackOptions, updateReferences: true, c)), new MyCodeAction( string.Format(FeaturesResources.Encapsulate_field_colon_0_but_still_use_field, field.Name), - c => EncapsulateFieldsAsync(document, fields, updateReferences: false, c))); + c => EncapsulateFieldsAsync(document, fields, fallbackOptions, updateReferences: false, c))); } public async Task EncapsulateFieldsAsync( Document document, ImmutableArray fields, + EncapsulateFieldOptions fallbackOptions, bool updateReferences, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -110,7 +111,7 @@ public async Task EncapsulateFieldsAsync( var result = await client.TryInvokeAsync)>>( solution, - (service, solutionInfo, cancellationToken) => service.EncapsulateFieldsAsync(solutionInfo, document.Id, fieldSymbolKeys, updateReferences, cancellationToken), + (service, solutionInfo, cancellationToken) => service.EncapsulateFieldsAsync(solutionInfo, document.Id, fieldSymbolKeys, fallbackOptions, updateReferences, cancellationToken), cancellationToken).ConfigureAwait(false); if (!result.HasValue) @@ -124,10 +125,10 @@ public async Task EncapsulateFieldsAsync( } return await EncapsulateFieldsInCurrentProcessAsync( - document, fields, updateReferences, cancellationToken).ConfigureAwait(false); + document, fields, fallbackOptions, updateReferences, cancellationToken).ConfigureAwait(false); } - private async Task EncapsulateFieldsInCurrentProcessAsync(Document document, ImmutableArray fields, bool updateReferences, CancellationToken cancellationToken) + private async Task EncapsulateFieldsInCurrentProcessAsync(Document document, ImmutableArray fields, EncapsulateFieldOptions fallbackOptions, bool updateReferences, CancellationToken cancellationToken) { Contract.ThrowIfTrue(fields.Length == 0); @@ -143,7 +144,7 @@ private async Task EncapsulateFieldsInCurrentProcessAsync(Document doc if (field.GetSymbolKey(cancellationToken).Resolve(compilation, cancellationToken: cancellationToken).Symbol is not IFieldSymbol currentField) continue; - var nextSolution = await EncapsulateFieldAsync(document, currentField, updateReferences, cancellationToken).ConfigureAwait(false); + var nextSolution = await EncapsulateFieldAsync(document, currentField, updateReferences, fallbackOptions, cancellationToken).ConfigureAwait(false); if (nextSolution == null) continue; @@ -154,8 +155,11 @@ private async Task EncapsulateFieldsInCurrentProcessAsync(Document doc } private async Task EncapsulateFieldAsync( - Document document, IFieldSymbol field, - bool updateReferences, CancellationToken cancellationToken) + Document document, + IFieldSymbol field, + bool updateReferences, + EncapsulateFieldOptions fallbackOptions, + CancellationToken cancellationToken) { var originalField = field; var (finalFieldName, generatedPropertyName) = GenerateFieldAndPropertyNames(field); @@ -202,6 +206,7 @@ private async Task EncapsulateFieldAsync( var rewrittenFieldDeclaration = await RewriteFieldNameAndAccessibilityAsync(finalFieldName, markFieldPrivate, document, declarationAnnotation, cancellationToken).ConfigureAwait(false); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + document = await Formatter.FormatAsync(document.WithSyntaxRoot(rewrittenFieldDeclaration), Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); solution = document.Project.Solution; @@ -231,8 +236,10 @@ private async Task EncapsulateFieldAsync( new SyntaxAnnotation(), document); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); + var solutionWithProperty = await AddPropertyAsync( - document, document.Project.Solution, field, generatedProperty, formattingOptions, cancellationToken).ConfigureAwait(false); + document, document.Project.Solution, field, generatedProperty, formattingOptions, simplifierOptions, cancellationToken).ConfigureAwait(false); return solutionWithProperty; } @@ -318,7 +325,14 @@ private ISet GetConstructorLocations(INamedTypeSymbol containingType) internal abstract IEnumerable GetConstructorNodes(INamedTypeSymbol containingType); - protected static async Task AddPropertyAsync(Document document, Solution destinationSolution, IFieldSymbol field, IPropertySymbol property, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + protected static async Task AddPropertyAsync( + Document document, + Solution destinationSolution, + IFieldSymbol field, + IPropertySymbol property, + SyntaxFormattingOptions formattingOptions, + SimplifierOptions simplifierOptions, + CancellationToken cancellationToken) { var codeGenerationService = document.GetLanguageService(); @@ -332,7 +346,7 @@ protected static async Task AddPropertyAsync(Document document, Soluti destinationSolution, destination, property, context, cancellationToken).ConfigureAwait(false); updatedDocument = await Formatter.FormatAsync(updatedDocument, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); - updatedDocument = await Simplifier.ReduceAsync(updatedDocument, cancellationToken: cancellationToken).ConfigureAwait(false); + updatedDocument = await Simplifier.ReduceAsync(updatedDocument, simplifierOptions, cancellationToken).ConfigureAwait(false); return updatedDocument.Project.Solution; } diff --git a/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldOptions.cs b/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldOptions.cs new file mode 100644 index 0000000000000..29070875bebbd --- /dev/null +++ b/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldOptions.cs @@ -0,0 +1,12 @@ +// 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; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.EncapsulateField; + +[DataContract] +internal readonly record struct EncapsulateFieldOptions( + [property: DataMember(Order = 0)] SimplifierOptions SimplifierOptions); diff --git a/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldRefactoringProvider.cs b/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldRefactoringProvider.cs index f936e59e6db14..606142d8928d1 100644 --- a/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldRefactoringProvider.cs +++ b/src/Features/Core/Portable/EncapsulateField/EncapsulateFieldRefactoringProvider.cs @@ -26,7 +26,11 @@ public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContex { var (document, textSpan, cancellationToken) = context; var service = document.GetLanguageService(); - var actions = await service.GetEncapsulateFieldCodeActionsAsync(document, textSpan, cancellationToken).ConfigureAwait(false); + + var fallbackOptions = new EncapsulateFieldOptions( + SimplifierOptions: context.Options(document.Project.LanguageServices).SimplifierOptions); + + var actions = await service.GetEncapsulateFieldCodeActionsAsync(document, textSpan, fallbackOptions, cancellationToken).ConfigureAwait(false); context.RegisterRefactorings(actions); } } diff --git a/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs b/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs index ac5bbb3dbf8a0..aafe8d671de79 100644 --- a/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs +++ b/src/Features/Core/Portable/EncapsulateField/IRemoteEncapsulateFieldService.cs @@ -18,6 +18,7 @@ internal interface IRemoteEncapsulateFieldService PinnedSolutionInfo solutionInfo, DocumentId documentId, ImmutableArray fieldSymbolKeys, + EncapsulateFieldOptions fallbackOptions, bool updateReferences, CancellationToken cancellationToken); } diff --git a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs index 0ea7726d5142a..9e3b7d1021387 100644 --- a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs +++ b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs @@ -289,6 +289,7 @@ private static async Task GetFormattedSolutionAsync(Solution unformatt var document = formattedSolution.GetDocument(documentId); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); var formattedDocument = await Formatter.FormatAsync( document, @@ -299,7 +300,8 @@ private static async Task GetFormattedSolutionAsync(Solution unformatt var simplifiedDocument = await Simplifier.ReduceAsync( formattedDocument, Simplifier.Annotation, - cancellationToken: cancellationToken).ConfigureAwait(false); + simplifierOptions, + cancellationToken).ConfigureAwait(false); formattedSolution = simplifiedDocument.Project.Solution; } diff --git a/src/Features/Core/Portable/ExtractMethod/ExtractMethodResult.cs b/src/Features/Core/Portable/ExtractMethod/ExtractMethodResult.cs index b47327e345306..bc220976d354e 100644 --- a/src/Features/Core/Portable/ExtractMethod/ExtractMethodResult.cs +++ b/src/Features/Core/Portable/ExtractMethod/ExtractMethodResult.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Formatting.Rules; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -90,15 +91,16 @@ internal ExtractMethodResult( var root = await DocumentWithoutFinalFormatting.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = root.ReplaceToken(InvocationNameToken, InvocationNameToken.WithAdditionalAnnotations(annotation)); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(DocumentWithoutFinalFormatting, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var annotatedDocument = DocumentWithoutFinalFormatting.WithSyntaxRoot(root); - var simplifiedDocument = await Simplifier.ReduceAsync(annotatedDocument, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false); + var simplifiedDocument = await Simplifier.ReduceAsync(annotatedDocument, Simplifier.Annotation, cleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); var simplifiedRoot = await simplifiedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var options = await SyntaxFormattingOptions.FromDocumentAsync(DocumentWithoutFinalFormatting, cancellationToken).ConfigureAwait(false); var services = DocumentWithoutFinalFormatting.Project.Solution.Workspace.Services; var formattedDocument = simplifiedDocument.WithSyntaxRoot( - Formatter.Format(simplifiedRoot, Formatter.Annotation, services, options, FormattingRules, cancellationToken)); + Formatter.Format(simplifiedRoot, Formatter.Annotation, services, cleanupOptions.FormattingOptions, FormattingRules, cancellationToken)); var formattedRoot = await formattedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return (formattedDocument, formattedRoot.GetAnnotatedTokens(annotation).Single()); diff --git a/src/Features/Core/Portable/Formatting/AbstractNewDocumentFormattingService.cs b/src/Features/Core/Portable/Formatting/AbstractNewDocumentFormattingService.cs index e7f59e6c693dc..15d06e7a3ce98 100644 --- a/src/Features/Core/Portable/Formatting/AbstractNewDocumentFormattingService.cs +++ b/src/Features/Core/Portable/Formatting/AbstractNewDocumentFormattingService.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host.Mef; using Roslyn.Utilities; @@ -32,7 +33,7 @@ private IEnumerable GetProviders() return _providerValues; } - public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { foreach (var provider in GetProviders()) { @@ -52,7 +53,7 @@ public async Task FormatNewDocumentAsync(Document document, Document? // before we call the next provider, otherwise they might not see things as they are meant to be. // Because formatting providers often re-use code fix logic, they are often written assuming this will // happen. - document = await CodeAction.CleanupDocumentAsync(document, cancellationToken).ConfigureAwait(false); + document = await CodeAction.CleanupDocumentAsync(document, options, cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (FatalError.ReportAndCatchUnlessCanceled(ex, cancellationToken, ErrorSeverity.General)) { diff --git a/src/Features/Core/Portable/Formatting/INewDocumentFormattingProvider.cs b/src/Features/Core/Portable/Formatting/INewDocumentFormattingProvider.cs index 3012091569619..1612691204b45 100644 --- a/src/Features/Core/Portable/Formatting/INewDocumentFormattingProvider.cs +++ b/src/Features/Core/Portable/Formatting/INewDocumentFormattingProvider.cs @@ -4,12 +4,13 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; namespace Microsoft.CodeAnalysis.Formatting { internal interface INewDocumentFormattingProvider { - /// - Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken); + /// + Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/Formatting/INewDocumentFormattingService.cs b/src/Features/Core/Portable/Formatting/INewDocumentFormattingService.cs index 74b3452f825f7..80e6f58a7fdc5 100644 --- a/src/Features/Core/Portable/Formatting/INewDocumentFormattingService.cs +++ b/src/Features/Core/Portable/Formatting/INewDocumentFormattingService.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Formatting @@ -16,6 +17,6 @@ internal interface INewDocumentFormattingService : ILanguageService /// The document to format. /// An optional additional document that can be used to inform the formatting operation. /// A cancellation token. - Task FormatNewDocumentAsync(Document document, Document? hintDocument, SyntaxFormattingOptions options, CancellationToken cancellationToken); + Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs b/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs index 6b7f4a4bb3cf6..0d9a624da1027 100644 --- a/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs +++ b/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs @@ -63,7 +63,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) return; } - var hideAdvancedMembers = context.Options(document.Project.Language).HideAdvancedMembers; + var hideAdvancedMembers = context.Options(document.Project.LanguageServices).HideAdvancedMembers; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var matchingTypes = await GetMatchingTypesAsync(document, semanticModel, node, hideAdvancedMembers, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs index 4daf9502e6281..42db6a142687a 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; @@ -312,8 +313,8 @@ private async Task> GetGenerateInNewFileOperati var formattingService = newDocument.GetLanguageService(); if (formattingService is not null) { - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(_semanticDocument.Document, _cancellationToken).ConfigureAwait(false); - codeGenResult = await formattingService.FormatNewDocumentAsync(codeGenResult, _semanticDocument.Document, formattingOptions, _cancellationToken).ConfigureAwait(false); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(_semanticDocument.Document, fallbackOptions: null, _cancellationToken).ConfigureAwait(false); + codeGenResult = await formattingService.FormatNewDocumentAsync(codeGenResult, _semanticDocument.Document, cleanupOptions, _cancellationToken).ConfigureAwait(false); } } diff --git a/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs b/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs index b15c4fd3d2640..47e275514e026 100644 --- a/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs +++ b/src/Features/Core/Portable/ImplementAbstractClass/AbstractImplementAbstractClassCodeFixProvider.cs @@ -42,7 +42,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) return; var data = await ImplementAbstractClassData.TryGetDataAsync( - document, classNode, GetClassIdentifier(classNode), context.Options(document.Project.Language).ImplementTypeOptions, cancellationToken).ConfigureAwait(false); + document, classNode, GetClassIdentifier(classNode), context.Options(document.Project.LanguageServices).ImplementTypeOptions, cancellationToken).ConfigureAwait(false); if (data == null) return; diff --git a/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.AbstractIntroduceVariableCodeAction.cs b/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.AbstractIntroduceVariableCodeAction.cs index 4d16d6b2d0f7f..38eb1732c5e5d 100644 --- a/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.AbstractIntroduceVariableCodeAction.cs +++ b/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.AbstractIntroduceVariableCodeAction.cs @@ -49,7 +49,8 @@ internal AbstractIntroduceVariableCodeAction( protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken) { var changedDocument = await GetChangedDocumentCoreAsync(cancellationToken).ConfigureAwait(false); - return await Simplifier.ReduceAsync(changedDocument, cancellationToken: cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(changedDocument, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + return await Simplifier.ReduceAsync(changedDocument, simplifierOptions, cancellationToken).ConfigureAwait(false); } private async Task GetChangedDocumentCoreAsync(CancellationToken cancellationToken) diff --git a/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.IntroduceVariableAllOccurrenceCodeAction.cs b/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.IntroduceVariableAllOccurrenceCodeAction.cs index b48273827f380..f3a6e31eafc5f 100644 --- a/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.IntroduceVariableAllOccurrenceCodeAction.cs +++ b/src/Features/Core/Portable/IntroduceVariable/AbstractIntroduceVariableService.IntroduceVariableAllOccurrenceCodeAction.cs @@ -31,7 +31,9 @@ internal IntroduceVariableAllOccurrenceCodeAction( protected override async Task PostProcessChangesAsync(Document document, CancellationToken cancellationToken) { var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + + document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, simplifierOptions, cancellationToken).ConfigureAwait(false); document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false); return document; diff --git a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs index 2f8aea25577e4..19f2619684215 100644 --- a/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs +++ b/src/Features/Core/Portable/MetadataAsSource/AbstractMetadataAsSourceService.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -24,15 +22,22 @@ namespace Microsoft.CodeAnalysis.MetadataAsSource { internal abstract partial class AbstractMetadataAsSourceService : IMetadataAsSourceService { - public async Task AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + public async Task AddSourceToAsync( + Document document, + Compilation symbolCompilation, + ISymbol symbol, + SyntaxFormattingOptions formattingOptions, + SimplifierOptions simplifierOptions, + CancellationToken cancellationToken) { if (document == null) { throw new ArgumentNullException(nameof(document)); } - var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken); + var newSemanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var rootNamespace = newSemanticModel.GetEnclosingNamespace(position: 0, cancellationToken); + Contract.ThrowIfNull(rootNamespace); var context = new CodeGenerationContext( contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), @@ -51,11 +56,11 @@ public async Task AddSourceToAsync(Document document, Compilation symb document = await AddNullableRegionsAsync(document, cancellationToken).ConfigureAwait(false); - var docCommentFormattingService = document.GetLanguageService(); + var docCommentFormattingService = document.GetRequiredLanguageService(); var docWithDocComments = await ConvertDocCommentsToRegularCommentsAsync(document, docCommentFormattingService, cancellationToken).ConfigureAwait(false); var docWithAssemblyInfo = await AddAssemblyInfoRegionAsync(docWithDocComments, symbolCompilation, symbol.GetOriginalUnreducedDefinition(), cancellationToken).ConfigureAwait(false); - var node = await docWithAssemblyInfo.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var node = await docWithAssemblyInfo.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var formattedDoc = await Formatter.FormatAsync( docWithAssemblyInfo, @@ -65,7 +70,7 @@ public async Task AddSourceToAsync(Document document, Compilation symb cancellationToken).ConfigureAwait(false); var reducers = GetReducers(); - return await Simplifier.ReduceAsync(formattedDoc, reducers, null, cancellationToken).ConfigureAwait(false); + return await Simplifier.ReduceAsync(formattedDoc, reducers, simplifierOptions, cancellationToken).ConfigureAwait(false); } protected abstract Task AddNullableRegionsAsync(Document document, CancellationToken cancellationToken); @@ -99,7 +104,7 @@ private static INamespaceOrTypeSymbol CreateCodeGenerationSymbol(Document docume var topLevelNamespaceSymbol = symbol.ContainingNamespace; var topLevelNamedType = MetadataAsSourceHelpers.GetTopLevelContainingNamedType(symbol); - var canImplementImplicitly = document.GetLanguageService().SupportsImplicitInterfaceImplementation; + var canImplementImplicitly = document.GetRequiredLanguageService().SupportsImplicitInterfaceImplementation; var docCommentFormattingService = document.GetLanguageService(); INamespaceOrTypeSymbol wrappedType = new WrappedNamedTypeSymbol(topLevelNamedType, canImplementImplicitly, docCommentFormattingService); diff --git a/src/Features/Core/Portable/MetadataAsSource/DecompilationMetadataAsSourceFileProvider.cs b/src/Features/Core/Portable/MetadataAsSource/DecompilationMetadataAsSourceFileProvider.cs index 1387299960d96..79b25b8767313 100644 --- a/src/Features/Core/Portable/MetadataAsSource/DecompilationMetadataAsSourceFileProvider.cs +++ b/src/Features/Core/Portable/MetadataAsSource/DecompilationMetadataAsSourceFileProvider.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -79,6 +80,7 @@ public DecompilationMetadataAsSourceFileProvider() .GetRequiredDocument(temporaryProjectInfoAndDocumentId.Item2); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(temporaryDocument, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(temporaryDocument, options.SimplifierOptions, cancellationToken).ConfigureAwait(false); if (useDecompiler) { @@ -107,7 +109,7 @@ public DecompilationMetadataAsSourceFileProvider() if (!useDecompiler) { var sourceFromMetadataService = temporaryDocument.Project.LanguageServices.GetRequiredService(); - temporaryDocument = await sourceFromMetadataService.AddSourceToAsync(temporaryDocument, compilation, symbol, formattingOptions, cancellationToken).ConfigureAwait(false); + temporaryDocument = await sourceFromMetadataService.AddSourceToAsync(temporaryDocument, compilation, symbol, formattingOptions, simplifierOptions, cancellationToken).ConfigureAwait(false); } // We have the content, so write it out to disk diff --git a/src/Features/Core/Portable/MetadataAsSource/IMetadataAsSourceService.cs b/src/Features/Core/Portable/MetadataAsSource/IMetadataAsSourceService.cs index 7a032a04a219b..f8689f463c795 100644 --- a/src/Features/Core/Portable/MetadataAsSource/IMetadataAsSourceService.cs +++ b/src/Features/Core/Portable/MetadataAsSource/IMetadataAsSourceService.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.MetadataAsSource { @@ -23,6 +24,6 @@ internal interface IMetadataAsSourceService : ILanguageService /// The symbol to generate source for /// To cancel document operations /// The updated document - Task AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken = default); + Task AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, SyntaxFormattingOptions formattingOptions, SimplifierOptions simplifierOptions, CancellationToken cancellationToken = default); } } diff --git a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceOptions.cs b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceOptions.cs index 2443af58b00c5..9b2f4313f6b15 100644 --- a/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceOptions.cs +++ b/src/Features/Core/Portable/MetadataAsSource/MetadataAsSourceOptions.cs @@ -2,6 +2,8 @@ // 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.Simplification; + namespace Microsoft.CodeAnalysis.MetadataAsSource { /// @@ -12,13 +14,14 @@ namespace Microsoft.CodeAnalysis.MetadataAsSource /// Whether navigation should try to use the default Microsoft and /// Nuget symbol servers regardless of debugger settings internal readonly record struct MetadataAsSourceOptions( + SimplifierOptions? SimplifierOptions = null, bool NavigateToDecompiledSources = true, bool AlwaysUseDefaultSymbolServers = true) { public static readonly MetadataAsSourceOptions Default = new(); public MetadataAsSourceOptions() - : this(NavigateToDecompiledSources: true) + : this(SimplifierOptions: null) { } } diff --git a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveItemsToNamespaceCodeAction.cs b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveItemsToNamespaceCodeAction.cs index a052948c87713..eef94890a6c15 100644 --- a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveItemsToNamespaceCodeAction.cs +++ b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveItemsToNamespaceCodeAction.cs @@ -2,6 +2,8 @@ // 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.ChangeNamespace; + namespace Microsoft.CodeAnalysis.MoveToNamespace { internal abstract partial class AbstractMoveToNamespaceCodeAction @@ -10,8 +12,8 @@ private class MoveItemsToNamespaceCodeAction : AbstractMoveToNamespaceCodeAction { public override string Title => FeaturesResources.Move_contents_to_namespace; - public MoveItemsToNamespaceCodeAction(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult) - : base(changeNamespaceService, analysisResult) + public MoveItemsToNamespaceCodeAction(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult, ChangeNamespaceOptionsProvider changeNamespaceOptions) + : base(changeNamespaceService, analysisResult, changeNamespaceOptions) { } } diff --git a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveTypeToNamespaceCodeAction.cs b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveTypeToNamespaceCodeAction.cs index 0c403a550a6cd..090fb8b058346 100644 --- a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveTypeToNamespaceCodeAction.cs +++ b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.MoveTypeToNamespaceCodeAction.cs @@ -2,6 +2,8 @@ // 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.ChangeNamespace; + namespace Microsoft.CodeAnalysis.MoveToNamespace { internal abstract partial class AbstractMoveToNamespaceCodeAction @@ -10,8 +12,8 @@ private class MoveTypeToNamespaceCodeAction : AbstractMoveToNamespaceCodeAction { public override string Title => FeaturesResources.Move_to_namespace; - public MoveTypeToNamespaceCodeAction(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult) - : base(changeNamespaceService, analysisResult) + public MoveTypeToNamespaceCodeAction(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult, ChangeNamespaceOptionsProvider changeNamespaceOptions) + : base(changeNamespaceService, analysisResult, changeNamespaceOptions) { } } diff --git a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.cs b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.cs index 00534fe23c5bc..253db52b650e8 100644 --- a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.cs +++ b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceCodeAction.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeActions.WorkspaceServices; using Roslyn.Utilities; @@ -17,11 +18,13 @@ internal abstract partial class AbstractMoveToNamespaceCodeAction : CodeActionWi { private readonly IMoveToNamespaceService _moveToNamespaceService; private readonly MoveToNamespaceAnalysisResult _moveToNamespaceAnalysisResult; + private readonly ChangeNamespaceOptionsProvider _changeNamespaceOptions; - public AbstractMoveToNamespaceCodeAction(IMoveToNamespaceService moveToNamespaceService, MoveToNamespaceAnalysisResult analysisResult) + public AbstractMoveToNamespaceCodeAction(IMoveToNamespaceService moveToNamespaceService, MoveToNamespaceAnalysisResult analysisResult, ChangeNamespaceOptionsProvider changeNamespaceOptions) { _moveToNamespaceService = moveToNamespaceService; _moveToNamespaceAnalysisResult = analysisResult; + _changeNamespaceOptions = changeNamespaceOptions; } public override object GetOptions(CancellationToken cancellationToken) @@ -42,6 +45,7 @@ protected override async Task> ComputeOperation var moveToNamespaceResult = await _moveToNamespaceService.MoveToNamespaceAsync( _moveToNamespaceAnalysisResult, moveToNamespaceOptions.Namespace, + _changeNamespaceOptions, cancellationToken).ConfigureAwait(false); if (moveToNamespaceResult.Succeeded) @@ -81,11 +85,11 @@ private static ImmutableArray CreateRenameOperations(MoveTo return operations.ToImmutable(); } - public static AbstractMoveToNamespaceCodeAction Generate(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult) + public static AbstractMoveToNamespaceCodeAction Generate(IMoveToNamespaceService changeNamespaceService, MoveToNamespaceAnalysisResult analysisResult, ChangeNamespaceOptionsProvider changeNamespaceOptions) => analysisResult.Container switch { - MoveToNamespaceAnalysisResult.ContainerType.NamedType => new MoveTypeToNamespaceCodeAction(changeNamespaceService, analysisResult), - MoveToNamespaceAnalysisResult.ContainerType.Namespace => new MoveItemsToNamespaceCodeAction(changeNamespaceService, analysisResult), + MoveToNamespaceAnalysisResult.ContainerType.NamedType => new MoveTypeToNamespaceCodeAction(changeNamespaceService, analysisResult, changeNamespaceOptions), + MoveToNamespaceAnalysisResult.ContainerType.Namespace => new MoveItemsToNamespaceCodeAction(changeNamespaceService, analysisResult, changeNamespaceOptions), _ => throw ExceptionUtilities.UnexpectedValue(analysisResult.Container) }; } diff --git a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceService.cs b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceService.cs index 11e92a4f545f9..c315c056424df 100644 --- a/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceService.cs +++ b/src/Features/Core/Portable/MoveToNamespace/AbstractMoveToNamespaceService.cs @@ -24,9 +24,9 @@ namespace Microsoft.CodeAnalysis.MoveToNamespace { internal interface IMoveToNamespaceService : ILanguageService { - Task> GetCodeActionsAsync(Document document, TextSpan span, CancellationToken cancellationToken); + Task> GetCodeActionsAsync(Document document, TextSpan span, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); Task AnalyzeTypeAtPositionAsync(Document document, int position, CancellationToken cancellationToken); - Task MoveToNamespaceAsync(MoveToNamespaceAnalysisResult analysisResult, string targetNamespace, CancellationToken cancellationToken); + Task MoveToNamespaceAsync(MoveToNamespaceAnalysisResult analysisResult, string targetNamespace, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); MoveToNamespaceOptionsResult GetChangeNamespaceOptions(Document document, string defaultNamespace, ImmutableArray namespaces); IMoveToNamespaceOptionsService OptionsService { get; } } @@ -49,6 +49,7 @@ protected AbstractMoveToNamespaceService(IMoveToNamespaceOptionsService moveToNa public async Task> GetCodeActionsAsync( Document document, TextSpan span, + ChangeNamespaceOptionsProvider changeNamespaceOptions, CancellationToken cancellationToken) { // Code actions cannot be completed without the options needed @@ -59,7 +60,7 @@ public async Task> GetCodeActi if (typeAnalysisResult.CanPerform) { - return ImmutableArray.Create(AbstractMoveToNamespaceCodeAction.Generate(this, typeAnalysisResult)); + return ImmutableArray.Create(AbstractMoveToNamespaceCodeAction.Generate(this, typeAnalysisResult, changeNamespaceOptions)); } } @@ -166,6 +167,7 @@ private static bool ContainsMultipleTypesInSpine(SyntaxNode node) public Task MoveToNamespaceAsync( MoveToNamespaceAnalysisResult analysisResult, string targetNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { if (!analysisResult.CanPerform) @@ -175,8 +177,8 @@ public Task MoveToNamespaceAsync( return analysisResult.Container switch { - MoveToNamespaceAnalysisResult.ContainerType.Namespace => MoveItemsInNamespaceAsync(analysisResult.Document, analysisResult.SyntaxNode, targetNamespace, cancellationToken), - MoveToNamespaceAnalysisResult.ContainerType.NamedType => MoveTypeToNamespaceAsync(analysisResult.Document, analysisResult.SyntaxNode, targetNamespace, cancellationToken), + MoveToNamespaceAnalysisResult.ContainerType.Namespace => MoveItemsInNamespaceAsync(analysisResult.Document, analysisResult.SyntaxNode, targetNamespace, options, cancellationToken), + MoveToNamespaceAnalysisResult.ContainerType.NamedType => MoveTypeToNamespaceAsync(analysisResult.Document, analysisResult.SyntaxNode, targetNamespace, options, cancellationToken), _ => throw new InvalidOperationException(), }; } @@ -208,6 +210,7 @@ private static async Task MoveItemsInNamespaceAsync( Document document, SyntaxNode container, string targetNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { var memberSymbols = await GetMemberSymbolsAsync(document, container, cancellationToken).ConfigureAwait(false); @@ -226,6 +229,7 @@ private static async Task MoveItemsInNamespaceAsync( document, container, targetNamespace, + options, cancellationToken).ConfigureAwait(false); return new MoveToNamespaceResult(originalSolution, changedSolution, document.Id, newNameOriginalSymbolMapping); @@ -235,6 +239,7 @@ private static async Task MoveTypeToNamespaceAsync( Document document, SyntaxNode container, string targetNamespace, + ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken) { var moveTypeService = document.GetLanguageService(); @@ -272,6 +277,7 @@ private static async Task MoveTypeToNamespaceAsync( mergedDocument, syntaxNode, targetNamespace, + options, cancellationToken).ConfigureAwait(false); } diff --git a/src/Features/Core/Portable/MoveToNamespace/MoveToNamespaceCodeActionProvider.cs b/src/Features/Core/Portable/MoveToNamespace/MoveToNamespaceCodeActionProvider.cs index ad1bcf4f48095..9c0f902d9dfac 100644 --- a/src/Features/Core/Portable/MoveToNamespace/MoveToNamespaceCodeActionProvider.cs +++ b/src/Features/Core/Portable/MoveToNamespace/MoveToNamespaceCodeActionProvider.cs @@ -7,6 +7,7 @@ using System.Composition; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -27,7 +28,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte { var (document, textSpan, cancellationToken) = context; var moveToNamespaceService = document.GetLanguageService(); - var actions = await moveToNamespaceService.GetCodeActionsAsync(document, textSpan, cancellationToken).ConfigureAwait(false); + var actions = await moveToNamespaceService.GetCodeActionsAsync(document, textSpan, ChangeNamespaceOptions.CreateProvider(context.Options), cancellationToken).ConfigureAwait(false); context.RegisterRefactorings(actions); } } diff --git a/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs b/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs index 1a1ef00e6a0ac..ed6501cd2ea4c 100644 --- a/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs +++ b/src/Features/Core/Portable/Shared/Utilities/ExtractTypeHelpers.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; @@ -87,12 +88,12 @@ internal static class ExtractTypeHelpers context, cancellationToken).ConfigureAwait(false); - var newTypeFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(newTypeDocument, cancellationToken).ConfigureAwait(false); + var newCleanupOptions = await CodeCleanupOptions.FromDocumentAsync(newTypeDocument, fallbackOptions: null, cancellationToken).ConfigureAwait(false); var formattingService = newTypeDocument.GetLanguageService(); if (formattingService is not null) { - newTypeDocument = await formattingService.FormatNewDocumentAsync(newTypeDocument, hintDocument, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false); + newTypeDocument = await formattingService.FormatNewDocumentAsync(newTypeDocument, hintDocument, newCleanupOptions, cancellationToken).ConfigureAwait(false); } var syntaxRoot = await newTypeDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); @@ -105,8 +106,8 @@ internal static class ExtractTypeHelpers newTypeDocument = newTypeDocument.WithSyntaxRoot(annotatedRoot); - var simplified = await Simplifier.ReduceAsync(newTypeDocument, cancellationToken: cancellationToken).ConfigureAwait(false); - var formattedDocument = await Formatter.FormatAsync(simplified, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false); + var simplified = await Simplifier.ReduceAsync(newTypeDocument, newCleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); + var formattedDocument = await Formatter.FormatAsync(simplified, newCleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false); return (formattedDocument, typeAnnotation); } diff --git a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs index 737e5dfc062d8..74d29d3be55fd 100644 --- a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.QualifyMemberAccess; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.SimplifyThisOrMe @@ -18,12 +19,14 @@ internal abstract class AbstractSimplifyThisOrMeDiagnosticAnalyzer< TLanguageKindEnum, TExpressionSyntax, TThisExpressionSyntax, - TMemberAccessExpressionSyntax> : + TMemberAccessExpressionSyntax, + TSimplifierOptions> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TThisExpressionSyntax : TExpressionSyntax where TMemberAccessExpressionSyntax : TExpressionSyntax + where TSimplifierOptions : SimplifierOptions { private readonly ImmutableArray _kindsOfInterest; @@ -43,7 +46,7 @@ protected AbstractSimplifyThisOrMeDiagnosticAnalyzer() protected abstract ISyntaxFacts GetSyntaxFacts(); protected abstract bool CanSimplifyTypeNameExpression( - SemanticModel model, TMemberAccessExpressionSyntax memberAccess, OptionSet optionSet, out TextSpan issueSpan, CancellationToken cancellationToken); + SemanticModel model, TMemberAccessExpressionSyntax memberAccess, TSimplifierOptions options, out TextSpan issueSpan, CancellationToken cancellationToken); public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -51,6 +54,8 @@ public override DiagnosticAnalyzerCategory GetAnalyzerCategory() protected override void InitializeWorker(AnalysisContext context) => context.RegisterSyntaxNodeAction(AnalyzeNode, _kindsOfInterest); + protected abstract TSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree); + private void AnalyzeNode(SyntaxNodeAnalysisContext context) { var cancellationToken = context.CancellationToken; @@ -61,13 +66,13 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) return; } - var analyzerOptions = context.Options; var syntaxTree = node.SyntaxTree; - var optionSet = analyzerOptions.GetAnalyzerOptionSet(syntaxTree, cancellationToken); + + var simplifierOptions = GetSimplifierOptions(context.Options, syntaxTree); var model = context.SemanticModel; if (!CanSimplifyTypeNameExpression( - model, expr, optionSet, out var issueSpan, cancellationToken)) + model, expr, simplifierOptions, out var issueSpan, cancellationToken)) { return; } @@ -83,8 +88,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) return; } - var applicableOption = QualifyMembersHelpers.GetApplicableOptionFromSymbolKind(symbolInfo.Symbol.Kind); - var optionValue = optionSet.GetOption(applicableOption, model.Language); + var optionValue = simplifierOptions.QualifyMemberAccess(symbolInfo.Symbol.Kind); if (optionValue == null) { return; diff --git a/src/Features/Core/Portable/SimplifyTypeNames/AbstractSimplifyTypeNamesCodeFixProvider.cs b/src/Features/Core/Portable/SimplifyTypeNames/AbstractSimplifyTypeNamesCodeFixProvider.cs index d8f7c5d6900d8..c4048f8c26339 100644 --- a/src/Features/Core/Portable/SimplifyTypeNames/AbstractSimplifyTypeNamesCodeFixProvider.cs +++ b/src/Features/Core/Portable/SimplifyTypeNames/AbstractSimplifyTypeNamesCodeFixProvider.cs @@ -13,20 +13,21 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.LanguageServices; -using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.SimplifyTypeNames { - internal abstract partial class AbstractSimplifyTypeNamesCodeFixProvider + internal abstract partial class AbstractSimplifyTypeNamesCodeFixProvider : SyntaxEditorBasedCodeFixProvider where TSyntaxKind : struct + where TSimplifierOptions : SimplifierOptions { - private readonly SimplifyTypeNamesDiagnosticAnalyzerBase _analyzer; + private readonly SimplifyTypeNamesDiagnosticAnalyzerBase _analyzer; protected AbstractSimplifyTypeNamesCodeFixProvider( - SimplifyTypeNamesDiagnosticAnalyzerBase analyzer) + SimplifyTypeNamesDiagnosticAnalyzerBase analyzer) { _analyzer = analyzer; } @@ -42,7 +43,7 @@ protected AbstractSimplifyTypeNamesCodeFixProvider( private (SyntaxNode, string diagnosticId) GetNodeToSimplify( SyntaxNode root, SemanticModel model, TextSpan span, - OptionSet optionSet, CancellationToken cancellationToken) + TSimplifierOptions options, CancellationToken cancellationToken) { var token = root.FindToken(span.Start, findInsideTrivia: true); if (!token.Span.IntersectsWith(span)) @@ -54,7 +55,7 @@ protected AbstractSimplifyTypeNamesCodeFixProvider( string topmostDiagnosticId = null; foreach (var node in token.GetAncestors()) { - if (node.Span.IntersectsWith(span) && CanSimplifyTypeNameExpression(model, node, optionSet, span, out var diagnosticId, cancellationToken)) + if (node.Span.IntersectsWith(span) && CanSimplifyTypeNameExpression(model, node, options, span, out var diagnosticId, cancellationToken)) { // keep overwriting the best simplifiable node as long as we keep finding them. topmostSimplifiableNode = node; @@ -79,10 +80,10 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var options = (TSimplifierOptions)await SimplifierOptions.FromDocumentAsync(document, context.Options(document.Project.LanguageServices).SimplifierOptions, cancellationToken).ConfigureAwait(false); var (node, diagnosticId) = GetNodeToSimplify( - root, model, span, documentOptions, cancellationToken); + root, model, span, options, cancellationToken); if (node == null) return; @@ -101,13 +102,13 @@ protected override async Task FixAllAsync( { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var simplifierOptions = (TSimplifierOptions)await SimplifierOptions.FromDocumentAsync(document, options(document.Project.LanguageServices).SimplifierOptions, cancellationToken).ConfigureAwait(false); foreach (var diagnostic in diagnostics) { var (node, _) = GetNodeToSimplify( root, model, diagnostic.Location.SourceSpan, - documentOptions, cancellationToken); + simplifierOptions, cancellationToken); if (node == null) return; @@ -118,12 +119,12 @@ protected override async Task FixAllAsync( } } - private bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, OptionSet optionSet, TextSpan span, out string diagnosticId, CancellationToken cancellationToken) + private bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, TSimplifierOptions options, TextSpan span, out string diagnosticId, CancellationToken cancellationToken) { diagnosticId = null; if (!_analyzer.IsCandidate(node) || !_analyzer.CanSimplifyTypeNameExpression( - model, node, optionSet, out var issueSpan, out diagnosticId, out _, cancellationToken)) + model, node, options, out var issueSpan, out diagnosticId, out _, cancellationToken)) { return false; } diff --git a/src/Features/Core/Portable/SimplifyTypeNames/SimplifyTypeNamesDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/SimplifyTypeNames/SimplifyTypeNamesDiagnosticAnalyzerBase.cs index 31c955c328795..fe6393072ae8d 100644 --- a/src/Features/Core/Portable/SimplifyTypeNames/SimplifyTypeNamesDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/SimplifyTypeNames/SimplifyTypeNamesDiagnosticAnalyzerBase.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -27,7 +28,10 @@ namespace Microsoft.CodeAnalysis.SimplifyTypeNames { - internal abstract class SimplifyTypeNamesDiagnosticAnalyzerBase : DiagnosticAnalyzer, IBuiltInAnalyzer where TLanguageKindEnum : struct + internal abstract class SimplifyTypeNamesDiagnosticAnalyzerBase + : DiagnosticAnalyzer, IBuiltInAnalyzer + where TLanguageKindEnum : struct + where TSimplifierOptions : SimplifierOptions { #if LOG private static string _logFile = @"c:\temp\simplifytypenames.txt"; @@ -68,7 +72,7 @@ internal abstract class SimplifyTypeNamesDiagnosticAnalyzerBase> option; DiagnosticDescriptor descriptor; ReportDiagnostic severity; switch (diagnosticId) @@ -163,12 +166,11 @@ internal static Diagnostic CreateDiagnostic(SemanticModel model, OptionSet optio break; case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId: - option = inDeclaration - ? CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration - : CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess; - descriptor = s_descriptorPreferBuiltinOrFrameworkType; + var optionValue = inDeclaration + ? options.PreferPredefinedTypeKeywordInDeclaration + : options.PreferPredefinedTypeKeywordInMemberAccess; - var optionValue = optionSet.GetOption(option, model.Language)!; + descriptor = s_descriptorPreferBuiltinOrFrameworkType; severity = optionValue.Notification.Severity; break; default: @@ -210,7 +212,7 @@ public DiagnosticAnalyzerCategory GetAnalyzerCategory() private class AnalyzerImpl { - private readonly SimplifyTypeNamesDiagnosticAnalyzerBase _analyzer; + private readonly SimplifyTypeNamesDiagnosticAnalyzerBase _analyzer; /// /// Tracks the analysis state of syntax trees in a compilation. Each syntax tree has the properties: @@ -237,7 +239,7 @@ private class AnalyzerImpl private readonly ConcurrentDictionary completed, SimpleIntervalTree? intervalTree)> _codeBlockIntervals = new(); - public AnalyzerImpl(SimplifyTypeNamesDiagnosticAnalyzerBase analyzer) + public AnalyzerImpl(SimplifyTypeNamesDiagnosticAnalyzerBase analyzer) => _analyzer = analyzer; public void AnalyzeCodeBlock(CodeBlockAnalysisContext context) diff --git a/src/Features/Core/Portable/Snippets/SnippetFunctionService.cs b/src/Features/Core/Portable/Snippets/SnippetFunctionService.cs index 4aa7f180eb464..c2b59bfcd6899 100644 --- a/src/Features/Core/Portable/Snippets/SnippetFunctionService.cs +++ b/src/Features/Core/Portable/Snippets/SnippetFunctionService.cs @@ -35,7 +35,7 @@ internal abstract class SnippetFunctionService : ILanguageService /// For a specified snippet field, replace it with the fully qualified name then simplify in the context of the document /// in order to retrieve the simplified type name. /// - public static async Task GetSimplifiedTypeNameAsync(Document document, TextSpan fieldSpan, string fullyQualifiedTypeName, CancellationToken cancellationToken) + public static async Task GetSimplifiedTypeNameAsync(Document document, TextSpan fieldSpan, string fullyQualifiedTypeName, SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { // Insert the function parameter (fully qualified type name) into the document. var updatedTextSpan = new TextSpan(fieldSpan.Start, fullyQualifiedTypeName.Length); @@ -45,7 +45,7 @@ internal abstract class SnippetFunctionService : ILanguageService var documentWithFullyQualifiedTypeName = document.WithText(text.WithChanges(textChange)); // Simplify - var simplifiedTypeName = await GetSimplifiedTypeNameAtSpanAsync(documentWithFullyQualifiedTypeName, updatedTextSpan, cancellationToken).ConfigureAwait(false); + var simplifiedTypeName = await GetSimplifiedTypeNameAtSpanAsync(documentWithFullyQualifiedTypeName, updatedTextSpan, simplifierOptions, cancellationToken).ConfigureAwait(false); return simplifiedTypeName; } @@ -53,7 +53,7 @@ internal abstract class SnippetFunctionService : ILanguageService /// For a document with the default switch snippet inserted, generate the expanded set of cases based on the value /// of the field currently inserted into the switch statement. /// - public async Task GetSwitchExpansionAsync(Document document, TextSpan caseGenerationLocation, TextSpan switchExpressionLocation, CancellationToken cancellationToken) + public async Task GetSwitchExpansionAsync(Document document, TextSpan caseGenerationLocation, TextSpan switchExpressionLocation, SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { var typeSymbol = await GetEnumSymbolAsync(document, switchExpressionLocation, cancellationToken).ConfigureAwait(false); if (typeSymbol?.TypeKind != TypeKind.Enum) @@ -69,7 +69,7 @@ internal abstract class SnippetFunctionService : ILanguageService // Find and use the most simplified legal version of the enum type name in this context var fullyQualifiedEnumName = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var simplifiedTypeName = await GetSimplifiedEnumNameAsync(document, fullyQualifiedEnumName, enumFields.First().Name, caseGenerationLocation, cancellationToken).ConfigureAwait(false); + var simplifiedTypeName = await GetSimplifiedEnumNameAsync(document, fullyQualifiedEnumName, enumFields.First().Name, caseGenerationLocation, simplifierOptions, cancellationToken).ConfigureAwait(false); if (simplifiedTypeName == null) { return null; @@ -126,17 +126,18 @@ public static bool TryGetSnippetFunctionInfo( string fullyQualifiedTypeName, string firstEnumMemberName, TextSpan caseGenerationLocation, + SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { // Insert switch with enum case into the document. var (documentWithFullyQualified, fullyQualifiedTypeLocation) = await GetDocumentWithEnumCaseAsync(document, fullyQualifiedTypeName, firstEnumMemberName, caseGenerationLocation, cancellationToken).ConfigureAwait(false); // Simplify enum case. - var simplifiedEnum = await GetSimplifiedTypeNameAtSpanAsync(documentWithFullyQualified, fullyQualifiedTypeLocation, cancellationToken).ConfigureAwait(false); + var simplifiedEnum = await GetSimplifiedTypeNameAtSpanAsync(documentWithFullyQualified, fullyQualifiedTypeLocation, simplifierOptions, cancellationToken).ConfigureAwait(false); return simplifiedEnum; } - private static async Task GetSimplifiedTypeNameAtSpanAsync(Document documentWithFullyQualifiedTypeName, TextSpan fullyQualifiedTypeSpan, CancellationToken cancellationToken) + private static async Task GetSimplifiedTypeNameAtSpanAsync(Document documentWithFullyQualifiedTypeName, TextSpan fullyQualifiedTypeSpan, SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { // Simplify var typeAnnotation = new SyntaxAnnotation(); @@ -151,7 +152,7 @@ public static bool TryGetSnippetFunctionInfo( var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation)); var documentWithAnnotations = documentWithFullyQualifiedTypeName.WithSyntaxRoot(updatedRoot); - var simplifiedDocument = await Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).ConfigureAwait(false); + var simplifiedDocument = await Simplifier.ReduceAsync(documentWithAnnotations, simplifierOptions, cancellationToken).ConfigureAwait(false); var simplifiedRoot = await simplifiedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var simplifiedTypeName = simplifiedRoot.GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString(); return simplifiedTypeName; diff --git a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs index d2752c63438fc..fb8cf487ab84c 100644 --- a/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs +++ b/src/Features/Core/Portable/SpellCheck/AbstractSpellCheckCodeFixProvider.cs @@ -118,7 +118,7 @@ private async Task CreateSpellCheckCodeIssueAsync( // - We believe spell-check should only compare what you have typed to what symbol would be offered here. var options = CompletionOptions.Default with { - HideAdvancedMembers = context.Options(document.Project.Language).HideAdvancedMembers, + HideAdvancedMembers = context.Options(document.Project.LanguageServices).HideAdvancedMembers, SnippetsBehavior = SnippetsRule.NeverInclude, ShowItemsFromUnimportedNamespaces = false, TargetTypedCompletionFilter = false, diff --git a/src/Features/Core/Portable/Wrapping/AbstractWrappingCodeRefactoringProvider.cs b/src/Features/Core/Portable/Wrapping/AbstractWrappingCodeRefactoringProvider.cs index f0e74dbfd704b..d54d2493c0e7c 100644 --- a/src/Features/Core/Portable/Wrapping/AbstractWrappingCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/Wrapping/AbstractWrappingCodeRefactoringProvider.cs @@ -45,7 +45,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var token = root.FindToken(position); var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); - var options = GetWrappingOptions(configOptions, context.Options(document.Project.Language)); + var options = GetWrappingOptions(configOptions, context.Options(document.Project.LanguageServices)); foreach (var node in token.GetRequiredParent().AncestorsAndSelf()) { diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DefaultDiagnosticAnalyzerService.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DefaultDiagnosticAnalyzerService.cs index 5544664855183..a4ad7569e739b 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/DefaultDiagnosticAnalyzerService.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/DefaultDiagnosticAnalyzerService.cs @@ -162,7 +162,7 @@ private async Task> GetDiagnosticsAsync( if (analyzers.IsEmpty) return ImmutableArray.Empty; - var ideOptions = _service._globalOptions.GetIdeAnalyzerOptions(project.Language); + var ideOptions = _service._globalOptions.GetIdeAnalyzerOptions(project); var compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync( project, ideOptions, analyzers, includeSuppressedDiagnostics: false, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs index d8aadbc4882b4..7c343d558a941 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.CompilationManager.cs @@ -24,7 +24,7 @@ internal partial class DiagnosticIncrementalAnalyzer return null; } - var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project.Language); + var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project); if (_projectCompilationsWithAnalyzers.TryGetValue(project, out var compilationWithAnalyzers) && ((WorkspaceAnalyzerOptions)compilationWithAnalyzers!.AnalysisOptions.Options!).IdeOptions == ideOptions) diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs index cd7f50098eb14..9fa626514040f 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs @@ -260,7 +260,7 @@ protected override async Task AppendDiagnosticsAsync(Project project, IEnumerabl // get analyzers that are not suppressed. var stateSets = StateManager.GetOrCreateStateSets(project).Where(s => ShouldIncludeStateSet(project, s)).ToImmutableArrayOrEmpty(); - var ideOptions = Owner.AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project.Language); + var ideOptions = Owner.AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project); // unlike the suppressed (disabled) analyzer, we will include hidden diagnostic only analyzers here. var compilation = await CreateCompilationWithAnalyzersAsync(project, ideOptions, stateSets, IncludeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs index 99f77ca564dad..dff2ea6da5a2f 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_GetDiagnosticsForSpan.cs @@ -88,7 +88,7 @@ public static async Task CreateAsync( var stateSets = owner._stateManager .GetOrCreateStateSets(document.Project).Where(s => DocumentAnalysisExecutor.IsAnalyzerEnabledForProject(s.Analyzer, document.Project, owner.GlobalOptions)); - var ideOptions = owner.AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(document.Project.Language); + var ideOptions = owner.AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(document.Project); var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(document.Project, ideOptions, stateSets, includeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs index 3d62cdbd54389..73b8f5c895116 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs @@ -146,7 +146,7 @@ private async Task AnalyzeProjectAsync(Project project, bool forceAnalyzerRun, C .Where(a => DocumentAnalysisExecutor.IsAnalyzerEnabledForProject(a, project, GlobalOptions) && !a.IsOpenFileOnly(options)); // get driver only with active analyzers. - var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project.Language); + var ideOptions = AnalyzerService.GlobalOptions.GetIdeAnalyzerOptions(project); var compilationWithAnalyzers = await DocumentAnalysisExecutor.CreateCompilationWithAnalyzersAsync(project, ideOptions, activeAnalyzers, includeSuppressedDiagnostics: true, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/Options/AutoFormattingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs similarity index 98% rename from src/Features/Core/Portable/Options/AutoFormattingOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs index 3626ea10265a7..92bf0bd3401c6 100644 --- a/src/Features/Core/Portable/Options/AutoFormattingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs @@ -6,8 +6,6 @@ namespace Microsoft.CodeAnalysis.Formatting; -// TODO: move to LSP layer - internal static class AutoFormattingOptionsStorage { public static AutoFormattingOptions GetAutoFormattingOptions(this IGlobalOptionService globalOptions, string language) diff --git a/src/Features/LanguageServer/Protocol/Features/Options/BlockStructureOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/BlockStructureOptionsStorage.cs index ab630ee962014..0dd1f2832a658 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/BlockStructureOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/BlockStructureOptionsStorage.cs @@ -4,57 +4,56 @@ using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Structure +namespace Microsoft.CodeAnalysis.Structure; + +internal static class BlockStructureOptionsStorage { - internal static class BlockStructureOptionsStorage - { - public static BlockStructureOptions GetBlockStructureOptions(this IGlobalOptionService globalOptions, Project project) - => GetBlockStructureOptions(globalOptions, project.Language, isMetadataAsSource: project.Solution.Workspace.Kind == WorkspaceKind.MetadataAsSource); - - public static BlockStructureOptions GetBlockStructureOptions(this IGlobalOptionService globalOptions, string language, bool isMetadataAsSource) - => new( - ShowBlockStructureGuidesForCommentsAndPreprocessorRegions: globalOptions.GetOption(ShowBlockStructureGuidesForCommentsAndPreprocessorRegions, language), - ShowBlockStructureGuidesForDeclarationLevelConstructs: globalOptions.GetOption(ShowBlockStructureGuidesForDeclarationLevelConstructs, language), - ShowBlockStructureGuidesForCodeLevelConstructs: globalOptions.GetOption(ShowBlockStructureGuidesForCodeLevelConstructs, language), - ShowOutliningForCommentsAndPreprocessorRegions: globalOptions.GetOption(ShowOutliningForCommentsAndPreprocessorRegions, language), - ShowOutliningForDeclarationLevelConstructs: globalOptions.GetOption(ShowOutliningForDeclarationLevelConstructs, language), - ShowOutliningForCodeLevelConstructs: globalOptions.GetOption(ShowOutliningForCodeLevelConstructs, language), - CollapseRegionsWhenCollapsingToDefinitions: globalOptions.GetOption(CollapseRegionsWhenCollapsingToDefinitions, language), - MaximumBannerLength: globalOptions.GetOption(MaximumBannerLength, language), - IsMetadataAsSource: isMetadataAsSource); - - private const string FeatureName = "BlockStructureOptions"; - - public static readonly PerLanguageOption2 ShowBlockStructureGuidesForCommentsAndPreprocessorRegions = new( - FeatureName, "ShowBlockStructureGuidesForCommentsAndPreprocessorRegions", BlockStructureOptions.Default.ShowBlockStructureGuidesForCommentsAndPreprocessorRegions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForCommentsAndPreprocessorRegions")); - - public static readonly PerLanguageOption2 ShowBlockStructureGuidesForDeclarationLevelConstructs = new( - FeatureName, "ShowBlockStructureGuidesForDeclarationLevelConstructs", BlockStructureOptions.Default.ShowBlockStructureGuidesForDeclarationLevelConstructs, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForDeclarationLevelConstructs")); - - public static readonly PerLanguageOption2 ShowBlockStructureGuidesForCodeLevelConstructs = new( - FeatureName, "ShowBlockStructureGuidesForCodeLevelConstructs", BlockStructureOptions.Default.ShowBlockStructureGuidesForCodeLevelConstructs, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForCodeLevelConstructs")); - - public static readonly PerLanguageOption2 ShowOutliningForCommentsAndPreprocessorRegions = new( - FeatureName, "ShowOutliningForCommentsAndPreprocessorRegions", BlockStructureOptions.Default.ShowOutliningForCommentsAndPreprocessorRegions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForCommentsAndPreprocessorRegions")); - - public static readonly PerLanguageOption2 ShowOutliningForDeclarationLevelConstructs = new( - FeatureName, "ShowOutliningForDeclarationLevelConstructs", BlockStructureOptions.Default.ShowOutliningForDeclarationLevelConstructs, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForDeclarationLevelConstructs")); - - public static readonly PerLanguageOption2 ShowOutliningForCodeLevelConstructs = new( - FeatureName, "ShowOutliningForCodeLevelConstructs", BlockStructureOptions.Default.ShowOutliningForCodeLevelConstructs, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForCodeLevelConstructs")); - - public static readonly PerLanguageOption2 CollapseRegionsWhenCollapsingToDefinitions = new( - FeatureName, "CollapseRegionsWhenCollapsingToDefinitions", BlockStructureOptions.Default.CollapseRegionsWhenCollapsingToDefinitions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.CollapseRegionsWhenCollapsingToDefinitions")); - - public static readonly PerLanguageOption2 MaximumBannerLength = new( - FeatureName, "MaximumBannerLength", BlockStructureOptions.Default.MaximumBannerLength, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.MaximumBannerLength")); - } + public static BlockStructureOptions GetBlockStructureOptions(this IGlobalOptionService globalOptions, Project project) + => GetBlockStructureOptions(globalOptions, project.Language, isMetadataAsSource: project.Solution.Workspace.Kind == WorkspaceKind.MetadataAsSource); + + public static BlockStructureOptions GetBlockStructureOptions(this IGlobalOptionService globalOptions, string language, bool isMetadataAsSource) + => new( + ShowBlockStructureGuidesForCommentsAndPreprocessorRegions: globalOptions.GetOption(ShowBlockStructureGuidesForCommentsAndPreprocessorRegions, language), + ShowBlockStructureGuidesForDeclarationLevelConstructs: globalOptions.GetOption(ShowBlockStructureGuidesForDeclarationLevelConstructs, language), + ShowBlockStructureGuidesForCodeLevelConstructs: globalOptions.GetOption(ShowBlockStructureGuidesForCodeLevelConstructs, language), + ShowOutliningForCommentsAndPreprocessorRegions: globalOptions.GetOption(ShowOutliningForCommentsAndPreprocessorRegions, language), + ShowOutliningForDeclarationLevelConstructs: globalOptions.GetOption(ShowOutliningForDeclarationLevelConstructs, language), + ShowOutliningForCodeLevelConstructs: globalOptions.GetOption(ShowOutliningForCodeLevelConstructs, language), + CollapseRegionsWhenCollapsingToDefinitions: globalOptions.GetOption(CollapseRegionsWhenCollapsingToDefinitions, language), + MaximumBannerLength: globalOptions.GetOption(MaximumBannerLength, language), + IsMetadataAsSource: isMetadataAsSource); + + private const string FeatureName = "BlockStructureOptions"; + + public static readonly PerLanguageOption2 ShowBlockStructureGuidesForCommentsAndPreprocessorRegions = new( + FeatureName, "ShowBlockStructureGuidesForCommentsAndPreprocessorRegions", BlockStructureOptions.Default.ShowBlockStructureGuidesForCommentsAndPreprocessorRegions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForCommentsAndPreprocessorRegions")); + + public static readonly PerLanguageOption2 ShowBlockStructureGuidesForDeclarationLevelConstructs = new( + FeatureName, "ShowBlockStructureGuidesForDeclarationLevelConstructs", BlockStructureOptions.Default.ShowBlockStructureGuidesForDeclarationLevelConstructs, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForDeclarationLevelConstructs")); + + public static readonly PerLanguageOption2 ShowBlockStructureGuidesForCodeLevelConstructs = new( + FeatureName, "ShowBlockStructureGuidesForCodeLevelConstructs", BlockStructureOptions.Default.ShowBlockStructureGuidesForCodeLevelConstructs, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowBlockStructureGuidesForCodeLevelConstructs")); + + public static readonly PerLanguageOption2 ShowOutliningForCommentsAndPreprocessorRegions = new( + FeatureName, "ShowOutliningForCommentsAndPreprocessorRegions", BlockStructureOptions.Default.ShowOutliningForCommentsAndPreprocessorRegions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForCommentsAndPreprocessorRegions")); + + public static readonly PerLanguageOption2 ShowOutliningForDeclarationLevelConstructs = new( + FeatureName, "ShowOutliningForDeclarationLevelConstructs", BlockStructureOptions.Default.ShowOutliningForDeclarationLevelConstructs, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForDeclarationLevelConstructs")); + + public static readonly PerLanguageOption2 ShowOutliningForCodeLevelConstructs = new( + FeatureName, "ShowOutliningForCodeLevelConstructs", BlockStructureOptions.Default.ShowOutliningForCodeLevelConstructs, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowOutliningForCodeLevelConstructs")); + + public static readonly PerLanguageOption2 CollapseRegionsWhenCollapsingToDefinitions = new( + FeatureName, "CollapseRegionsWhenCollapsingToDefinitions", BlockStructureOptions.Default.CollapseRegionsWhenCollapsingToDefinitions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.CollapseRegionsWhenCollapsingToDefinitions")); + + public static readonly PerLanguageOption2 MaximumBannerLength = new( + FeatureName, "MaximumBannerLength", BlockStructureOptions.Default.MaximumBannerLength, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.MaximumBannerLength")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs index f9e96a8b39750..15a80efaa3155 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/ClassificationOptionsStorage.cs @@ -4,26 +4,25 @@ using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Classification +namespace Microsoft.CodeAnalysis.Classification; + +internal static class ClassificationOptionsStorage { - internal static class ClassificationOptionsStorage - { - public static ClassificationOptions GetClassificationOptions(this IGlobalOptionService globalOptions, string language) - => new( - ClassifyReassignedVariables: globalOptions.GetOption(ClassifyReassignedVariables, language), - ColorizeRegexPatterns: globalOptions.GetOption(ColorizeRegexPatterns, language), - ColorizeJsonPatterns: globalOptions.GetOption(ColorizeJsonPatterns, language)); + public static ClassificationOptions GetClassificationOptions(this IGlobalOptionService globalOptions, string language) + => new( + ClassifyReassignedVariables: globalOptions.GetOption(ClassifyReassignedVariables, language), + ColorizeRegexPatterns: globalOptions.GetOption(ColorizeRegexPatterns, language), + ColorizeJsonPatterns: globalOptions.GetOption(ColorizeJsonPatterns, language)); - public static PerLanguageOption2 ClassifyReassignedVariables = - new("ClassificationOptions", "ClassifyReassignedVariables", ClassificationOptions.Default.ClassifyReassignedVariables, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.ClassificationOptions.ClassifyReassignedVariables")); + public static PerLanguageOption2 ClassifyReassignedVariables = + new("ClassificationOptions", "ClassifyReassignedVariables", ClassificationOptions.Default.ClassifyReassignedVariables, + storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.ClassificationOptions.ClassifyReassignedVariables")); - public static PerLanguageOption2 ColorizeRegexPatterns = - new("RegularExpressionsOptions", "ColorizeRegexPatterns", ClassificationOptions.Default.ColorizeRegexPatterns, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ColorizeRegexPatterns")); + public static PerLanguageOption2 ColorizeRegexPatterns = + new("RegularExpressionsOptions", "ColorizeRegexPatterns", ClassificationOptions.Default.ColorizeRegexPatterns, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ColorizeRegexPatterns")); - public static PerLanguageOption2 ColorizeJsonPatterns = - new("JsonFeatureOptions", "ColorizeJsonPatterns", ClassificationOptions.Default.ColorizeJsonPatterns, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ColorizeJsonPatterns")); - } + public static PerLanguageOption2 ColorizeJsonPatterns = + new("JsonFeatureOptions", "ColorizeJsonPatterns", ClassificationOptions.Default.ColorizeJsonPatterns, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ColorizeJsonPatterns")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs index b08d6555cd385..90e9c1145c703 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs @@ -4,101 +4,100 @@ using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Completion +namespace Microsoft.CodeAnalysis.Completion; + +internal static class CompletionOptionsStorage { - internal static class CompletionOptionsStorage - { - public static CompletionOptions GetCompletionOptions(this IGlobalOptionService options, string language) - => new( - TriggerOnTyping: options.GetOption(TriggerOnTyping, language), - TriggerOnTypingLetters: options.GetOption(TriggerOnTypingLetters, language), - TriggerOnDeletion: options.GetOption(TriggerOnDeletion, language), - TriggerInArgumentLists: options.GetOption(TriggerInArgumentLists, language), - EnterKeyBehavior: options.GetOption(EnterKeyBehavior, language), - SnippetsBehavior: options.GetOption(SnippetsBehavior, language), - HideAdvancedMembers: options.GetOption(HideAdvancedMembers, language), - ShowNameSuggestions: options.GetOption(ShowNameSuggestions, language), - ShowItemsFromUnimportedNamespaces: options.GetOption(ShowItemsFromUnimportedNamespaces, language), - UnnamedSymbolCompletionDisabled: options.GetOption(UnnamedSymbolCompletionDisabledFeatureFlag), - TargetTypedCompletionFilter: options.GetOption(TargetTypedCompletionFilterFeatureFlag), - TypeImportCompletion: options.GetOption(TypeImportCompletionFeatureFlag), - ProvideDateAndTimeCompletions: options.GetOption(ProvideDateAndTimeCompletions, language), - ProvideRegexCompletions: options.GetOption(ProvideRegexCompletions, language), - ForceExpandedCompletionIndexCreation: options.GetOption(ForceExpandedCompletionIndexCreation), - UpdateImportCompletionCacheInBackground: options.GetOption(UpdateImportCompletionCacheInBackground)); - - // feature flags - - public static readonly Option2 TypeImportCompletionFeatureFlag = new(nameof(CompletionOptions), nameof(TypeImportCompletionFeatureFlag), - CompletionOptions.Default.TypeImportCompletion, - new FeatureFlagStorageLocation("Roslyn.TypeImportCompletion")); - - public static readonly Option2 TargetTypedCompletionFilterFeatureFlag = new(nameof(CompletionOptions), nameof(TargetTypedCompletionFilterFeatureFlag), - CompletionOptions.Default.TargetTypedCompletionFilter, - new FeatureFlagStorageLocation("Roslyn.TargetTypedCompletionFilter")); - - public static readonly Option2 UnnamedSymbolCompletionDisabledFeatureFlag = new(nameof(CompletionOptions), nameof(UnnamedSymbolCompletionDisabledFeatureFlag), - CompletionOptions.Default.UnnamedSymbolCompletionDisabled, - new FeatureFlagStorageLocation("Roslyn.UnnamedSymbolCompletionDisabled")); - - // This is serialized by the Visual Studio-specific LanguageSettingsPersister - public static readonly PerLanguageOption2 HideAdvancedMembers = new(nameof(CompletionOptions), nameof(HideAdvancedMembers), CompletionOptions.Default.HideAdvancedMembers); - - // This is serialized by the Visual Studio-specific LanguageSettingsPersister - public static readonly PerLanguageOption2 TriggerOnTyping = new(nameof(CompletionOptions), nameof(TriggerOnTyping), CompletionOptions.Default.TriggerOnTyping); - - public static readonly PerLanguageOption2 TriggerOnTypingLetters = new(nameof(CompletionOptions), nameof(TriggerOnTypingLetters), CompletionOptions.Default.TriggerOnTypingLetters, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerOnTypingLetters")); - - public static readonly PerLanguageOption2 TriggerOnDeletion = new(nameof(CompletionOptions), nameof(TriggerOnDeletion), CompletionOptions.Default.TriggerOnDeletion, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerOnDeletion")); - - public static readonly PerLanguageOption2 EnterKeyBehavior = - new(nameof(CompletionOptions), nameof(EnterKeyBehavior), CompletionOptions.Default.EnterKeyBehavior, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.EnterKeyBehavior")); - - public static readonly PerLanguageOption2 SnippetsBehavior = - new(nameof(CompletionOptions), nameof(SnippetsBehavior), CompletionOptions.Default.SnippetsBehavior, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SnippetsBehavior")); - - public static readonly PerLanguageOption2 ShowNameSuggestions = - new(nameof(CompletionOptions), nameof(ShowNameSuggestions), CompletionOptions.Default.ShowNameSuggestions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowNameSuggestions")); - - //Dev16 options - - // Use tri-value so the default state can be used to turn on the feature with experimentation service. - public static readonly PerLanguageOption2 ShowItemsFromUnimportedNamespaces = - new(nameof(CompletionOptions), nameof(ShowItemsFromUnimportedNamespaces), CompletionOptions.Default.ShowItemsFromUnimportedNamespaces, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowItemsFromUnimportedNamespaces")); - - public static readonly PerLanguageOption2 TriggerInArgumentLists = - new(nameof(CompletionOptions), nameof(TriggerInArgumentLists), CompletionOptions.Default.TriggerInArgumentLists, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerInArgumentLists")); - - // Test-only option - public static readonly Option2 ForceExpandedCompletionIndexCreation - = new(nameof(CompletionOptions), nameof(ForceExpandedCompletionIndexCreation), defaultValue: false); - - // Set to true to update import completion cache in background if the provider isn't supposed to be triggered in the context. - // (cache will alsways be refreshed when provider is triggered) - public static readonly Option2 UpdateImportCompletionCacheInBackground - = new(nameof(CompletionOptions), nameof(UpdateImportCompletionCacheInBackground), defaultValue: false); - - // Embedded languages: - - public static PerLanguageOption2 ProvideRegexCompletions = - new( - "RegularExpressionsOptions", - nameof(ProvideRegexCompletions), - CompletionOptions.Default.ProvideRegexCompletions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ProvideRegexCompletions")); - - public static readonly PerLanguageOption2 ProvideDateAndTimeCompletions = - new( - "DateAndTime", - nameof(ProvideDateAndTimeCompletions), - CompletionOptions.Default.ProvideDateAndTimeCompletions, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ProvideDateAndTimeCompletions")); - } + public static CompletionOptions GetCompletionOptions(this IGlobalOptionService options, string language) + => new( + TriggerOnTyping: options.GetOption(TriggerOnTyping, language), + TriggerOnTypingLetters: options.GetOption(TriggerOnTypingLetters, language), + TriggerOnDeletion: options.GetOption(TriggerOnDeletion, language), + TriggerInArgumentLists: options.GetOption(TriggerInArgumentLists, language), + EnterKeyBehavior: options.GetOption(EnterKeyBehavior, language), + SnippetsBehavior: options.GetOption(SnippetsBehavior, language), + HideAdvancedMembers: options.GetOption(HideAdvancedMembers, language), + ShowNameSuggestions: options.GetOption(ShowNameSuggestions, language), + ShowItemsFromUnimportedNamespaces: options.GetOption(ShowItemsFromUnimportedNamespaces, language), + UnnamedSymbolCompletionDisabled: options.GetOption(UnnamedSymbolCompletionDisabledFeatureFlag), + TargetTypedCompletionFilter: options.GetOption(TargetTypedCompletionFilterFeatureFlag), + TypeImportCompletion: options.GetOption(TypeImportCompletionFeatureFlag), + ProvideDateAndTimeCompletions: options.GetOption(ProvideDateAndTimeCompletions, language), + ProvideRegexCompletions: options.GetOption(ProvideRegexCompletions, language), + ForceExpandedCompletionIndexCreation: options.GetOption(ForceExpandedCompletionIndexCreation), + UpdateImportCompletionCacheInBackground: options.GetOption(UpdateImportCompletionCacheInBackground)); + + // feature flags + + public static readonly Option2 TypeImportCompletionFeatureFlag = new(nameof(CompletionOptions), nameof(TypeImportCompletionFeatureFlag), + CompletionOptions.Default.TypeImportCompletion, + new FeatureFlagStorageLocation("Roslyn.TypeImportCompletion")); + + public static readonly Option2 TargetTypedCompletionFilterFeatureFlag = new(nameof(CompletionOptions), nameof(TargetTypedCompletionFilterFeatureFlag), + CompletionOptions.Default.TargetTypedCompletionFilter, + new FeatureFlagStorageLocation("Roslyn.TargetTypedCompletionFilter")); + + public static readonly Option2 UnnamedSymbolCompletionDisabledFeatureFlag = new(nameof(CompletionOptions), nameof(UnnamedSymbolCompletionDisabledFeatureFlag), + CompletionOptions.Default.UnnamedSymbolCompletionDisabled, + new FeatureFlagStorageLocation("Roslyn.UnnamedSymbolCompletionDisabled")); + + // This is serialized by the Visual Studio-specific LanguageSettingsPersister + public static readonly PerLanguageOption2 HideAdvancedMembers = new(nameof(CompletionOptions), nameof(HideAdvancedMembers), CompletionOptions.Default.HideAdvancedMembers); + + // This is serialized by the Visual Studio-specific LanguageSettingsPersister + public static readonly PerLanguageOption2 TriggerOnTyping = new(nameof(CompletionOptions), nameof(TriggerOnTyping), CompletionOptions.Default.TriggerOnTyping); + + public static readonly PerLanguageOption2 TriggerOnTypingLetters = new(nameof(CompletionOptions), nameof(TriggerOnTypingLetters), CompletionOptions.Default.TriggerOnTypingLetters, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerOnTypingLetters")); + + public static readonly PerLanguageOption2 TriggerOnDeletion = new(nameof(CompletionOptions), nameof(TriggerOnDeletion), CompletionOptions.Default.TriggerOnDeletion, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerOnDeletion")); + + public static readonly PerLanguageOption2 EnterKeyBehavior = + new(nameof(CompletionOptions), nameof(EnterKeyBehavior), CompletionOptions.Default.EnterKeyBehavior, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.EnterKeyBehavior")); + + public static readonly PerLanguageOption2 SnippetsBehavior = + new(nameof(CompletionOptions), nameof(SnippetsBehavior), CompletionOptions.Default.SnippetsBehavior, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SnippetsBehavior")); + + public static readonly PerLanguageOption2 ShowNameSuggestions = + new(nameof(CompletionOptions), nameof(ShowNameSuggestions), CompletionOptions.Default.ShowNameSuggestions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowNameSuggestions")); + + //Dev16 options + + // Use tri-value so the default state can be used to turn on the feature with experimentation service. + public static readonly PerLanguageOption2 ShowItemsFromUnimportedNamespaces = + new(nameof(CompletionOptions), nameof(ShowItemsFromUnimportedNamespaces), CompletionOptions.Default.ShowItemsFromUnimportedNamespaces, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowItemsFromUnimportedNamespaces")); + + public static readonly PerLanguageOption2 TriggerInArgumentLists = + new(nameof(CompletionOptions), nameof(TriggerInArgumentLists), CompletionOptions.Default.TriggerInArgumentLists, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.TriggerInArgumentLists")); + + // Test-only option + public static readonly Option2 ForceExpandedCompletionIndexCreation + = new(nameof(CompletionOptions), nameof(ForceExpandedCompletionIndexCreation), defaultValue: false); + + // Set to true to update import completion cache in background if the provider isn't supposed to be triggered in the context. + // (cache will alsways be refreshed when provider is triggered) + public static readonly Option2 UpdateImportCompletionCacheInBackground + = new(nameof(CompletionOptions), nameof(UpdateImportCompletionCacheInBackground), defaultValue: false); + + // Embedded languages: + + public static PerLanguageOption2 ProvideRegexCompletions = + new( + "RegularExpressionsOptions", + nameof(ProvideRegexCompletions), + CompletionOptions.Default.ProvideRegexCompletions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ProvideRegexCompletions")); + + public static readonly PerLanguageOption2 ProvideDateAndTimeCompletions = + new( + "DateAndTime", + nameof(ProvideDateAndTimeCompletions), + CompletionOptions.Default.ProvideDateAndTimeCompletions, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ProvideDateAndTimeCompletions")); } diff --git a/src/Features/Core/Portable/Options/DocumentationCommentOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs similarity index 98% rename from src/Features/Core/Portable/Options/DocumentationCommentOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs index 249bb5c4c3a24..d8018e8553bfd 100644 --- a/src/Features/Core/Portable/Options/DocumentationCommentOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs @@ -7,8 +7,6 @@ namespace Microsoft.CodeAnalysis.DocumentationComments; -// TODO: move to LSP layer - internal static class DocumentationCommentOptionsStorage { public static DocumentationCommentOptions GetDocumentationCommentOptions(this IGlobalOptionService globalOptions, DocumentOptionSet documentOptions) diff --git a/src/Features/Core/Portable/Options/ExtractMethodOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs similarity index 97% rename from src/Features/Core/Portable/Options/ExtractMethodOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs index 727319e2b558a..fa7f762a27208 100644 --- a/src/Features/Core/Portable/Options/ExtractMethodOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs @@ -6,7 +6,6 @@ namespace Microsoft.CodeAnalysis.ExtractMethod; -// TODO: move to LSP layer internal static class ExtractMethodOptionsStorage { public static ExtractMethodOptions GetExtractMethodOptions(this IGlobalOptionService globalOptions, string language) diff --git a/src/Features/Core/Portable/Options/HighlightingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs similarity index 98% rename from src/Features/Core/Portable/Options/HighlightingOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs index f73b7cf3db134..0b348595eba77 100644 --- a/src/Features/Core/Portable/Options/HighlightingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs @@ -6,7 +6,6 @@ namespace Microsoft.CodeAnalysis.DocumentHighlighting; -// TODO: move to LSP layer internal static class HighlightingOptionsStorage { public static HighlightingOptions GetHighlightingOptions(this IGlobalOptionService globalOptions, string language) diff --git a/src/Features/Core/Portable/Options/IdeAnalyzerOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs similarity index 88% rename from src/Features/Core/Portable/Options/IdeAnalyzerOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs index a9c50a709eaf4..3dac3a7484fba 100644 --- a/src/Features/Core/Portable/Options/IdeAnalyzerOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs @@ -3,21 +3,30 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Diagnostics; -// TODO: move to LSP layer internal static class IdeAnalyzerOptionsStorage { - public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this IGlobalOptionService globalOptions, string language) - => new( + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this IGlobalOptionService globalOptions, Project project) + => GetIdeAnalyzerOptions(globalOptions, project.Solution.Workspace.Services, project.Language); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this IGlobalOptionService globalOptions, HostWorkspaceServices services, string language) + { + var provider = services.GetLanguageService(language); + + return new( CrashOnAnalyzerException: globalOptions.GetOption(CrashOnAnalyzerException), FadeOutUnusedImports: globalOptions.GetOption(FadeOutUnusedImports, language), FadeOutUnreachableCode: globalOptions.GetOption(FadeOutUnreachableCode, language), ReportInvalidPlaceholdersInStringDotFormatCalls: globalOptions.GetOption(ReportInvalidPlaceholdersInStringDotFormatCalls, language), ReportInvalidRegexPatterns: globalOptions.GetOption(ReportInvalidRegexPatterns, language), ReportInvalidJsonPatterns: globalOptions.GetOption(ReportInvalidJsonPatterns, language), - DetectAndOfferEditorFeaturesForProbableJsonStrings: globalOptions.GetOption(DetectAndOfferEditorFeaturesForProbableJsonStrings, language)); + DetectAndOfferEditorFeaturesForProbableJsonStrings: globalOptions.GetOption(DetectAndOfferEditorFeaturesForProbableJsonStrings, language), + SimplifierOptions: provider?.GetOptions(globalOptions)); + } // for testing only internal static void SetIdeAnalyzerOptions(this IGlobalOptionService globalOptions, string language, IdeAnalyzerOptions options) diff --git a/src/Features/Core/Portable/Options/IndentationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs similarity index 97% rename from src/Features/Core/Portable/Options/IndentationOptionsStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs index f120ebc5de9b2..0d69f6b4d20af 100644 --- a/src/Features/Core/Portable/Options/IndentationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs @@ -11,7 +11,6 @@ namespace Microsoft.CodeAnalysis.Indentation; internal static class IndentationOptionsStorage { - // TODO: move to LSP layer public static async Task GetIndentationOptionsAsync(this IGlobalOptionService globalOptions, Document document, CancellationToken cancellationToken) { var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Features/Options/InternalDiagnosticsOptions.cs b/src/Features/LanguageServer/Protocol/Features/Options/InternalDiagnosticsOptions.cs index cb6f0bf50c15c..2be5ca07a6cf4 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/InternalDiagnosticsOptions.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/InternalDiagnosticsOptions.cs @@ -4,11 +4,10 @@ using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Diagnostics +namespace Microsoft.CodeAnalysis.Diagnostics; + +internal static class InternalDiagnosticsOptions { - internal static class InternalDiagnosticsOptions - { - public static readonly Option2 NormalDiagnosticMode = new("InternalDiagnosticsOptions", "NormalDiagnosticMode", defaultValue: DiagnosticMode.Default, - storageLocation: new LocalUserProfileStorageLocation(@"Roslyn\Internal\Diagnostics\NormalDiagnosticMode")); - } + public static readonly Option2 NormalDiagnosticMode = new("InternalDiagnosticsOptions", "NormalDiagnosticMode", defaultValue: DiagnosticMode.Default, + storageLocation: new LocalUserProfileStorageLocation(@"Roslyn\Internal\Diagnostics\NormalDiagnosticMode")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/MetadataAsSourceOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/MetadataAsSourceOptionsStorage.cs index ee8e7e24bcb0c..c35d03e2b8613 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/MetadataAsSourceOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/MetadataAsSourceOptionsStorage.cs @@ -2,28 +2,25 @@ // 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.Composition; -using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Options.Providers; +using Microsoft.CodeAnalysis.Simplification; -namespace Microsoft.CodeAnalysis.MetadataAsSource +namespace Microsoft.CodeAnalysis.MetadataAsSource; + +internal static class MetadataAsSourceOptionsStorage { - internal static class MetadataAsSourceOptionsStorage - { - public static MetadataAsSourceOptions GetMetadataAsSourceOptions(this IGlobalOptionService globalOptions) - => new( - NavigateToDecompiledSources: globalOptions.GetOption(NavigateToDecompiledSources), - AlwaysUseDefaultSymbolServers: globalOptions.GetOption(AlwaysUseDefaultSymbolServers)); + public static MetadataAsSourceOptions GetMetadataAsSourceOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) + => new( + SimplifierOptions: globalOptions.GetSimplifierOptions(languageServices), + NavigateToDecompiledSources: globalOptions.GetOption(NavigateToDecompiledSources), + AlwaysUseDefaultSymbolServers: globalOptions.GetOption(AlwaysUseDefaultSymbolServers)); - public static Option2 NavigateToDecompiledSources = - new("FeatureOnOffOptions", "NavigateToDecompiledSources", defaultValue: true, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.NavigateToDecompiledSources")); + public static Option2 NavigateToDecompiledSources = + new("FeatureOnOffOptions", "NavigateToDecompiledSources", defaultValue: true, + storageLocation: new RoamingProfileStorageLocation($"TextEditor.NavigateToDecompiledSources")); - public static Option2 AlwaysUseDefaultSymbolServers = - new("FeatureOnOffOptions", "AlwaysUseDefaultSymbolServers", defaultValue: true, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.AlwaysUseDefaultSymbolServers")); - } + public static Option2 AlwaysUseDefaultSymbolServers = + new("FeatureOnOffOptions", "AlwaysUseDefaultSymbolServers", defaultValue: true, + storageLocation: new RoamingProfileStorageLocation($"TextEditor.AlwaysUseDefaultSymbolServers")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SignatureHelpOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SignatureHelpOptionsStorage.cs index 82c287f298695..7cf5d259cae15 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/SignatureHelpOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/SignatureHelpOptionsStorage.cs @@ -5,12 +5,11 @@ using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.SignatureHelp +namespace Microsoft.CodeAnalysis.SignatureHelp; + +internal static class SignatureHelpOptionsStorage { - internal static class SignatureHelpOptionsStorage - { - public static SignatureHelpOptions GetSignatureHelpOptions(this IGlobalOptionService globalOptions, string language) - => new( - HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, language)); - } + public static SignatureHelpOptions GetSignatureHelpOptions(this IGlobalOptionService globalOptions, string language) + => new( + HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, language)); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs new file mode 100644 index 0000000000000..7fab81e6ef776 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.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.Host; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Simplification; + +internal interface ISimplifierOptionsStorage : ILanguageService +{ + SimplifierOptions GetOptions(IGlobalOptionService globalOptions); +} + +internal static class SimplifierOptionsStorage +{ + public static Task GetSimplifierOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) + => SimplifierOptions.FromDocumentAsync(document, globalOptions.GetSimplifierOptions(document.Project.LanguageServices), cancellationToken); + + public static SimplifierOptions? GetSimplifierOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) + => languageServices.GetService()?.GetOptions(globalOptions); +} diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SolutionCrawlerOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SolutionCrawlerOptionsStorage.cs index d79dc94922507..d10ce27861020 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/SolutionCrawlerOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/SolutionCrawlerOptionsStorage.cs @@ -5,48 +5,47 @@ using System; using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.SolutionCrawler +namespace Microsoft.CodeAnalysis.SolutionCrawler; + +internal static class SolutionCrawlerOptionsStorage { - internal static class SolutionCrawlerOptionsStorage + /// + /// Option to turn configure background analysis scope for the current user. + /// + public static readonly PerLanguageOption2 BackgroundAnalysisScopeOption = new( + "SolutionCrawlerOptionsStorage", "BackgroundAnalysisScopeOption", defaultValue: BackgroundAnalysisScope.Default, + storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.BackgroundAnalysisScopeOption")); + + /// + /// Option to turn configure background analysis scope for the current solution. + /// + public static readonly Option2 SolutionBackgroundAnalysisScopeOption = new( + "SolutionCrawlerOptionsStorage", "SolutionBackgroundAnalysisScopeOption", defaultValue: null); + + public static readonly PerLanguageOption2 RemoveDocumentDiagnosticsOnDocumentClose = new( + "ServiceFeatureOnOffOptions", "RemoveDocumentDiagnosticsOnDocumentClose", defaultValue: false, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RemoveDocumentDiagnosticsOnDocumentClose")); + + /// + /// Enables forced scope when low VM is detected to improve performance. + /// + public static bool LowMemoryForcedMinimalBackgroundAnalysis = false; + + /// + /// Gets the effective background analysis scope for the current solution. + /// + /// Gets the solution-specific analysis scope set through + /// , or the default analysis scope if no solution-specific + /// scope is set. + /// + public static BackgroundAnalysisScope GetBackgroundAnalysisScope(this IGlobalOptionService globalOptions, string language) { - /// - /// Option to turn configure background analysis scope for the current user. - /// - public static readonly PerLanguageOption2 BackgroundAnalysisScopeOption = new( - "SolutionCrawlerOptionsStorage", "BackgroundAnalysisScopeOption", defaultValue: BackgroundAnalysisScope.Default, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.BackgroundAnalysisScopeOption")); - - /// - /// Option to turn configure background analysis scope for the current solution. - /// - public static readonly Option2 SolutionBackgroundAnalysisScopeOption = new( - "SolutionCrawlerOptionsStorage", "SolutionBackgroundAnalysisScopeOption", defaultValue: null); - - public static readonly PerLanguageOption2 RemoveDocumentDiagnosticsOnDocumentClose = new( - "ServiceFeatureOnOffOptions", "RemoveDocumentDiagnosticsOnDocumentClose", defaultValue: false, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RemoveDocumentDiagnosticsOnDocumentClose")); - - /// - /// Enables forced scope when low VM is detected to improve performance. - /// - public static bool LowMemoryForcedMinimalBackgroundAnalysis = false; - - /// - /// Gets the effective background analysis scope for the current solution. - /// - /// Gets the solution-specific analysis scope set through - /// , or the default analysis scope if no solution-specific - /// scope is set. - /// - public static BackgroundAnalysisScope GetBackgroundAnalysisScope(this IGlobalOptionService globalOptions, string language) + if (LowMemoryForcedMinimalBackgroundAnalysis) { - if (LowMemoryForcedMinimalBackgroundAnalysis) - { - return BackgroundAnalysisScope.Minimal; - } - - return globalOptions.GetOption(SolutionBackgroundAnalysisScopeOption) ?? - globalOptions.GetOption(BackgroundAnalysisScopeOption, language); + return BackgroundAnalysisScope.Minimal; } + + return globalOptions.GetOption(SolutionBackgroundAnalysisScopeOption) ?? + globalOptions.GetOption(BackgroundAnalysisScopeOption, language); } } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs index f16587510fa34..6fbe5cb5f57de 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationOptionsStorage.cs @@ -5,47 +5,46 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Storage; -namespace Microsoft.CodeAnalysis.Host +namespace Microsoft.CodeAnalysis.Host; + +internal static class WorkspaceConfigurationOptionsStorage { - internal static class WorkspaceConfigurationOptionsStorage - { - public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(this IGlobalOptionService globalOptions) - => new( - CacheStorage: globalOptions.GetOption(CloudCacheFeatureFlag) ? StorageDatabase.CloudCache : globalOptions.GetOption(Database), - DisableProjectCacheService: globalOptions.GetOption(DisableProjectCacheService), - DisableRecoverableTrees: globalOptions.GetOption(DisableRecoverableTrees), - EnableOpeningSourceGeneratedFiles: globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspace) ?? - globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag)); - - public static readonly Option2 Database = new( - "FeatureManager/Storage", nameof(Database), WorkspaceConfigurationOptions.Default.CacheStorage, - new LocalUserProfileStorageLocation(@"Roslyn\Internal\OnOff\Features\Database")); - - public static readonly Option2 CloudCacheFeatureFlag = new( - "FeatureManager/Storage", "CloudCacheFeatureFlag", WorkspaceConfigurationOptions.Default.CacheStorage == StorageDatabase.CloudCache, - new FeatureFlagStorageLocation("Roslyn.CloudCache3")); - - /// - /// Disables if the workspace creates recoverable trees when from its s. - /// - public static readonly Option2 DisableRecoverableTrees = new( - "WorkspaceConfigurationOptions", "DisableRecoverableTrees", WorkspaceConfigurationOptions.Default.DisableRecoverableTrees, - new FeatureFlagStorageLocation("Roslyn.DisableRecoverableTrees")); - - public static readonly Option2 DisableProjectCacheService = new( - "WorkspaceConfigurationOptions", nameof(DisableProjectCacheService), WorkspaceConfigurationOptions.Default.DisableProjectCacheService, - new FeatureFlagStorageLocation("Roslyn.DisableProjectCacheService")); - - /// - /// This option allows the user to enable this. We are putting this behind a feature flag for now since we could have extensions - /// surprised by this and we want some time to work through those issues. - /// - public static readonly Option2 EnableOpeningSourceGeneratedFilesInWorkspace = new( - "WorkspaceConfigurationOptions", "EnableOpeningSourceGeneratedFilesInWorkspace", defaultValue: null, - new RoamingProfileStorageLocation("TextEditor.Roslyn.Specific.EnableOpeningSourceGeneratedFilesInWorkspaceExperiment")); - - public static readonly Option2 EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag = new( - "WorkspaceConfigurationOptions", "EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag", WorkspaceConfigurationOptions.Default.EnableOpeningSourceGeneratedFiles, - new FeatureFlagStorageLocation("Roslyn.SourceGeneratorsEnableOpeningInWorkspace")); - } + public static WorkspaceConfigurationOptions GetWorkspaceConfigurationOptions(this IGlobalOptionService globalOptions) + => new( + CacheStorage: globalOptions.GetOption(CloudCacheFeatureFlag) ? StorageDatabase.CloudCache : globalOptions.GetOption(Database), + DisableProjectCacheService: globalOptions.GetOption(DisableProjectCacheService), + DisableRecoverableTrees: globalOptions.GetOption(DisableRecoverableTrees), + EnableOpeningSourceGeneratedFiles: globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspace) ?? + globalOptions.GetOption(EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag)); + + public static readonly Option2 Database = new( + "FeatureManager/Storage", nameof(Database), WorkspaceConfigurationOptions.Default.CacheStorage, + new LocalUserProfileStorageLocation(@"Roslyn\Internal\OnOff\Features\Database")); + + public static readonly Option2 CloudCacheFeatureFlag = new( + "FeatureManager/Storage", "CloudCacheFeatureFlag", WorkspaceConfigurationOptions.Default.CacheStorage == StorageDatabase.CloudCache, + new FeatureFlagStorageLocation("Roslyn.CloudCache3")); + + /// + /// Disables if the workspace creates recoverable trees when from its s. + /// + public static readonly Option2 DisableRecoverableTrees = new( + "WorkspaceConfigurationOptions", "DisableRecoverableTrees", WorkspaceConfigurationOptions.Default.DisableRecoverableTrees, + new FeatureFlagStorageLocation("Roslyn.DisableRecoverableTrees")); + + public static readonly Option2 DisableProjectCacheService = new( + "WorkspaceConfigurationOptions", nameof(DisableProjectCacheService), WorkspaceConfigurationOptions.Default.DisableProjectCacheService, + new FeatureFlagStorageLocation("Roslyn.DisableProjectCacheService")); + + /// + /// This option allows the user to enable this. We are putting this behind a feature flag for now since we could have extensions + /// surprised by this and we want some time to work through those issues. + /// + public static readonly Option2 EnableOpeningSourceGeneratedFilesInWorkspace = new( + "WorkspaceConfigurationOptions", "EnableOpeningSourceGeneratedFilesInWorkspace", defaultValue: null, + new RoamingProfileStorageLocation("TextEditor.Roslyn.Specific.EnableOpeningSourceGeneratedFilesInWorkspaceExperiment")); + + public static readonly Option2 EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag = new( + "WorkspaceConfigurationOptions", "EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag", WorkspaceConfigurationOptions.Default.EnableOpeningSourceGeneratedFiles, + new FeatureFlagStorageLocation("Roslyn.SourceGeneratorsEnableOpeningInWorkspace")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationService.cs b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationService.cs index 9def0f584375c..e42b269ae1d35 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationService.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/WorkspaceConfigurationService.cs @@ -8,25 +8,24 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Host +namespace Microsoft.CodeAnalysis.Host; + +[ExportWorkspaceService(typeof(IWorkspaceConfigurationService)), Shared] +internal sealed class WorkspaceConfigurationService : IWorkspaceConfigurationService { - [ExportWorkspaceService(typeof(IWorkspaceConfigurationService)), Shared] - internal sealed class WorkspaceConfigurationService : IWorkspaceConfigurationService - { - private readonly IGlobalOptionService _globalOptions; - private WorkspaceConfigurationOptions? _lazyOptions; + private readonly IGlobalOptionService _globalOptions; + private WorkspaceConfigurationOptions? _lazyOptions; - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public WorkspaceConfigurationService(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public WorkspaceConfigurationService(IGlobalOptionService globalOptions) + { + _globalOptions = globalOptions; + } - public WorkspaceConfigurationOptions Options - => _lazyOptions ??= _globalOptions.GetWorkspaceConfigurationOptions(); + public WorkspaceConfigurationOptions Options + => _lazyOptions ??= _globalOptions.GetWorkspaceConfigurationOptions(); - internal void Clear() - => _lazyOptions = null; - } + internal void Clear() + => _lazyOptions = null; } diff --git a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs index 7b655a7fdc579..27109a471f4a8 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Definitions/AbstractGoToDefinitionHandler.cs @@ -67,7 +67,7 @@ public AbstractGoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSour { if (!typeOnly || symbol is ITypeSymbol) { - var options = _globalOptions.GetMetadataAsSourceOptions(); + var options = _globalOptions.GetMetadataAsSourceOptions(document.Project.LanguageServices); var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, signaturesOnly: false, options, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; diff --git a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs index 99540d07f0711..4846eb433a7aa 100644 --- a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/InlineCompletionsHandler.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Snippets; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -99,8 +100,9 @@ public InlineCompletionsHandler(XmlSnippetParser xmlSnippetParser) // Use the formatting options specified by the client to format the snippet. var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(request.Options, context.Document, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(context.Document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); - var formattedLspSnippet = await GetFormattedLspSnippetAsync(parsedSnippet, wordOnLeft.Value, context.Document, sourceText, formattingOptions, cancellationToken).ConfigureAwait(false); + var formattedLspSnippet = await GetFormattedLspSnippetAsync(parsedSnippet, wordOnLeft.Value, context.Document, sourceText, formattingOptions, simplifierOptions, cancellationToken).ConfigureAwait(false); return new VSInternalInlineCompletionList { @@ -122,11 +124,18 @@ public InlineCompletionsHandler(XmlSnippetParser xmlSnippetParser) /// /// Note that the operations in this method are sensitive to the context in the document and so must be calculated on each request. /// - private static async Task GetFormattedLspSnippetAsync(ParsedXmlSnippet parsedSnippet, TextSpan snippetShortcut, Document originalDocument, SourceText originalSourceText, SyntaxFormattingOptions options, CancellationToken cancellationToken) + private static async Task GetFormattedLspSnippetAsync( + ParsedXmlSnippet parsedSnippet, + TextSpan snippetShortcut, + Document originalDocument, + SourceText originalSourceText, + SyntaxFormattingOptions formattingOptions, + SimplifierOptions simplifierOptions, + CancellationToken cancellationToken) { // Calculate the snippet text with defaults + snippet function results. var (snippetFullText, fields, caretSpan) = await GetReplacedSnippetTextAsync( - originalDocument, originalSourceText, snippetShortcut, parsedSnippet, cancellationToken).ConfigureAwait(false); + originalDocument, originalSourceText, snippetShortcut, parsedSnippet, simplifierOptions, cancellationToken).ConfigureAwait(false); // Create a document with the default snippet text that we can use to format the snippet. var textChange = new TextChange(snippetShortcut, snippetFullText); @@ -136,7 +145,7 @@ private static async Task GetFormattedLspSnippetAsync(ParsedXmlSnippet p var root = await originalDocument.WithText(documentWithSnippetText).GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var spanToFormat = TextSpan.FromBounds(textChange.Span.Start, snippetEndPosition); - var formattingChanges = Formatter.GetFormattedTextChanges(root, spanToFormat, originalDocument.Project.Solution.Workspace.Services, options, cancellationToken: cancellationToken) + var formattingChanges = Formatter.GetFormattedTextChanges(root, spanToFormat, originalDocument.Project.Solution.Workspace.Services, formattingOptions, cancellationToken: cancellationToken) ?.ToImmutableArray() ?? ImmutableArray.Empty; var formattedText = documentWithSnippetText.WithChanges(formattingChanges); @@ -200,6 +209,7 @@ static TextSpan GetTextSpanInContextOfSnippet(int positionInFullText, int snippe SourceText originalSourceText, TextSpan snippetSpan, ParsedXmlSnippet parsedSnippet, + SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { var documentWithDefaultSnippet = originalDocument.WithText( @@ -228,7 +238,7 @@ static TextSpan GetTextSpanInContextOfSnippet(int positionInFullText, int snippe // To avoid a bunch of document changes and re-parsing, we always calculate the snippet function result // against the document with the default snippet text applied to it instead of with each incremental function result. // So we need to remember the index into the original document. - part = await functionPart.WithSnippetFunctionResultAsync(documentWithDefaultSnippet, new TextSpan(locationInDefaultSnippet, part.DefaultText.Length), cancellationToken).ConfigureAwait(false); + part = await functionPart.WithSnippetFunctionResultAsync(documentWithDefaultSnippet, new TextSpan(locationInDefaultSnippet, part.DefaultText.Length), simplifierOptions, cancellationToken).ConfigureAwait(false); } // Only store spans for editable fields or the cursor location, we don't need to get back to anything else. diff --git a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/XmlSnippetParser.ParsedXmlSnippet.cs b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/XmlSnippetParser.ParsedXmlSnippet.cs index 925d86259707b..d6ae271ecb170 100644 --- a/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/XmlSnippetParser.ParsedXmlSnippet.cs +++ b/src/Features/LanguageServer/Protocol/Handler/InlineCompletions/XmlSnippetParser.ParsedXmlSnippet.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.LanguageServer.Handler.InlineCompletions; @@ -40,7 +41,7 @@ internal record SnippetFieldPart(string FieldName, string DefaultText, int? Edit internal record SnippetFunctionPart(string FieldName, string DefaultText, int? EditIndex, string FunctionName, string? FunctionParam) : SnippetFieldPart(FieldName, DefaultText, EditIndex) { - public async Task WithSnippetFunctionResultAsync(Document documentWithSnippet, TextSpan fieldSpan, CancellationToken cancellationToken) + public async Task WithSnippetFunctionResultAsync(Document documentWithSnippet, TextSpan fieldSpan, SimplifierOptions simplifierOptions, CancellationToken cancellationToken) { var snippetFunctionService = documentWithSnippet.Project.GetRequiredLanguageService(); switch (FunctionName) @@ -51,7 +52,7 @@ public async Task WithSnippetFunctionResultAsync(Document d return this; } - var simplifiedTypeName = await SnippetFunctionService.GetSimplifiedTypeNameAsync(documentWithSnippet, fieldSpan, FunctionParam, cancellationToken).ConfigureAwait(false); + var simplifiedTypeName = await SnippetFunctionService.GetSimplifiedTypeNameAsync(documentWithSnippet, fieldSpan, FunctionParam, simplifierOptions, cancellationToken).ConfigureAwait(false); if (simplifiedTypeName == null) { return this; diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index 3de6b96acd04d..e99ebd1d3c9a3 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -53,9 +53,10 @@ - + + diff --git a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.vb b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.vb index b0a6a512fc8f6..06ce76fa0ecee 100644 --- a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.vb +++ b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/TypeSyntaxSimplifierWalker.vb @@ -7,6 +7,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Shared.Collections Imports Microsoft.CodeAnalysis.Text +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames @@ -36,7 +37,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Private ReadOnly _analyzer As VisualBasicSimplifyTypeNamesDiagnosticAnalyzer Private ReadOnly _semanticModel As SemanticModel - Private ReadOnly _optionSet As OptionSet + Private ReadOnly _options As VisualBasicSimplifierOptions Private ReadOnly _ignoredSpans As SimpleIntervalTree(Of TextSpan, TextSpanIntervalIntrospector) Private ReadOnly _cancellationToken As CancellationToken @@ -66,12 +67,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames End Get End Property - Public Sub New(analyzer As VisualBasicSimplifyTypeNamesDiagnosticAnalyzer, semanticModel As SemanticModel, optionSet As OptionSet, ignoredSpans As SimpleIntervalTree(Of TextSpan, TextSpanIntervalIntrospector), cancellationToken As CancellationToken) + Public Sub New(analyzer As VisualBasicSimplifyTypeNamesDiagnosticAnalyzer, semanticModel As SemanticModel, options As VisualBasicSimplifierOptions, ignoredSpans As SimpleIntervalTree(Of TextSpan, TextSpanIntervalIntrospector), cancellationToken As CancellationToken) MyBase.New(SyntaxWalkerDepth.StructuredTrivia) _analyzer = analyzer _semanticModel = semanticModel - _optionSet = optionSet + _options = options _ignoredSpans = ignoredSpans _cancellationToken = cancellationToken @@ -184,7 +185,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Private Function TrySimplify(node As SyntaxNode) As Boolean Dim diagnostic As Diagnostic = Nothing - If Not _analyzer.TrySimplify(_semanticModel, node, diagnostic, _optionSet, _cancellationToken) Then + If Not _analyzer.TrySimplify(_semanticModel, node, diagnostic, _options, _cancellationToken) Then Return False End If diff --git a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb index 8579b85422ad7..2456c2287bdb3 100644 --- a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb @@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Shared.Collections Imports Microsoft.CodeAnalysis.SimplifyTypeNames Imports Microsoft.CodeAnalysis.Text +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -17,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Friend NotInheritable Class VisualBasicSimplifyTypeNamesDiagnosticAnalyzer - Inherits SimplifyTypeNamesDiagnosticAnalyzerBase(Of SyntaxKind) + Inherits SimplifyTypeNamesDiagnosticAnalyzerBase(Of SyntaxKind, VisualBasicSimplifierOptions) Private Shared ReadOnly s_kindsOfInterest As ImmutableArray(Of SyntaxKind) = ImmutableArray.Create( SyntaxKind.QualifiedName, @@ -38,10 +39,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Dim semanticModel = context.SemanticModel Dim cancellationToken = context.CancellationToken - Dim syntaxTree = semanticModel.SyntaxTree - Dim optionSet = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken) + Dim simplifierOptions = context.Options.GetVisualBasicSimplifierOptions(semanticModel.SyntaxTree) - Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, optionSet, ignoredSpans:=Nothing, cancellationToken) + Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, simplifierOptions, ignoredSpans:=Nothing, cancellationToken) simplifier.Visit(context.CodeBlock) Return simplifier.Diagnostics End Function @@ -51,10 +51,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Dim cancellationToken = context.CancellationToken Dim syntaxTree = semanticModel.SyntaxTree - Dim optionSet = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken) + Dim configOptions = context.Options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree) + Dim simplifierOptions = context.Options.GetVisualBasicSimplifierOptions(semanticModel.SyntaxTree) Dim root = syntaxTree.GetRoot(cancellationToken) - Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, optionSet, ignoredSpans:=codeBlockIntervalTree, cancellationToken) + Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, simplifierOptions, ignoredSpans:=codeBlockIntervalTree, cancellationToken) simplifier.Visit(root) Return simplifier.Diagnostics End Function @@ -68,7 +69,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames End Function Friend Overrides Function CanSimplifyTypeNameExpression( - model As SemanticModel, node As SyntaxNode, optionSet As OptionSet, + model As SemanticModel, node As SyntaxNode, options As VisualBasicSimplifierOptions, ByRef issueSpan As TextSpan, ByRef diagnosticId As String, ByRef inDeclaration As Boolean, cancellationToken As CancellationToken) As Boolean issueSpan = Nothing @@ -87,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames End If Dim replacementSyntax As ExpressionSyntax = Nothing - If Not ExpressionSimplifier.Instance.TrySimplify(expression, model, optionSet, replacementSyntax, issueSpan, cancellationToken) Then + If Not ExpressionSimplifier.Instance.TrySimplify(expression, model, options, replacementSyntax, issueSpan, cancellationToken) Then Return False End If diff --git a/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb b/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb index 7199cf45bd65a..51b0f473ae6cd 100644 --- a/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb +++ b/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb @@ -4,6 +4,7 @@ Imports System.Composition Imports System.Threading +Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Host.Mef @@ -17,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Public Sub New() End Sub - Public Function FormatNewDocumentAsync(document As Document, hintDocument As Document, options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements INewDocumentFormattingProvider.FormatNewDocumentAsync + Public Function FormatNewDocumentAsync(document As Document, hintDocument As Document, options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements INewDocumentFormattingProvider.FormatNewDocumentAsync Return Formatter.OrganizeImportsAsync(document, cancellationToken) End Function End Class diff --git a/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb b/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb index 41e153d3a8c24..2103001078cf6 100644 --- a/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/ImplementInterface/VisualBasicImplementInterfaceCodeFixProvider.vb @@ -61,7 +61,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ImplementInterface Dim service = document.GetLanguageService(Of IImplementInterfaceService)() Dim actions = service.GetCodeActions( document, - context.Options(document.Project.Language).ImplementTypeOptions, + context.Options(document.Project.LanguageServices).ImplementTypeOptions, Await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(False), typeNode, cancellationToken) diff --git a/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb index 315c9020ae6b1..bd7e94245a4a0 100644 --- a/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb @@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.SimplifyThisOrMe Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices Imports Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyThisOrMe @@ -19,19 +20,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyThisOrMe SyntaxKind, ExpressionSyntax, MeExpressionSyntax, - MemberAccessExpressionSyntax) + MemberAccessExpressionSyntax, + VisualBasicSimplifierOptions) Protected Overrides Function GetSyntaxFacts() As ISyntaxFacts Return VisualBasicSyntaxFacts.Instance End Function + Protected Overrides Function GetSimplifierOptions(options As AnalyzerOptions, syntaxTree As SyntaxTree) As VisualBasicSimplifierOptions + Return options.GetVisualBasicSimplifierOptions(syntaxTree) + End Function + Protected Overrides Function CanSimplifyTypeNameExpression( model As SemanticModel, memberAccess As MemberAccessExpressionSyntax, - optionSet As OptionSet, ByRef issueSpan As TextSpan, + options As VisualBasicSimplifierOptions, ByRef issueSpan As TextSpan, cancellationToken As CancellationToken) As Boolean Dim replacementSyntax As ExpressionSyntax = Nothing - Return ExpressionSimplifier.Instance.TrySimplify(memberAccess, model, optionSet, replacementSyntax, issueSpan, cancellationToken) + Return ExpressionSimplifier.Instance.TrySimplify(memberAccess, model, options, replacementSyntax, issueSpan, cancellationToken) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.vb b/src/Features/VisualBasic/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.vb index 5752a5acc11d8..d28d543d2b490 100644 --- a/src/Features/VisualBasic/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/SimplifyTypeNames/SimplifyTypeNamesCodeFixProvider.vb @@ -8,6 +8,7 @@ Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.SimplifyTypeNames +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyTypeNames @@ -15,7 +16,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyTypeNames Partial Friend Class SimplifyTypeNamesCodeFixProvider - Inherits AbstractSimplifyTypeNamesCodeFixProvider(Of SyntaxKind) + Inherits AbstractSimplifyTypeNamesCodeFixProvider(Of SyntaxKind, VisualBasicSimplifierOptions) diff --git a/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs index 66ecf8cdd0fcf..1fa3106504b86 100644 --- a/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs +++ b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting; using Microsoft.CodeAnalysis.Formatting; @@ -76,61 +77,62 @@ public static OmniSharpSyntaxFormattingOptionsWrapper Create( bool newLineForMembersInObjectInit, bool newLineForMembersInAnonymousTypes, bool newLineForClausesInQuery) - => new(new CSharpSyntaxFormattingOptions( - new LineFormattingOptions( - 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)); + => new(formattingOptions: new CSharpSyntaxFormattingOptions( + new LineFormattingOptions( + 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), + simplifierOptions: CSharpSimplifierOptions.Default); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs index c60ad8943d52b..a7181ba1a4a51 100644 --- a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs +++ b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs @@ -13,10 +13,8 @@ internal readonly record struct OmniSharpCodeActionOptions( OmniSharpImplementTypeOptions ImplementTypeOptions) { internal CodeActionOptions GetCodeActionOptions() - => new( - SymbolSearchOptions.Default, - new ImplementTypeOptions( - InsertionBehavior: (ImplementTypeInsertionBehavior)ImplementTypeOptions.InsertionBehavior, - PropertyGenerationBehavior: (ImplementTypePropertyGenerationBehavior)ImplementTypeOptions.PropertyGenerationBehavior)); + => new(ImplementTypeOptions: new( + InsertionBehavior: (ImplementTypeInsertionBehavior)ImplementTypeOptions.InsertionBehavior, + PropertyGenerationBehavior: (ImplementTypePropertyGenerationBehavior)ImplementTypeOptions.PropertyGenerationBehavior)); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs index 65dc921a7f9f3..8e3e5dbf477db 100644 --- a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs +++ b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs @@ -54,7 +54,7 @@ public static FixAllContext CreateFixAllContext( codeActionEquivalenceKey, diagnosticIds, fixAllDiagnosticProvider, - language => optionsProvider(language).GetCodeActionOptions()), + languageServices => optionsProvider(languageServices.Language).GetCodeActionOptions()), new ProgressTracker(), cancellationToken); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs index cadbac84be4ea..08017496c278e 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpFormatter.cs @@ -15,7 +15,7 @@ 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); + => Formatter.FormatAsync(document, spans, options.FormattingOptions, rules: null, cancellationToken); public static async Task OrganizeImportsAsync(Document document, OmniSharpOrganizeImportsOptionsWrapper options, CancellationToken cancellationToken) { diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs index 5ff2ccf0b9e0f..bf6039b17e0d1 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs @@ -5,20 +5,27 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting { internal readonly record struct OmniSharpSyntaxFormattingOptionsWrapper { - internal readonly SyntaxFormattingOptions UnderlyingObject; + internal readonly SyntaxFormattingOptions FormattingOptions; + internal readonly SimplifierOptions SimplifierOptions; - internal OmniSharpSyntaxFormattingOptionsWrapper(SyntaxFormattingOptions underlyingObject) - => UnderlyingObject = underlyingObject; + internal OmniSharpSyntaxFormattingOptionsWrapper(SyntaxFormattingOptions formattingOptions, SimplifierOptions simplifierOptions) + { + FormattingOptions = formattingOptions; + SimplifierOptions = simplifierOptions; + } public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) { - var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - return new OmniSharpSyntaxFormattingOptionsWrapper(options); + var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + + return new OmniSharpSyntaxFormattingOptionsWrapper(formattingOptions, simplifierOptions); } } } diff --git a/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs b/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs index 63c4dc0921433..ff2e30751a96d 100644 --- a/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.MetadataAsSource; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.MetadataAsSource { @@ -28,8 +29,11 @@ internal static class OmniSharpMetadataAsSourceService public static async Task AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); + var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - return await service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + + return await service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions, simplifierOptions, cancellationToken).ConfigureAwait(false); } /// @@ -46,7 +50,7 @@ public static async Task AddSourceToAsync(Document document, Compilati public static Task AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, OmniSharpSyntaxFormattingOptionsWrapper formattingOptions, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); - return service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions.UnderlyingObject, cancellationToken); + return service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions.FormattingOptions, formattingOptions.SimplifierOptions, cancellationToken); } } } diff --git a/src/VisualStudio/Core/Def/CodeCleanup/AbstractCodeCleanUpFixer.cs b/src/VisualStudio/Core/Def/CodeCleanup/AbstractCodeCleanUpFixer.cs index f235a0fc5db71..564667b3c88f5 100644 --- a/src/VisualStudio/Core/Def/CodeCleanup/AbstractCodeCleanUpFixer.cs +++ b/src/VisualStudio/Core/Def/CodeCleanup/AbstractCodeCleanUpFixer.cs @@ -134,7 +134,7 @@ private async Task FixHierarchyContentAsync(IVsHierarchyCodeCleanupScope h } var document = solution.GetRequiredDocument(documentId); - var options = _globalOptions.GetCodeActionOptions(document.Project.Language); + var options = _globalOptions.GetCodeActionOptions(document.Project.LanguageServices); return await FixDocumentAsync(document, options, context).ConfigureAwait(true); } } @@ -203,7 +203,7 @@ async Task ApplyFixAsync(ProgressTracker progressTracker, Cancellation var document = buffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); Contract.ThrowIfNull(document); - var options = _globalOptions.GetCodeActionOptions(document.Project.Language); + var options = _globalOptions.GetCodeActionOptions(document.Project.LanguageServices); var newDoc = await FixDocumentAsync(document, context.EnabledFixIds, progressTracker, options, cancellationToken).ConfigureAwait(true); return newDoc.Project.Solution; } @@ -290,7 +290,7 @@ private async Task FixProjectAsync( progressTracker.AddItems(project.DocumentIds.Count); } - var ideOptions = _globalOptions.GetCodeActionOptions(project.Language); + var ideOptions = _globalOptions.GetCodeActionOptions(project.LanguageServices); foreach (var documentId in project.DocumentIds) { diff --git a/src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs b/src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs index 56a7eef0495a3..4f0f721f5358f 100644 --- a/src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs +++ b/src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -324,26 +325,26 @@ private async Task FormatDocumentCreatedFromTemplateAsync(IVsHierarchy hierarchy var documentId = DocumentId.CreateNewId(projectToAddTo.Id); var forkedSolution = projectToAddTo.Solution.AddDocument(DocumentInfo.Create(documentId, filePath, loader: new FileTextLoader(filePath, defaultEncoding: null), filePath: filePath)); - var addedDocument = forkedSolution.GetDocument(documentId)!; + var addedDocument = forkedSolution.GetRequiredDocument(documentId); - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(addedDocument, cancellationToken).ConfigureAwait(true); + var cleanupOptions = await CodeCleanupOptions.FromDocumentAsync(addedDocument, fallbackOptions: null, cancellationToken).ConfigureAwait(true); // Call out to various new document formatters to tweak what they want var formattingService = addedDocument.GetLanguageService(); if (formattingService is not null) { - addedDocument = await formattingService.FormatNewDocumentAsync(addedDocument, hintDocument: null, formattingOptions, cancellationToken).ConfigureAwait(true); + addedDocument = await formattingService.FormatNewDocumentAsync(addedDocument, hintDocument: null, cleanupOptions, cancellationToken).ConfigureAwait(true); } var rootToFormat = await addedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(true); // Format document var unformattedText = await addedDocument.GetTextAsync(cancellationToken).ConfigureAwait(true); - var formattedRoot = Formatter.Format(rootToFormat, workspace.Services, formattingOptions, cancellationToken); + var formattedRoot = Formatter.Format(rootToFormat, workspace.Services, cleanupOptions.FormattingOptions, cancellationToken); var formattedText = formattedRoot.GetText(unformattedText.Encoding, unformattedText.ChecksumAlgorithm); // Ensure the line endings are normalized. The formatter doesn't touch everything if it doesn't need to. - var targetLineEnding = formattingOptions.NewLine; + var targetLineEnding = cleanupOptions.FormattingOptions.NewLine; var originalText = formattedText; foreach (var originalLine in originalText.Lines) diff --git a/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs b/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs index a4cd5c55d4fef..52968f5c64c83 100644 --- a/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs +++ b/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs @@ -65,7 +65,7 @@ internal abstract class AbstractSnippetExpansionClient : ForegroundThreadAffinit protected readonly Guid LanguageServiceGuid; protected readonly ITextView TextView; protected readonly ITextBuffer SubjectBuffer; - protected readonly IGlobalOptionService GlobalOptions; + internal readonly IGlobalOptionService GlobalOptions; private readonly ImmutableArray> _allArgumentProviders; private ImmutableArray _argumentProviders; diff --git a/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs b/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs index e5ae82936d202..bffd8dfbe24e7 100644 --- a/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs +++ b/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionGenerateSwitchCases.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Text; using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan; @@ -56,7 +57,9 @@ protected override int FieldChanged(string field, out int requeryFunction) return (VSConstants.S_OK, snippetFunctionService.SwitchDefaultCaseForm, hasCurrentValue); } - var value = await snippetFunctionService.GetSwitchExpansionAsync(document, caseGenerationSpan.Value, switchExpressionSpan.Value, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await document.GetSimplifierOptionsAsync(snippetExpansionClient.GlobalOptions, cancellationToken).ConfigureAwait(false); + + var value = await snippetFunctionService.GetSwitchExpansionAsync(document, caseGenerationSpan.Value, switchExpressionSpan.Value, simplifierOptions, cancellationToken).ConfigureAwait(false); if (value == null) { return (VSConstants.S_OK, snippetFunctionService.SwitchDefaultCaseForm, hasCurrentValue); diff --git a/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs b/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs index a4771e60f23c3..6a4aa15ccc149 100644 --- a/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs +++ b/src/VisualStudio/Core/Def/Snippets/SnippetFunctions/SnippetFunctionSimpleTypeName.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.VisualStudio.Text; using TextSpan = Microsoft.CodeAnalysis.Text.TextSpan; using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan; @@ -45,7 +45,9 @@ public SnippetFunctionSimpleTypeName( return (VSConstants.E_FAIL, value, hasDefaultValue); } - var simplifiedTypeName = await SnippetFunctionService.GetSimplifiedTypeNameAsync(document, fieldSpan.Value, _fullyQualifiedName, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await document.GetSimplifierOptionsAsync(snippetExpansionClient.GlobalOptions, cancellationToken).ConfigureAwait(false); + + var simplifiedTypeName = await SnippetFunctionService.GetSimplifiedTypeNameAsync(document, fieldSpan.Value, _fullyQualifiedName, simplifierOptions, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(simplifiedTypeName)) { return (VSConstants.E_FAIL, value, hasDefaultValue); diff --git a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs index d835b1f65e8d9..079bc5f2bc78e 100644 --- a/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs +++ b/src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioSuppressionFixService.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.Editor.Implementation.Suggestions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -298,16 +299,17 @@ private async Task ApplySuppressionFixAsync(IEnumerable? diagnos // We have different suppression fixers for every language. // So we need to group diagnostics by the containing project language and apply fixes separately. - var languages = new HashSet(projectDiagnosticsToFixMap.Select(p => p.Key.Language).Concat(documentDiagnosticsToFixMap.Select(kvp => kvp.Key.Project.Language))); + var languageServices = new HashSet(projectDiagnosticsToFixMap.Select(p => p.Key.LanguageServices).Concat(documentDiagnosticsToFixMap.Select(kvp => kvp.Key.Project.LanguageServices))); - foreach (var language in languages) + foreach (var languageService in languageServices) { // Use the Fix multiple occurrences service to compute a bulk suppression fix for the specified document and project diagnostics, // show a preview changes dialog and then apply the fix to the workspace. cancellationToken.ThrowIfCancellationRequested(); - var options = _globalOptions.GetCodeActionOptions(language); + var language = languageService.Language; + var options = _globalOptions.GetCodeActionOptions(languageService); var optionsProvider = new CodeActionOptionsProvider(_ => options); var documentDiagnosticsPerLanguage = GetDocumentDiagnosticsMappedToNewSolution(documentDiagnosticsToFixMap, newSolution, language); @@ -372,7 +374,7 @@ private async Task ApplySuppressionFixAsync(IEnumerable? diagnos newSolution, fixAllPreviewChangesTitle: title, fixAllTopLevelHeader: title, - languageOpt: languages?.Count == 1 ? languages.Single() : null, + languageOpt: languageServices?.Count == 1 ? languageServices.Single().Language : null, workspace: _workspace); if (newSolution == null) { diff --git a/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs b/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs index 3f1705282b801..be96f2931f05a 100644 --- a/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs +++ b/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs @@ -217,6 +217,8 @@ public static Tuple EnsureEventHandler( throw new InvalidOperationException(ServicesVSResources.Can_t_find_where_to_insert_member); } + var globalOptions = targetDocument.Project.Solution.Workspace.Services.GetRequiredService().GlobalOptions; + var options = codeGenerationService.GetOptions( targetSyntaxTree.Options, documentOptions, @@ -225,11 +227,13 @@ public static Tuple EnsureEventHandler( var newType = codeGenerationService.AddMethod(destinationType, newMethod, options, cancellationToken); var newRoot = targetSyntaxTree.GetRoot(cancellationToken).ReplaceNode(destinationType, newType); + var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(targetDocument, cancellationToken).WaitAndGetResult_Venus(cancellationToken); + var simplifierOptions = targetDocument.GetSimplifierOptionsAsync(globalOptions, cancellationToken).WaitAndGetResult_Venus(cancellationToken); + newRoot = Simplifier.ReduceAsync( - targetDocument.WithSyntaxRoot(newRoot), Simplifier.Annotation, null, cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetSyntaxRootSynchronously(cancellationToken); + targetDocument.WithSyntaxRoot(newRoot), Simplifier.Annotation, simplifierOptions, cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetSyntaxRootSynchronously(cancellationToken); var formattingRules = additionalFormattingRule.Concat(Formatter.GetDefaultFormattingRules(targetDocument)); - var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(targetDocument, cancellationToken).WaitAndGetResult_Venus(cancellationToken); newRoot = Formatter.Format( newRoot, diff --git a/src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolNavigationService.cs b/src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolNavigationService.cs index b66f02e32a750..91e629a91de54 100644 --- a/src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolNavigationService.cs +++ b/src/VisualStudio/Core/Def/Workspace/VisualStudioSymbolNavigationService.cs @@ -124,7 +124,7 @@ public VisualStudioSymbolNavigationService( private async Task GetNavigableLocationForMetadataAsync( Project project, ISymbol symbol, CancellationToken cancellationToken) { - var masOptions = _globalOptions.GetMetadataAsSourceOptions(); + var masOptions = _globalOptions.GetMetadataAsSourceOptions(project.LanguageServices); var result = await _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly: false, masOptions, cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs index e841628c3c4b9..a82086259243f 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs @@ -1083,13 +1083,11 @@ private SyntaxNode InsertNode( if (!batchMode) { - document = _threadingContext.JoinableTaskFactory.Run(() => - Simplifier.ReduceAsync( - document, - annotation, - optionSet: null, - cancellationToken: cancellationToken) - ); + document = _threadingContext.JoinableTaskFactory.Run(async () => + { + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + return await Simplifier.ReduceAsync(document, annotation, simplifierOptions, cancellationToken).ConfigureAwait(false); + }); } document = FormatAnnotatedNode(document, annotation, new[] { _lineAdjustmentFormattingRule, _endRegionFormattingRule }, cancellationToken); diff --git a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs index 849133f824a22..388795532ac15 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs @@ -703,8 +703,11 @@ int IVBFileCodeModelEvents.EndEdit() if (_batchDocument != null) { // perform expensive operations at once - var newDocument = State.ThreadingContext.JoinableTaskFactory.Run(() => - Simplifier.ReduceAsync(_batchDocument, Simplifier.Annotation, cancellationToken: CancellationToken.None)); + var newDocument = State.ThreadingContext.JoinableTaskFactory.Run(async () => + { + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(_batchDocument, fallbackOptions: null, CancellationToken.None).ConfigureAwait(false); + return await Simplifier.ReduceAsync(_batchDocument, Simplifier.Annotation, simplifierOptions, CancellationToken.None).ConfigureAwait(false); + }); _batchDocument.Project.Solution.Workspace.TryApplyChanges(newDocument.Project.Solution); diff --git a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs index 8720b87aa8428..cfbaaca97a9ba 100644 --- a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -45,24 +46,22 @@ void Method() } }"; - using (var workspace = CreateWorkspace(LanguageNames.CSharp, code)) - { - var analyzerType = typeof(CSharpUseExplicitTypeDiagnosticAnalyzer); - var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType); + using var workspace = CreateWorkspace(LanguageNames.CSharp, code); + var analyzerType = typeof(CSharpUseExplicitTypeDiagnosticAnalyzer); + var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, IdeAnalyzerOptions.Default); - var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); - Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id); - Assert.Equal(DiagnosticSeverity.Hidden, diagnostics[0].Severity); + var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); + Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id); + Assert.Equal(DiagnosticSeverity.Hidden, diagnostics[0].Severity); - // set option - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, new CodeStyleOption(false, NotificationOption.Suggestion)))); - analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType); + var ideOptions = new IdeAnalyzerOptions( + SimplifierOptions: new CSharpSimplifierOptions(varWhenTypeIsApparent: new CodeStyleOption2(false, NotificationOption2.Suggestion))); - diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); - Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id); - Assert.Equal(DiagnosticSeverity.Info, diagnostics[0].Severity); - } + analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, ideOptions); + + diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); + Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id); + Assert.Equal(DiagnosticSeverity.Info, diagnostics[0].Severity); } [Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)] @@ -82,14 +81,14 @@ End Sub .WithChangedOption(CodeStyleOptions2.PreferNullPropagation, LanguageNames.VisualBasic, new CodeStyleOption2(false, NotificationOption2.Silent)))); var analyzerType = typeof(VisualBasicUseNullPropagationDiagnosticAnalyzer); - var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType); + var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, IdeAnalyzerOptions.Default); Assert.True(analyzerResult.IsEmpty); // set option workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options .WithChangedOption(CodeStyleOptions2.PreferNullPropagation, LanguageNames.VisualBasic, new CodeStyleOption2(true, NotificationOption2.Error)))); - analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType); + analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, IdeAnalyzerOptions.Default); var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); Assert.Equal(IDEDiagnosticIds.UseNullPropagationDiagnosticId, diagnostics[0].Id); @@ -111,7 +110,7 @@ public async Task TestCancellation() try { - var task = Task.Run(() => AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, source.Token)); + var task = Task.Run(() => AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, IdeAnalyzerOptions.Default, source.Token)); // wait random milli-second var random = new Random(Environment.TickCount); @@ -217,7 +216,7 @@ void Method() private static InProcOrRemoteHostAnalyzerRunner CreateAnalyzerRunner() => new(new DiagnosticAnalyzerInfoCache()); - private static async Task AnalyzeAsync(TestWorkspace workspace, ProjectId projectId, Type analyzerType, CancellationToken cancellationToken = default) + private static async Task AnalyzeAsync(TestWorkspace workspace, ProjectId projectId, Type analyzerType, IdeAnalyzerOptions ideOptions, CancellationToken cancellationToken = default) { var executor = CreateAnalyzerRunner(); @@ -226,7 +225,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, IdeAnalyzerOptions.Default)); + new WorkspaceAnalyzerOptions(project.AnalyzerOptions, project.Solution, ideOptions)); var result = await executor.AnalyzeProjectAsync(project, analyzerDriver, forceExecuteAllAnalyzers: true, logPerformanceInfo: false, getTelemetryInfo: false, cancellationToken); diff --git a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs index cb2c3dc254201..adbcbe894fa56 100644 --- a/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs +++ b/src/VisualStudio/Xaml/Impl/Implementation/LanguageServer/Handler/Definitions/GoToDefinitionHandler.cs @@ -173,7 +173,7 @@ public GoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileSe var project = context.Document?.GetCodeProject(); if (project != null) { - var options = globalOptions.GetMetadataAsSourceOptions(); + var options = globalOptions.GetMetadataAsSourceOptions(project.LanguageServices); var declarationFile = await metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly: true, options, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; locations.Add(new LSP.Location diff --git a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.NodesAndTokensToReduceComputer.cs b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.NodesAndTokensToReduceComputer.cs index c0567199845c8..23aed3551219c 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.NodesAndTokensToReduceComputer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.NodesAndTokensToReduceComputer.cs @@ -14,7 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Simplification { - internal partial class CSharpSimplificationService : AbstractSimplificationService + internal partial class CSharpSimplificationService { private class NodesAndTokensToReduceComputer : CSharpSyntaxRewriter { diff --git a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs index d281c3cf13c0e..6ee54271b0f42 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -12,6 +10,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; @@ -45,7 +44,13 @@ public CSharpSimplificationService() : base(s_reducers) { } - public override SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation annotationForReplacedAliasIdentifier, Func expandInsideNode, bool expandParameter, CancellationToken cancellationToken) + public override SimplifierOptions DefaultOptions + => CSharpSimplifierOptions.Default; + + public override SimplifierOptions GetSimplifierOptions(AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions) + => CSharpSimplifierOptions.Create(options, (CSharpSimplifierOptions?)fallbackOptions); + + public override SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation? annotationForReplacedAliasIdentifier, Func? expandInsideNode, bool expandParameter, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Simplifier_ExpandNode, cancellationToken)) { @@ -70,8 +75,10 @@ TypeConstraintSyntax or } } - public override SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel, Func expandInsideNode, CancellationToken cancellationToken) + public override SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel, Func? expandInsideNode, CancellationToken cancellationToken) { + Contract.ThrowIfNull(token.Parent); + using (Logger.LogBlock(FunctionId.Simplifier_ExpandToken, cancellationToken)) { var rewriter = new Expander(semanticModel, expandInsideNode, false, cancellationToken); @@ -105,14 +112,14 @@ public static SyntaxToken TryEscapeIdentifierToken(SyntaxToken syntaxToken, Synt } var parent = parentOfToken.Parent; - if (parentOfToken is SimpleNameSyntax && parent.Kind() == SyntaxKind.XmlNameAttribute) + if (parentOfToken is SimpleNameSyntax && parent.IsKind(SyntaxKind.XmlNameAttribute)) { // do not try to escape XML name attributes return syntaxToken; } // do not escape global in a namespace qualified name - if (parent.Kind() == SyntaxKind.AliasQualifiedName && + if (parent.IsKind(SyntaxKind.AliasQualifiedName) && syntaxToken.ValueText == "global") { return syntaxToken; diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs index 40a92c1dc9529..a000589689374 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.AbstractReductionRewriter.cs @@ -2,17 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Simplification; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Simplification { @@ -22,10 +21,10 @@ protected abstract class AbstractReductionRewriter : CSharpSyntaxRewriter, IRedu { private readonly ObjectPool _pool; - protected CSharpParseOptions ParseOptions { get; private set; } - protected OptionSet OptionSet { get; private set; } + protected CSharpParseOptions? ParseOptions { get; private set; } + protected CSharpSimplifierOptions? Options { get; private set; } protected CancellationToken CancellationToken { get; private set; } - protected SemanticModel SemanticModel { get; private set; } + protected SemanticModel? SemanticModel { get; private set; } public bool HasMoreWork { get; private set; } @@ -38,17 +37,19 @@ protected abstract class AbstractReductionRewriter : CSharpSyntaxRewriter, IRedu protected AbstractReductionRewriter(ObjectPool pool) => _pool = pool; - public void Initialize(ParseOptions parseOptions, OptionSet optionSet, CancellationToken cancellationToken) + public void Initialize(ParseOptions parseOptions, SimplifierOptions options, CancellationToken cancellationToken) { + Contract.ThrowIfNull(options); + ParseOptions = (CSharpParseOptions)parseOptions; - OptionSet = optionSet; + Options = (CSharpSimplifierOptions)options; CancellationToken = cancellationToken; } public void Dispose() { ParseOptions = null; - OptionSet = null; + Options = null; CancellationToken = CancellationToken.None; _processedParentNodes.Clear(); SemanticModel = null; @@ -58,7 +59,15 @@ public void Dispose() _pool.Free(this); } - private static SyntaxNode GetParentNode(SyntaxNode node) + [MemberNotNull(nameof(Options), nameof(ParseOptions), nameof(SemanticModel))] + public void RequireInitialized() + { + Contract.ThrowIfNull(ParseOptions); + Contract.ThrowIfNull(Options); + Contract.ThrowIfNull(SemanticModel); + } + + private static SyntaxNode? GetParentNode(SyntaxNode node) => node switch { ExpressionSyntax expression => GetParentNode(expression), @@ -70,7 +79,7 @@ private static SyntaxNode GetParentNode(SyntaxNode node) private static SyntaxNode GetParentNode(ExpressionSyntax expression) { var lastExpression = expression; - for (SyntaxNode current = expression; current != null; current = current.Parent) + for (SyntaxNode? current = expression; current != null; current = current.Parent) { if (current is ExpressionSyntax currentExpression) { @@ -78,13 +87,14 @@ private static SyntaxNode GetParentNode(ExpressionSyntax expression) } } + Contract.ThrowIfNull(lastExpression.Parent); return lastExpression.Parent; } private static SyntaxNode GetParentNode(PatternSyntax pattern) { var lastPattern = pattern; - for (SyntaxNode current = pattern; current != null; current = current.Parent) + for (SyntaxNode? current = pattern; current != null; current = current.Parent) { if (current is PatternSyntax currentPattern) { @@ -92,6 +102,7 @@ private static SyntaxNode GetParentNode(PatternSyntax pattern) } } + Contract.ThrowIfNull(lastPattern.Parent); return lastPattern.Parent; } @@ -102,6 +113,7 @@ private static SyntaxNode GetParentNode(CrefSyntax cref) .OfType() .LastOrDefault(); + Contract.ThrowIfNull(topMostCref.Parent); return topMostCref.Parent; } @@ -109,10 +121,10 @@ protected SyntaxNode SimplifyNode( TNode node, SyntaxNode newNode, SyntaxNode parentNode, - Func simplifier) + Func simplifier) where TNode : SyntaxNode { - Debug.Assert(parentNode != null); + RequireInitialized(); this.CancellationToken.ThrowIfCancellationRequested(); @@ -129,7 +141,7 @@ protected SyntaxNode SimplifyNode( if (!node.HasAnnotation(SimplificationHelpers.DontSimplifyAnnotation)) { - var simplifiedNode = simplifier(node, this.SemanticModel, this.OptionSet, this.CancellationToken); + var simplifiedNode = simplifier(node, this.SemanticModel, this.Options, this.CancellationToken); if (simplifiedNode != node) { _processedParentNodes.Add(parentNode); @@ -144,7 +156,7 @@ protected SyntaxNode SimplifyNode( protected SyntaxNode SimplifyExpression( TExpression expression, SyntaxNode newNode, - Func simplifier) + Func simplifier) where TExpression : SyntaxNode { var parentNode = GetParentNode(expression); @@ -154,12 +166,14 @@ protected SyntaxNode SimplifyExpression( return SimplifyNode(expression, newNode, parentNode, simplifier); } - protected SyntaxToken SimplifyToken(SyntaxToken token, Func simplifier) + protected SyntaxToken SimplifyToken(SyntaxToken token, Func simplifier) { + RequireInitialized(); + this.CancellationToken.ThrowIfCancellationRequested(); return token.HasAnnotation(Simplifier.Annotation) - ? simplifier(token, this.SemanticModel, this.OptionSet, this.CancellationToken) + ? simplifier(token, this.SemanticModel, this.Options, this.CancellationToken) : token; } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.cs index ab994785f46a4..e9d52550059cb 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/AbstractCSharpReducer.cs @@ -14,5 +14,10 @@ internal abstract partial class AbstractCSharpReducer : AbstractReducer protected AbstractCSharpReducer(ObjectPool pool) : base(pool) { } + + public sealed override bool IsApplicable(SimplifierOptions options) + => IsApplicable((CSharpSimplifierOptions)options); + + protected abstract bool IsApplicable(CSharpSimplifierOptions options); } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.cs index b89cb525e4d0f..7c45a8d50b8f5 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpCastReducer.cs @@ -9,8 +9,8 @@ using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.Simplification { @@ -23,9 +23,12 @@ public CSharpCastReducer() : base(s_pool) { } - private static readonly Func s_simplifyCast = SimplifyCast; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; - private static ExpressionSyntax SimplifyCast(CastExpressionSyntax node, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) + private static readonly Func s_simplifyCast = SimplifyCast; + + private static ExpressionSyntax SimplifyCast(CastExpressionSyntax node, SemanticModel semanticModel, SimplifierOptions options, CancellationToken cancellationToken) { if (!CastSimplifier.IsUnnecessaryCast(node, semanticModel, cancellationToken)) { diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs index c794d49d18217..5eaf06750c7fa 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.Rewriter.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.Simplification { @@ -24,15 +25,15 @@ public Rewriter(ObjectPool pool) _simplifyDefaultExpression = SimplifyDefaultExpression; } - private readonly Func _simplifyDefaultExpression; + private readonly Func _simplifyDefaultExpression; private SyntaxNode SimplifyDefaultExpression( DefaultExpressionSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { - var preferSimpleDefaultExpression = optionSet.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression).Value; + var preferSimpleDefaultExpression = options.PreferSimpleDefaultExpression.Value; if (node.CanReplaceWithDefaultLiteral(ParseOptions, preferSimpleDefaultExpression, semanticModel, cancellationToken)) { diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs index 560951edef4fa..8246972fde934 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpDefaultExpressionReducer.cs @@ -16,5 +16,8 @@ internal partial class CSharpDefaultExpressionReducer : AbstractCSharpReducer public CSharpDefaultExpressionReducer() : base(s_pool) { } + + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpEscapingReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpEscapingReducer.cs index 724f077f6b1a6..15a9689552b61 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpEscapingReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpEscapingReducer.cs @@ -21,16 +21,19 @@ internal partial class CSharpEscapingReducer : AbstractCSharpReducer private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyIdentifierToken = SimplifyIdentifierToken; + public CSharpEscapingReducer() : base(s_pool) { } - private static readonly Func s_simplifyIdentifierToken = SimplifyIdentifierToken; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxToken SimplifyIdentifierToken( SyntaxToken token, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { var unescapedIdentifier = token.ValueText; diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.cs index ee889336e0897..52d48f8c2c31a 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpExtensionMethodReducer.cs @@ -21,16 +21,19 @@ internal partial class CSharpExtensionMethodReducer : AbstractCSharpReducer private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyExtensionMethod = SimplifyExtensionMethod; + public CSharpExtensionMethodReducer() : base(s_pool) { } - private static readonly Func s_simplifyExtensionMethod = SimplifyExtensionMethod; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxNode SimplifyExtensionMethod( InvocationExpressionSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { var rewrittenNode = node; diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs index 8a9d24d349303..083b2604f1521 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.Rewriter.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.Simplification { @@ -24,9 +25,9 @@ public Rewriter(ObjectPool pool) s_simplifyTupleName = SimplifyTupleName; } - private readonly Func s_simplifyTupleName; + private readonly Func s_simplifyTupleName; - private ArgumentSyntax SimplifyTupleName(ArgumentSyntax node, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) + private ArgumentSyntax SimplifyTupleName(ArgumentSyntax node, SemanticModel semanticModel, SimplifierOptions options, CancellationToken cancellationToken) { if (CanSimplifyTupleElementName(node, this.ParseOptions)) { @@ -36,9 +37,9 @@ private ArgumentSyntax SimplifyTupleName(ArgumentSyntax node, SemanticModel sema return node; } - private static readonly Func s_simplifyAnonymousTypeMemberName = SimplifyAnonymousTypeMemberName; + private static readonly Func s_simplifyAnonymousTypeMemberName = SimplifyAnonymousTypeMemberName; - private static SyntaxNode SimplifyAnonymousTypeMemberName(AnonymousObjectMemberDeclaratorSyntax node, SemanticModel semanticModel, OptionSet optionSet, CancellationToken canellationToken) + private static SyntaxNode SimplifyAnonymousTypeMemberName(AnonymousObjectMemberDeclaratorSyntax node, SemanticModel semanticModel, SimplifierOptions options, CancellationToken canellationToken) { if (CanSimplifyAnonymousTypeMemberName(node)) diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.cs index 5c6476d9fde7c..548fcd8eb098f 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpInferredMemberNameReducer.cs @@ -21,5 +21,8 @@ internal partial class CSharpInferredMemberNameReducer : AbstractCSharpReducer public CSharpInferredMemberNameReducer() : base(s_pool) { } + + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.cs index 060b459076970..3a4bc280da799 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpMiscellaneousReducer.cs @@ -24,10 +24,15 @@ internal partial class CSharpMiscellaneousReducer : AbstractCSharpReducer private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyParameter = SimplifyParameter; + public CSharpMiscellaneousReducer() : base(s_pool) { } + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; + private static bool CanRemoveTypeFromParameter( ParameterSyntax parameterSyntax, SemanticModel semanticModel, @@ -61,12 +66,10 @@ private static bool CanRemoveTypeFromParameter( return false; } - private static readonly Func s_simplifyParameter = SimplifyParameter; - private static SyntaxNode SimplifyParameter( ParameterSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + SimplifierOptions options, CancellationToken cancellationToken) { if (CanRemoveTypeFromParameter(node, semanticModel, cancellationToken)) @@ -79,12 +82,12 @@ private static SyntaxNode SimplifyParameter( return node; } - private static readonly Func s_simplifyParenthesizedLambdaExpression = SimplifyParenthesizedLambdaExpression; + private static readonly Func s_simplifyParenthesizedLambdaExpression = SimplifyParenthesizedLambdaExpression; private static SyntaxNode SimplifyParenthesizedLambdaExpression( ParenthesizedLambdaExpressionSyntax parenthesizedLambda, SemanticModel semanticModel, - OptionSet optionSet, + SimplifierOptions options, CancellationToken cancellationToken) { if (parenthesizedLambda.ParameterList != null && @@ -107,12 +110,12 @@ private static SyntaxNode SimplifyParenthesizedLambdaExpression( return parenthesizedLambda; } - private static readonly Func s_simplifyBlock = SimplifyBlock; + private static readonly Func s_simplifyBlock = SimplifyBlock; private static SyntaxNode SimplifyBlock( BlockSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { if (node.Statements.Count != 1) @@ -125,7 +128,7 @@ private static SyntaxNode SimplifyBlock( return node; } - switch (optionSet.GetOption(CSharpCodeStyleOptions.PreferBraces).Value) + switch (options.PreferBraces.Value) { case PreferBracesPreference.Always: default: diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.cs index 2aeaff2c19345..1f285d5c23a83 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNameReducer.cs @@ -21,16 +21,19 @@ internal partial class CSharpNameReducer : AbstractCSharpReducer private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyName = SimplifyName; + public CSharpNameReducer() : base(s_pool) { } - private static readonly Func s_simplifyName = SimplifyName; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxNode SimplifyName( SyntaxNode node, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { SyntaxNode replacementNode; @@ -38,7 +41,7 @@ private static SyntaxNode SimplifyName( if (node.IsKind(SyntaxKind.QualifiedCref, out QualifiedCrefSyntax crefSyntax)) { if (!QualifiedCrefSimplifier.Instance.TrySimplify( - crefSyntax, semanticModel, optionSet, + crefSyntax, semanticModel, options, out var crefReplacement, out _, cancellationToken)) { return node; @@ -49,7 +52,7 @@ private static SyntaxNode SimplifyName( else { var expressionSyntax = (ExpressionSyntax)node; - if (!ExpressionSimplifier.Instance.TrySimplify(expressionSyntax, semanticModel, optionSet, out var expressionReplacement, out _, cancellationToken)) + if (!ExpressionSimplifier.Instance.TrySimplify(expressionSyntax, semanticModel, options, out var expressionReplacement, out _, cancellationToken)) { return node; } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.cs index 857fe8704dcd0..192c0474daed4 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpNullableAnnotationReducer.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CSharp.Simplification { @@ -18,16 +19,19 @@ internal sealed partial class CSharpNullableAnnotationReducer : AbstractCSharpRe private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyNullableType = SimplifyNullableType; + public CSharpNullableAnnotationReducer() : base(s_pool) { } - private static readonly Func s_simplifyNullableType = SimplifyNullableType; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxNode SimplifyNullableType( NullableTypeSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + SimplifierOptions options, CancellationToken cancellationToken) { // If annotations are enabled, there's no further simplification to do diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.cs index 8e632075d40b4..f4e5e9878d52d 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedExpressionReducer.cs @@ -19,16 +19,19 @@ internal partial class CSharpParenthesizedExpressionReducer : AbstractCSharpRedu private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyParentheses = SimplifyParentheses; + public CSharpParenthesizedExpressionReducer() : base(s_pool) { } - private static readonly Func s_simplifyParentheses = SimplifyParentheses; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxNode SimplifyParentheses( ParenthesizedExpressionSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + SimplifierOptions options, CancellationToken cancellationToken) { if (node.CanRemoveParentheses(semanticModel, cancellationToken)) diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.cs index 69ef2f312d569..06b0a5185ebfc 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpParenthesizedPatternReducer.cs @@ -21,16 +21,19 @@ internal partial class CSharpParenthesizedPatternReducer : AbstractCSharpReducer private static readonly ObjectPool s_pool = new( () => new Rewriter(s_pool)); + private static readonly Func s_simplifyParentheses = SimplifyParentheses; + public CSharpParenthesizedPatternReducer() : base(s_pool) { } - private static readonly Func s_simplifyParentheses = SimplifyParentheses; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => true; private static SyntaxNode SimplifyParentheses( ParenthesizedPatternSyntax node, SemanticModel semanticModel, - OptionSet optionSet, + SimplifierOptions options, CancellationToken cancellationToken) { if (node.CanRemoveParentheses()) diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.Rewriter.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.Rewriter.cs index f613b68d9a43a..c3c14d905664e 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.Rewriter.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.Rewriter.cs @@ -37,7 +37,7 @@ private SyntaxNode ProcessTypeSyntax(TypeSyntax typeSyntax) } var typeStyle = CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName( - typeSyntax, this.SemanticModel, this.OptionSet, this.CancellationToken); + typeSyntax, this.SemanticModel, this.Options, this.CancellationToken); if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert()) { diff --git a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.cs b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.cs index 5ab37200a8096..8a68cb8b07635 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Reducers/CSharpVarReducer.cs @@ -4,8 +4,6 @@ #nullable disable -using Microsoft.CodeAnalysis.CSharp.CodeStyle; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp.Simplification @@ -19,9 +17,9 @@ public CSharpVarReducer() : base(s_pool) { } - public override bool IsApplicable(OptionSet optionSet) - => optionSet.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes).Value || - optionSet.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent).Value || - optionSet.GetOption(CSharpCodeStyleOptions.VarElsewhere).Value; + protected override bool IsApplicable(CSharpSimplifierOptions options) + => options.VarForBuiltInTypes.Value || + options.VarWhenTypeIsApparent.Value || + options.VarElsewhere.Value; } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/AbstractCSharpSimplifier.cs b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/AbstractCSharpSimplifier.cs index c384a213b07b7..c09c209b78425 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/AbstractCSharpSimplifier.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/AbstractCSharpSimplifier.cs @@ -9,11 +9,11 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Simplification.Simplifiers; +using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers @@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers /// Contains helpers used by several simplifier subclasses. /// internal abstract class AbstractCSharpSimplifier - : AbstractSimplifier + : AbstractSimplifier where TSyntax : SyntaxNode where TSimplifiedSyntax : SyntaxNode { @@ -394,9 +394,9 @@ protected static bool InsideNameOfExpression(ExpressionSyntax expression, Semant return nameOfInvocationExpr != null; } - protected static bool PreferPredefinedTypeKeywordInMemberAccess(ExpressionSyntax expression, OptionSet optionSet, SemanticModel semanticModel) + protected static bool PreferPredefinedTypeKeywordInMemberAccess(ExpressionSyntax expression, CSharpSimplifierOptions options, SemanticModel semanticModel) { - if (!SimplificationHelpers.PreferPredefinedTypeKeywordInMemberAccess(optionSet, semanticModel.Language)) + if (!options.PreferPredefinedTypeKeywordInMemberAccess.Value) return false; return (expression.IsDirectChildOfMemberAccessExpression() || expression.InsideCrefReference()) && diff --git a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/ExpressionSimplifier.cs b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/ExpressionSimplifier.cs index a6457f3d5ab50..60d87fda5a7fd 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/ExpressionSimplifier.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/ExpressionSimplifier.cs @@ -33,12 +33,12 @@ private ExpressionSimplifier() public override bool TrySimplify( ExpressionSyntax expression, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, out ExpressionSyntax replacementNode, out TextSpan issueSpan, CancellationToken cancellationToken) { - if (TryReduceExplicitName(expression, semanticModel, out var replacementTypeNode, out issueSpan, optionSet, cancellationToken)) + if (TryReduceExplicitName(expression, semanticModel, out var replacementTypeNode, out issueSpan, options, cancellationToken)) { replacementNode = replacementTypeNode; return true; @@ -52,7 +52,7 @@ private static bool TryReduceExplicitName( SemanticModel semanticModel, out TypeSyntax replacementNode, out TextSpan issueSpan, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { replacementNode = null; @@ -62,10 +62,10 @@ private static bool TryReduceExplicitName( return false; if (expression.IsKind(SyntaxKind.SimpleMemberAccessExpression, out MemberAccessExpressionSyntax memberAccess)) - return TryReduceMemberAccessExpression(memberAccess, semanticModel, out replacementNode, out issueSpan, optionSet, cancellationToken); + return TryReduceMemberAccessExpression(memberAccess, semanticModel, out replacementNode, out issueSpan, options, cancellationToken); if (expression is NameSyntax name) - return NameSimplifier.Instance.TrySimplify(name, semanticModel, optionSet, out replacementNode, out issueSpan, cancellationToken); + return NameSimplifier.Instance.TrySimplify(name, semanticModel, options, out replacementNode, out issueSpan, cancellationToken); return false; } @@ -75,7 +75,7 @@ private static bool TryReduceMemberAccessExpression( SemanticModel semanticModel, out TypeSyntax replacementNode, out TextSpan issueSpan, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { replacementNode = null; @@ -108,7 +108,7 @@ private static bool TryReduceMemberAccessExpression( return false; if (memberAccess.Expression.IsKind(SyntaxKind.ThisExpression) && - !SimplificationHelpers.ShouldSimplifyThisOrMeMemberAccessExpression(semanticModel, optionSet, symbol)) + !SimplificationHelpers.ShouldSimplifyThisOrMeMemberAccessExpression(options, symbol)) { return false; } @@ -155,7 +155,7 @@ private static bool TryReduceMemberAccessExpression( } // Check if the Expression can be replaced by Predefined Type keyword - if (PreferPredefinedTypeKeywordInMemberAccess(memberAccess, optionSet, semanticModel)) + if (PreferPredefinedTypeKeywordInMemberAccess(memberAccess, options, semanticModel)) { if (symbol != null && symbol.IsKind(SymbolKind.NamedType)) { diff --git a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/NameSimplifier.cs b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/NameSimplifier.cs index 6e0a271a45bab..37d0a1a38e18f 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/NameSimplifier.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/NameSimplifier.cs @@ -33,7 +33,7 @@ private NameSimplifier() public override bool TrySimplify( NameSyntax name, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, out TypeSyntax replacementNode, out TextSpan issueSpan, CancellationToken cancellationToken) @@ -237,8 +237,8 @@ public override bool TrySimplify( // Don't simplify to predefined type if name is part of a QualifiedName. // QualifiedNames can't contain PredefinedTypeNames (although MemberAccessExpressions can). // In other words, the left side of a QualifiedName can't be a PredefinedTypeName. - var inDeclarationContext = PreferPredefinedTypeKeywordInDeclarations(name, optionSet, semanticModel); - var inMemberAccessContext = PreferPredefinedTypeKeywordInMemberAccess(name, optionSet, semanticModel); + var inDeclarationContext = PreferPredefinedTypeKeywordInDeclarations(name, options, semanticModel); + var inMemberAccessContext = PreferPredefinedTypeKeywordInMemberAccess(name, options, semanticModel); if (!name.Parent.IsKind(SyntaxKind.QualifiedName) && (inDeclarationContext || inMemberAccessContext)) { @@ -713,12 +713,12 @@ private static bool IsInScriptClass(SemanticModel model, NameSyntax name) return false; } - private static bool PreferPredefinedTypeKeywordInDeclarations(NameSyntax name, OptionSet optionSet, SemanticModel semanticModel) + private static bool PreferPredefinedTypeKeywordInDeclarations(NameSyntax name, CSharpSimplifierOptions options, SemanticModel semanticModel) { return !name.IsDirectChildOfMemberAccessExpression() && !name.InsideCrefReference() && !InsideNameOfExpression(name, semanticModel) && - SimplificationHelpers.PreferPredefinedTypeKeywordInDeclarations(optionSet, semanticModel.Language); + options.PreferPredefinedTypeKeywordInDeclaration.Value; } } } diff --git a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/QualifiedCrefSimplifier.cs b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/QualifiedCrefSimplifier.cs index e07e4437db4f5..a1210d65e6307 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/QualifiedCrefSimplifier.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/Simplifiers/QualifiedCrefSimplifier.cs @@ -8,7 +8,6 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; @@ -27,7 +26,7 @@ private QualifiedCrefSimplifier() public override bool TrySimplify( QualifiedCrefSyntax crefSyntax, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, out CrefSyntax replacementNode, out TextSpan issueSpan, CancellationToken cancellationToken) @@ -38,7 +37,7 @@ public override bool TrySimplify( var memberCref = crefSyntax.Member; // Currently we are dealing with only the NameMemberCrefs - if (SimplificationHelpers.PreferPredefinedTypeKeywordInMemberAccess(optionSet, semanticModel.Language) && + if (options.PreferPredefinedTypeKeywordInMemberAccess.Value && memberCref.IsKind(SyntaxKind.NameMemberCref, out NameMemberCrefSyntax nameMemberCref)) { var symbolInfo = semanticModel.GetSymbolInfo(nameMemberCref.Name, cancellationToken); diff --git a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs index aa876c30812af..ad6f7fd99e0d4 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; @@ -81,6 +82,8 @@ private static async Task TestAsync( var formattingOptions = CSharpSyntaxFormattingOptions.Default; + var simplifierOptions = CSharpSimplifierOptions.Default; + var imported = useSymbolAnnotations ? await ImportAdder.AddImportsFromSymbolAnnotationAsync(doc, addImportOptions, CancellationToken.None) : await ImportAdder.AddImportsFromSyntaxesAsync(doc, addImportOptions, CancellationToken.None); @@ -94,7 +97,7 @@ private static async Task TestAsync( if (simplifiedText != null) { - var reduced = await Simplifier.ReduceAsync(imported); + var reduced = await Simplifier.ReduceAsync(imported, simplifierOptions, CancellationToken.None); var formatted = await Formatter.FormatAsync(reduced, SyntaxAnnotation.ElasticAnnotation, formattingOptions, CancellationToken.None); var actualText = (await formatted.GetTextAsync()).ToString(); diff --git a/src/Workspaces/CSharpTest/CodeGeneration/SymbolEditorTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/SymbolEditorTests.cs index e9356e594fce4..4ebd4e27f1a53 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/SymbolEditorTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/SymbolEditorTests.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Simplification; @@ -52,7 +53,7 @@ private static async Task> GetSymbolsAsync(Solution solutio private static async Task GetActualAsync(Document document) { - document = await Simplifier.ReduceAsync(document); + document = await Simplifier.ReduceAsync(document, CSharpSimplifierOptions.Default, CancellationToken.None); document = await Formatter.FormatAsync(document, Formatter.Annotation, CSharpSyntaxFormattingOptions.Default, CancellationToken.None); document = await Formatter.FormatAsync(document, SyntaxAnnotation.ElasticAnnotation, CSharpSyntaxFormattingOptions.Default, CancellationToken.None); return (await document.GetSyntaxRootAsync()).ToFullString(); diff --git a/src/Workspaces/Core/Portable/ChangeNamespace/ChangeNamespaceOptions.cs b/src/Workspaces/Core/Portable/ChangeNamespace/ChangeNamespaceOptions.cs new file mode 100644 index 0000000000000..624e2dfdba43a --- /dev/null +++ b/src/Workspaces/Core/Portable/ChangeNamespace/ChangeNamespaceOptions.cs @@ -0,0 +1,47 @@ +// 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; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.ChangeNamespace; + +[DataContract] +internal readonly record struct ChangeNamespaceOptions( + [property: DataMember(Order = 0)] SyntaxFormattingOptions FormattingOptions, + [property: DataMember(Order = 1)] AddImportPlacementOptions AddImportOptions, + [property: DataMember(Order = 2)] SimplifierOptions SimplifierOptions) +{ + public static async ValueTask FromDocumentAsync(Document document, ChangeNamespaceOptions? fallbackOptions, CancellationToken cancellationToken) + { + var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var addImportsOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions?.SimplifierOptions, cancellationToken).ConfigureAwait(false); + + return new ChangeNamespaceOptions(formattingOptions, addImportsOptions, simplifierOptions); + } + + public static ChangeNamespaceOptions GetDefault(HostLanguageServices languageServices) + { + var formattingOptions = languageServices.GetRequiredService().DefaultOptions; + var addImportsOptions = AddImportPlacementOptions.Default; + var simplifierOptions = languageServices.GetRequiredService().DefaultOptions; + + return new ChangeNamespaceOptions(formattingOptions, addImportsOptions, simplifierOptions); + } + + public static ChangeNamespaceOptionsProvider CreateProvider(CodeActionOptionsProvider options) + => new(languageServices => new ChangeNamespaceOptions( + FormattingOptions: languageServices.GetRequiredService().DefaultOptions, + AddImportOptions: AddImportPlacementOptions.Default, + SimplifierOptions: options(languageServices).SimplifierOptions ?? languageServices.GetRequiredService().DefaultOptions)); +} + +internal delegate ChangeNamespaceOptions ChangeNamespaceOptionsProvider(HostLanguageServices languageServices); diff --git a/src/Workspaces/Core/Portable/Rename/IChangeNamespaceService.cs b/src/Workspaces/Core/Portable/ChangeNamespace/IChangeNamespaceService.cs similarity index 93% rename from src/Workspaces/Core/Portable/Rename/IChangeNamespaceService.cs rename to src/Workspaces/Core/Portable/ChangeNamespace/IChangeNamespaceService.cs index 27bb7f1d81eb4..6992bf3b149fe 100644 --- a/src/Workspaces/Core/Portable/Rename/IChangeNamespaceService.cs +++ b/src/Workspaces/Core/Portable/ChangeNamespace/IChangeNamespaceService.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.ChangeNamespace { @@ -52,12 +53,12 @@ internal interface IChangeNamespaceService : ILanguageService /// If the declared namespace for is already identical to , then it will be /// a no-op and original solution will be returned. /// - Task ChangeNamespaceAsync(Document document, SyntaxNode container, string targetNamespace, CancellationToken cancellationToken); + Task ChangeNamespaceAsync(Document document, SyntaxNode container, string targetNamespace, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); /// /// Using only the top level namespace declarations of a document, change all of them to the target namespace. Will only /// use namespace containers considered valid by /// - Task TryChangeTopLevelNamespacesAsync(Document document, string targetNamespace, CancellationToken cancellationToken); + Task TryChangeTopLevelNamespacesAsync(Document document, string targetNamespace, ChangeNamespaceOptionsProvider options, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs b/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs index 708440802f964..4eea7b3ee3cfe 100644 --- a/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs +++ b/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CaseCorrection; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editing; @@ -309,27 +310,27 @@ protected async Task PostProcessChangesAsync(Solution changedSolution, /// The document changed by the . /// A cancellation token. /// A document with the post processing changes applied. - protected virtual Task PostProcessChangesAsync(Document document, CancellationToken cancellationToken) - => CleanupDocumentAsync(document, cancellationToken); + protected virtual async Task PostProcessChangesAsync(Document document, CancellationToken cancellationToken) + { + var options = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + return await CleanupDocumentAsync(document, options, cancellationToken).ConfigureAwait(false); + } internal static async Task CleanupDocumentAsync( - Document document, CancellationToken cancellationToken) + Document document, CodeCleanupOptions options, CancellationToken cancellationToken) { if (document.SupportsSyntaxTree) { - var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); - document = await ImportAdder.AddImportsFromSymbolAnnotationAsync( - document, Simplifier.AddImportsAnnotation, addImportOptions, cancellationToken).ConfigureAwait(false); + document, Simplifier.AddImportsAnnotation, options.AddImportOptions, cancellationToken).ConfigureAwait(false); - document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false); + document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, options.SimplifierOptions, cancellationToken).ConfigureAwait(false); // format any node with explicit formatter annotation - document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); + document = await Formatter.FormatAsync(document, Formatter.Annotation, options.FormattingOptions, cancellationToken).ConfigureAwait(false); // format any elastic whitespace - document = await Formatter.FormatAsync(document, SyntaxAnnotation.ElasticAnnotation, formattingOptions, cancellationToken).ConfigureAwait(false); + document = await Formatter.FormatAsync(document, SyntaxAnnotation.ElasticAnnotation, options.FormattingOptions, cancellationToken).ConfigureAwait(false); document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Core/Portable/CodeCleanup/AbstractCodeCleanerService.cs b/src/Workspaces/Core/Portable/CodeCleanup/AbstractCodeCleanerService.cs index b9a3a9f39cf3c..70097a479306d 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/AbstractCodeCleanerService.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/AbstractCodeCleanerService.cs @@ -27,7 +27,7 @@ internal abstract class AbstractCodeCleanerService : ICodeCleanerService public abstract ImmutableArray GetDefaultProviders(); protected abstract ImmutableArray GetSpansToAvoid(SyntaxNode root); - public async Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, ImmutableArray providers, CancellationToken cancellationToken) + public async Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, ImmutableArray providers, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.CodeCleanup_CleanupAsync, cancellationToken)) { @@ -455,7 +455,7 @@ private static bool CleanupWholeNode(TextSpan nodeSpan, ImmutableArray private async Task IterateAllCodeCleanupProvidersAsync( Document originalDocument, Document annotatedDocument, - SyntaxFormattingOptions options, + CodeCleanupOptions options, Func> spanGetter, ImmutableArray codeCleaners, CancellationToken cancellationToken) diff --git a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs index aee43fe399a36..e82151c164474 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CodeCleanup { @@ -78,7 +79,8 @@ public static Task CleanupAsync(Document document, TextSpan span, Immu public static async Task CleanupAsync(Document document, ImmutableArray spans, ImmutableArray providers = default, CancellationToken cancellationToken = default) { var cleanupService = document.GetRequiredLanguageService(); - var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var options = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + return await cleanupService.CleanupAsync(document, spans, options, providers, cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs new file mode 100644 index 0000000000000..16be6e9049815 --- /dev/null +++ b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs @@ -0,0 +1,28 @@ +// 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 System.Runtime.Serialization; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.AddImport; + +namespace Microsoft.CodeAnalysis.CodeCleanup +{ + [DataContract] + internal readonly record struct CodeCleanupOptions( + [property: DataMember(Order = 0)] SyntaxFormattingOptions FormattingOptions, + [property: DataMember(Order = 1)] SimplifierOptions SimplifierOptions, + [property: DataMember(Order = 2)] AddImportPlacementOptions AddImportOptions) + { + public static async ValueTask FromDocumentAsync(Document document, CodeCleanupOptions? fallbackOptions, CancellationToken cancellationToken) + { + var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var simplifierOptions = await SimplifierOptions.FromDocumentAsync(document, fallbackOptions?.SimplifierOptions, cancellationToken).ConfigureAwait(false); + var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + return new CodeCleanupOptions(formattingOptions, simplifierOptions, addImportOptions); + } + } +} diff --git a/src/Workspaces/Core/Portable/CodeCleanup/ICodeCleanerService.cs b/src/Workspaces/Core/Portable/CodeCleanup/ICodeCleanerService.cs index f9f47a1551ea9..46e3eb71a1a41 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/ICodeCleanerService.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/ICodeCleanerService.cs @@ -27,7 +27,7 @@ internal interface ICodeCleanerService : ILanguageService /// /// This will run all provided code cleaners in an order that is given to the method. /// - Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, ImmutableArray providers, CancellationToken cancellationToken); + Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, ImmutableArray providers, CancellationToken cancellationToken); /// /// This will run all provided code cleaners in an order that is given to the method. diff --git a/src/Workspaces/Core/Portable/CodeCleanup/Providers/FormatCodeCleanupProvider.cs b/src/Workspaces/Core/Portable/CodeCleanup/Providers/FormatCodeCleanupProvider.cs index 707c1d34a32fa..21831e950b539 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/Providers/FormatCodeCleanupProvider.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/Providers/FormatCodeCleanupProvider.cs @@ -25,11 +25,11 @@ public FormatCodeCleanupProvider(IEnumerable? rules = nu public string Name => PredefinedCodeCleanupProviderNames.Format; - public async Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, CancellationToken cancellationToken) + public async Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, CancellationToken cancellationToken) { var formatter = document.GetRequiredLanguageService(); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var result = formatter.GetFormattingResult(root, spans, options, _rules, cancellationToken); + var result = formatter.GetFormattingResult(root, spans, options.FormattingOptions, _rules, cancellationToken); // apply changes to an old text if it already exists return document.TryGetText(out var oldText) ? diff --git a/src/Workspaces/Core/Portable/CodeCleanup/Providers/ICodeCleanupProvider.cs b/src/Workspaces/Core/Portable/CodeCleanup/Providers/ICodeCleanupProvider.cs index 52f2f2959a1be..04af6177ffb50 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/Providers/ICodeCleanupProvider.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/Providers/ICodeCleanupProvider.cs @@ -24,7 +24,7 @@ internal interface ICodeCleanupProvider /// /// This should apply its code clean up logic to the spans of the document. /// - Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, CancellationToken cancellationToken); + Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, CancellationToken cancellationToken); /// /// This will run all provided code cleaners in an order that is given to the method. diff --git a/src/Workspaces/Core/Portable/CodeCleanup/Providers/SimplificationCodeCleanupProvider.cs b/src/Workspaces/Core/Portable/CodeCleanup/Providers/SimplificationCodeCleanupProvider.cs index 70ea4aefd3909..d96c3b54f8657 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/Providers/SimplificationCodeCleanupProvider.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/Providers/SimplificationCodeCleanupProvider.cs @@ -16,8 +16,8 @@ internal class SimplificationCodeCleanupProvider : ICodeCleanupProvider { public string Name => PredefinedCodeCleanupProviderNames.Simplification; - public Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, CancellationToken cancellationToken) - => Simplifier.ReduceAsync(document, spans, null, cancellationToken); + public Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, CancellationToken cancellationToken) + => Simplifier.ReduceAsync(document, spans, options.SimplifierOptions, cancellationToken); public Task CleanupAsync(SyntaxNode root, ImmutableArray spans, SyntaxFormattingOptions options, HostWorkspaceServices services, CancellationToken cancellationToken) { diff --git a/src/Workspaces/Core/Portable/CodeFixes/CodeFixContext.cs b/src/Workspaces/Core/Portable/CodeFixes/CodeFixContext.cs index 62ebe6c86ce69..2621ebceaf0fd 100644 --- a/src/Workspaces/Core/Portable/CodeFixes/CodeFixContext.cs +++ b/src/Workspaces/Core/Portable/CodeFixes/CodeFixContext.cs @@ -57,7 +57,7 @@ namespace Microsoft.CodeAnalysis.CodeFixes [Obsolete] bool ITypeScriptCodeFixContext.IsBlocking - => Options("TypeScript").IsBlocking; + => Options(Document.Project.LanguageServices).IsBlocking; /// /// Creates a code fix context to be passed into method. diff --git a/src/Workspaces/Core/Portable/CodeRefactorings/CodeRefactoringContext.cs b/src/Workspaces/Core/Portable/CodeRefactorings/CodeRefactoringContext.cs index c2a3f38862c1d..51e14ba5b91b0 100644 --- a/src/Workspaces/Core/Portable/CodeRefactorings/CodeRefactoringContext.cs +++ b/src/Workspaces/Core/Portable/CodeRefactorings/CodeRefactoringContext.cs @@ -35,7 +35,7 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings [Obsolete] bool ITypeScriptCodeRefactoringContext.IsBlocking - => Options("TypeScript").IsBlocking; + => Options(Document.Project.LanguageServices).IsBlocking; private readonly Action _registerRefactoring; diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs index 7d5663897dfb3..07a0d90b694df 100644 --- a/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs +++ b/src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs @@ -28,8 +28,7 @@ namespace Microsoft.CodeAnalysis.Editing /// The trees generated by this API will try to respect user preferences when /// possible. For example, generating /// will be done in a way such that "this." or "Me." will be simplified according to user - /// preference if any - /// overload is called. + /// preference if is used. /// public abstract class SyntaxGenerator : ILanguageService { diff --git a/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs b/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs index 3357cb27e9a84..f72e59031232d 100644 --- a/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs +++ b/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Options { @@ -22,22 +23,22 @@ internal interface IGlobalOptionService /// /// Gets the current value of the specific option. /// - T? GetOption(Option option); + T GetOption(Option option); /// /// Gets the current value of the specific option. /// - T? GetOption(Option2 option); + T GetOption(Option2 option); /// /// Gets the current value of the specific option. /// - T? GetOption(PerLanguageOption option, string? languageName); + T GetOption(PerLanguageOption option, string? languageName); /// /// Gets the current value of the specific option. /// - T? GetOption(PerLanguageOption2 option, string? languageName); + T GetOption(PerLanguageOption2 option, string? languageName); /// /// Gets the current value of the specific option. diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs index 81103af8b8978..507a5c1249a7a 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs @@ -159,8 +159,9 @@ internal async Task SimplifyAsync(Solution solution, IEnumerable.Empty) { _analysis = analysis; + _options = options; } public override string GetDescription(CultureInfo? culture) @@ -42,7 +44,7 @@ public override string GetDescription(CultureInfo? culture) internal override async Task GetModifiedSolutionAsync(Document document, DocumentRenameOptions options, CancellationToken cancellationToken) { var changeNamespaceService = document.GetRequiredLanguageService(); - var solution = await changeNamespaceService.TryChangeTopLevelNamespacesAsync(document, _analysis.TargetNamespace, cancellationToken).ConfigureAwait(false); + var solution = await changeNamespaceService.TryChangeTopLevelNamespacesAsync(document, _analysis.TargetNamespace, _options, cancellationToken).ConfigureAwait(false); // If the solution fails to update fail silently. The user will see no large // negative impact from not doing this modification, and it's possible the document @@ -50,13 +52,13 @@ internal override async Task GetModifiedSolutionAsync(Document documen return solution ?? document.Project.Solution; } - public static SyncNamespaceDocumentAction? TryCreate(Document document, IReadOnlyList newFolders, CancellationToken _) + public static SyncNamespaceDocumentAction? TryCreate(Document document, IReadOnlyList newFolders, ChangeNamespaceOptionsProvider options) { var analysisResult = Analyze(document, newFolders); if (analysisResult.HasValue) { - return new SyncNamespaceDocumentAction(analysisResult.Value); + return new SyncNamespaceDocumentAction(analysisResult.Value, options); } return null; diff --git a/src/Workspaces/Core/Portable/Rename/Renamer.cs b/src/Workspaces/Core/Portable/Rename/Renamer.cs index 163084fbccf22..7dc73d80dc5db 100644 --- a/src/Workspaces/Core/Portable/Rename/Renamer.cs +++ b/src/Workspaces/Core/Portable/Rename/Renamer.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Options; @@ -89,18 +90,24 @@ public static Task RenameDocumentAsync( /// The new name for the document. Pass null or the same name to keep unchanged. /// Options used to configure rename of a type contained in the document that matches the document's name. /// The new set of folders for the property - public static async Task RenameDocumentAsync( - Document document, + public static Task RenameDocumentAsync( + Document document!!, DocumentRenameOptions options, string? newDocumentName, IReadOnlyList? newDocumentFolders = null, CancellationToken cancellationToken = default) { - if (document is null) - { - throw new ArgumentNullException(nameof(document)); - } + return RenameDocumentAsync(document, options, ChangeNamespaceOptions.GetDefault, newDocumentName, newDocumentFolders, cancellationToken); + } + internal static async Task RenameDocumentAsync( + Document document, + DocumentRenameOptions options, + ChangeNamespaceOptionsProvider changeNamespaceOptions, + string? newDocumentName, + IReadOnlyList? newDocumentFolders, + CancellationToken cancellationToken) + { if (document.Services.GetService() != null) { // Don't advertise that we can file rename generated documents that map to a different file. @@ -117,7 +124,7 @@ public static async Task RenameDocumentAsync( if (newDocumentFolders != null && !newDocumentFolders.SequenceEqual(document.Folders)) { - var action = SyncNamespaceDocumentAction.TryCreate(document, newDocumentFolders, cancellationToken); + var action = SyncNamespaceDocumentAction.TryCreate(document, newDocumentFolders, changeNamespaceOptions); actions.AddIfNotNull(action); } diff --git a/src/Workspaces/Core/Portable/Simplification/AbstractReducer.IExpressionRewriter.cs b/src/Workspaces/Core/Portable/Simplification/AbstractReducer.IExpressionRewriter.cs index ab9cb2469b38f..5a46962ab857d 100644 --- a/src/Workspaces/Core/Portable/Simplification/AbstractReducer.IExpressionRewriter.cs +++ b/src/Workspaces/Core/Portable/Simplification/AbstractReducer.IExpressionRewriter.cs @@ -6,7 +6,6 @@ using System; using System.Threading; -using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.Simplification { @@ -14,7 +13,7 @@ internal abstract partial class AbstractReducer { internal interface IReductionRewriter : IDisposable { - void Initialize(ParseOptions parseOptions, OptionSet optionSet, CancellationToken cancellationToken); + void Initialize(ParseOptions parseOptions, SimplifierOptions options, CancellationToken cancellationToken); SyntaxNodeOrToken VisitNodeOrToken(SyntaxNodeOrToken nodeOrTokenToReduce, SemanticModel semanticModel, bool simplifyAllDescendants); diff --git a/src/Workspaces/Core/Portable/Simplification/AbstractReducer.cs b/src/Workspaces/Core/Portable/Simplification/AbstractReducer.cs index 1f8b033d556a1..909f59b0b110a 100644 --- a/src/Workspaces/Core/Portable/Simplification/AbstractReducer.cs +++ b/src/Workspaces/Core/Portable/Simplification/AbstractReducer.cs @@ -4,7 +4,6 @@ #nullable disable -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.Simplification @@ -19,6 +18,6 @@ protected AbstractReducer(ObjectPool pool) public IReductionRewriter GetOrCreateRewriter() => _pool.Allocate(); - public virtual bool IsApplicable(OptionSet optionSet) => true; + public abstract bool IsApplicable(SimplifierOptions options); } } diff --git a/src/Workspaces/Core/Portable/Simplification/AbstractSimplificationService.cs b/src/Workspaces/Core/Portable/Simplification/AbstractSimplificationService.cs index 3bc29b86ea608..5218bae207e0c 100644 --- a/src/Workspaces/Core/Portable/Simplification/AbstractSimplificationService.cs +++ b/src/Workspaces/Core/Portable/Simplification/AbstractSimplificationService.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -12,17 +10,14 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Collections; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; -#if DEBUG -using Microsoft.CodeAnalysis.Shared.Extensions; -#endif - namespace Microsoft.CodeAnalysis.Simplification { internal abstract class AbstractSimplificationService : ISimplificationService @@ -42,16 +37,19 @@ protected AbstractSimplificationService(ImmutableArray reducers protected abstract SemanticModel GetSpeculativeSemanticModel(ref SyntaxNode nodeToSpeculate, SemanticModel originalSemanticModel, SyntaxNode originalNode); protected abstract bool NodeRequiresNonSpeculativeSemanticModel(SyntaxNode node); + public abstract SimplifierOptions DefaultOptions { get; } + public abstract SimplifierOptions GetSimplifierOptions(AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions); + protected virtual SyntaxNode TransformReducedNode(SyntaxNode reducedNode, SyntaxNode originalNode) => reducedNode; - public abstract SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation annotationForReplacedAliasIdentifier, Func expandInsideNode, bool expandParameter, CancellationToken cancellationToken); - public abstract SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel, Func expandInsideNode, CancellationToken cancellationToken); + public abstract SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation? annotationForReplacedAliasIdentifier, Func? expandInsideNode, bool expandParameter, CancellationToken cancellationToken); + public abstract SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel, Func? expandInsideNode, CancellationToken cancellationToken); public async Task ReduceAsync( Document document, ImmutableArray spans, - OptionSet optionSet = null, + SimplifierOptions options, ImmutableArray reducers = default, CancellationToken cancellationToken = default) { @@ -65,9 +63,7 @@ public async Task ReduceAsync( return document; } - optionSet ??= await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); // Chaining of the Speculative SemanticModel (i.e. Generating a speculative SemanticModel from an existing Speculative SemanticModel) is not supported // Hence make sure we always start working off of the actual SemanticModel instead of a speculative SemanticModel. @@ -79,7 +75,7 @@ public async Task ReduceAsync( var originalDocHasErrors = await document.HasAnyErrorsAsync(cancellationToken).ConfigureAwait(false); #endif - var reduced = await this.ReduceCoreAsync(document, spanList, optionSet, reducers, cancellationToken).ConfigureAwait(false); + var reduced = await this.ReduceCoreAsync(document, spanList, options, reducers, cancellationToken).ConfigureAwait(false); if (reduced != document) { @@ -98,7 +94,7 @@ public async Task ReduceAsync( private async Task ReduceCoreAsync( Document document, ImmutableArray spans, - OptionSet optionSet, + SimplifierOptions options, ImmutableArray reducers, CancellationToken cancellationToken) { @@ -108,7 +104,7 @@ private async Task ReduceCoreAsync( bool isNodeOrTokenOutsideSimplifySpans(SyntaxNodeOrToken nodeOrToken) => !spansTree.HasIntervalThatOverlapsWith(nodeOrToken.FullSpan.Start, nodeOrToken.FullSpan.Length); - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // prep namespace imports marked for simplification @@ -120,7 +116,7 @@ bool isNodeOrTokenOutsideSimplifySpans(SyntaxNodeOrToken nodeOrToken) => if (hasImportsToSimplify) { document = document.WithSyntaxRoot(root); - semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); root = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); } @@ -137,7 +133,7 @@ bool isNodeOrTokenOutsideSimplifySpans(SyntaxNodeOrToken nodeOrToken) => // Take out any reducers that don't even apply with the current // set of users options. i.e. no point running 'reduce to var' // if the user doesn't have the 'var' preference set. - reducers = reducers.WhereAsArray(r => r.IsApplicable(optionSet)); + reducers = reducers.WhereAsArray(r => r.IsApplicable(options)); var reducedNodesMap = new ConcurrentDictionary(); var reducedTokensMap = new ConcurrentDictionary(); @@ -145,7 +141,7 @@ bool isNodeOrTokenOutsideSimplifySpans(SyntaxNodeOrToken nodeOrToken) => // Reduce all the nodesAndTokensToReduce using the given reducers/rewriters and // store the reduced nodes and/or tokens in the reduced nodes/tokens maps. // Note that this method doesn't update the original syntax tree. - await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, optionSet, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false); + await this.ReduceAsync(document, root, nodesAndTokensToReduce, reducers, options, semanticModel, reducedNodesMap, reducedTokensMap, cancellationToken).ConfigureAwait(false); if (reducedNodesMap.Any() || reducedTokensMap.Any()) { @@ -176,7 +172,7 @@ private async Task ReduceAsync( SyntaxNode root, ImmutableArray nodesAndTokensToReduce, ImmutableArray reducers, - OptionSet optionSet, + SimplifierOptions options, SemanticModel semanticModel, ConcurrentDictionary reducedNodesMap, ConcurrentDictionary reducedTokensMap, @@ -205,7 +201,7 @@ private async Task ReduceAsync( cancellationToken.ThrowIfCancellationRequested(); using var rewriter = reducer.GetOrCreateRewriter(); - rewriter.Initialize(document.Project.ParseOptions, optionSet, cancellationToken); + rewriter.Initialize(document.Project.ParseOptions, options, cancellationToken); do { @@ -228,7 +224,7 @@ private async Task ReduceAsync( currentNodeOrToken = currentNodeOrToken.WithAdditionalAnnotations(annotation); var replacedParent = isNode ? - nodeOrToken.Parent.ReplaceNode(nodeOrToken.AsNode(), currentNodeOrToken.AsNode()) : + nodeOrToken.Parent.ReplaceNode(nodeOrToken.AsNode()!, currentNodeOrToken.AsNode()!) : nodeOrToken.Parent.ReplaceToken(nodeOrToken.AsToken(), currentNodeOrToken.AsToken()); currentNodeOrToken = replacedParent @@ -238,21 +234,21 @@ private async Task ReduceAsync( if (isNode) { - var currentNode = currentNodeOrToken.AsNode(); - if (this.NodeRequiresNonSpeculativeSemanticModel(nodeOrToken.AsNode())) + var currentNode = currentNodeOrToken.AsNode()!; + if (this.NodeRequiresNonSpeculativeSemanticModel(nodeOrToken.AsNode()!)) { // Since this node cannot be speculated, we are replacing the Document with the changes and get a new SemanticModel var marker = new SyntaxAnnotation(); - var newRoot = root.ReplaceNode(nodeOrToken.AsNode(), currentNode.WithAdditionalAnnotations(marker)); + var newRoot = root.ReplaceNode(nodeOrToken.AsNode()!, currentNode.WithAdditionalAnnotations(marker)); var newDocument = document.WithSyntaxRoot(newRoot); - semanticModelForReduce = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + semanticModelForReduce = await newDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); newRoot = await semanticModelForReduce.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); currentNodeOrToken = newRoot.DescendantNodes().Single(c => c.HasAnnotation(marker)); } else { // Create speculative semantic model for simplified node. - semanticModelForReduce = GetSpeculativeSemanticModel(ref currentNode, semanticModel, nodeOrToken.AsNode()); + semanticModelForReduce = GetSpeculativeSemanticModel(ref currentNode, semanticModel, nodeOrToken.AsNode()!); currentNodeOrToken = currentNode; } } @@ -269,7 +265,7 @@ private async Task ReduceAsync( { if (isNode) { - reducedNodesMap[nodeOrToken.AsNode()] = currentNodeOrToken.AsNode(); + reducedNodesMap[nodeOrToken.AsNode()!] = currentNodeOrToken.AsNode()!; } else { @@ -308,7 +304,7 @@ private async Task RemoveUnusedNamespaceImportsAsync( SyntaxAnnotation removeIfUnusedAnnotation, CancellationToken cancellationToken) { - var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var addedImports = root.GetAnnotatedNodes(removeIfUnusedAnnotation); var unusedImports = new HashSet(); diff --git a/src/Workspaces/Core/Portable/Simplification/ISimplificationService.cs b/src/Workspaces/Core/Portable/Simplification/ISimplificationService.cs index 5ad425b96df6b..aab4d215fc2c7 100644 --- a/src/Workspaces/Core/Portable/Simplification/ISimplificationService.cs +++ b/src/Workspaces/Core/Portable/Simplification/ISimplificationService.cs @@ -2,38 +2,39 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Simplification { internal interface ISimplificationService : ILanguageService { + SimplifierOptions DefaultOptions { get; } + SimplifierOptions GetSimplifierOptions(AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions); + SyntaxNode Expand( SyntaxNode node, SemanticModel semanticModel, - SyntaxAnnotation annotationForReplacedAliasIdentifier, - Func expandInsideNode, + SyntaxAnnotation? annotationForReplacedAliasIdentifier, + Func? expandInsideNode, bool expandParameter, CancellationToken cancellationToken); SyntaxToken Expand( SyntaxToken token, SemanticModel semanticModel, - Func expandInsideNode, + Func? expandInsideNode, CancellationToken cancellationToken); Task ReduceAsync( Document document, ImmutableArray spans, - OptionSet optionSet = null, + SimplifierOptions options, ImmutableArray reducers = default, CancellationToken cancellationToken = default); } diff --git a/src/Workspaces/Core/Portable/Simplification/Simplifier.cs b/src/Workspaces/Core/Portable/Simplification/Simplifier.cs index e26c903fa565e..a2e5295f7ebac 100644 --- a/src/Workspaces/Core/Portable/Simplification/Simplifier.cs +++ b/src/Workspaces/Core/Portable/Simplification/Simplifier.cs @@ -145,7 +145,15 @@ public static async Task ReduceAsync(Document document, OptionSet? opt } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); +#pragma warning disable RS0030 // Do not used banned APIs return await ReduceAsync(document, root.FullSpan, optionSet, cancellationToken).ConfigureAwait(false); +#pragma warning restore + } + + internal static async Task ReduceAsync(Document document, SimplifierOptions options, CancellationToken cancellationToken) + { + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + return await ReduceAsync(document, root.FullSpan, options, cancellationToken).ConfigureAwait(false); } /// @@ -165,7 +173,15 @@ public static async Task ReduceAsync(Document document, SyntaxAnnotati } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); +#pragma warning disable RS0030 // Do not used banned APIs return await ReduceAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(t => t.FullSpan), optionSet, cancellationToken).ConfigureAwait(false); +#pragma warning restore + } + + internal static async Task ReduceAsync(Document document, SyntaxAnnotation annotation, SimplifierOptions options, CancellationToken cancellationToken) + { + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + return await ReduceAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(t => t.FullSpan), options, cancellationToken).ConfigureAwait(false); } /// @@ -179,14 +195,19 @@ public static Task ReduceAsync(Document document, TextSpan span, Optio throw new ArgumentNullException(nameof(document)); } +#pragma warning disable RS0030 // Do not used banned APIs return ReduceAsync(document, SpecializedCollections.SingletonEnumerable(span), optionSet, cancellationToken); } +#pragma warning restore + + internal static Task ReduceAsync(Document document, TextSpan span, SimplifierOptions options, CancellationToken cancellationToken) + => ReduceAsync(document, SpecializedCollections.SingletonEnumerable(span), options, cancellationToken); /// /// Reduce the sub-trees annotated with found within the specified spans. /// The annotated node and all child nodes will be reduced. /// - public static Task ReduceAsync(Document document, IEnumerable spans, OptionSet? optionSet = null, CancellationToken cancellationToken = default) + public static async Task ReduceAsync(Document document, IEnumerable spans, OptionSet? optionSet = null, CancellationToken cancellationToken = default) { if (document == null) { @@ -198,17 +219,30 @@ public static Task ReduceAsync(Document document, IEnumerable().ReduceAsync( - document, spans.ToImmutableArrayOrEmpty(), optionSet, cancellationToken: cancellationToken); + var options = await GetOptionsAsync(document, optionSet, cancellationToken).ConfigureAwait(false); + + return await document.GetRequiredLanguageService().ReduceAsync( + document, spans.ToImmutableArrayOrEmpty(), options, reducers: default, cancellationToken).ConfigureAwait(false); } + internal static Task ReduceAsync(Document document, IEnumerable spans, SimplifierOptions options, CancellationToken cancellationToken) + => document.GetRequiredLanguageService().ReduceAsync( + document, spans.ToImmutableArrayOrEmpty(), options, reducers: default, cancellationToken); + internal static async Task ReduceAsync( - Document document, ImmutableArray reducers, OptionSet? optionSet = null, CancellationToken cancellationToken = default) + Document document, ImmutableArray reducers, SimplifierOptions options, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return await document.GetRequiredLanguageService() - .ReduceAsync(document, ImmutableArray.Create(root.FullSpan), optionSet, + .ReduceAsync(document, ImmutableArray.Create(root.FullSpan), options, reducers, cancellationToken).ConfigureAwait(false); } + + internal static async Task GetOptionsAsync(Document document, OptionSet? optionSet, CancellationToken cancellationToken) + { + return (optionSet != null) ? + SimplifierOptions.Create(optionSet, document.Project.Solution.Workspace.Services, fallbackOptions: null, document.Project.Language) : + await SimplifierOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + } } } diff --git a/src/Workspaces/Core/Portable/Simplification/Simplifiers/AbstractSimplifier.cs b/src/Workspaces/Core/Portable/Simplification/Simplifiers/AbstractSimplifier.cs index 8c828b8c0da39..2ffccd11d95d1 100644 --- a/src/Workspaces/Core/Portable/Simplification/Simplifiers/AbstractSimplifier.cs +++ b/src/Workspaces/Core/Portable/Simplification/Simplifiers/AbstractSimplifier.cs @@ -5,19 +5,19 @@ #nullable disable using System.Threading; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Simplification.Simplifiers { - internal abstract class AbstractSimplifier + internal abstract class AbstractSimplifier where TSyntax : SyntaxNode where TSimplifiedSyntax : SyntaxNode + where TSimplifierOptions : SimplifierOptions { public abstract bool TrySimplify( TSyntax syntax, SemanticModel semanticModel, - OptionSet optionSet, + TSimplifierOptions options, out TSimplifiedSyntax replacementNode, out TextSpan issueSpan, CancellationToken cancellationToken); diff --git a/src/Workspaces/CoreTest/CodeCleanup/MockCodeCleanupProvider.cs b/src/Workspaces/CoreTest/CodeCleanup/MockCodeCleanupProvider.cs index 15195e451f58d..27bb54693dd23 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/MockCodeCleanupProvider.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/MockCodeCleanupProvider.cs @@ -6,10 +6,10 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeCleanup.Providers; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.UnitTests.CodeCleanup @@ -25,8 +25,8 @@ public MockCodeCleanupProvider() public string Name => nameof(MockCodeCleanupProvider); - public Task CleanupAsync(Document document, ImmutableArray spans, SyntaxFormattingOptions options, CancellationToken cancellationToken) - => (CleanupDocumentAsyncImpl ?? throw new NotImplementedException()).Invoke(document, spans, options, cancellationToken); + public Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, CancellationToken cancellationToken) + => (CleanupDocumentAsyncImpl ?? throw new NotImplementedException()).Invoke(document, spans, options.FormattingOptions, cancellationToken); public Task CleanupAsync(SyntaxNode root, ImmutableArray spans, SyntaxFormattingOptions options, HostWorkspaceServices services, CancellationToken cancellationToken) => Task.FromResult((CleanupNodeImpl ?? throw new NotImplementedException()).Invoke(root, spans, options, services)); diff --git a/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs b/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs index 94c0c22680e45..ed40d5cc5dd75 100644 --- a/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs +++ b/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs @@ -15,6 +15,7 @@ using System.Threading; using System.Threading.Tasks; using MessagePack; +using MessagePack.Formatters; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -153,6 +154,19 @@ public void TypesUsedInRemoteApisMustBeMessagePackSerializable() { errors.Add($"{type} referenced by {declaringMember} is an internal enum and needs a custom formatter"); } + else if (type.IsAbstract) + { + // custom abstract types must be explicitly listed in MessagePackFormatters.AbstractTypeFormatters + if (!MessagePackFormatters.Formatters.Any( + formatter => formatter.GetType() is { IsGenericType: true } and var formatterType && + formatterType.GetGenericTypeDefinition() == typeof(ForceTypelessFormatter<>) && + formatterType.GenericTypeArguments[0] == type)) + { + errors.Add($"{type} referenced by {declaringMember} is abstract but ForceTypelessFormatter<{type}> is not listed in {nameof(MessagePackFormatters)}.{nameof(MessagePackFormatters.Formatters)}"); + } + + continue; + } else { errors.Add($"{type} referenced by {declaringMember} failed to serialize with exception: {e}"); diff --git a/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs b/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs new file mode 100644 index 0000000000000..c4849e3621f84 --- /dev/null +++ b/src/Workspaces/CoreTest/Simplifier/SimplifierTests.cs @@ -0,0 +1,159 @@ +// 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.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Simplification; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.VisualBasic.Simplification; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.Simplification; + +[UseExportProvider] +[Trait(Traits.Feature, Traits.Features.Simplification)] +public class SimplifierTests +{ + private static Document GetDocument() + { + var workspace = new AdhocWorkspace(); + var project = workspace.AddProject("CSharpTest", LanguageNames.CSharp); + return workspace.AddDocument(project.Id, "CSharpFile.cs", SourceText.From("class C { }")); + } + + [Fact] + public async Task ExpandAsync_BadArguments() + { + var node = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Test")); + var semanticModel = await GetDocument().GetRequiredSemanticModelAsync(CancellationToken.None); + + await Assert.ThrowsAsync("node", () => Simplifier.ExpandAsync(node: null!, document: null!)); + await Assert.ThrowsAsync("document", () => Simplifier.ExpandAsync(node: node, document: null!)); + await Assert.ThrowsAsync("document", () => Simplifier.ExpandAsync(token: default, document: null!)); + } + + [Fact] + public async Task Expand_BadArguments() + { + var node = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("Test")); + var semanticModel = await GetDocument().GetRequiredSemanticModelAsync(CancellationToken.None); + + Assert.Throws("node", () => Simplifier.Expand(node: null!, semanticModel: null!, workspace: null!)); + Assert.Throws("semanticModel", () => Simplifier.Expand(node, semanticModel: null!, workspace: null!)); + Assert.Throws("workspace", () => Simplifier.Expand(node, semanticModel, workspace: null!)); + Assert.Throws("semanticModel", () => Simplifier.Expand(token: default, semanticModel: null!, workspace: null!)); + Assert.Throws("workspace", () => Simplifier.Expand(token: default, semanticModel, workspace: null!)); + } + + [Fact] + public async Task ReduceAsync_BadArguments() + { + var document = GetDocument(); + +#pragma warning disable RS0030 // Do not used banned APIs + await Assert.ThrowsAsync("document", () => Simplifier.ReduceAsync(document: null!)); + await Assert.ThrowsAsync("document", () => Simplifier.ReduceAsync(document: null!, annotation: null!)); + await Assert.ThrowsAsync("annotation", () => Simplifier.ReduceAsync(document, annotation: null!)); + await Assert.ThrowsAsync("document", () => Simplifier.ReduceAsync(document: null!, span: default)); + await Assert.ThrowsAsync("document", () => Simplifier.ReduceAsync(document: null!, spans: null!)); + await Assert.ThrowsAsync("spans", () => Simplifier.ReduceAsync(document, spans: null!)); +#pragma warning restore + } + + [Fact] + public async Task ReduceAsync_Options() + { + using var workspace = new AdhocWorkspace(); + var csProject = workspace.AddProject("CS", LanguageNames.CSharp); + var vbProject = workspace.AddProject("VB", LanguageNames.VisualBasic); + var csDocument = workspace.AddDocument(csProject.Id, "File.cs", SourceText.From("class C { }")); + var vbDocument = workspace.AddDocument(vbProject.Id, "File.vb", SourceText.From("Class C : End Class")); + + var updatedOptions = GetOptionSetWithChangedPublicOptions(workspace.CurrentSolution.Options); + + // Validate that options are read from specified OptionSet: + + ValidateCSharpOptions((CSharpSimplifierOptions)await Simplifier.GetOptionsAsync(csDocument, updatedOptions, CancellationToken.None)); + ValidateVisualBasicOptions((VisualBasicSimplifierOptions)await Simplifier.GetOptionsAsync(vbDocument, updatedOptions, CancellationToken.None)); + + // Validate that options are read from solution snapshot as a fallback (we have no editorconfig file, so all options should fall back): + + var solutionWithUpdatedOptions = workspace.CurrentSolution.WithOptions(updatedOptions); + var csDocumentWithUpdatedOptions = solutionWithUpdatedOptions.GetRequiredDocument(csDocument.Id); + var vbDocumentWithUpdatedOptions = solutionWithUpdatedOptions.GetRequiredDocument(vbDocument.Id); + + ValidateCSharpOptions((CSharpSimplifierOptions)await Simplifier.GetOptionsAsync(csDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)); + ValidateVisualBasicOptions((VisualBasicSimplifierOptions)await Simplifier.GetOptionsAsync(vbDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)); + + static OptionSet GetOptionSetWithChangedPublicOptions(OptionSet options) + { + // all public options and their non-default values: + + var publicOptions = new (IOption, object)[] + { + (CodeStyleOptions.QualifyFieldAccess, false), + (CodeStyleOptions.QualifyPropertyAccess, false), + (CodeStyleOptions.QualifyMethodAccess, false), + (CodeStyleOptions.QualifyEventAccess, false), + (CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, false), + (CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, false), + (CSharpCodeStyleOptions.VarForBuiltInTypes, false), + (CSharpCodeStyleOptions.VarWhenTypeIsApparent, false), + (CSharpCodeStyleOptions.VarElsewhere, false), + (CSharpCodeStyleOptions.PreferSimpleDefaultExpression, false), + (CSharpCodeStyleOptions.PreferBraces, PreferBracesPreference.WhenMultiline), + }; + + var updatedOptions = options; + foreach (var (option, newValue) in publicOptions) + { + var languages = (option is IPerLanguageOption) ? new[] { LanguageNames.CSharp, LanguageNames.VisualBasic } : new string?[] { null }; + + foreach (var language in languages) + { + var key = new OptionKey(option, language); + var current = (ICodeStyleOption)options.GetOption(key)!; + updatedOptions = updatedOptions.WithChangedOption(key, current.WithValue(newValue)); + } + } + + return updatedOptions; + } + + static void ValidateCommonOptions(SimplifierOptions simplifierOptions) + { + Assert.False(simplifierOptions.QualifyFieldAccess.Value); + Assert.False(simplifierOptions.QualifyPropertyAccess.Value); + Assert.False(simplifierOptions.QualifyMethodAccess.Value); + Assert.False(simplifierOptions.QualifyEventAccess.Value); + Assert.False(simplifierOptions.PreferPredefinedTypeKeywordInMemberAccess.Value); + Assert.False(simplifierOptions.PreferPredefinedTypeKeywordInDeclaration.Value); + } + + static void ValidateCSharpOptions(CSharpSimplifierOptions simplifierOptions) + { + ValidateCommonOptions(simplifierOptions); + + Assert.False(simplifierOptions.VarForBuiltInTypes.Value); + Assert.False(simplifierOptions.VarWhenTypeIsApparent.Value); + Assert.False(simplifierOptions.VarElsewhere.Value); + Assert.False(simplifierOptions.PreferSimpleDefaultExpression.Value); + Assert.Equal(PreferBracesPreference.WhenMultiline, simplifierOptions.PreferBraces.Value); + } + + static void ValidateVisualBasicOptions(VisualBasicSimplifierOptions simplifierOptions) + { + ValidateCommonOptions(simplifierOptions); + } + } +} diff --git a/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs b/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs index 18dc308593fac..bebad327e4f4b 100644 --- a/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs +++ b/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs @@ -8,6 +8,8 @@ using MessagePack; using MessagePack.Formatters; using MessagePack.Resolvers; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote @@ -18,18 +20,22 @@ namespace Microsoft.CodeAnalysis.Remote /// internal sealed class MessagePackFormatters { - private static readonly ImmutableArray s_formatters = ImmutableArray.Create( + internal static readonly ImmutableArray Formatters = ImmutableArray.Create( SolutionIdFormatter.Instance, ProjectIdFormatter.Instance, - DocumentIdFormatter.Instance); + DocumentIdFormatter.Instance, + // ForceTypelessFormatter needs to be listed here for each Roslyn abstract type T that is being serialized OOP. + // TODO: add a resolver that provides these https://github.com/dotnet/roslyn/issues/60724 + new ForceTypelessFormatter(), + new ForceTypelessFormatter()); private static readonly ImmutableArray s_resolvers = ImmutableArray.Create( StandardResolverAllowPrivate.Instance); - internal static readonly IFormatterResolver DefaultResolver = CompositeResolver.Create(s_formatters, s_resolvers); + internal static readonly IFormatterResolver DefaultResolver = CompositeResolver.Create(Formatters, s_resolvers); internal static IFormatterResolver CreateResolver(ImmutableArray additionalFormatters, ImmutableArray additionalResolvers) - => (additionalFormatters.IsEmpty && additionalResolvers.IsEmpty) ? DefaultResolver : CompositeResolver.Create(s_formatters.AddRange(additionalFormatters), s_resolvers.AddRange(additionalResolvers)); + => (additionalFormatters.IsEmpty && additionalResolvers.IsEmpty) ? DefaultResolver : CompositeResolver.Create(Formatters.AddRange(additionalFormatters), s_resolvers.AddRange(additionalResolvers)); internal sealed class SolutionIdFormatter : IMessagePackFormatter { diff --git a/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs b/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs index fb0b5cb700709..188a9b4f787d9 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ConvertTupleToStructCodeRefactoringProvider/RemoteConvertTupleToStructCodeRefactoringService.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.ConvertTupleToStruct; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -79,8 +80,11 @@ private static async Task CleanupAsync(Solution oldSolution, Solution foreach (var docId in changes) { - var cleaned = await CodeAction.CleanupDocumentAsync( - newSolution.GetDocument(docId), cancellationToken).ConfigureAwait(false); + var document = newSolution.GetDocument(docId); + + var options = await CodeCleanupOptions.FromDocumentAsync(document, fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var cleaned = await CodeAction.CleanupDocumentAsync(document, options, cancellationToken).ConfigureAwait(false); + var cleanedRoot = await cleaned.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); final = final.WithDocumentSyntaxRoot(docId, cleanedRoot); } diff --git a/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs b/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs index db5f56e87ed84..a2c9ca8e15c9e 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/EncapsulateField/RemoteEncapsulateFieldService.cs @@ -32,6 +32,7 @@ public RemoteEncapsulateFieldService(in ServiceConstructionArguments arguments) PinnedSolutionInfo solutionInfo, DocumentId documentId, ImmutableArray fieldSymbolKeys, + EncapsulateFieldOptions fallbackOptions, bool updateReferences, CancellationToken cancellationToken) { @@ -54,7 +55,7 @@ public RemoteEncapsulateFieldService(in ServiceConstructionArguments arguments) var service = document.GetLanguageService(); var newSolution = await service.EncapsulateFieldsAsync( - document, fields.ToImmutable(), updateReferences, cancellationToken).ConfigureAwait(false); + document, fields.ToImmutable(), fallbackOptions, updateReferences, cancellationToken).ConfigureAwait(false); return await RemoteUtilities.GetDocumentTextChangesAsync( solution, newSolution, cancellationToken).ConfigureAwait(false); }, cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems index 5cdd4a00dc47c..4d82ba5af601d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems @@ -102,6 +102,7 @@ + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs index 974186ddbd5c5..0eebd58006a10 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs @@ -35,6 +35,9 @@ internal class CSharpSyntaxFormatting : AbstractSyntaxFormatting public override ImmutableArray GetDefaultFormattingRules() => _rules; + public override SyntaxFormattingOptions DefaultOptions + => CSharpSyntaxFormattingOptions.Default; + public override SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options) => CSharpSyntaxFormattingOptions.Create(options); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs new file mode 100644 index 0000000000000..e5fa3865c875e --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs @@ -0,0 +1,90 @@ +// 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.Runtime.Serialization; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.CSharp.Simplification +{ + [DataContract] + internal sealed class CSharpSimplifierOptions : SimplifierOptions + { + [DataMember(Order = BaseMemberCount + 0)] + public readonly CodeStyleOption2 VarForBuiltInTypes; + + [DataMember(Order = BaseMemberCount + 1)] + public readonly CodeStyleOption2 VarWhenTypeIsApparent; + + [DataMember(Order = BaseMemberCount + 2)] + public readonly CodeStyleOption2 VarElsewhere; + + [DataMember(Order = BaseMemberCount + 3)] + public readonly CodeStyleOption2 PreferSimpleDefaultExpression; + + [DataMember(Order = BaseMemberCount + 4)] + public readonly CodeStyleOption2 PreferBraces; + + public CSharpSimplifierOptions( + CodeStyleOption2? qualifyFieldAccess = null, + CodeStyleOption2? qualifyPropertyAccess = null, + CodeStyleOption2? qualifyMethodAccess = null, + CodeStyleOption2? qualifyEventAccess = null, + CodeStyleOption2? preferPredefinedTypeKeywordInMemberAccess = null, + CodeStyleOption2? preferPredefinedTypeKeywordInDeclaration = null, + CodeStyleOption2? varForBuiltInTypes = null, + CodeStyleOption2? varWhenTypeIsApparent = null, + CodeStyleOption2? varElsewhere = null, + CodeStyleOption2? preferSimpleDefaultExpression = null, + CodeStyleOption2? preferBraces = null) + : base( + qualifyFieldAccess: qualifyFieldAccess ?? Default.QualifyFieldAccess, + qualifyPropertyAccess: qualifyPropertyAccess ?? Default.QualifyPropertyAccess, + qualifyMethodAccess: qualifyMethodAccess ?? Default.QualifyMethodAccess, + qualifyEventAccess: qualifyEventAccess ?? Default.QualifyEventAccess, + preferPredefinedTypeKeywordInMemberAccess: preferPredefinedTypeKeywordInMemberAccess ?? Default.PreferPredefinedTypeKeywordInMemberAccess, + preferPredefinedTypeKeywordInDeclaration: preferPredefinedTypeKeywordInDeclaration ?? Default.PreferPredefinedTypeKeywordInDeclaration) + { + VarForBuiltInTypes = varForBuiltInTypes ?? Default.VarForBuiltInTypes; + VarWhenTypeIsApparent = varWhenTypeIsApparent ?? Default.VarWhenTypeIsApparent; + VarElsewhere = varElsewhere ?? Default.VarElsewhere; + PreferSimpleDefaultExpression = preferSimpleDefaultExpression ?? Default.PreferSimpleDefaultExpression; + PreferBraces = preferBraces ?? Default.PreferBraces; + } + + public static readonly CSharpSimplifierOptions Default = new( + qualifyFieldAccess: CodeStyleOptions2.QualifyFieldAccess.DefaultValue, + qualifyPropertyAccess: CodeStyleOptions2.QualifyPropertyAccess.DefaultValue, + qualifyMethodAccess: CodeStyleOptions2.QualifyMethodAccess.DefaultValue, + qualifyEventAccess: CodeStyleOptions2.QualifyEventAccess.DefaultValue, + preferPredefinedTypeKeywordInMemberAccess: CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess.DefaultValue, + preferPredefinedTypeKeywordInDeclaration: CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration.DefaultValue, + varForBuiltInTypes: CSharpCodeStyleOptions.VarForBuiltInTypes.DefaultValue, + varWhenTypeIsApparent: CSharpCodeStyleOptions.VarWhenTypeIsApparent.DefaultValue, + varElsewhere: CSharpCodeStyleOptions.VarElsewhere.DefaultValue, + preferSimpleDefaultExpression: CSharpCodeStyleOptions.PreferSimpleDefaultExpression.DefaultValue, + preferBraces: CSharpCodeStyleOptions.PreferBraces.DefaultValue); + + internal static CSharpSimplifierOptions Create(AnalyzerConfigOptions options, CSharpSimplifierOptions? fallbackOptions) + { + fallbackOptions ??= Default; + + return new( + qualifyFieldAccess: options.GetEditorConfigOption(CodeStyleOptions2.QualifyFieldAccess, fallbackOptions.QualifyFieldAccess), + qualifyPropertyAccess: options.GetEditorConfigOption(CodeStyleOptions2.QualifyPropertyAccess, fallbackOptions.QualifyPropertyAccess), + qualifyMethodAccess: options.GetEditorConfigOption(CodeStyleOptions2.QualifyMethodAccess, fallbackOptions.QualifyMethodAccess), + qualifyEventAccess: options.GetEditorConfigOption(CodeStyleOptions2.QualifyEventAccess, fallbackOptions.QualifyEventAccess), + preferPredefinedTypeKeywordInMemberAccess: options.GetEditorConfigOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, fallbackOptions.PreferPredefinedTypeKeywordInMemberAccess), + preferPredefinedTypeKeywordInDeclaration: options.GetEditorConfigOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, fallbackOptions.PreferPredefinedTypeKeywordInDeclaration), + varForBuiltInTypes: options.GetEditorConfigOption(CSharpCodeStyleOptions.VarForBuiltInTypes, fallbackOptions.VarForBuiltInTypes), + varWhenTypeIsApparent: options.GetEditorConfigOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, fallbackOptions.VarWhenTypeIsApparent), + varElsewhere: options.GetEditorConfigOption(CSharpCodeStyleOptions.VarElsewhere, fallbackOptions.VarElsewhere), + preferSimpleDefaultExpression: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, fallbackOptions.PreferSimpleDefaultExpression), + preferBraces: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferBraces, fallbackOptions.PreferBraces)); + } + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.State.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.State.cs index 4c5d9fbb68870..78e5ffe0bc6e6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.State.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.State.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -33,15 +34,15 @@ protected readonly struct State public State( SyntaxNode declaration, SemanticModel semanticModel, - OptionSet optionSet, CancellationToken cancellationToken) + CSharpSimplifierOptions options, CancellationToken cancellationToken) { TypeStylePreference = default; IsInIntrinsicTypeContext = default; IsTypeApparentInContext = default; - var styleForIntrinsicTypes = optionSet.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes); - var styleForApparent = optionSet.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent); - var styleForElsewhere = optionSet.GetOption(CSharpCodeStyleOptions.VarElsewhere); + var styleForIntrinsicTypes = options.VarForBuiltInTypes; + var styleForApparent = options.VarWhenTypeIsApparent; + var styleForElsewhere = options.VarElsewhere; _forBuiltInTypes = styleForIntrinsicTypes.Notification.Severity; _whenTypeIsApparent = styleForApparent.Notification.Severity; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.cs index 1f497769bcaee..189f3c9a2bbe5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpTypeStyleHelper.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; #if CODE_STYLE @@ -21,7 +22,7 @@ internal struct TypeStyleResult private readonly CSharpTypeStyleHelper _helper; private readonly TypeSyntax _typeName; private readonly SemanticModel _semanticModel; - private readonly OptionSet _optionSet; + private readonly CSharpSimplifierOptions _options; private readonly CancellationToken _cancellationToken; /// @@ -39,12 +40,12 @@ internal struct TypeStyleResult public readonly bool IsStylePreferred; public readonly ReportDiagnostic Severity; - public TypeStyleResult(CSharpTypeStyleHelper helper, TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, bool isStylePreferred, ReportDiagnostic severity, CancellationToken cancellationToken) : this() + public TypeStyleResult(CSharpTypeStyleHelper helper, TypeSyntax typeName, SemanticModel semanticModel, CSharpSimplifierOptions options, bool isStylePreferred, ReportDiagnostic severity, CancellationToken cancellationToken) : this() { _helper = helper; _typeName = typeName; _semanticModel = semanticModel; - _optionSet = optionSet; + _options = options; _cancellationToken = cancellationToken; IsStylePreferred = isStylePreferred; @@ -52,7 +53,7 @@ public TypeStyleResult(CSharpTypeStyleHelper helper, TypeSyntax typeName, Semant } public bool CanConvert() - => _helper.TryAnalyzeVariableDeclaration(_typeName, _semanticModel, _optionSet, _cancellationToken); + => _helper.TryAnalyzeVariableDeclaration(_typeName, _semanticModel, _options, _cancellationToken); } internal abstract partial class CSharpTypeStyleHelper @@ -61,7 +62,7 @@ internal abstract partial class CSharpTypeStyleHelper public virtual TypeStyleResult AnalyzeTypeName( TypeSyntax typeName, SemanticModel semanticModel, - OptionSet optionSet, CancellationToken cancellationToken) + CSharpSimplifierOptions options, CancellationToken cancellationToken) { if (typeName?.FirstAncestorOrSelf(a => a.IsKind(SyntaxKind.DeclarationExpression, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement)) is not { } declaration) { @@ -69,18 +70,19 @@ public virtual TypeStyleResult AnalyzeTypeName( } var state = new State( - declaration, semanticModel, optionSet, cancellationToken); + declaration, semanticModel, options, cancellationToken); var isStylePreferred = this.IsStylePreferred(in state); var severity = state.GetDiagnosticSeverityPreference(); return new TypeStyleResult( - this, typeName, semanticModel, optionSet, isStylePreferred, severity, cancellationToken); + this, typeName, semanticModel, options, isStylePreferred, severity, cancellationToken); } internal abstract bool TryAnalyzeVariableDeclaration( - TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken); + TypeSyntax typeName, SemanticModel semanticModel, CSharpSimplifierOptions options, CancellationToken cancellationToken); - protected abstract bool AssignmentSupportsStylePreference(SyntaxToken identifier, TypeSyntax typeName, ExpressionSyntax initializer, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken); + protected abstract bool AssignmentSupportsStylePreference( + SyntaxToken identifier, TypeSyntax typeName, ExpressionSyntax initializer, SemanticModel semanticModel, CSharpSimplifierOptions options, CancellationToken cancellationToken); internal TypeSyntax? FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseExplicitTypeHelper.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseExplicitTypeHelper.cs index f664091fb300f..4c702e9137bd7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseExplicitTypeHelper.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseExplicitTypeHelper.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -70,7 +71,7 @@ protected override bool ShouldAnalyzeForEachStatement(ForEachStatementSyntax for internal override bool TryAnalyzeVariableDeclaration( TypeSyntax typeName, SemanticModel semanticModel, - OptionSet optionSet, CancellationToken cancellationToken) + CSharpSimplifierOptions options, CancellationToken cancellationToken) { // var (x, y) = e; // foreach (var (x, y) in e) ... @@ -95,7 +96,7 @@ internal override bool TryAnalyzeVariableDeclaration( RoslynDebug.AssertNotNull(variable.Initializer); if (!AssignmentSupportsStylePreference( variable.Identifier, typeName, variable.Initializer.Value, - semanticModel, optionSet, cancellationToken)) + semanticModel, options, cancellationToken)) { return false; } @@ -111,7 +112,7 @@ internal override bool TryAnalyzeVariableDeclaration( { if (!AssignmentSupportsStylePreference( foreachStatement.Identifier, typeName, foreachStatement.Expression, - semanticModel, optionSet, cancellationToken)) + semanticModel, options, cancellationToken)) { return false; } @@ -144,7 +145,7 @@ protected override bool AssignmentSupportsStylePreference( TypeSyntax typeName, ExpressionSyntax initializer, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { // is or contains an anonymous type diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs index a836866613880..a424248347bda 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/TypeStyle/CSharpUseImplicitTypeHelper.cs @@ -14,6 +14,7 @@ using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeAnalysis.CSharp.Simplification; #if CODE_STYLE using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; @@ -33,7 +34,7 @@ private CSharpUseImplicitTypeHelper() public override TypeStyleResult AnalyzeTypeName( TypeSyntax typeName, SemanticModel semanticModel, - OptionSet optionSet, CancellationToken cancellationToken) + CSharpSimplifierOptions options, CancellationToken cancellationToken) { if (typeName.StripRefIfNeeded().IsVar) { @@ -46,7 +47,7 @@ public override TypeStyleResult AnalyzeTypeName( } return base.AnalyzeTypeName( - typeName, semanticModel, optionSet, cancellationToken); + typeName, semanticModel, options, cancellationToken); } public override bool ShouldAnalyzeVariableDeclaration(VariableDeclarationSyntax variableDeclaration, CancellationToken cancellationToken) @@ -95,7 +96,7 @@ protected override bool IsStylePreferred(in State state) internal override bool TryAnalyzeVariableDeclaration( TypeSyntax typeName, SemanticModel semanticModel, - OptionSet optionSet, CancellationToken cancellationToken) + CSharpSimplifierOptions options, CancellationToken cancellationToken) { Debug.Assert(!typeName.StripRefIfNeeded().IsVar, "'var' special case should have prevented analysis of this variable."); @@ -146,7 +147,7 @@ internal override bool TryAnalyzeVariableDeclaration( if (AssignmentSupportsStylePreference( variable.Identifier, typeName, initializer, - semanticModel, optionSet, cancellationToken)) + semanticModel, options, cancellationToken)) { return true; } @@ -274,7 +275,7 @@ protected override bool AssignmentSupportsStylePreference( TypeSyntax typeName, ExpressionSyntax initializer, SemanticModel semanticModel, - OptionSet optionSet, + CSharpSimplifierOptions options, CancellationToken cancellationToken) { var expression = GetInitializerExpression(initializer); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOption2`1.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOption2`1.cs index c40d2ff605060..80a777ac97b4a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOption2`1.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOption2`1.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Xml.Linq; using Microsoft.CodeAnalysis.Diagnostics; using Roslyn.Utilities; @@ -37,6 +38,7 @@ internal interface ICodeStyleOption : IObjectWritable /// hosts that expect the value to be a boolean. Specifically, if the enum value is 0 or 1 /// then those values will write back as false/true. /// + [DataContract] internal sealed partial class CodeStyleOption2 : ICodeStyleOption, IEquatable?> { static CodeStyleOption2() @@ -48,16 +50,18 @@ static CodeStyleOption2() private const int SerializationVersion = 1; - private readonly NotificationOption2 _notification; + [DataMember(Order = 0)] + public T Value { get; } + + [DataMember(Order = 1)] + public NotificationOption2 Notification { get; } public CodeStyleOption2(T value, NotificationOption2 notification) { Value = value; - _notification = notification; + Notification = notification; } - public T Value { get; } - object? ICodeStyleOption.Value => this.Value; ICodeStyleOption ICodeStyleOption.WithValue(object value) => new CodeStyleOption2((T)value, Notification); ICodeStyleOption ICodeStyleOption.WithNotification(NotificationOption2 notification) => new CodeStyleOption2(Value, notification); @@ -72,11 +76,6 @@ ICodeStyleOption ICodeStyleOption.AsCodeStyleOption() private int EnumValueAsInt32 => (int)(object)Value!; - public NotificationOption2 Notification - { - get => _notification; - } - public XElement ToXElement() => new("CodeStyleOption", // Ensure that we use "CodeStyleOption" as the name for back compat. new XAttribute(nameof(SerializationVersion), SerializationVersion), diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs index c68ba4f1e92f9..41b498d3d7a50 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.CodeStyle; using Roslyn.Utilities; using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems index ec9796f1fcfb0..c59148beee61e 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems @@ -404,6 +404,7 @@ + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs index 483bc0fce1a49..31d34a2ff238f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; +using Roslyn.Utilities; #if CODE_STYLE using TOption = Microsoft.CodeAnalysis.Options.IOption2; @@ -54,12 +55,15 @@ private static T GetOptionWithAssertOnFailure(AnalyzerConfigOptions analyzerC } public static bool TryGetEditorConfigOptionOrDefault(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, out T value) - => TryGetEditorConfigOption(analyzerConfigOptions, option, useDefaultIfMissing: true, out value!); + => TryGetEditorConfigOption(analyzerConfigOptions, option, (T?)option.DefaultValue, out value!); public static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, [MaybeNullWhen(false)] out T value) - => TryGetEditorConfigOption(analyzerConfigOptions, option, useDefaultIfMissing: false, out value); + => TryGetEditorConfigOption(analyzerConfigOptions, option, defaultValue: default, out value); - private static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, bool useDefaultIfMissing, out T? value) + public static T GetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, T defaultValue) + => TryGetEditorConfigOption(analyzerConfigOptions, option, new Optional(defaultValue), out var value) ? value! : throw ExceptionUtilities.Unreachable; + + private static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, Optional defaultValue, out T? value) { var hasEditorConfigStorage = false; foreach (var storageLocation in option.StorageLocations) @@ -87,9 +91,9 @@ private static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analy } } - if (useDefaultIfMissing) + if (defaultValue.HasValue) { - value = (T?)option.DefaultValue; + value = defaultValue.Value; return hasEditorConfigStorage; } else diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AbstractSyntaxFormattingService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AbstractSyntaxFormattingService.cs index 887b5b23f345e..caa6018f7a7c1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AbstractSyntaxFormattingService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AbstractSyntaxFormattingService.cs @@ -25,6 +25,7 @@ protected AbstractSyntaxFormatting() { } + public abstract SyntaxFormattingOptions DefaultOptions { get; } public abstract SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options); public abstract ImmutableArray GetDefaultFormattingRules(); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs index 73af81ac1d358..79ee7fb40e671 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs @@ -21,7 +21,9 @@ namespace Microsoft.CodeAnalysis.Formatting { internal interface ISyntaxFormatting { + SyntaxFormattingOptions DefaultOptions { get; } SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options); + ImmutableArray GetDefaultFormattingRules(); IFormattingResult GetFormattingResult(SyntaxNode node, IEnumerable? spans, SyntaxFormattingOptions options, IEnumerable? rules, CancellationToken cancellationToken); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs new file mode 100644 index 0000000000000..f3903c79ff275 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs @@ -0,0 +1,81 @@ +// 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; +using Microsoft.CodeAnalysis.CodeStyle; +using Roslyn.Utilities; + +#if !CODE_STYLE +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; +#endif + +namespace Microsoft.CodeAnalysis.Simplification +{ + internal abstract class SimplifierOptions + { + [DataMember(Order = 0)] + public readonly CodeStyleOption2 QualifyFieldAccess; + + [DataMember(Order = 1)] + public readonly CodeStyleOption2 QualifyPropertyAccess; + + [DataMember(Order = 2)] + public readonly CodeStyleOption2 QualifyMethodAccess; + + [DataMember(Order = 3)] + public readonly CodeStyleOption2 QualifyEventAccess; + + [DataMember(Order = 4)] + public readonly CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess; + + [DataMember(Order = 5)] + public readonly CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration; + + protected const int BaseMemberCount = 6; + + protected SimplifierOptions( + CodeStyleOption2 qualifyFieldAccess, + CodeStyleOption2 qualifyPropertyAccess, + CodeStyleOption2 qualifyMethodAccess, + CodeStyleOption2 qualifyEventAccess, + CodeStyleOption2 preferPredefinedTypeKeywordInMemberAccess, + CodeStyleOption2 preferPredefinedTypeKeywordInDeclaration) + { + QualifyFieldAccess = qualifyFieldAccess; + QualifyPropertyAccess = qualifyPropertyAccess; + QualifyMethodAccess = qualifyMethodAccess; + QualifyEventAccess = qualifyEventAccess; + PreferPredefinedTypeKeywordInMemberAccess = preferPredefinedTypeKeywordInMemberAccess; + PreferPredefinedTypeKeywordInDeclaration = preferPredefinedTypeKeywordInDeclaration; + } + + public CodeStyleOption2 QualifyMemberAccess(SymbolKind symbolKind) + => symbolKind switch + { + SymbolKind.Field => QualifyFieldAccess, + SymbolKind.Property => QualifyPropertyAccess, + SymbolKind.Method => QualifyMethodAccess, + SymbolKind.Event => QualifyEventAccess, + _ => throw ExceptionUtilities.UnexpectedValue(symbolKind), + }; + +#if !CODE_STYLE + public static SimplifierOptions Create(OptionSet options, HostWorkspaceServices services, SimplifierOptions? fallbackOptions, string language) + { + var simplificationService = services.GetRequiredLanguageService(language); + var configOptions = options.AsAnalyzerConfigOptions(services.GetRequiredService(), language); + return simplificationService.GetSimplifierOptions(configOptions, fallbackOptions); + } + + public static async Task FromDocumentAsync(Document document, SimplifierOptions? fallbackOptions, CancellationToken cancellationToken) + { + var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + return Create(documentOptions, document.Project.Solution.Workspace.Services, fallbackOptions, document.Project.Language); + } +#endif + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb new file mode 100644 index 0000000000000..a22efd25c5a1a --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb @@ -0,0 +1,52 @@ +' 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. + +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Simplification +Imports Microsoft.CodeAnalysis.CodeStyle +Imports System.Runtime.Serialization + +Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification + + Friend NotInheritable Class VisualBasicSimplifierOptions + Inherits SimplifierOptions + + Public Sub New( + qualifyFieldAccess As CodeStyleOption2(Of Boolean), + qualifyPropertyAccess As CodeStyleOption2(Of Boolean), + qualifyMethodAccess As CodeStyleOption2(Of Boolean), + qualifyEventAccess As CodeStyleOption2(Of Boolean), + preferPredefinedTypeKeywordInMemberAccess As CodeStyleOption2(Of Boolean), + preferPredefinedTypeKeywordInDeclaration As CodeStyleOption2(Of Boolean)) + + MyBase.New( + qualifyFieldAccess, + qualifyPropertyAccess, + qualifyMethodAccess, + qualifyEventAccess, + preferPredefinedTypeKeywordInMemberAccess, + preferPredefinedTypeKeywordInDeclaration) + End Sub + + Public Shared ReadOnly [Default] As New VisualBasicSimplifierOptions( + qualifyFieldAccess:=CodeStyleOptions2.QualifyFieldAccess.DefaultValue, + qualifyPropertyAccess:=CodeStyleOptions2.QualifyPropertyAccess.DefaultValue, + qualifyMethodAccess:=CodeStyleOptions2.QualifyMethodAccess.DefaultValue, + qualifyEventAccess:=CodeStyleOptions2.QualifyEventAccess.DefaultValue, + preferPredefinedTypeKeywordInMemberAccess:=CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess.DefaultValue, + preferPredefinedTypeKeywordInDeclaration:=CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration.DefaultValue) + + Friend Overloads Shared Function Create(options As AnalyzerConfigOptions, fallbackOptions As VisualBasicSimplifierOptions) As VisualBasicSimplifierOptions + fallbackOptions = If(fallbackOptions, VisualBasicSimplifierOptions.Default) + + Return New VisualBasicSimplifierOptions( + qualifyFieldAccess:=options.GetEditorConfigOption(CodeStyleOptions2.QualifyFieldAccess, fallbackOptions.QualifyFieldAccess), + qualifyPropertyAccess:=options.GetEditorConfigOption(CodeStyleOptions2.QualifyPropertyAccess, fallbackOptions.QualifyPropertyAccess), + qualifyMethodAccess:=options.GetEditorConfigOption(CodeStyleOptions2.QualifyMethodAccess, fallbackOptions.QualifyMethodAccess), + qualifyEventAccess:=options.GetEditorConfigOption(CodeStyleOptions2.QualifyEventAccess, fallbackOptions.QualifyEventAccess), + preferPredefinedTypeKeywordInMemberAccess:=options.GetEditorConfigOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, fallbackOptions.PreferPredefinedTypeKeywordInMemberAccess), + preferPredefinedTypeKeywordInDeclaration:=options.GetEditorConfigOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, fallbackOptions.PreferPredefinedTypeKeywordInDeclaration)) + End Function + End Class +End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems index 713aac3187b9c..d9c054f576520 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems @@ -38,6 +38,7 @@ + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs index 05ca44c08662c..db4aeaf9b00a2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ITypeSymbolExtensions.TypeSyntaxGeneratorVisitor.cs @@ -333,8 +333,7 @@ public override TypeSyntax VisitNamespace(INamespaceSymbol symbol) /// /// We always unilaterally add "global::" to all named types/namespaces. This - /// will then be trimmed off if possible by calls to - /// + /// will then be trimmed off if possible by the simplifier. /// private static TypeSyntax AddGlobalAlias(INamespaceOrTypeSymbol symbol, SimpleNameSyntax syntax) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs index a496b709e4c4e..bf486b845cf3a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs @@ -4,7 +4,10 @@ using System.Runtime.Serialization; using Microsoft.CodeAnalysis.ExtractMethod; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.ImplementType; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.SymbolSearch; namespace Microsoft.CodeAnalysis.CodeActions @@ -21,14 +24,16 @@ internal readonly struct CodeActionOptions /// Options available to code fixes that are supplied by the IDE (i.e. not stored in editorconfig). /// [DataContract] - internal readonly record struct CodeActionOptions( - [property: DataMember(Order = 0)] SymbolSearchOptions SearchOptions, - [property: DataMember(Order = 1)] ImplementTypeOptions ImplementTypeOptions, - [property: DataMember(Order = 2)] ExtractMethodOptions ExtractMethodOptions, - [property: DataMember(Order = 3)] bool HideAdvancedMembers = false, - [property: DataMember(Order = 4)] bool IsBlocking = false, - [property: DataMember(Order = 5)] int WrappingColumn = CodeActionOptions.DefaultWrappingColumn) + internal readonly record struct CodeActionOptions { + [DataMember(Order = 0)] public SymbolSearchOptions SearchOptions { get; init; } + [DataMember(Order = 1)] public ImplementTypeOptions ImplementTypeOptions { get; init; } + [DataMember(Order = 2)] public ExtractMethodOptions ExtractMethodOptions { get; init; } + [DataMember(Order = 3)] public SimplifierOptions? SimplifierOptions { get; init; } + [DataMember(Order = 4)] public bool HideAdvancedMembers { get; init; } + [DataMember(Order = 5)] public bool IsBlocking { get; init; } + [DataMember(Order = 6)] public int WrappingColumn { get; init; } + /// /// Default value of 120 was picked based on the amount of code in a github.com diff at 1080p. /// That resolution is the most common value as per the last DevDiv survey as well as the latest @@ -41,18 +46,26 @@ internal readonly record struct CodeActionOptions( /// public const int DefaultWrappingColumn = 120; - public CodeActionOptions() - : this(searchOptions: null) + public CodeActionOptions( + SymbolSearchOptions? SearchOptions = null, + ImplementTypeOptions? ImplementTypeOptions = null, + ExtractMethodOptions? ExtractMethodOptions = null, + SimplifierOptions? SimplifierOptions = null, + bool HideAdvancedMembers = false, + bool IsBlocking = false, + int WrappingColumn = DefaultWrappingColumn) { + this.SearchOptions = SearchOptions ?? SymbolSearchOptions.Default; + this.ImplementTypeOptions = ImplementTypeOptions ?? ImplementType.ImplementTypeOptions.Default; + this.ExtractMethodOptions = ExtractMethodOptions ?? ExtractMethod.ExtractMethodOptions.Default; + this.SimplifierOptions = SimplifierOptions; + this.HideAdvancedMembers = HideAdvancedMembers; + this.IsBlocking = IsBlocking; + this.WrappingColumn = WrappingColumn; } - public CodeActionOptions( - SymbolSearchOptions? searchOptions = null, - ImplementTypeOptions? implementTypeOptions = null, - ExtractMethodOptions? extractMethodOptions = null) - : this(SearchOptions: searchOptions ?? SymbolSearchOptions.Default, - ImplementTypeOptions: implementTypeOptions ?? ImplementTypeOptions.Default, - ExtractMethodOptions: extractMethodOptions ?? ExtractMethodOptions.Default) + public CodeActionOptions() + : this(SearchOptions: null) { } @@ -60,5 +73,5 @@ public CodeActionOptions( } #endif - internal delegate CodeActionOptions CodeActionOptionsProvider(string language); + internal delegate CodeActionOptions CodeActionOptionsProvider(HostLanguageServices languageService); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs index 3929b0465ec9f..faa02701a9a4f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs @@ -22,10 +22,17 @@ namespace Microsoft.CodeAnalysis.AddImport { [DataContract] internal record struct AddImportPlacementOptions( - [property: DataMember(Order = 0)] bool PlaceSystemNamespaceFirst, - [property: DataMember(Order = 1)] bool PlaceImportsInsideNamespaces, - [property: DataMember(Order = 2)] bool AllowInHiddenRegions) + [property: DataMember(Order = 0)] bool PlaceSystemNamespaceFirst = true, + [property: DataMember(Order = 1)] bool PlaceImportsInsideNamespaces = false, + [property: DataMember(Order = 2)] bool AllowInHiddenRegions = false) { + public AddImportPlacementOptions() + : this(PlaceSystemNamespaceFirst: true) + { + } + + public static readonly AddImportPlacementOptions Default = new(); + public static async Task FromDocumentAsync(Document document, CancellationToken cancellationToken) { #if CODE_STYLE diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Helpers/SimplificationHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplificationHelpers.cs similarity index 78% rename from src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Helpers/SimplificationHelpers.cs rename to src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplificationHelpers.cs index 43467029eae4e..feceeca6d1cff 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Helpers/SimplificationHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplificationHelpers.cs @@ -5,16 +5,9 @@ #nullable disable using System.Linq; -using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#else -using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet; -#endif - namespace Microsoft.CodeAnalysis.Simplification { internal static class SimplificationHelpers @@ -110,8 +103,7 @@ internal static bool IsValidSymbolInfo(ISymbol symbol) return symbol != null && !symbol.IsErrorType(); } - internal static bool ShouldSimplifyThisOrMeMemberAccessExpression( - SemanticModel semanticModel, OptionSet optionSet, ISymbol symbol) + internal static bool ShouldSimplifyThisOrMeMemberAccessExpression(SimplifierOptions options, ISymbol symbol) { // If we're accessing a static member off of this/me then we should always consider this // simplifiable. Note: in C# this isn't even legal to access a static off of `this`, @@ -119,21 +111,15 @@ internal static bool ShouldSimplifyThisOrMeMemberAccessExpression( if (symbol.IsStatic) return true; - if ((symbol.IsKind(SymbolKind.Field) && optionSet.GetOption(CodeStyleOptions2.QualifyFieldAccess, semanticModel.Language).Value || - (symbol.IsKind(SymbolKind.Property) && optionSet.GetOption(CodeStyleOptions2.QualifyPropertyAccess, semanticModel.Language).Value) || - (symbol.IsKind(SymbolKind.Method) && optionSet.GetOption(CodeStyleOptions2.QualifyMethodAccess, semanticModel.Language).Value) || - (symbol.IsKind(SymbolKind.Event) && optionSet.GetOption(CodeStyleOptions2.QualifyEventAccess, semanticModel.Language).Value))) + if ((symbol.IsKind(SymbolKind.Field) && options.QualifyFieldAccess.Value || + (symbol.IsKind(SymbolKind.Property) && options.QualifyPropertyAccess.Value) || + (symbol.IsKind(SymbolKind.Method) && options.QualifyMethodAccess.Value) || + (symbol.IsKind(SymbolKind.Event) && options.QualifyEventAccess.Value))) { return false; } return true; } - - internal static bool PreferPredefinedTypeKeywordInDeclarations(OptionSet optionSet, string language) - => optionSet.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language).Value; - - internal static bool PreferPredefinedTypeKeywordInMemberAccess(OptionSet optionSet, string language) - => optionSet.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, language).Value; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems index 8d54b8d6496ce..9137f6e29efa0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems @@ -20,7 +20,7 @@ - + diff --git a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/AbstractTokensCodeCleanupProvider.vb b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/AbstractTokensCodeCleanupProvider.vb index 9eef93cdd24c1..c7ff2a0c4b23c 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/AbstractTokensCodeCleanupProvider.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/AbstractTokensCodeCleanupProvider.vb @@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers Protected MustOverride Function GetRewriterAsync( document As Document, root As SyntaxNode, spans As ImmutableArray(Of TextSpan), cancellationToken As CancellationToken) As Task(Of Rewriter) - Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync + Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Dim rewriter As Rewriter = Await GetRewriterAsync(document, root, spans, cancellationToken).ConfigureAwait(False) Dim newRoot = rewriter.Visit(root) diff --git a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/CaseCorrectionCodeCleanupProvider.vb b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/CaseCorrectionCodeCleanupProvider.vb index e4cd067bbaf8f..6917e660f9053 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/CaseCorrectionCodeCleanupProvider.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/CaseCorrectionCodeCleanupProvider.vb @@ -28,7 +28,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers End Get End Property - Public Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync + Public Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync Return CaseCorrector.CaseCorrectAsync(document, spans, cancellationToken) End Function diff --git a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb index 7ad4b805deded..f75b77fcdfc13 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb @@ -31,9 +31,9 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers End Get End Property - Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync + Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) - Dim newRoot = Await CleanupAsync(root, spans, options, document.Project.Solution.Workspace.Services, cancellationToken).ConfigureAwait(False) + Dim newRoot = Await CleanupAsync(root, spans, options.FormattingOptions, document.Project.Solution.Workspace.Services, cancellationToken).ConfigureAwait(False) Return If(root Is newRoot, document, document.WithSyntaxRoot(newRoot)) End Function diff --git a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/RemoveUnnecessaryLineContinuationCodeCleanupProvider.vb b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/RemoveUnnecessaryLineContinuationCodeCleanupProvider.vb index 9bcd1c84bfdfc..842092f714594 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/RemoveUnnecessaryLineContinuationCodeCleanupProvider.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/RemoveUnnecessaryLineContinuationCodeCleanupProvider.vb @@ -29,7 +29,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers End Get End Property - Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As SyntaxFormattingOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync + Public Async Function CleanupAsync(document As Document, spans As ImmutableArray(Of TextSpan), options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements ICodeCleanupProvider.CleanupAsync ' Is this VB 9? If so, we shouldn't remove line continuations because implicit line continuation was introduced in VB 10. Dim parseOptions = TryCast(document.Project.ParseOptions, VisualBasicParseOptions) If parseOptions?.LanguageVersion <= LanguageVersion.VisualBasic9 Then @@ -37,7 +37,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers End If Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) - Dim newRoot = Await CleanupAsync(root, spans, options, document.Project.Solution.Workspace.Services, cancellationToken).ConfigureAwait(False) + Dim newRoot = Await CleanupAsync(root, spans, options.FormattingOptions, document.Project.Solution.Workspace.Services, cancellationToken).ConfigureAwait(False) Return If(newRoot Is root, document, document.WithSyntaxRoot(newRoot)) End Function diff --git a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormatting.vb b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormatting.vb index 4e0a60a5a3e25..adea2938f1526 100644 --- a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormatting.vb +++ b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormatting.vb @@ -28,6 +28,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Return _rules End Function + Public Overrides ReadOnly Property DefaultOptions As SyntaxFormattingOptions + Get + Return VisualBasicSyntaxFormattingOptions.Default + End Get + End Property + Public Overrides Function GetFormattingOptions(options As AnalyzerConfigOptions) As SyntaxFormattingOptions Return VisualBasicSyntaxFormattingOptions.Create(options) End Function diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.AbstractReductionRewriter.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.AbstractReductionRewriter.vb index 8b98b289b8199..e822248d01aa4 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.AbstractReductionRewriter.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.AbstractReductionRewriter.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Protected CancellationToken As CancellationToken Protected Property ParseOptions As VisualBasicParseOptions - Private _simplificationOptions As OptionSet + Private _simplificationOptions As VisualBasicSimplifierOptions Private ReadOnly _processedParentNodes As HashSet(Of SyntaxNode) = New HashSet(Of SyntaxNode)() Private _semanticModel As SemanticModel @@ -30,9 +30,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification _pool = pool End Sub - Public Sub Initialize(parseOptions As ParseOptions, optionSet As OptionSet, cancellationToken As CancellationToken) Implements IReductionRewriter.Initialize + Public Sub Initialize(parseOptions As ParseOptions, options As SimplifierOptions, cancellationToken As CancellationToken) Implements IReductionRewriter.Initialize Me.ParseOptions = DirectCast(parseOptions, VisualBasicParseOptions) - _simplificationOptions = optionSet + _simplificationOptions = DirectCast(options, VisualBasicSimplifierOptions) Me.CancellationToken = cancellationToken End Sub @@ -49,6 +49,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification _pool.Free(Me) End Sub + Public Sub RequireInitialized() + Contract.ThrowIfNull(ParseOptions) + Debug.Assert(_simplificationOptions IsNot Nothing) + Debug.Assert(_semanticModel IsNot Nothing) + End Sub + Public ReadOnly Property HasMoreWork As Boolean Implements IReductionRewriter.HasMoreWork Get Return _hasMoreWork @@ -74,9 +80,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification node As TNode, newNode As SyntaxNode, parentNode As SyntaxNode, - simplifyFunc As Func(Of TNode, SemanticModel, OptionSet, CancellationToken, SyntaxNode) + simplifyFunc As Func(Of TNode, SemanticModel, VisualBasicSimplifierOptions, CancellationToken, SyntaxNode) ) As SyntaxNode + RequireInitialized() Debug.Assert(parentNode IsNot Nothing) CancellationToken.ThrowIfCancellationRequested() @@ -105,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Protected Function SimplifyToken( token As SyntaxToken, newToken As SyntaxToken, - simplifyFunc As Func(Of SyntaxToken, SemanticModel, OptionSet, CancellationToken, SyntaxToken) + simplifyFunc As Func(Of SyntaxToken, SemanticModel, VisualBasicSimplifierOptions, CancellationToken, SyntaxToken) ) As SyntaxToken If token.Kind = SyntaxKind.None Then @@ -149,7 +156,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Protected Function SimplifyExpression(Of TExpression As ExpressionSyntax)( expression As TExpression, newNode As SyntaxNode, - simplifier As Func(Of TExpression, SemanticModel, OptionSet, CancellationToken, SyntaxNode) + simplifier As Func(Of TExpression, SemanticModel, VisualBasicSimplifierOptions, CancellationToken, SyntaxNode) ) As SyntaxNode Return SimplifyNode(expression, newNode, GetParentNode(expression), simplifier) @@ -158,7 +165,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Protected Function SimplifyStatement(Of TStatement As StatementSyntax)( statement As TStatement, newNode As SyntaxNode, - simplifier As Func(Of TStatement, SemanticModel, OptionSet, CancellationToken, SyntaxNode) + simplifier As Func(Of TStatement, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) ) As SyntaxNode Return SimplifyNode(statement, newNode, GetParentNode(statement), simplifier) diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.vb index be1da80192c07..d31704bfdfb4c 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/AbstractVisualBasicReducer.vb @@ -18,12 +18,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification MyBase.New(pool) End Sub - Protected Shared ReadOnly s_reduceParentheses As Func(Of ParenthesizedExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf ReduceParentheses + Protected Shared ReadOnly s_reduceParentheses As Func(Of ParenthesizedExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf ReduceParentheses Protected Shared Function ReduceParentheses( node As ParenthesizedExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As SyntaxNode @@ -42,5 +42,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification ' We don't know how to simplify this. Return node End Function + + Public NotOverridable Overrides Function IsApplicable(options As SimplifierOptions) As Boolean + Return IsApplicable(CType(options, VisualBasicSimplifierOptions)) + End Function + + Public MustOverride Overloads Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCallReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCallReducer.vb index 37a1b5f6a67f1..22e148896c827 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCallReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCallReducer.vb @@ -15,16 +15,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyCallStatement As Func(Of CallStatementSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyCallStatement + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyCallStatement As Func(Of CallStatementSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyCallStatement + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Shared Function SimplifyCallStatement( callStatement As CallStatementSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ExecutableStatementSyntax diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCastReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCastReducer.vb index 82680ea3e8712..a11ab9f3e84b1 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCastReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicCastReducer.vb @@ -5,6 +5,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.PooledObjects +Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification @@ -14,16 +15,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyCast As Func(Of CastExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyCast + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyCast As Func(Of CastExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyCast + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Overloads Shared Function SimplifyCast( node As CastExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ExpressionSyntax @@ -34,12 +39,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Return node.Uncast() End Function - Private Shared ReadOnly s_simplifyPredefinedCast As Func(Of PredefinedCastExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyPredefinedCast + Private Shared ReadOnly s_simplifyPredefinedCast As Func(Of PredefinedCastExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyPredefinedCast Private Overloads Shared Function SimplifyPredefinedCast( node As PredefinedCastExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ExpressionSyntax diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicEscapingReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicEscapingReducer.vb index bb16ef4da24e1..9646191cfa63f 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicEscapingReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicEscapingReducer.vb @@ -19,9 +19,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification MyBase.New(s_pool) End Sub + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function + #Disable Warning IDE0060 ' Remove unused parameter - False positive, used as a delegate in a nested type. ' https://github.com/dotnet/roslyn/issues/44226 - Private Shared Function TryUnescapeToken(identifier As SyntaxToken, semanticModel As SemanticModel, optionSet As OptionSet, cancellationToken As CancellationToken) As SyntaxToken + Private Shared Function TryUnescapeToken(identifier As SyntaxToken, semanticModel As SemanticModel, options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken) As SyntaxToken #Enable Warning IDE0060 ' Remove unused parameter If Not identifier.IsBracketed Then Return identifier diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicExtensionMethodReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicExtensionMethodReducer.vb index b7e67bd324505..8bd16d2d385b1 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicExtensionMethodReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicExtensionMethodReducer.vb @@ -14,16 +14,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyInvocationExpression As Func(Of InvocationExpressionSyntax, SemanticModel, VisualBasicSimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyInvocationExpression + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyInvocationExpression As Func(Of InvocationExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyInvocationExpression + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Shared Function SimplifyInvocationExpression( invocationExpression As InvocationExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken ) As InvocationExpressionSyntax diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.Rewriter.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.Rewriter.vb index f2184a671a53d..26ff8009b40c2 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.Rewriter.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.Rewriter.vb @@ -5,6 +5,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.PooledObjects +Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification @@ -17,10 +18,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification MyBase.New(pool) End Sub - Private ReadOnly s_simplifyTupleName As Func(Of SimpleArgumentSyntax, SemanticModel, OptionSet, CancellationToken, SimpleArgumentSyntax) = AddressOf SimplifyTupleName - Private ReadOnly s_simplifyNamedFieldInitializer As Func(Of NamedFieldInitializerSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyNamedFieldInitializer + Private ReadOnly s_simplifyTupleName As Func(Of SimpleArgumentSyntax, SemanticModel, SimplifierOptions, CancellationToken, SimpleArgumentSyntax) = AddressOf SimplifyTupleName + Private ReadOnly s_simplifyNamedFieldInitializer As Func(Of NamedFieldInitializerSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyNamedFieldInitializer - Private Function SimplifyNamedFieldInitializer(node As NamedFieldInitializerSyntax, arg2 As SemanticModel, optionSet As OptionSet, arg4 As CancellationToken) As SyntaxNode + Private Function SimplifyNamedFieldInitializer(node As NamedFieldInitializerSyntax, arg2 As SemanticModel, options As SimplifierOptions, arg4 As CancellationToken) As SyntaxNode If CanSimplifyNamedFieldInitializer(node) Then Return SyntaxFactory.InferredFieldInitializer(node.Expression).WithTriviaFrom(node) End If @@ -31,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Function SimplifyTupleName( node As SimpleArgumentSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As SimpleArgumentSyntax diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.vb index 6d810474604ff..876497afa8e6c 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicInferredMemberNameReducer.vb @@ -19,5 +19,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Public Sub New() MyBase.New(s_pool) End Sub + + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicMiscellaneousReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicMiscellaneousReducer.vb index 4f132ecafa80e..f87a4abdfe1b9 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicMiscellaneousReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicMiscellaneousReducer.vb @@ -15,16 +15,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyParameter As Func(Of ParameterSyntax, SemanticModel, SimplifierOptions, CancellationToken, ParameterSyntax) = AddressOf SimplifyParameter + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyParameter As Func(Of ParameterSyntax, SemanticModel, OptionSet, CancellationToken, ParameterSyntax) = AddressOf SimplifyParameter + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Shared Function SimplifyParameter( parameter As ParameterSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ParameterSyntax If parameter.CanRemoveAsClause(semanticModel, cancellationToken) Then @@ -36,12 +40,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Return parameter End Function - Private Shared ReadOnly s_simplifyInvocationExpression As Func(Of InvocationExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyInvocationExpression + Private Shared ReadOnly s_simplifyInvocationExpression As Func(Of InvocationExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyInvocationExpression Private Shared Function SimplifyInvocationExpression( invocationExpression As InvocationExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As InvocationExpressionSyntax @@ -59,12 +63,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Return invocationExpression End Function - Private Shared ReadOnly s_simplifyObjectCreationExpression As Func(Of ObjectCreationExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyObjectCreationExpression + Private Shared ReadOnly s_simplifyObjectCreationExpression As Func(Of ObjectCreationExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyObjectCreationExpression Private Shared Function SimplifyObjectCreationExpression( objectCreationExpression As ObjectCreationExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ObjectCreationExpressionSyntax diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicNameReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicNameReducer.vb index 2326cefe8b8a6..6ce8c2a21f676 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicNameReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicNameReducer.vb @@ -19,23 +19,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyName As Func(Of ExpressionSyntax, SemanticModel, SimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyName + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyName As Func(Of ExpressionSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyName + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Overloads Shared Function SimplifyName( node As ExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As SimplifierOptions, cancellationToken As CancellationToken ) As ExpressionSyntax Dim replacementNode As ExpressionSyntax = Nothing Dim issueSpan As TextSpan If Not ExpressionSimplifier.Instance.TrySimplify( - node, semanticModel, optionSet, + node, semanticModel, DirectCast(options, VisualBasicSimplifierOptions), replacementNode, issueSpan, cancellationToken) Then Return node diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicParenthesesReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicParenthesesReducer.vb index a29d15bc3599c..edabaedbc7e29 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicParenthesesReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicParenthesesReducer.vb @@ -13,5 +13,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Public Sub New() MyBase.New(s_pool) End Sub + + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicVariableDeclaratorReducer.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicVariableDeclaratorReducer.vb index 4526f40c0de12..6e1271f8d602d 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicVariableDeclaratorReducer.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Reducers/VisualBasicVariableDeclaratorReducer.vb @@ -18,16 +18,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Private Shared ReadOnly s_pool As ObjectPool(Of IReductionRewriter) = New ObjectPool(Of IReductionRewriter)(Function() New Rewriter(s_pool)) + Private Shared ReadOnly s_simplifyVariableDeclarator As Func(Of VariableDeclaratorSyntax, SemanticModel, VisualBasicSimplifierOptions, CancellationToken, SyntaxNode) = AddressOf SimplifyVariableDeclarator + Public Sub New() MyBase.New(s_pool) End Sub - Private Shared ReadOnly s_simplifyVariableDeclarator As Func(Of VariableDeclaratorSyntax, SemanticModel, OptionSet, CancellationToken, SyntaxNode) = AddressOf SimplifyVariableDeclarator + Public Overrides Function IsApplicable(options As VisualBasicSimplifierOptions) As Boolean + Return True + End Function Private Overloads Shared Function SimplifyVariableDeclarator( node As VariableDeclaratorSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken ) As SyntaxNode Dim replacementNode As SyntaxNode = Nothing diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/AbstractVisualBasicSimplifier.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/AbstractVisualBasicSimplifier.vb index 9e0183be63796..07a47d4bfdef6 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/AbstractVisualBasicSimplifier.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/AbstractVisualBasicSimplifier.vb @@ -11,7 +11,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Friend MustInherit Class AbstractVisualBasicSimplifier(Of TSyntax As SyntaxNode, TSimplifiedSyntax As SyntaxNode) - Inherits AbstractSimplifier(Of TSyntax, TSimplifiedSyntax) + Inherits AbstractSimplifier(Of TSyntax, TSimplifiedSyntax, VisualBasicSimplifierOptions) ''' ''' Returns the predefined keyword kind for a given special type. @@ -180,10 +180,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Return False End Function - Protected Shared Function PreferPredefinedTypeKeywordInMemberAccess(expression As ExpressionSyntax, optionSet As OptionSet) As Boolean + Protected Shared Function PreferPredefinedTypeKeywordInMemberAccess(expression As ExpressionSyntax, options As VisualBasicSimplifierOptions) As Boolean Return (IsDirectChildOfMemberAccessExpression(expression) OrElse IsInCrefReferenceForPredefinedTypeInMemberAccessContext(expression)) AndAlso (Not InsideNameOfExpression(expression)) AndAlso - SimplificationHelpers.PreferPredefinedTypeKeywordInMemberAccess(optionSet, LanguageNames.VisualBasic) + options.PreferPredefinedTypeKeywordInMemberAccess.Value End Function Protected Shared Function InsideNameOfExpression(expr As ExpressionSyntax) As Boolean diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/ExpressionSimplifier.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/ExpressionSimplifier.vb index 6a205ee2caaa2..bdf8a1f4487cf 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/ExpressionSimplifier.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/ExpressionSimplifier.vb @@ -23,11 +23,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Public Overrides Function TrySimplify(expression As ExpressionSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As VisualBasicSimplifierOptions, ByRef replacementNode As ExpressionSyntax, ByRef issueSpan As TextSpan, cancellationToken As CancellationToken) As Boolean - If TryReduceExplicitName(expression, semanticModel, replacementNode, issueSpan, optionSet, cancellationToken) Then + If TryReduceExplicitName(expression, semanticModel, replacementNode, issueSpan, options, cancellationToken) Then Return True End If @@ -39,7 +39,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers semanticModel As SemanticModel, ByRef replacementNode As ExpressionSyntax, ByRef issueSpan As TextSpan, - optionSet As OptionSet, + options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken ) As Boolean replacementNode = Nothing @@ -50,12 +50,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Return TryReduce(memberAccess, semanticModel, replacementNode, issueSpan, - optionSet, + options, cancellationToken) ElseIf TypeOf expression Is NameSyntax Then Dim name = DirectCast(expression, NameSyntax) Return NameSimplifier.Instance.TrySimplify( - name, semanticModel, optionSet, + name, semanticModel, options, replacementNode, issueSpan, cancellationToken) End If @@ -65,9 +65,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Private Shared Function TryReduce( memberAccess As MemberAccessExpressionSyntax, semanticModel As SemanticModel, - ByRef replacementNode As ExpressionSyntax, - ByRef issueSpan As TextSpan, - optionSet As OptionSet, + ByRef replacementNode As ExpressionSyntax, + ByRef issueSpan As TextSpan, + options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken ) As Boolean If memberAccess.Expression Is Nothing OrElse memberAccess.Name Is Nothing Then @@ -96,7 +96,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers End If If memberAccess.Expression.IsKind(SyntaxKind.MeExpression) AndAlso - Not SimplificationHelpers.ShouldSimplifyThisOrMeMemberAccessExpression(semanticModel, optionSet, symbol) Then + Not SimplificationHelpers.ShouldSimplifyThisOrMeMemberAccessExpression(options, symbol) Then Return False End If @@ -123,7 +123,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Return True End If - If PreferPredefinedTypeKeywordInMemberAccess(memberAccess, optionSet) Then + If PreferPredefinedTypeKeywordInMemberAccess(memberAccess, options) Then If (symbol IsNot Nothing AndAlso symbol.IsKind(SymbolKind.NamedType)) Then Dim keywordKind = GetPredefinedKeywordKind(DirectCast(symbol, INamedTypeSymbol).SpecialType) If keywordKind <> SyntaxKind.None Then diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/NameSimplifier.vb b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/NameSimplifier.vb index cffebfafa94e9..784800c2847dd 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/NameSimplifier.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/Simplifiers/NameSimplifier.vb @@ -25,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Public Overrides Function TrySimplify( name As NameSyntax, semanticModel As SemanticModel, - optionSet As OptionSet, + options As VisualBasicSimplifierOptions, ByRef replacementNode As ExpressionSyntax, ByRef issueSpan As TextSpan, cancellationToken As CancellationToken) As Boolean @@ -164,8 +164,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers keywordKind, name.GetTrailingTrivia()) Dim valueText = TryCast(name, IdentifierNameSyntax)?.Identifier.ValueText - Dim inDeclarationContext = PreferPredefinedTypeKeywordInDeclarations(name, optionSet) - Dim inMemberAccessContext = PreferPredefinedTypeKeywordInMemberAccess(name, optionSet) + Dim inDeclarationContext = PreferPredefinedTypeKeywordInDeclarations(name, options) + Dim inMemberAccessContext = PreferPredefinedTypeKeywordInMemberAccess(name, options) If token.Text = valueText OrElse (inDeclarationContext OrElse inMemberAccessContext) Then Dim codeStyleOptionName As String = Nothing @@ -390,11 +390,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification.Simplifiers Return False End Function - Private Shared Function PreferPredefinedTypeKeywordInDeclarations(name As NameSyntax, optionSet As OptionSet) As Boolean + Private Shared Function PreferPredefinedTypeKeywordInDeclarations(name As NameSyntax, options As VisualBasicSimplifierOptions) As Boolean Return (Not IsDirectChildOfMemberAccessExpression(name)) AndAlso (Not InsideCrefReference(name)) AndAlso (Not InsideNameOfExpression(name)) AndAlso - SimplificationHelpers.PreferPredefinedTypeKeywordInDeclarations(optionSet, LanguageNames.VisualBasic) + options.PreferPredefinedTypeKeywordInDeclaration.Value End Function Private Shared Function CanSimplifyNullable(type As INamedTypeSymbol, name As NameSyntax) As Boolean diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb b/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb index 2bff6aaaec0e4..f46b72f4f0845 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb @@ -6,6 +6,7 @@ Imports System.Collections.Immutable Imports System.Composition Imports System.Threading Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Internal.Log Imports Microsoft.CodeAnalysis.Simplification @@ -36,6 +37,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification MyBase.New(s_reducers) End Sub + Public Overrides ReadOnly Property DefaultOptions As SimplifierOptions + Get + Return VisualBasicSimplifierOptions.Default + End Get + End Property + + Public Overrides Function GetSimplifierOptions(options As AnalyzerConfigOptions, fallbackOptions As SimplifierOptions) As SimplifierOptions + Return VisualBasicSimplifierOptions.Create(options, DirectCast(fallbackOptions, VisualBasicSimplifierOptions)) + End Function + Public Overrides Function Expand(node As SyntaxNode, semanticModel As SemanticModel, aliasReplacementAnnotation As SyntaxAnnotation, expandInsideNode As Func(Of SyntaxNode, Boolean), expandParameter As Boolean, cancellationToken As CancellationToken) As SyntaxNode Using Logger.LogBlock(FunctionId.Simplifier_ExpandNode, cancellationToken) If TypeOf node Is ExpressionSyntax OrElse diff --git a/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb b/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb index 3ff21757710de..b14c8a58a0041 100644 --- a/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb +++ b/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb @@ -9,6 +9,7 @@ Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.VisualBasic.Formatting +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Roslyn.Test.Utilities Imports Xunit @@ -88,6 +89,7 @@ End NameSpace" AllowInHiddenRegions:=False) Dim formattingOptions = VisualBasicSyntaxFormattingOptions.Default + Dim simplifierOptions = VisualBasicSimplifierOptions.Default Dim imported = If( useSymbolAnnotations, @@ -101,7 +103,7 @@ End NameSpace" End If If simplifiedText IsNot Nothing Then - Dim reduced = Await Simplifier.ReduceAsync(imported) + Dim reduced = Await Simplifier.ReduceAsync(imported, simplifierOptions, CancellationToken.None) Dim formatted = Await Formatter.FormatAsync(reduced, SyntaxAnnotation.ElasticAnnotation, formattingOptions, CancellationToken.None) Dim actualText = (Await formatted.GetTextAsync()).ToString() Assert.Equal(simplifiedText, actualText)