diff --git a/eng/config/BannedSymbols.txt b/eng/config/BannedSymbols.txt index 8a51cac5d9646..31de0c338aeba 100644 --- a/eng/config/BannedSymbols.txt +++ b/eng/config/BannedSymbols.txt @@ -9,6 +9,8 @@ M:Microsoft.CodeAnalysis.QuickInfo.QuickInfoService.GetQuickInfoAsync(Microsoft. M:Microsoft.CodeAnalysis.CodeFixes.FixAllContext.#ctor(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider,Microsoft.CodeAnalysis.CodeFixes.FixAllScope,System.String,System.Collections.Generic.IEnumerable{System.String},Microsoft.CodeAnalysis.CodeFixes.FixAllContext.DiagnosticProvider,System.Threading.CancellationToken); Use internal overload instead M:Microsoft.CodeAnalysis.CodeFixes.FixAllContext.#ctor(Microsoft.CodeAnalysis.Document,System.Nullable{Microsoft.CodeAnalysis.Text.TextSpan},Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider,Microsoft.CodeAnalysis.CodeFixes.FixAllScope,System.String,System.Collections.Generic.IEnumerable{System.String},Microsoft.CodeAnalysis.CodeFixes.FixAllContext.DiagnosticProvider,System.Threading.CancellationToken); Use internal overload instead M:Microsoft.CodeAnalysis.CodeFixes.FixAllContext.#ctor(Microsoft.CodeAnalysis.Project,Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider,Microsoft.CodeAnalysis.CodeFixes.FixAllScope,System.String,System.Collections.Generic.IEnumerable{System.String},Microsoft.CodeAnalysis.CodeFixes.FixAllContext.DiagnosticProvider,System.Threading.CancellationToken); Use internal overload instead +M:Microsoft.CodeAnalysis.Document.GetOptionsAsync(System.Threading.CancellationToken); Use Document.GetAnalyzerConfigOptionsAsync instead +T:Microsoft.CodeAnalysis.Options.DocumentOptionSet; Use AnalyzerConfigOptions instead M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetService``2(System.IServiceProvider); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing. M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetService``2(System.IServiceProvider,System.Boolean); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetServiceAsync``2(Microsoft.VisualStudio.Shell.IAsyncServiceProvider); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing @@ -25,6 +27,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.Formatting.Formatter.OrganizeImportsAsync(Microsoft.CodeAnalysis.Document,System.Threading.CancellationToken); Call IOrganizeImportsService.OrganizeImportsAsync directly 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 diff --git a/src/Analyzers/CSharp/Analyzers/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs index e98030f3b1242..9294203fccde4 100644 --- a/src/Analyzers/CSharp/Analyzers/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/AddBraces/CSharpAddBracesDiagnosticAnalyzer.cs @@ -48,9 +48,8 @@ protected override void InitializeWorker(AnalysisContext context) public void AnalyzeNode(SyntaxNodeAnalysisContext context) { var statement = context.Node; - var cancellationToken = context.CancellationToken; - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferBraces, statement.SyntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferBraces; if (option.Value == PreferBracesPreference.None) { return; @@ -102,7 +101,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context) return; } - if (ContainsInterleavedDirective(statement, embeddedStatement, cancellationToken)) + if (ContainsInterleavedDirective(statement, embeddedStatement, context.CancellationToken)) { return; } diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems index ae97995d350bd..e0ea0cd616b51 100644 --- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems +++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems @@ -19,6 +19,7 @@ + @@ -60,7 +61,6 @@ - diff --git a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs new file mode 100644 index 0000000000000..49b8beb1542a7 --- /dev/null +++ b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs @@ -0,0 +1,142 @@ +// 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 Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Diagnostics; + +/// +/// Provides C# analyzers a convenient access to editorconfig options with fallback to IDE default values. +/// +internal readonly struct CSharpAnalyzerOptionsProvider +{ + /// + /// Document editorconfig options. + /// + private readonly AnalyzerConfigOptions _options; + + /// + /// Fallback options - the default options in Code Style layer. + /// + private readonly IdeAnalyzerOptions _fallbackOptions; + + public CSharpAnalyzerOptionsProvider(AnalyzerConfigOptions options, IdeAnalyzerOptions fallbackOptions) + { + _options = options; + _fallbackOptions = fallbackOptions; + } + + public CSharpAnalyzerOptionsProvider(AnalyzerConfigOptions options, AnalyzerOptions fallbackOptions) + : this(options, fallbackOptions.GetIdeOptions()) + { + } + + // SimplifierOptions + + public CodeStyleOption2 VarForBuiltInTypes => GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes, FallbackSimplifierOptions.VarForBuiltInTypes); + public CodeStyleOption2 VarWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent, FallbackSimplifierOptions.VarWhenTypeIsApparent); + public CodeStyleOption2 VarElsewhere => GetOption(CSharpCodeStyleOptions.VarElsewhere, FallbackSimplifierOptions.VarElsewhere); + public CodeStyleOption2 PreferSimpleDefaultExpression => GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, FallbackSimplifierOptions.PreferSimpleDefaultExpression); + public CodeStyleOption2 PreferParameterNullChecking => GetOption(CSharpCodeStyleOptions.PreferParameterNullChecking, FallbackSimplifierOptions.PreferParameterNullChecking); + public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine => GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine, FallbackSimplifierOptions.AllowEmbeddedStatementsOnSameLine); + public CodeStyleOption2 PreferThrowExpression => GetOption(CSharpCodeStyleOptions.PreferThrowExpression, FallbackSimplifierOptions.PreferThrowExpression); + public CodeStyleOption2 PreferBraces => GetOption(CSharpCodeStyleOptions.PreferBraces, FallbackSimplifierOptions.PreferBraces); + + internal CSharpSimplifierOptions GetSimplifierOptions() + => _options.GetCSharpSimplifierOptions(FallbackSimplifierOptions); + + // SyntaxFormattingOptions + + public CodeStyleOption2 NamespaceDeclarations => GetOption(CSharpCodeStyleOptions.NamespaceDeclarations, FallbackSyntaxFormattingOptions.NamespaceDeclarations); + public CodeStyleOption2 PreferTopLevelStatements => GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements, FallbackSyntaxFormattingOptions.PreferTopLevelStatements); + + // AddImportPlacementOptions + + public CodeStyleOption2 UsingDirectivePlacement => GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, FallbackAddImportPlacementOptions.UsingDirectivePlacement); + + // CodeStyleOptions + + public CodeStyleOption2 ImplicitObjectCreationWhenTypeIsApparent => GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, FallbackCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent); + public CodeStyleOption2 PreferNullCheckOverTypeCheck => GetOption(CSharpCodeStyleOptions.PreferNullCheckOverTypeCheck, FallbackCodeStyleOptions.PreferNullCheckOverTypeCheck); + public CodeStyleOption2 AllowBlankLinesBetweenConsecutiveBraces => GetOption(CSharpCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces, FallbackCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces); + public CodeStyleOption2 AllowBlankLineAfterColonInConstructorInitializer => GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer, FallbackCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer); + public CodeStyleOption2 PreferConditionalDelegateCall => GetOption(CSharpCodeStyleOptions.PreferConditionalDelegateCall, FallbackCodeStyleOptions.PreferConditionalDelegateCall); + public CodeStyleOption2 PreferSwitchExpression => GetOption(CSharpCodeStyleOptions.PreferSwitchExpression, FallbackCodeStyleOptions.PreferSwitchExpression); + public CodeStyleOption2 PreferPatternMatching => GetOption(CSharpCodeStyleOptions.PreferPatternMatching, FallbackCodeStyleOptions.PreferPatternMatching); + public CodeStyleOption2 PreferPatternMatchingOverAsWithNullCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, FallbackCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck); + public CodeStyleOption2 PreferPatternMatchingOverIsWithCastCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, FallbackCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck); + public CodeStyleOption2 PreferNotPattern => GetOption(CSharpCodeStyleOptions.PreferNotPattern, FallbackCodeStyleOptions.PreferNotPattern); + public CodeStyleOption2 PreferExtendedPropertyPattern => GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern, FallbackCodeStyleOptions.PreferExtendedPropertyPattern); + public CodeStyleOption2 PreferInlinedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration, FallbackCodeStyleOptions.PreferInlinedVariableDeclaration); + public CodeStyleOption2 PreferDeconstructedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration, FallbackCodeStyleOptions.PreferDeconstructedVariableDeclaration); + public CodeStyleOption2 PreferIndexOperator => GetOption(CSharpCodeStyleOptions.PreferIndexOperator, FallbackCodeStyleOptions.PreferIndexOperator); + public CodeStyleOption2 PreferRangeOperator => GetOption(CSharpCodeStyleOptions.PreferRangeOperator, FallbackCodeStyleOptions.PreferRangeOperator); + public CodeStyleOption2 PreferUtf8StringLiterals => GetOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals, FallbackCodeStyleOptions.PreferUtf8StringLiterals); + public CodeStyleOption2 PreferredModifierOrder => GetOption(CSharpCodeStyleOptions.PreferredModifierOrder, FallbackCodeStyleOptions.PreferredModifierOrder); + public CodeStyleOption2 PreferSimpleUsingStatement => GetOption(CSharpCodeStyleOptions.PreferSimpleUsingStatement, FallbackCodeStyleOptions.PreferSimpleUsingStatement); + public CodeStyleOption2 PreferLocalOverAnonymousFunction => GetOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction, FallbackCodeStyleOptions.PreferLocalOverAnonymousFunction); + public CodeStyleOption2 PreferTupleSwap => GetOption(CSharpCodeStyleOptions.PreferTupleSwap, FallbackCodeStyleOptions.PreferTupleSwap); + public CodeStyleOption2 UnusedValueExpressionStatement => GetOption(CSharpCodeStyleOptions.UnusedValueExpressionStatement, FallbackCodeStyleOptions.UnusedValueExpressionStatement); + public CodeStyleOption2 UnusedValueAssignment => GetOption(CSharpCodeStyleOptions.UnusedValueAssignment, FallbackCodeStyleOptions.UnusedValueAssignment); + public CodeStyleOption2 PreferMethodGroupConversion => GetOption(CSharpCodeStyleOptions.PreferMethodGroupConversion, FallbackCodeStyleOptions.PreferMethodGroupConversion); + + // CodeGenerationOptions + + internal CSharpCodeGenerationOptions GetCodeGenerationOptions() + => _options.GetCSharpCodeGenerationOptions(FallbackCodeGenerationOptions); + + public CodeStyleOption2 PreferExpressionBodiedLambdas => GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas, FallbackCodeStyleOptions.PreferExpressionBodiedLambdas); + public CodeStyleOption2 PreferStaticLocalFunction => GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, FallbackCodeStyleOptions.PreferStaticLocalFunction); + + private TValue GetOption(Option2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private CSharpIdeCodeStyleOptions FallbackCodeStyleOptions + => (CSharpIdeCodeStyleOptions?)_fallbackOptions.CodeStyleOptions ?? CSharpIdeCodeStyleOptions.Default; + + private CSharpSimplifierOptions FallbackSimplifierOptions + => (CSharpSimplifierOptions?)_fallbackOptions.CleanupOptions?.SimplifierOptions ?? CSharpSimplifierOptions.Default; + + private CSharpSyntaxFormattingOptions FallbackSyntaxFormattingOptions + => (CSharpSyntaxFormattingOptions?)_fallbackOptions.CleanupOptions?.FormattingOptions ?? CSharpSyntaxFormattingOptions.Default; + + private AddImportPlacementOptions FallbackAddImportPlacementOptions + => _fallbackOptions.CleanupOptions?.AddImportOptions ?? AddImportPlacementOptions.Default; + + private CSharpCodeGenerationOptions FallbackCodeGenerationOptions + => (CSharpCodeGenerationOptions?)_fallbackOptions.GenerationOptions ?? CSharpCodeGenerationOptions.Default; + + public static explicit operator CSharpAnalyzerOptionsProvider(AnalyzerOptionsProvider provider) + => new(provider.GetAnalyzerConfigOptions(), provider.GetFallbackOptions()); + + public static implicit operator AnalyzerOptionsProvider(CSharpAnalyzerOptionsProvider provider) + => new(provider._options, provider._fallbackOptions); +} + +internal static class CSharpAnalyzerOptionsProviders +{ + public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this SemanticModelAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.SemanticModel.SyntaxTree), context.Options); + + public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this SyntaxNodeAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Node.SyntaxTree), context.Options); + + public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this SyntaxTreeAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Tree), context.Options); + + public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this CodeBlockAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.SemanticModel.SyntaxTree), context.Options); + + public static CSharpAnalyzerOptionsProvider GetCSharpAnalyzerOptions(this OperationAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Operation.Syntax.SyntaxTree), context.Options); +} diff --git a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertNamespaceAnalysis.cs b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertNamespaceAnalysis.cs index 7aa7dbbead3cd..05b9c965a7d68 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertNamespaceAnalysis.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertNamespaceAnalysis.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Linq; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; @@ -27,12 +28,11 @@ public static (string title, string equivalenceKey) GetInfo(NamespaceDeclaration _ => throw ExceptionUtilities.UnexpectedValue(preference), }; - public static bool CanOfferUseBlockScoped(OptionSet optionSet, BaseNamespaceDeclarationSyntax declaration, bool forAnalyzer) + public static bool CanOfferUseBlockScoped(CodeStyleOption2 option, BaseNamespaceDeclarationSyntax declaration, bool forAnalyzer) { if (declaration is not FileScopedNamespaceDeclarationSyntax) return false; - var option = optionSet.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations); var userPrefersRegularNamespaces = option.Value == NamespaceDeclarationPreference.BlockScoped; var analyzerDisabled = option.Notification.Severity == ReportDiagnostic.Suppress; var forRefactoring = !forAnalyzer; @@ -44,11 +44,11 @@ public static bool CanOfferUseBlockScoped(OptionSet optionSet, BaseNamespaceDecl return canOffer; } - internal static bool CanOfferUseFileScoped(OptionSet optionSet, CompilationUnitSyntax root, BaseNamespaceDeclarationSyntax declaration, bool forAnalyzer) - => CanOfferUseFileScoped(optionSet, root, declaration, forAnalyzer, root.SyntaxTree.Options.LanguageVersion()); + internal static bool CanOfferUseFileScoped(CodeStyleOption2 option, CompilationUnitSyntax root, BaseNamespaceDeclarationSyntax declaration, bool forAnalyzer) + => CanOfferUseFileScoped(option, root, declaration, forAnalyzer, root.SyntaxTree.Options.LanguageVersion()); internal static bool CanOfferUseFileScoped( - OptionSet optionSet, + CodeStyleOption2 option, CompilationUnitSyntax root, BaseNamespaceDeclarationSyntax declaration, bool forAnalyzer, @@ -63,7 +63,6 @@ internal static bool CanOfferUseFileScoped( if (version < LanguageVersion.CSharp10) return false; - var option = optionSet.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations); var userPrefersFileScopedNamespaces = option.Value == NamespaceDeclarationPreference.FileScoped; var analyzerDisabled = option.Notification.Severity == ReportDiagnostic.Suppress; var forRefactoring = !forAnalyzer; diff --git a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToBlockScopedNamespaceDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToBlockScopedNamespaceDiagnosticAnalyzer.cs index 4b6d0dfef636e..b8288c97c4d5f 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToBlockScopedNamespaceDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToBlockScopedNamespaceDiagnosticAnalyzer.cs @@ -36,24 +36,16 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeNamespace(SyntaxNodeAnalysisContext context) { - var options = context.Options; var namespaceDeclaration = (FileScopedNamespaceDeclarationSyntax)context.Node; - var syntaxTree = namespaceDeclaration.SyntaxTree; - var cancellationToken = context.CancellationToken; - var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); - - var diagnostic = AnalyzeNamespace(optionSet, namespaceDeclaration); + var diagnostic = AnalyzeNamespace(context.GetCSharpAnalyzerOptions().NamespaceDeclarations, namespaceDeclaration); if (diagnostic != null) context.ReportDiagnostic(diagnostic); } - private Diagnostic? AnalyzeNamespace(OptionSet optionSet, FileScopedNamespaceDeclarationSyntax declaration) + private Diagnostic? AnalyzeNamespace(CodeStyleOption2 option, FileScopedNamespaceDeclarationSyntax declaration) { - var tree = declaration.SyntaxTree; - var option = optionSet.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations); - - if (!ConvertNamespaceAnalysis.CanOfferUseBlockScoped(optionSet, declaration, forAnalyzer: true)) + if (!ConvertNamespaceAnalysis.CanOfferUseBlockScoped(option, declaration, forAnalyzer: true)) return null; // if the diagnostic is hidden, show it anywhere from the `namespace` keyword through the name. @@ -61,7 +53,7 @@ private void AnalyzeNamespace(SyntaxNodeAnalysisContext context) var severity = option.Notification.Severity; var diagnosticLocation = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) != ReportDiagnostic.Hidden ? declaration.Name.GetLocation() - : tree.GetLocation(TextSpan.FromBounds(declaration.SpanStart, declaration.SemicolonToken.Span.End)); + : declaration.SyntaxTree.GetLocation(TextSpan.FromBounds(declaration.SpanStart, declaration.SemicolonToken.Span.End)); return DiagnosticHelper.Create( this.Descriptor, diff --git a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToFileScopedNamespaceDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToFileScopedNamespaceDiagnosticAnalyzer.cs index 2f8ed54e81d6f..a1b53d61f3b65 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToFileScopedNamespaceDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertNamespace/ConvertToFileScopedNamespaceDiagnosticAnalyzer.cs @@ -36,26 +36,20 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeNamespace(SyntaxNodeAnalysisContext context) { - var options = context.Options; var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node; var syntaxTree = namespaceDeclaration.SyntaxTree; var cancellationToken = context.CancellationToken; var root = (CompilationUnitSyntax)syntaxTree.GetRoot(cancellationToken); - var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); - - var diagnostic = AnalyzeNamespace(optionSet, root, namespaceDeclaration); + var diagnostic = AnalyzeNamespace(context.GetCSharpAnalyzerOptions().NamespaceDeclarations, root, namespaceDeclaration); if (diagnostic != null) context.ReportDiagnostic(diagnostic); } - private Diagnostic? AnalyzeNamespace(OptionSet optionSet, CompilationUnitSyntax root, BaseNamespaceDeclarationSyntax declaration) + private Diagnostic? AnalyzeNamespace(CodeStyleOption2 option, CompilationUnitSyntax root, BaseNamespaceDeclarationSyntax declaration) { - var tree = declaration.SyntaxTree; - var option = optionSet.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations); - - if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(optionSet, root, declaration, forAnalyzer: true)) + if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(option, root, declaration, forAnalyzer: true)) return null; // if the diagnostic is hidden, show it anywhere from the `namespace` keyword through the name. @@ -63,7 +57,7 @@ private void AnalyzeNamespace(SyntaxNodeAnalysisContext context) var severity = option.Notification.Severity; var diagnosticLocation = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) != ReportDiagnostic.Hidden ? declaration.Name.GetLocation() - : tree.GetLocation(TextSpan.FromBounds(declaration.SpanStart, declaration.Name.Span.End)); + : declaration.SyntaxTree.GetLocation(TextSpan.FromBounds(declaration.SpanStart, declaration.Name.Span.End)); return DiagnosticHelper.Create( this.Descriptor, diff --git a/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToProgramMainDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToProgramMainDiagnosticAnalyzer.cs index 8822bc3889bc4..65a76845f21e6 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToProgramMainDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToProgramMainDiagnosticAnalyzer.cs @@ -42,11 +42,8 @@ protected override void InitializeWorker(AnalysisContext context) private void ProcessCompilationUnit(SyntaxNodeAnalysisContext context) { - var options = context.Options; var root = (CompilationUnitSyntax)context.Node; - - var optionSet = options.GetAnalyzerOptionSet(root.SyntaxTree, context.CancellationToken); - var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); + var option = context.GetCSharpAnalyzerOptions().PreferTopLevelStatements; if (!CanOfferUseProgramMain(option, root, context.Compilation, forAnalyzer: true)) return; diff --git a/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToTopLevelStatementsDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToTopLevelStatementsDiagnosticAnalyzer.cs index 7a668226ddbbb..a432c494c0491 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToTopLevelStatementsDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertProgram/ConvertToTopLevelStatementsDiagnosticAnalyzer.cs @@ -48,12 +48,8 @@ protected override void InitializeWorker(AnalysisContext context) private void ProcessCompilationUnit(SyntaxNodeAnalysisContext context) { - var options = context.Options; - var root = (CompilationUnitSyntax)context.Node; - // Don't want to suggest moving if the user doesn't have a preference for top-level-statements. - var optionSet = options.GetAnalyzerOptionSet(root.SyntaxTree, context.CancellationToken); - var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); + var option = context.GetCSharpAnalyzerOptions().PreferTopLevelStatements; if (!CanOfferUseTopLevelStatements(option, forAnalyzer: true)) return; @@ -64,6 +60,7 @@ private void ProcessCompilationUnit(SyntaxNodeAnalysisContext context) // Ok, the user does like top level statements. Check if we can find a suitable hit in this type that // indicates we're on the entrypoint of the program. + var root = (CompilationUnitSyntax)context.Node; var methodDeclarations = root.DescendantNodes(n => n is CompilationUnitSyntax or BaseNamespaceDeclarationSyntax or ClassDeclarationSyntax).OfType(); foreach (var methodDeclaration in methodDeclarations) { diff --git a/src/Analyzers/CSharp/Analyzers/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionDiagnosticAnalyzer.cs index c564bd3b73b80..7907456bd8568 100644 --- a/src/Analyzers/CSharp/Analyzers/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionDiagnosticAnalyzer.cs @@ -7,6 +7,7 @@ using System.Linq; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -40,19 +41,14 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { - var switchStatement = context.Node; - var syntaxTree = switchStatement.SyntaxTree; - - var options = context.Options; - var cancellationToken = context.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferSwitchExpression, syntaxTree, cancellationToken); + var styleOption = context.GetCSharpAnalyzerOptions().PreferSwitchExpression; if (!styleOption.Value) { // User has disabled this feature. return; } + var switchStatement = context.Node; if (switchStatement.GetDiagnostics().Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)) { return; diff --git a/src/Analyzers/CSharp/Analyzers/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs index 958e0a7e64a85..7f1cc89fb341b 100644 --- a/src/Analyzers/CSharp/Analyzers/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/InlineDeclaration/CSharpInlineDeclarationDiagnosticAnalyzer.cs @@ -8,6 +8,7 @@ using System.Threading; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -59,25 +60,22 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol? expressionType) { - var argumentNode = (ArgumentSyntax)context.Node; - var csOptions = (CSharpParseOptions)context.Node.SyntaxTree.Options; + var syntaxTree = context.Node.SyntaxTree; + var csOptions = (CSharpParseOptions)syntaxTree.Options; if (csOptions.LanguageVersion < LanguageVersion.CSharp7) { // out-vars are not supported prior to C# 7.0. return; } - var options = context.Options; - var syntaxTree = context.Node.SyntaxTree; - var cancellationToken = context.CancellationToken; - - var option = options.GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration, syntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferInlinedVariableDeclaration; if (!option.Value) { // Don't bother doing any work if the user doesn't even have this preference set. return; } + var argumentNode = (ArgumentSyntax)context.Node; if (argumentNode.RefOrOutKeyword.Kind() != SyntaxKind.OutKeyword) { // Immediately bail if this is not an out-argument. If it's not an out-argument @@ -122,6 +120,8 @@ private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context, INamedTypeSymb return; } + var cancellationToken = context.CancellationToken; + var semanticModel = context.SemanticModel; if (semanticModel.GetSymbolInfo(argumentExpression, cancellationToken).Symbol is not ILocalSymbol outLocalSymbol) { diff --git a/src/Analyzers/CSharp/Analyzers/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs index 6a4ef5206002c..ba4751097221a 100644 --- a/src/Analyzers/CSharp/Analyzers/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/InvokeDelegateWithConditionalAccess/InvokeDelegateWithConditionalAccessAnalyzer.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -37,19 +38,13 @@ protected override void InitializeWorker(AnalysisContext context) private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) { - var options = syntaxContext.Options; - var syntaxTree = syntaxContext.Node.SyntaxTree; - var cancellationToken = syntaxContext.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferConditionalDelegateCall, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferConditionalDelegateCall; if (!styleOption.Value) { - // Bail immediately if the user has disabled this feature. + // Bail if the user has disabled this feature. return; } - var severity = styleOption.Notification.Severity; - // look for the form "if (a != null)" or "if (null != a)" var ifStatement = (IfStatementSyntax)syntaxContext.Node; @@ -93,6 +88,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) return; } + var severity = styleOption.Notification.Severity; var condition = (BinaryExpressionSyntax)ifStatement.Condition; if (TryCheckVariableAndIfStatementForm( syntaxContext, ifStatement, condition, diff --git a/src/Analyzers/CSharp/Analyzers/MakeLocalFunctionStatic/MakeLocalFunctionStaticDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/MakeLocalFunctionStatic/MakeLocalFunctionStaticDiagnosticAnalyzer.cs index 045a203d9e77e..47bb26366544d 100644 --- a/src/Analyzers/CSharp/Analyzers/MakeLocalFunctionStatic/MakeLocalFunctionStaticDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/MakeLocalFunctionStatic/MakeLocalFunctionStaticDiagnosticAnalyzer.cs @@ -42,9 +42,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) return; } - var syntaxTree = context.Node.SyntaxTree; - var cancellationToken = context.CancellationToken; - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, syntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferStaticLocalFunction; if (!option.Value) { return; diff --git a/src/Analyzers/CSharp/Analyzers/MisplacedUsingDirectives/MisplacedUsingDirectivesDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/MisplacedUsingDirectives/MisplacedUsingDirectivesDiagnosticAnalyzer.cs index 6c3993d33454c..3ad7b5d86f483 100644 --- a/src/Analyzers/CSharp/Analyzers/MisplacedUsingDirectives/MisplacedUsingDirectivesDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/MisplacedUsingDirectives/MisplacedUsingDirectivesDiagnosticAnalyzer.cs @@ -56,7 +56,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeNamespaceNode(SyntaxNodeAnalysisContext context) { - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, context.Node.SyntaxTree, context.CancellationToken); + var option = context.GetCSharpAnalyzerOptions().UsingDirectivePlacement; if (option.Value != AddImportPlacement.OutsideNamespace) return; @@ -66,7 +66,7 @@ private void AnalyzeNamespaceNode(SyntaxNodeAnalysisContext context) private static void AnalyzeCompilationUnitNode(SyntaxNodeAnalysisContext context) { - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, context.Node.SyntaxTree, context.CancellationToken); + var option = context.GetCSharpAnalyzerOptions().UsingDirectivePlacement; var compilationUnit = (CompilationUnitSyntax)context.Node; if (option.Value != AddImportPlacement.InsideNamespace diff --git a/src/Analyzers/CSharp/Analyzers/NewLines/ConsecutiveBracePlacement/ConsecutiveBracePlacementDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/NewLines/ConsecutiveBracePlacement/ConsecutiveBracePlacementDiagnosticAnalyzer.cs index dcd1369de5365..156d3ff51486c 100644 --- a/src/Analyzers/CSharp/Analyzers/NewLines/ConsecutiveBracePlacement/ConsecutiveBracePlacementDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/NewLines/ConsecutiveBracePlacement/ConsecutiveBracePlacementDiagnosticAnalyzer.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; @@ -33,7 +34,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeTree(SyntaxTreeAnalysisContext context) { - var option = context.GetOption(CSharpCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces); + var option = context.GetCSharpAnalyzerOptions().AllowBlankLinesBetweenConsecutiveBraces; if (option.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/NewLines/ConstructorInitializerPlacement/ConstructorInitializerPlacementDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/NewLines/ConstructorInitializerPlacement/ConstructorInitializerPlacementDiagnosticAnalyzer.cs index c43f692c79b48..2eb320a8024ad 100644 --- a/src/Analyzers/CSharp/Analyzers/NewLines/ConstructorInitializerPlacement/ConstructorInitializerPlacementDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/NewLines/ConstructorInitializerPlacement/ConstructorInitializerPlacementDiagnosticAnalyzer.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -34,7 +35,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeTree(SyntaxTreeAnalysisContext context) { - var option = context.GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer); + var option = context.GetCSharpAnalyzerOptions().AllowBlankLineAfterColonInConstructorInitializer; if (option.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementDiagnosticAnalyzer.cs index e39cde3804d3e..830a990ece23d 100644 --- a/src/Analyzers/CSharp/Analyzers/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementDiagnosticAnalyzer.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -33,7 +34,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeTree(SyntaxTreeAnalysisContext context) { - var option = context.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine); + var option = context.GetCSharpAnalyzerOptions().AllowEmbeddedStatementsOnSameLine; if (option.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/OrderModifiers/CSharpOrderModifiersDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/OrderModifiers/CSharpOrderModifiersDiagnosticAnalyzer.cs index 2f5a2f6cebd85..84d285e5bdda7 100644 --- a/src/Analyzers/CSharp/Analyzers/OrderModifiers/CSharpOrderModifiersDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/OrderModifiers/CSharpOrderModifiersDiagnosticAnalyzer.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.LanguageServices; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -22,6 +24,9 @@ public CSharpOrderModifiersDiagnosticAnalyzer() { } + protected override CodeStyleOption2 GetPreferredOrderStyle(SyntaxTreeAnalysisContext context) + => context.GetCSharpAnalyzerOptions().PreferredModifierOrder; + protected override void Recurse( SyntaxTreeAnalysisContext context, Dictionary preferredOrder, diff --git a/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs index e180a2c800faa..6417e85a8a9ef 100644 --- a/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/QualifyMemberAccess/CSharpQualifyMemberAccessDiagnosticAnalyzer.cs @@ -9,18 +9,19 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.QualifyMemberAccess; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; 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 ISimplification Simplification + => CSharpSimplification.Instance; protected override bool IsAlreadyQualifiedMemberAccess(ExpressionSyntax node) => node.IsKind(SyntaxKind.ThisExpression); diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryLambdaExpression/CSharpRemoveUnnecessaryLambdaExpressionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryLambdaExpression/CSharpRemoveUnnecessaryLambdaExpressionDiagnosticAnalyzer.cs index 25cf721c05f31..b814e0258ae14 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryLambdaExpression/CSharpRemoveUnnecessaryLambdaExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnnecessaryLambdaExpression/CSharpRemoveUnnecessaryLambdaExpressionDiagnosticAnalyzer.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -62,7 +63,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, INamedTypeSymbol? var semanticModel = context.SemanticModel; var syntaxTree = semanticModel.SyntaxTree; - var preference = context.GetOption(CSharpCodeStyleOptions.PreferMethodGroupConversion); + var preference = context.GetCSharpAnalyzerOptions().PreferMethodGroupConversion; if (preference.Notification.Severity == ReportDiagnostic.Suppress) { // User doesn't care about this rule. diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs index 27d4df2cb6859..ba8cd581eaa65 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnreachableCode/CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs @@ -40,7 +40,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) { - var fadeCode = context.Options.GetIdeOptions().FadeOutUnreachableCode; + var fadeCode = context.GetIdeAnalyzerOptions().FadeOutUnreachableCode; var semanticModel = context.SemanticModel; var cancellationToken = context.CancellationToken; diff --git a/src/Analyzers/CSharp/Analyzers/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs index acca9e9d33600..49aa7b1def4c5 100644 --- a/src/Analyzers/CSharp/Analyzers/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -12,7 +13,7 @@ namespace Microsoft.CodeAnalysis.CSharp.RemoveUnusedParametersAndValues { [DiagnosticAnalyzer(LanguageNames.CSharp)] - internal class CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer : AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer + internal sealed class CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer : AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer { public CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer() : base(unusedValueExpressionStatementOption: CSharpCodeStyleOptions.UnusedValueExpressionStatement, @@ -33,6 +34,12 @@ protected override bool MethodHasHandlesClause(IMethodSymbol method) protected override bool IsIfConditionalDirective(SyntaxNode node) => node is IfDirectiveTriviaSyntax; + protected override CodeStyleOption2 GetUnusedValueExpressionStatementOption(AnalyzerOptionsProvider provider) + => ((CSharpAnalyzerOptionsProvider)provider).UnusedValueExpressionStatement; + + protected override CodeStyleOption2 GetUnusedValueAssignmentOption(AnalyzerOptionsProvider provider) + => ((CSharpAnalyzerOptionsProvider)provider).UnusedValueAssignment; + protected override bool ShouldBailOutFromRemovableAssignmentAnalysis(IOperation unusedSymbolWriteOperation) { // We don't want to recommend removing the write operation if it is within a statement diff --git a/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs b/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs deleted file mode 100644 index b931a6d3236c4..0000000000000 --- a/src/Analyzers/CSharp/Analyzers/Simplification/CSharpSimplifierOptionsFactory.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.CodeAnalysis.Diagnostics; -using Roslyn.Utilities; - -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(); - -#if CODE_STYLE - var fallbackOptions = (CSharpSimplifierOptions?)null; -#else - var fallbackOptions = (CSharpSimplifierOptions?)ideOptions.CleanupOptions?.SimplifierOptions; -#endif - return CSharpSimplifierOptions.Create(configOptions, fallbackOptions); - } -} diff --git a/src/Analyzers/CSharp/Analyzers/SimplifyPropertyPattern/CSharpSimplifyPropertyPatternDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/SimplifyPropertyPattern/CSharpSimplifyPropertyPatternDiagnosticAnalyzer.cs index b8c23b4bae93e..7259fff8ccd45 100644 --- a/src/Analyzers/CSharp/Analyzers/SimplifyPropertyPattern/CSharpSimplifyPropertyPatternDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/SimplifyPropertyPattern/CSharpSimplifyPropertyPatternDiagnosticAnalyzer.cs @@ -52,12 +52,8 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSubpattern(SyntaxNodeAnalysisContext syntaxContext) { - var options = syntaxContext.Options; - var syntaxTree = syntaxContext.Node.SyntaxTree; - var cancellationToken = syntaxContext.CancellationToken; - // Bail immediately if the user has disabled this feature. - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferExtendedPropertyPattern; if (!styleOption.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer.cs index 2d69dba72b897..141ecd5ab5388 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCompoundAssignment/CSharpUseCompoundCoalesceAssignmentDiagnosticAnalyzer.cs @@ -43,7 +43,7 @@ private void AnalyzeCoalesceExpression(SyntaxNodeAnalysisContext context) var coalesceExpression = (BinaryExpressionSyntax)context.Node; - var option = context.GetOption(CodeStyleOptions2.PreferCompoundAssignment, coalesceExpression.Language); + var option = context.GetAnalyzerOptions().PreferCompoundAssignment; // Bail immediately if the user has disabled this feature. if (!option.Value) diff --git a/src/Analyzers/CSharp/Analyzers/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs index f307fd5d2ca39..d91b1fa484072 100644 --- a/src/Analyzers/CSharp/Analyzers/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs @@ -42,8 +42,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeNode(SyntaxNodeAnalysisContext context) { - var cancellationToken = context.CancellationToken; - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration, context.Node.SyntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferDeconstructedVariableDeclaration; if (!option.Value) { return; diff --git a/src/Analyzers/CSharp/Analyzers/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs index ba272b9522e9a..45e9ec0c6c5c9 100644 --- a/src/Analyzers/CSharp/Analyzers/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseDefaultLiteral/CSharpUseDefaultLiteralDiagnosticAnalyzer.cs @@ -35,7 +35,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { var cancellationToken = context.CancellationToken; var syntaxTree = context.Node.SyntaxTree; - var preference = context.Options.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, syntaxTree, cancellationToken); + var preference = context.GetCSharpAnalyzerOptions().PreferSimpleDefaultExpression; var parseOptions = (CSharpParseOptions)syntaxTree.Options; var defaultExpression = (DefaultExpressionSyntax)context.Node; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs index a059441051ba5..9873326d450e2 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForAccessorsHelper.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -24,6 +26,9 @@ private UseExpressionBodyForAccessorsHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedAccessors; + protected override BlockSyntax? GetBody(AccessorDeclarationSyntax declaration) => declaration.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs index 1cc4dc3bb8219..f4594ebec841f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConstructorsHelper.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -24,6 +26,9 @@ private UseExpressionBodyForConstructorsHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedConstructors; + protected override BlockSyntax? GetBody(ConstructorDeclarationSyntax declaration) => declaration.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs index fc12ad3102e70..cbeeaa26d4e8f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForConversionOperatorsHelper.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -24,6 +26,9 @@ private UseExpressionBodyForConversionOperatorsHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedOperators; + protected override BlockSyntax? GetBody(ConversionOperatorDeclarationSyntax declaration) => declaration.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs index b5327f6e4bf1a..172a3494e6165 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForIndexersHelper.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -28,6 +29,9 @@ private UseExpressionBodyForIndexersHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedIndexers; + protected override BlockSyntax GetBody(IndexerDeclarationSyntax declaration) => GetBodyFromSingleGetAccessor(declaration.AccessorList); diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs index 5dd65fd98daaf..f5db5c1bf4288 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForLocalFunctionHelper.cs @@ -5,6 +5,8 @@ #nullable disable using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -27,6 +29,9 @@ private UseExpressionBodyForLocalFunctionHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedLocalFunctions; + protected override BlockSyntax GetBody(LocalFunctionStatementSyntax statement) => statement.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs index 6484dc079e4ac..3cfd363852a1d 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForMethodsHelper.cs @@ -5,6 +5,8 @@ #nullable disable using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -27,6 +29,9 @@ private UseExpressionBodyForMethodsHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedMethods; + protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration) => declaration.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs index e5c33d59906c5..644c5f0ac6a54 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForOperatorsHelper.cs @@ -5,6 +5,8 @@ #nullable disable using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -26,6 +28,9 @@ private UseExpressionBodyForOperatorsHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedOperators; + protected override BlockSyntax GetBody(OperatorDeclarationSyntax declaration) => declaration.Body; diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs index 53066d7605658..8e7730e35ca1b 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyForPropertiesHelper.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -28,6 +29,9 @@ private UseExpressionBodyForPropertiesHelper() { } + public override CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options) + => options.PreferExpressionBodiedProperties; + protected override BlockSyntax GetBody(PropertyDeclarationSyntax declaration) => GetBodyFromSingleGetAccessor(declaration.AccessorList); diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs index cb2b176770a5f..20feb442061c1 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper.cs @@ -7,10 +7,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Diagnostics.CodeAnalysis; - -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#endif +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody { @@ -23,11 +20,12 @@ internal abstract class UseExpressionBodyHelper public abstract EnforceOnBuild EnforceOnBuild { get; } public abstract ImmutableArray SyntaxKinds { get; } + public abstract CodeStyleOption2 GetExpressionBodyPreference(CSharpCodeGenerationOptions options); public abstract BlockSyntax? GetBody(SyntaxNode declaration); public abstract ArrowExpressionClauseSyntax? GetExpressionBody(SyntaxNode declaration); - public abstract bool CanOfferUseExpressionBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer); - public abstract bool CanOfferUseBlockBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax? expressionBody); + public abstract bool CanOfferUseExpressionBody(CodeStyleOption2 preference, SyntaxNode declaration, bool forAnalyzer); + public abstract bool CanOfferUseBlockBody(CodeStyleOption2 preference, SyntaxNode declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax? expressionBody); public abstract SyntaxNode Update(SemanticModel semanticModel, SyntaxNode declaration, bool useExpressionBody); public abstract Location GetDiagnosticLocation(SyntaxNode declaration); diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs index b8f2049c95638..3db4ec9edf106 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/Helpers/UseExpressionBodyHelper`1.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -72,11 +73,11 @@ protected UseExpressionBodyHelper( public override ArrowExpressionClauseSyntax? GetExpressionBody(SyntaxNode declaration) => GetExpressionBody((TDeclaration)declaration); - public override bool CanOfferUseExpressionBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer) - => CanOfferUseExpressionBody(optionSet, (TDeclaration)declaration, forAnalyzer); + public override bool CanOfferUseExpressionBody(CodeStyleOption2 preference, SyntaxNode declaration, bool forAnalyzer) + => CanOfferUseExpressionBody(preference, (TDeclaration)declaration, forAnalyzer); - public override bool CanOfferUseBlockBody(OptionSet optionSet, SyntaxNode declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax? expressionBody) - => CanOfferUseBlockBody(optionSet, (TDeclaration)declaration, forAnalyzer, out fixesError, out expressionBody); + public override bool CanOfferUseBlockBody(CodeStyleOption2 preference, SyntaxNode declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax? expressionBody) + => CanOfferUseBlockBody(preference, (TDeclaration)declaration, forAnalyzer, out fixesError, out expressionBody); public sealed override SyntaxNode Update(SemanticModel semanticModel, SyntaxNode declaration, bool useExpressionBody) => Update(semanticModel, (TDeclaration)declaration, useExpressionBody); @@ -92,12 +93,10 @@ protected virtual Location GetDiagnosticLocation(TDeclaration declaration) } public bool CanOfferUseExpressionBody( - OptionSet optionSet, TDeclaration declaration, bool forAnalyzer) + CodeStyleOption2 preference, TDeclaration declaration, bool forAnalyzer) { - var currentOptionValue = optionSet.GetOption(Option); - var preference = currentOptionValue.Value; - var userPrefersExpressionBodies = preference != ExpressionBodyPreference.Never; - var analyzerDisabled = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress; + var userPrefersExpressionBodies = preference.Value != ExpressionBodyPreference.Never; + var analyzerDisabled = preference.Notification.Severity == ReportDiagnostic.Suppress; // If the user likes expression bodies, then we offer expression bodies from the diagnostic analyzer. // If the user does not like expression bodies then we offer expression bodies from the refactoring provider. @@ -110,7 +109,7 @@ public bool CanOfferUseExpressionBody( // They don't have an expression body. See if we could convert the block they // have into one. - var conversionPreference = forAnalyzer ? preference : ExpressionBodyPreference.WhenPossible; + var conversionPreference = forAnalyzer ? preference.Value : ExpressionBodyPreference.WhenPossible; return TryConvertToExpressionBody(declaration, conversionPreference, expressionWhenOnSingleLine: out _, semicolonWhenOnSingleLine: out _); @@ -174,16 +173,14 @@ protected bool TryConvertToExpressionBodyForBaseProperty( } public bool CanOfferUseBlockBody( - OptionSet optionSet, + CodeStyleOption2 preference, TDeclaration declaration, bool forAnalyzer, out bool fixesError, [NotNullWhen(true)] out ArrowExpressionClauseSyntax? expressionBody) { - var currentOptionValue = optionSet.GetOption(Option); - var preference = currentOptionValue.Value; - var userPrefersBlockBodies = preference == ExpressionBodyPreference.Never; - var analyzerDisabled = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress; + var userPrefersBlockBodies = preference.Value == ExpressionBodyPreference.Never; + var analyzerDisabled = preference.Notification.Severity == ReportDiagnostic.Suppress; expressionBody = GetExpressionBody(declaration); if (expressionBody?.TryConvertToBlock( diff --git a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs index f3de1871fe248..8d3703f1e526e 100644 --- a/src/Analyzers/CSharp/Analyzers/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseExpressionBody/UseExpressionBodyDiagnosticAnalyzer.cs @@ -4,7 +4,9 @@ using System.Collections.Immutable; using System.Linq; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -50,10 +52,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { - var options = context.Options; - var syntaxTree = context.Node.SyntaxTree; - var cancellationToken = context.CancellationToken; - var optionSet = options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); + var options = context.GetCSharpAnalyzerOptions().GetCodeGenerationOptions(); var nodeKind = context.Node.Kind(); @@ -63,13 +62,13 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) var grandparent = context.Node.GetRequiredParent().GetRequiredParent(); if (grandparent.Kind() == SyntaxKind.PropertyDeclaration && - AnalyzeSyntax(optionSet, grandparent, UseExpressionBodyForPropertiesHelper.Instance) != null) + AnalyzeSyntax(options, grandparent, UseExpressionBodyForPropertiesHelper.Instance) != null) { return; } if (grandparent.Kind() == SyntaxKind.IndexerDeclaration && - AnalyzeSyntax(optionSet, grandparent, UseExpressionBodyForIndexersHelper.Instance) != null) + AnalyzeSyntax(options, grandparent, UseExpressionBodyForIndexersHelper.Instance) != null) { return; } @@ -79,7 +78,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { if (helper.SyntaxKinds.Contains(nodeKind)) { - var diagnostic = AnalyzeSyntax(optionSet, context.Node, helper); + var diagnostic = AnalyzeSyntax(options, context.Node, helper); if (diagnostic != null) { context.ReportDiagnostic(diagnostic); @@ -90,12 +89,12 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) } private static Diagnostic? AnalyzeSyntax( - OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper) + CSharpCodeGenerationOptions options, SyntaxNode declaration, UseExpressionBodyHelper helper) { - var preferExpressionBodiedOption = optionSet.GetOption(helper.Option); - var severity = preferExpressionBodiedOption.Notification.Severity; + var preference = helper.GetExpressionBodyPreference(options); + var severity = preference.Notification.Severity; - if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true)) + if (helper.CanOfferUseExpressionBody(preference, declaration, forAnalyzer: true)) { var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden ? declaration.GetLocation() @@ -108,7 +107,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) location, severity, additionalLocations: additionalLocations, properties: properties); } - if (helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true, out var fixesError, out var expressionBody)) + if (helper.CanOfferUseBlockBody(preference, declaration, forAnalyzer: true, out var fixesError, out var expressionBody)) { // They have an expression body. Create a diagnostic to convert it to a block // if they don't want expression bodies for this member. diff --git a/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs index 71af8d9bad828..a7562d39f6354 100644 --- a/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseImplicitObjectCreation/CSharpUseImplicitObjectCreationDiagnosticAnalyzer.cs @@ -37,16 +37,13 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { - var options = context.Options; var syntaxTree = context.Node.SyntaxTree; - var semanticModel = context.SemanticModel; - var cancellationToken = context.CancellationToken; // Not available prior to C# 9. if (syntaxTree.Options.LanguageVersion() < LanguageVersion.CSharp9) return; - var styleOption = options.GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, syntaxTree, cancellationToken); + var styleOption = context.GetCSharpAnalyzerOptions().ImplicitObjectCreationWhenTypeIsApparent; if (!styleOption.Value) { // Bail immediately if the user has disabled this feature. @@ -65,6 +62,8 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) var objectCreation = (ObjectCreationExpressionSyntax)context.Node; TypeSyntax? typeNode; + var semanticModel = context.SemanticModel; + var cancellationToken = context.CancellationToken; if (objectCreation.Parent.IsKind(SyntaxKind.EqualsValueClause) && objectCreation.Parent.Parent.IsKind(SyntaxKind.VariableDeclarator) && @@ -76,7 +75,7 @@ objectCreation.Parent.Parent.Parent is VariableDeclarationSyntax variableDeclara var helper = CSharpUseImplicitTypeHelper.Instance; if (helper.ShouldAnalyzeVariableDeclaration(variableDeclaration, cancellationToken)) { - var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); + var simplifierOptions = context.GetCSharpAnalyzerOptions().GetSimplifierOptions(); if (helper.AnalyzeTypeName(typeNode, semanticModel, simplifierOptions, cancellationToken).IsStylePreferred) { diff --git a/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs b/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs index 61b66eb9d4c92..6f976b6947d45 100644 --- a/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs +++ b/src/Analyzers/CSharp/Analyzers/UseImplicitOrExplicitType/CSharpTypeStyleDiagnosticAnalyzerBase.cs @@ -55,7 +55,6 @@ protected override void InitializeWorker(AnalysisContext context) private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) { var declarationStatement = context.Node; - var syntaxTree = context.Node.SyntaxTree; var cancellationToken = context.CancellationToken; var semanticModel = context.SemanticModel; @@ -65,7 +64,7 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) return; } - var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); + var simplifierOptions = context.GetCSharpAnalyzerOptions().GetSimplifierOptions(); var typeStyle = Helper.AnalyzeTypeName( declaredType, semanticModel, simplifierOptions, cancellationToken); diff --git a/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs index a5cca6b434aaa..370ab9d158fd8 100644 --- a/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs @@ -177,7 +177,7 @@ private void AnalyzeInvokedMember( return; // Don't bother analyzing if the user doesn't like using Index/Range operators. - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferIndexOperator, binaryExpression.SyntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferIndexOperator; if (!option.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs index c446d62bb52ae..99d59c8b0719f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs @@ -74,23 +74,19 @@ protected override void InitializeWorker(AnalysisContext context) }); } - private void AnalyzeInvocation( - OperationAnalysisContext context, InfoCache infoCache) + private void AnalyzeInvocation(OperationAnalysisContext context, InfoCache infoCache) { - var operation = context.Operation; - var syntaxTree = operation.SemanticModel!.SyntaxTree; - var cancellationToken = context.CancellationToken; - // Check if the user wants these operators. - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferRangeOperator, syntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferRangeOperator; if (!option.Value) return; + var operation = context.Operation; var result = AnalyzeInvocation((IInvocationOperation)operation, infoCache); if (result == null) return; - if (CSharpSemanticFacts.Instance.IsInExpressionTree(operation.SemanticModel, operation.Syntax, infoCache.ExpressionOfTType, cancellationToken)) + if (CSharpSemanticFacts.Instance.IsInExpressionTree(operation.SemanticModel, operation.Syntax, infoCache.ExpressionOfTType, context.CancellationToken)) return; context.ReportDiagnostic(CreateDiagnostic(result.Value, option.Notification.Severity)); diff --git a/src/Analyzers/CSharp/Analyzers/UseInferredMemberName/CSharpUseInferredMemberNameDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseInferredMemberName/CSharpUseInferredMemberNameDiagnosticAnalyzer.cs index 8eddca62e9f03..694fa3e91ee03 100644 --- a/src/Analyzers/CSharp/Analyzers/UseInferredMemberName/CSharpUseInferredMemberNameDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseInferredMemberName/CSharpUseInferredMemberNameDiagnosticAnalyzer.cs @@ -21,29 +21,29 @@ internal sealed class CSharpUseInferredMemberNameDiagnosticAnalyzer : AbstractUs protected override void InitializeWorker(AnalysisContext context) => context.RegisterSyntaxNodeAction(AnalyzeSyntax, SyntaxKind.NameColon, SyntaxKind.NameEquals); - protected override void LanguageSpecificAnalyzeSyntax(SyntaxNodeAnalysisContext context, SyntaxTree syntaxTree, AnalyzerOptions options, CancellationToken cancellationToken) + protected override void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { switch (context.Node.Kind()) { case SyntaxKind.NameColon: - ReportDiagnosticsIfNeeded((NameColonSyntax)context.Node, context, options, syntaxTree, cancellationToken); + ReportDiagnosticsIfNeeded((NameColonSyntax)context.Node, context); break; case SyntaxKind.NameEquals: - ReportDiagnosticsIfNeeded((NameEqualsSyntax)context.Node, context, options, syntaxTree, cancellationToken); + ReportDiagnosticsIfNeeded((NameEqualsSyntax)context.Node, context); break; } } - private void ReportDiagnosticsIfNeeded(NameColonSyntax nameColon, SyntaxNodeAnalysisContext context, AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken) + private void ReportDiagnosticsIfNeeded(NameColonSyntax nameColon, SyntaxNodeAnalysisContext context) { if (!nameColon.Parent.IsKind(SyntaxKind.Argument, out ArgumentSyntax? argument)) { return; } + var syntaxTree = context.Node.SyntaxTree; var parseOptions = (CSharpParseOptions)syntaxTree.Options; - var preference = options.GetOption( - CodeStyleOptions2.PreferInferredTupleNames, context.Compilation.Language, syntaxTree, cancellationToken); + var preference = context.GetAnalyzerOptions().PreferInferredTupleNames; if (!preference.Value || !CSharpInferredMemberNameSimplifier.CanSimplifyTupleElementName(argument, parseOptions)) { @@ -61,15 +61,14 @@ private void ReportDiagnosticsIfNeeded(NameColonSyntax nameColon, SyntaxNodeAnal additionalUnnecessaryLocations: ImmutableArray.Create(syntaxTree.GetLocation(fadeSpan)))); } - private void ReportDiagnosticsIfNeeded(NameEqualsSyntax nameEquals, SyntaxNodeAnalysisContext context, AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken) + private void ReportDiagnosticsIfNeeded(NameEqualsSyntax nameEquals, SyntaxNodeAnalysisContext context) { if (!nameEquals.Parent.IsKind(SyntaxKind.AnonymousObjectMemberDeclarator, out AnonymousObjectMemberDeclaratorSyntax? anonCtor)) { return; } - var preference = options.GetOption( - CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames, context.Compilation.Language, syntaxTree, cancellationToken); + var preference = context.GetAnalyzerOptions().PreferInferredAnonymousTypeMemberNames; if (!preference.Value || !CSharpInferredMemberNameSimplifier.CanSimplifyAnonymousTypeMemberName(anonCtor)) { @@ -84,7 +83,7 @@ private void ReportDiagnosticsIfNeeded(NameEqualsSyntax nameEquals, SyntaxNodeAn nameEquals.GetLocation(), preference.Notification.Severity, additionalLocations: ImmutableArray.Empty, - additionalUnnecessaryLocations: ImmutableArray.Create(syntaxTree.GetLocation(fadeSpan)))); + additionalUnnecessaryLocations: ImmutableArray.Create(context.Node.SyntaxTree.GetLocation(fadeSpan)))); } } } diff --git a/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs index 65fa7ec208d27..97d8fb93e8a37 100644 --- a/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseIsNullCheckForCastAndEqualityOperatorDiagnosticAnalyzer.cs @@ -43,18 +43,14 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { - var cancellationToken = context.CancellationToken; - - var semanticModel = context.SemanticModel; - var syntaxTree = semanticModel.SyntaxTree; - - var option = context.Options.GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod, semanticModel.Language, syntaxTree, cancellationToken); + var option = context.GetAnalyzerOptions().PreferIsNullCheckOverReferenceEqualityMethod; if (!option.Value) { return; } var binaryExpression = (BinaryExpressionSyntax)context.Node; + var semanticModel = context.SemanticModel; if (!IsObjectCastAndNullCheck(semanticModel, binaryExpression.Left, binaryExpression.Right) && !IsObjectCastAndNullCheck(semanticModel, binaryExpression.Right, binaryExpression.Left)) diff --git a/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckDiagnosticAnalyzer.cs index 5ebc11a04aa7d..5ef4c84b979a2 100644 --- a/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseIsNullCheck/CSharpUseNullCheckOverTypeCheckDiagnosticAnalyzer.cs @@ -44,7 +44,7 @@ protected override void InitializeWorker(AnalysisContext context) private static bool ShouldAnalyze(OperationAnalysisContext context, out ReportDiagnostic severity) { - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferNullCheckOverTypeCheck, context.Operation.Syntax.SyntaxTree, context.CancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferNullCheckOverTypeCheck; if (!option.Value) { severity = ReportDiagnostic.Default; diff --git a/src/Analyzers/CSharp/Analyzers/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs index 0a744ffc75192..870167cfb603f 100644 --- a/src/Analyzers/CSharp/Analyzers/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs @@ -70,11 +70,7 @@ protected override void InitializeWorker(AnalysisContext context) private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTypeSymbol? expressionType) { - var options = syntaxContext.Options; - var syntaxTree = syntaxContext.Node.SyntaxTree; - var cancellationToken = syntaxContext.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferLocalOverAnonymousFunction; if (!styleOption.Value) { // Bail immediately if the user has disabled this feature. @@ -108,6 +104,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp return; } + var cancellationToken = syntaxContext.CancellationToken; var local = semanticModel.GetDeclaredSymbol(localDeclaration.Declaration.Variables[0], cancellationToken); if (local == null) { diff --git a/src/Analyzers/CSharp/Analyzers/UseParameterNullChecking/CSharpUseParameterNullCheckingDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseParameterNullChecking/CSharpUseParameterNullCheckingDiagnosticAnalyzer.cs index e6402204cebb3..b3725c399473d 100644 --- a/src/Analyzers/CSharp/Analyzers/UseParameterNullChecking/CSharpUseParameterNullCheckingDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseParameterNullChecking/CSharpUseParameterNullCheckingDiagnosticAnalyzer.cs @@ -102,12 +102,7 @@ private void AnalyzeSyntax( IMethodSymbol argumentNullExceptionStringConstructor, IMethodSymbol? referenceEqualsMethod) { - var cancellationToken = context.CancellationToken; - - var semanticModel = context.SemanticModel; - var syntaxTree = semanticModel.SyntaxTree; - - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferParameterNullChecking, syntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferParameterNullChecking; if (!option.Value) { return; @@ -131,6 +126,9 @@ private void AnalyzeSyntax( return; } + var cancellationToken = context.CancellationToken; + var semanticModel = context.SemanticModel; + var methodSymbol = node is AnonymousFunctionExpressionSyntax ? (IMethodSymbol?)semanticModel.GetSymbolInfo(node, cancellationToken).Symbol : (IMethodSymbol?)semanticModel.GetDeclaredSymbol(node, cancellationToken); diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzer.cs index ab35e699fba96..da07ded9d37f1 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternCombinators/CSharpUsePatternCombinatorsDiagnosticAnalyzer.cs @@ -66,7 +66,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) return; var cancellationToken = context.CancellationToken; - var styleOption = context.Options.GetOption(CSharpCodeStyleOptions.PreferPatternMatching, syntaxTree, cancellationToken); + var styleOption = context.GetCSharpAnalyzerOptions().PreferPatternMatching; if (!styleOption.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs index 882fabea89b1e..2e7279c53a56e 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpAsAndNullCheckDiagnosticAnalyzer.cs @@ -58,10 +58,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) return; } - var options = syntaxContext.Options; - var cancellationToken = syntaxContext.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferPatternMatchingOverAsWithNullCheck; if (!styleOption.Value) { // Bail immediately if the user has disabled this feature. @@ -92,6 +89,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) } } + var cancellationToken = syntaxContext.CancellationToken; if (semanticModel.GetSymbolInfo(comparison, cancellationToken).GetAnySymbol().IsUserDefinedOperator()) { return; diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs index 1cd16f268b061..58aee7d8e1841 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpIsAndCastCheckDiagnosticAnalyzer.cs @@ -48,11 +48,7 @@ protected override void InitializeWorker(AnalysisContext context) private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) { - var options = syntaxContext.Options; - var syntaxTree = syntaxContext.Node.SyntaxTree; - var cancellationToken = syntaxContext.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferPatternMatchingOverIsWithCastCheck; if (!styleOption.Value) { // Bail immediately if the user has disabled this feature. @@ -63,6 +59,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) // "x is Type y" is only available in C# 7.0 and above. Don't offer this refactoring // in projects targeting a lesser version. + var syntaxTree = syntaxContext.Node.SyntaxTree; if (syntaxTree.Options.LanguageVersion() < LanguageVersion.CSharp7) { return; @@ -100,6 +97,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) return; } + var cancellationToken = syntaxContext.CancellationToken; var semanticModel = syntaxContext.SemanticModel; var localSymbol = (ILocalSymbol)semanticModel.GetRequiredDeclaredSymbol(declarator, cancellationToken); var isType = semanticModel.GetTypeInfo(castExpression.Type).Type; diff --git a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs index 8573a3cc7dcf9..22eb9b3e6e3f0 100644 --- a/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UsePatternMatching/CSharpUseNotPatternDiagnosticAnalyzer.cs @@ -54,18 +54,13 @@ protected override void InitializeWorker(AnalysisContext context) private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) { - var node = syntaxContext.Node; - var syntaxTree = node.SyntaxTree; - - var options = syntaxContext.Options; - var cancellationToken = syntaxContext.CancellationToken; - // Bail immediately if the user has disabled this feature. - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferNotPattern, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferNotPattern; if (!styleOption.Value) return; // Look for the form: !(...) + var node = syntaxContext.Node; if (node is not PrefixUnaryExpressionSyntax(SyntaxKind.LogicalNotExpression) { Operand: ParenthesizedExpressionSyntax parenthesizedExpression diff --git a/src/Analyzers/CSharp/Analyzers/UseSimpleUsingStatement/UseSimpleUsingStatementDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseSimpleUsingStatement/UseSimpleUsingStatementDiagnosticAnalyzer.cs index afdcf914b0e02..a6ed7194931ce 100644 --- a/src/Analyzers/CSharp/Analyzers/UseSimpleUsingStatement/UseSimpleUsingStatementDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseSimpleUsingStatement/UseSimpleUsingStatementDiagnosticAnalyzer.cs @@ -116,7 +116,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) return; } - var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferSimpleUsingStatement, syntaxTree, cancellationToken); + var option = context.GetCSharpAnalyzerOptions().PreferSimpleUsingStatement; if (!option.Value) { return; diff --git a/src/Analyzers/CSharp/Analyzers/UseThrowExpression/CSharpUseThrowExpressionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseThrowExpression/CSharpUseThrowExpressionDiagnosticAnalyzer.cs index 83bf4a2a32768..eaa426af470dd 100644 --- a/src/Analyzers/CSharp/Analyzers/UseThrowExpression/CSharpUseThrowExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseThrowExpression/CSharpUseThrowExpressionDiagnosticAnalyzer.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System.Threading; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; using Microsoft.CodeAnalysis.Diagnostics; @@ -19,6 +21,9 @@ public CSharpUseThrowExpressionDiagnosticAnalyzer() { } + protected override CodeStyleOption2 PreferThrowExpressionStyle(OperationAnalysisContext context) + => context.GetCSharpAnalyzerOptions().PreferThrowExpression; + protected override bool IsSupported(Compilation compilation) => compilation.LanguageVersion() >= LanguageVersion.CSharp7; diff --git a/src/Analyzers/CSharp/Analyzers/UseTupleSwap/CSharpUseTupleSwapDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseTupleSwap/CSharpUseTupleSwapDiagnosticAnalyzer.cs index ab56c84b265c3..cc27ffb5ac1dc 100644 --- a/src/Analyzers/CSharp/Analyzers/UseTupleSwap/CSharpUseTupleSwapDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseTupleSwap/CSharpUseTupleSwapDiagnosticAnalyzer.cs @@ -61,11 +61,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext syntaxContext) { - var options = syntaxContext.Options; - var syntaxTree = syntaxContext.Node.SyntaxTree; - var cancellationToken = syntaxContext.CancellationToken; - - var styleOption = options.GetOption(CSharpCodeStyleOptions.PreferTupleSwap, syntaxTree, cancellationToken); + var styleOption = syntaxContext.GetCSharpAnalyzerOptions().PreferTupleSwap; if (!styleOption.Value) return; diff --git a/src/Analyzers/CSharp/Analyzers/UseUTF8StringLiteral/UseUTF8StringLiteralDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseUTF8StringLiteral/UseUTF8StringLiteralDiagnosticAnalyzer.cs index 392cb91c74b0a..af6d671787255 100644 --- a/src/Analyzers/CSharp/Analyzers/UseUTF8StringLiteral/UseUTF8StringLiteralDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseUTF8StringLiteral/UseUTF8StringLiteralDiagnosticAnalyzer.cs @@ -33,7 +33,7 @@ public enum ArrayCreationOperationLocation public UseUTF8StringLiteralDiagnosticAnalyzer() : base(IDEDiagnosticIds.UseUTF8StringLiteralDiagnosticId, EnforceOnBuildValues.UseUTF8StringLiteral, - CSharpCodeStyleOptions.PreferUTF8StringLiterals, + CSharpCodeStyleOptions.PreferUtf8StringLiterals, LanguageNames.CSharp, new LocalizableResourceString(nameof(CSharpAnalyzersResources.Convert_to_UTF8_string_literal), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)), new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_UTF8_string_literal), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources))) @@ -59,7 +59,7 @@ private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol var arrayCreationOperation = (IArrayCreationOperation)context.Operation; // Don't offer if the user doesn't want it - var option = context.GetOption(CSharpCodeStyleOptions.PreferUTF8StringLiterals); + var option = context.GetCSharpAnalyzerOptions().PreferUtf8StringLiterals; if (!option.Value) return; diff --git a/src/Analyzers/CSharp/CodeFixes/AddInheritdoc/AddInheritdocCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/AddInheritdoc/AddInheritdocCodeFixProvider.cs index 44ea9b207bf3f..f5a87f37db9ce 100644 --- a/src/Analyzers/CSharp/CodeFixes/AddInheritdoc/AddInheritdocCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/AddInheritdoc/AddInheritdocCodeFixProvider.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; @@ -97,12 +98,12 @@ protected override async Task FixAllAsync(Document document, ImmutableArray comment. var xmlSpaceAfterTripleSlash = Token(leading: TriviaList(DocumentationCommentExterior("///")), SyntaxKind.XmlTextLiteralToken, text: " ", valueText: " ", trailing: default); diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs index e1911e95d818b..969bae5494f04 100644 --- a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs @@ -70,8 +70,8 @@ protected override async Task FixAllAsync( var namespaceDecl = (BaseNamespaceDeclarationSyntax)diagnostic.AdditionalLocations[0].FindNode(cancellationToken); - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(CSharpSyntaxFormatting.Instance, fallbackOptions, cancellationToken).ConfigureAwait(false); - var converted = await ConvertAsync(document, namespaceDecl, formattingOptions, cancellationToken).ConfigureAwait(false); + var options = await document.GetCSharpCodeFixOptionsProviderAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var converted = await ConvertAsync(document, namespaceDecl, options.GetFormattingOptions(), cancellationToken).ConfigureAwait(false); editor.ReplaceNode( editor.OriginalRoot, diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs b/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs index b32372fde10d8..779bc531903e5 100644 --- a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs +++ b/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs @@ -89,7 +89,7 @@ public static async Task ConvertAsync(Document document, BaseNamespace return null; // Auto-formatting options are not relevant since they only control behavior on typing. - var indentationOptions = new IndentationOptions(options, AutoFormattingOptions.Default); + var indentationOptions = new IndentationOptions(options); var indentation = indentationService.GetIndentation(document, openBraceLine + 1, indentationOptions, cancellationToken); diff --git a/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.AddNewKeywordAction.cs b/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.AddNewKeywordAction.cs index 8c2e1915c9af0..51e0bc614a527 100644 --- a/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.AddNewKeywordAction.cs +++ b/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.AddNewKeywordAction.cs @@ -12,54 +12,45 @@ using Microsoft.CodeAnalysis.CSharp.LanguageServices; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Shared.Extensions; - -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#else -using Microsoft.CodeAnalysis.Options; -#endif +using Microsoft.CodeAnalysis.CodeActions; namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.HideBase { internal partial class HideBaseCodeFixProvider { - private class AddNewKeywordAction : CodeActions.CodeAction + private class AddNewKeywordAction : CodeAction { private readonly Document _document; private readonly SyntaxNode _node; + private readonly CodeActionOptionsProvider _fallbackOptions; public override string Title => CSharpCodeFixesResources.Hide_base_member; - public AddNewKeywordAction(Document document, SyntaxNode node) + public AddNewKeywordAction(Document document, SyntaxNode node, CodeActionOptionsProvider fallbackOptions) { _document = document; _node = node; + _fallbackOptions = fallbackOptions; } protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken) { var root = await _document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var options = await _document.GetCSharpCodeFixOptionsProviderAsync(_fallbackOptions, cancellationToken).ConfigureAwait(false); -#if CODE_STYLE - var options = _document.Project.AnalyzerOptions.GetAnalyzerOptionSet(_node.SyntaxTree, cancellationToken); -#else - var options = await _document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif - - var newNode = GetNewNode(_node, options); + var newNode = GetNewNode(_node, options.PreferredModifierOrder.Value); var newRoot = root.ReplaceNode(_node, newNode); return _document.WithSyntaxRoot(newRoot); } - private static SyntaxNode GetNewNode(SyntaxNode node, OptionSet options) + private static SyntaxNode GetNewNode(SyntaxNode node, string preferredModifierOrder) { var syntaxFacts = CSharpSyntaxFacts.Instance; var modifiers = syntaxFacts.GetModifiers(node); var newModifiers = modifiers.Add(SyntaxFactory.Token(SyntaxKind.NewKeyword)); - var option = options.GetOption(CSharpCodeStyleOptions.PreferredModifierOrder); - if (!CSharpOrderModifiersHelper.Instance.TryGetOrComputePreferredOrder(option.Value, out var preferredOrder) || + if (!CSharpOrderModifiersHelper.Instance.TryGetOrComputePreferredOrder(preferredModifierOrder, out var preferredOrder) || !AbstractOrderModifiersHelpers.IsOrdered(preferredOrder, modifiers)) { return syntaxFacts.WithModifiers(node, newModifiers); diff --git a/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.cs index 91f4ad6c7aee0..221d08dc6c512 100644 --- a/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/HideBase/HideBaseCodeFixProvider.cs @@ -7,6 +7,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -45,7 +46,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) if (originalNode == null) return; - context.RegisterCodeFix(new AddNewKeywordAction(context.Document, originalNode), context.Diagnostics); + context.RegisterCodeFix(new AddNewKeywordAction(context.Document, originalNode, context.GetOptionsProvider()), context.Diagnostics); } } } diff --git a/src/Analyzers/CSharp/CodeFixes/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs index ba3ba696829af..4a0b969452f36 100644 --- a/src/Analyzers/CSharp/CodeFixes/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/InlineDeclaration/CSharpInlineDeclarationCodeFixProvider.cs @@ -57,11 +57,7 @@ protected override async Task FixAllAsync( Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { -#if CODE_STYLE - var optionSet = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(editor.OriginalRoot.SyntaxTree, cancellationToken); -#else - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif + var options = await document.GetCSharpCodeFixOptionsProviderAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); // Gather all statements to be removed // We need this to find the statements we can safely attach trivia to @@ -93,7 +89,7 @@ await editor.ApplyExpressionLevelSemanticEditsAsync( (_1, _2, _3) => true, (semanticModel, currentRoot, t, currentNode) => ReplaceIdentifierWithInlineDeclaration( - optionSet, semanticModel, currentRoot, t.declarator, + options, semanticModel, currentRoot, t.declarator, t.identifier, currentNode, declarationsToRemove, document.Project.Solution.Workspace.Services, cancellationToken), cancellationToken).ConfigureAwait(false); @@ -116,7 +112,7 @@ private static (VariableDeclaratorSyntax declarator, IdentifierNameSyntax identi } private static SyntaxNode ReplaceIdentifierWithInlineDeclaration( - OptionSet options, SemanticModel semanticModel, + CSharpCodeFixOptionsProvider options, SemanticModel semanticModel, SyntaxNode currentRoot, VariableDeclaratorSyntax declarator, IdentifierNameSyntax identifier, SyntaxNode currentNode, HashSet declarationsToRemove, @@ -261,7 +257,7 @@ private static SyntaxNode ReplaceIdentifierWithInlineDeclaration( } public static TypeSyntax GenerateTypeSyntaxOrVar( - ITypeSymbol symbol, OptionSet options) + ITypeSymbol symbol, CSharpCodeFixOptionsProvider options) { var useVar = IsVarDesired(symbol, options); @@ -274,16 +270,16 @@ public static TypeSyntax GenerateTypeSyntaxOrVar( : symbol.GenerateTypeSyntax(); } - private static bool IsVarDesired(ITypeSymbol type, OptionSet options) + private static bool IsVarDesired(ITypeSymbol type, CSharpCodeFixOptionsProvider options) { // If they want it for intrinsics, and this is an intrinsic, then use var. if (type.IsSpecialType() == true) { - return options.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes).Value; + return options.VarForBuiltInTypes.Value; } // If they want "var" whenever possible, then use "var". - return options.GetOption(CSharpCodeStyleOptions.VarElsewhere).Value; + return options.VarElsewhere.Value; } private static DeclarationExpressionSyntax GetDeclarationExpression( diff --git a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs index 8fd0aa048df7e..00e7438ad6932 100644 --- a/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/MisplacedUsingDirectives/MisplacedUsingDirectivesCodeFixProvider.cs @@ -25,12 +25,6 @@ using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#else -using Microsoft.CodeAnalysis.Options; -#endif - namespace Microsoft.CodeAnalysis.CSharp.MisplacedUsingDirectives { /// @@ -64,19 +58,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) 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 simplifierOptions = await document.GetSimplifierOptionsAsync(CSharpSimplification.Instance, context.GetOptionsProvider(), cancellationToken).ConfigureAwait(false); - - var codeStyleOption = options.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement); + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.GetOptionsProvider(), cancellationToken).ConfigureAwait(false); + var simplifierOptions = options.GetSimplifierOptions(); // 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, codeStyleOption); + var (placement, preferPreservation) = DeterminePlacement(compilationUnit, options.UsingDirectivePlacement); if (preferPreservation) return; @@ -153,7 +141,7 @@ private static async Task GetTransformedDocumentAsync( // Simplify usings now that they have been moved and are in the proper context. #if CODE_STYLE -#pragma warning disable RS0030 // Do not used banned APIs +#pragma warning disable RS0030 // Do not used banned APIs (ReduceAsync with SimplifierOptions isn't public) return await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, optionSet: null, cancellationToken).ConfigureAwait(false); #pragma warning restore #else diff --git a/src/Analyzers/CSharp/CodeFixes/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementCodeFixProvider.cs index dd41a9e4dc596..263043f4849c0 100644 --- a/src/Analyzers/CSharp/CodeFixes/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/NewLines/EmbeddedStatementPlacement/EmbeddedStatementPlacementCodeFixProvider.cs @@ -39,27 +39,20 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( CSharpCodeFixesResources.Place_statement_on_following_line, - c => UpdateDocumentAsync(document, diagnostic, c), + c => FixAllAsync(document, ImmutableArray.Create(diagnostic), context.GetOptionsProvider(), c), nameof(CSharpCodeFixesResources.Place_statement_on_following_line)), context.Diagnostics); return Task.CompletedTask; } - private static Task UpdateDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) - => FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken); - - public static async Task FixAllAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + public static async Task FixAllAsync(Document document, ImmutableArray diagnostics, CodeActionOptionsProvider codeActionOptionsProvider, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(root, document.Project.Solution.Workspace.Services); -#if CODE_STYLE - var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(editor.OriginalRoot.SyntaxTree, cancellationToken); -#else - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif + var options = await document.GetCSharpCodeFixOptionsProviderAsync(codeActionOptionsProvider, cancellationToken).ConfigureAwait(false); - var endOfLineTrivia = SyntaxFactory.ElasticEndOfLine(options.GetOption(FormattingOptions2.NewLine, LanguageNames.CSharp)); + var endOfLineTrivia = SyntaxFactory.ElasticEndOfLine(options.NewLine); foreach (var diagnostic in diagnostics) FixOne(editor, diagnostic, endOfLineTrivia, cancellationToken); @@ -142,6 +135,6 @@ private static SyntaxToken AddLeadingTrivia(SyntaxToken token, SyntaxTrivia triv public override FixAllProvider GetFixAllProvider() => FixAllProvider.Create( - async (context, document, diagnostics) => await FixAllAsync(document, diagnostics, context.CancellationToken).ConfigureAwait(false)); + async (context, document, diagnostics) => await FixAllAsync(document, diagnostics, context.GetOptionsProvider(), context.CancellationToken).ConfigureAwait(false)); } } diff --git a/src/Analyzers/CSharp/CodeFixes/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs index 61753e17ce410..00e6c8a620590 100644 --- a/src/Analyzers/CSharp/CodeFixes/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/OrderModifiers/CSharpOrderModifiersCodeFixProvider.cs @@ -5,25 +5,32 @@ using System.Collections.Immutable; using System.Composition; using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.LanguageServices; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.OrderModifiers; namespace Microsoft.CodeAnalysis.CSharp.OrderModifiers { [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.OrderModifiers), Shared] - internal class CSharpOrderModifiersCodeFixProvider : AbstractOrderModifiersCodeFixProvider + internal sealed class CSharpOrderModifiersCodeFixProvider : AbstractOrderModifiersCodeFixProvider { private const string CS0267 = nameof(CS0267); // The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or 'void' [ImportingConstructor] [SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")] public CSharpOrderModifiersCodeFixProvider() - : base(CSharpSyntaxFacts.Instance, CSharpCodeStyleOptions.PreferredModifierOrder, CSharpOrderModifiersHelper.Instance) + : base(CSharpSyntaxFacts.Instance, CSharpOrderModifiersHelper.Instance) { } + protected override CodeStyleOption2 GetCodeStyleOption(AnalyzerOptionsProvider options) + => ((CSharpAnalyzerOptionsProvider)options).PreferredModifierOrder; + protected override ImmutableArray FixableCompilerErrorIds { get; } = ImmutableArray.Create(CS0267); } } diff --git a/src/Analyzers/CSharp/CodeFixes/UseDefaultLiteral/CSharpUseDefaultLiteralCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseDefaultLiteral/CSharpUseDefaultLiteralCodeFixProvider.cs index 8f751d5842722..55fad8454a415 100644 --- a/src/Analyzers/CSharp/CodeFixes/UseDefaultLiteral/CSharpUseDefaultLiteralCodeFixProvider.cs +++ b/src/Analyzers/CSharp/CodeFixes/UseDefaultLiteral/CSharpUseDefaultLiteralCodeFixProvider.cs @@ -54,10 +54,10 @@ protected override async Task FixAllAsync( // to replace one at a time, and only actually replace if it's still safe to do so. var parseOptions = (CSharpParseOptions)document.Project.ParseOptions; - var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var preferSimpleDefaultExpression = document.Project.AnalyzerOptions.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression, tree, cancellationToken).Value; - var workspace = document.Project.Solution.Workspace; + var options = (CSharpAnalyzerOptionsProvider)await document.GetAnalyzerOptionsProviderAsync(cancellationToken).ConfigureAwait(false); + var preferSimpleDefaultExpression = options.PreferSimpleDefaultExpression.Value; + var originalRoot = editor.OriginalRoot; var originalNodes = diagnostics.SelectAsArray( diff --git a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs index 29134c5de0c6b..143b42bf932bb 100644 --- a/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs +++ b/src/Analyzers/CSharp/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.cs @@ -377,7 +377,7 @@ enum E }, Options = { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault }, }, }.RunAsync(); } @@ -399,7 +399,7 @@ ref struct S1 { } }", Options = { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault }, }, }.RunAsync(); } @@ -421,7 +421,7 @@ readonly struct S1 { } }", Options = { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault }, }, }.RunAsync(); } @@ -437,7 +437,7 @@ internal class [|C1|] { }", class C1 { }", Options = { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault }, + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault }, }, }.RunAsync(); } diff --git a/src/Analyzers/Core/Analyzers/AbstractParenthesesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/AbstractParenthesesDiagnosticAnalyzer.cs index 006957cb9a605..5526c4045304a 100644 --- a/src/Analyzers/Core/Analyzers/AbstractParenthesesDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/AbstractParenthesesDiagnosticAnalyzer.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Precedence; using Roslyn.Utilities; @@ -23,25 +24,27 @@ protected AbstractParenthesesDiagnosticAnalyzer( { } - protected static PerLanguageOption2> GetLanguageOption(PrecedenceKind precedenceKind) - { - switch (precedenceKind) + protected static CodeStyleOption2 GetLanguageOption(AnalyzerOptionsProvider options, PrecedenceKind precedenceKind) + => precedenceKind switch { - case PrecedenceKind.Arithmetic: - case PrecedenceKind.Shift: - case PrecedenceKind.Bitwise: - return CodeStyleOptions2.ArithmeticBinaryParentheses; - case PrecedenceKind.Relational: - case PrecedenceKind.Equality: - return CodeStyleOptions2.RelationalBinaryParentheses; - case PrecedenceKind.Logical: - case PrecedenceKind.Coalesce: - return CodeStyleOptions2.OtherBinaryParentheses; - case PrecedenceKind.Other: - return CodeStyleOptions2.OtherParentheses; - } + PrecedenceKind.Arithmetic or PrecedenceKind.Shift or PrecedenceKind.Bitwise => options.ArithmeticBinaryParentheses, + PrecedenceKind.Relational or PrecedenceKind.Equality => options.RelationalBinaryParentheses, + PrecedenceKind.Logical or PrecedenceKind.Coalesce => options.OtherBinaryParentheses, + PrecedenceKind.Other => options.OtherParentheses, + _ => throw ExceptionUtilities.UnexpectedValue(precedenceKind), + }; - throw ExceptionUtilities.UnexpectedValue(precedenceKind); - } + protected static string GetEquivalenceKey(PrecedenceKind precedenceKind) + => precedenceKind switch + { + PrecedenceKind.Arithmetic or PrecedenceKind.Shift or PrecedenceKind.Bitwise => "ArithmeticBinary", + PrecedenceKind.Relational or PrecedenceKind.Equality => "RelationalBinary", + PrecedenceKind.Logical or PrecedenceKind.Coalesce => "OtherBinary", + PrecedenceKind.Other => "Other", + _ => throw ExceptionUtilities.UnexpectedValue(precedenceKind), + }; + + protected static ImmutableArray GetAllEquivalenceKeys() + => ImmutableArray.Create("ArithmeticBinary", "RelationalBinary", "OtherBinary", "Other"); } } diff --git a/src/Analyzers/Core/Analyzers/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs index 462188d6dcd5e..860d166bda010 100644 --- a/src/Analyzers/Core/Analyzers/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/AddAccessibilityModifiers/AbstractAddAccessibilityModifiersDiagnosticAnalyzer.cs @@ -14,7 +14,7 @@ internal abstract class AbstractAddAccessibilityModifiersDiagnosticAnalyzer option, TCompilationUnitSyntax compilationUnitSyntax); diff --git a/src/Analyzers/Core/Analyzers/AddRequiredParentheses/AbstractAddRequiredParenthesesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/AddRequiredParentheses/AbstractAddRequiredParenthesesDiagnosticAnalyzer.cs index 93d00393d172d..910a78bb03352 100644 --- a/src/Analyzers/Core/Analyzers/AddRequiredParentheses/AbstractAddRequiredParenthesesDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/AddRequiredParentheses/AbstractAddRequiredParenthesesDiagnosticAnalyzer.cs @@ -4,11 +4,13 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Precedence; using Microsoft.CodeAnalysis.RemoveUnnecessaryParentheses; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.AddRequiredParentheses { @@ -26,15 +28,9 @@ internal abstract class AbstractAddRequiredParenthesesDiagnosticAnalyzer< static AbstractAddRequiredParenthesesDiagnosticAnalyzer() { - var options = new[] - { - CodeStyleOptions2.ArithmeticBinaryParentheses, CodeStyleOptions2.OtherBinaryParentheses, - CodeStyleOptions2.OtherParentheses, CodeStyleOptions2.RelationalBinaryParentheses - }; - var includeArray = new[] { false, true }; - foreach (var option in options) + foreach (var equivalenceKey in GetAllEquivalenceKeys()) { foreach (var includeInFixAll in includeArray) { @@ -44,16 +40,12 @@ static AbstractAddRequiredParenthesesDiagnosticAnalyzer() properties = properties.Add(AddRequiredParenthesesConstants.IncludeInFixAll, ""); } - var equivalenceKey = GetEquivalenceKey(option); properties = properties.Add(AddRequiredParenthesesConstants.EquivalenceKey, equivalenceKey); s_cachedProperties.Add((includeInFixAll, equivalenceKey), properties); } } } - private static string GetEquivalenceKey(PerLanguageOption2> parentPrecedence) - => parentPrecedence.Name; - private static ImmutableDictionary GetProperties(bool includeInFixAll, string equivalenceKey) => s_cachedProperties[(includeInFixAll, equivalenceKey)]; @@ -94,16 +86,20 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) return; } - var childPrecedence = GetLanguageOption(_precedenceService.GetPrecedenceKind(binaryLike)); - var parentPrecedence = GetLanguageOption(_precedenceService.GetPrecedenceKind(parentBinaryLike)); + var options = context.GetAnalyzerOptions(); + var childPrecedenceKind = _precedenceService.GetPrecedenceKind(binaryLike); + var parentPrecedenceKind = _precedenceService.GetPrecedenceKind(parentBinaryLike); + + var childEquivalenceKey = GetEquivalenceKey(childPrecedenceKind); + var parentEquivalenceKey = GetEquivalenceKey(parentPrecedenceKind); // only add parentheses within the same precedence band. - if (parentPrecedence != childPrecedence) + if (childEquivalenceKey != parentEquivalenceKey) { return; } - var preference = context.GetOption(parentPrecedence, binaryLike.Language); + var preference = GetLanguageOption(options, childPrecedenceKind); if (preference.Value != ParenthesesPreference.AlwaysForClarity) { return; @@ -111,14 +107,13 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) var additionalLocations = ImmutableArray.Create(binaryLike.GetLocation()); var precedence = GetPrecedence(binaryLike); - var equivalenceKey = GetEquivalenceKey(parentPrecedence); // In a case like "a + b * c * d", we'll add parens to make "a + (b * c * d)". // To make this user experience more pleasant, we will place the diagnostic on // both *'s. AddDiagnostics( context, binaryLike, precedence, preference.Notification.Severity, - additionalLocations, equivalenceKey, includeInFixAll: true); + additionalLocations, childEquivalenceKey, includeInFixAll: true); } private void AddDiagnostics( diff --git a/src/Analyzers/Core/Analyzers/Analyzers.projitems b/src/Analyzers/Core/Analyzers/Analyzers.projitems index 0429c552528a5..02e058b758a0e 100644 --- a/src/Analyzers/Core/Analyzers/Analyzers.projitems +++ b/src/Analyzers/Core/Analyzers/Analyzers.projitems @@ -31,7 +31,6 @@ - @@ -85,7 +84,6 @@ - diff --git a/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs index 4d9824659ce63..ed5c19ef9d007 100644 --- a/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/FileHeaders/AbstractFileHeaderDiagnosticAnalyzer.cs @@ -50,8 +50,8 @@ private void HandleSyntaxTree(SyntaxTreeAnalysisContext context) return; } - if (!context.Options.TryGetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, tree, out var fileHeaderTemplate) - || string.IsNullOrEmpty(fileHeaderTemplate)) + var fileHeaderTemplate = context.GetAnalyzerOptions().FileHeaderTemplate; + if (string.IsNullOrEmpty(fileHeaderTemplate)) { return; } diff --git a/src/Analyzers/Core/Analyzers/ForEachCast/AbstractForEachCastDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/ForEachCast/AbstractForEachCastDiagnosticAnalyzer.cs index b65af4b04aa1e..ef0817a7c738c 100644 --- a/src/Analyzers/Core/Analyzers/ForEachCast/AbstractForEachCastDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/ForEachCast/AbstractForEachCastDiagnosticAnalyzer.cs @@ -63,7 +63,7 @@ protected void AnalyzeSyntax( if (context.Node is not TForEachStatementSyntax node) return; - var option = context.GetOption(CodeStyleOptions2.ForEachExplicitCastInSource, semanticModel.Language); + var option = context.GetAnalyzerOptions().ForEachExplicitCastInSource; Contract.ThrowIfFalse(option.Value is ForEachExplicitCastInSourcePreference.Always or ForEachExplicitCastInSourcePreference.WhenStronglyTyped); if (semanticModel.GetOperation(node, cancellationToken) is not IForEachLoopOperation loopOperation) diff --git a/src/Analyzers/Core/Analyzers/Formatting/AbstractFormattingAnalyzer.cs b/src/Analyzers/Core/Analyzers/Formatting/AbstractFormattingAnalyzer.cs index 5b7888a4a96b5..39823b1f37fe5 100644 --- a/src/Analyzers/Core/Analyzers/Formatting/AbstractFormattingAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/Formatting/AbstractFormattingAnalyzer.cs @@ -34,7 +34,7 @@ protected sealed override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { - var options = context.Options.GetSyntaxFormattingOptions(context.Tree, SyntaxFormatting); + var options = context.GetAnalyzerOptions().GetSyntaxFormattingOptions(SyntaxFormatting); FormattingAnalyzerHelper.AnalyzeSyntaxTree(context, SyntaxFormatting, Descriptor, options); } } diff --git a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs b/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs deleted file mode 100644 index 307510969c339..0000000000000 --- a/src/Analyzers/Core/Analyzers/Helpers/AnalyzerOptionsExtensions.cs +++ /dev/null @@ -1,161 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.Serialization; -using System.Diagnostics.CodeAnalysis; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.CodeCleanup; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Host; -using Roslyn.Utilities; - -#if CODE_STYLE -using TOption = Microsoft.CodeAnalysis.Options.IOption2; -#else -using TOption = Microsoft.CodeAnalysis.Options.IOption; -#endif - -#if CODE_STYLE -namespace Microsoft.CodeAnalysis.CodeCleanup -{ - internal readonly struct CodeCleanupOptions - { - } -} -#endif - -namespace Microsoft.CodeAnalysis.Diagnostics -{ - /// - /// IDE specific options available to analyzers in a specific project (language). - /// - /// Default values for , or null if not available (the project language does not support these options). - [DataContract] - internal sealed record class IdeAnalyzerOptions( - [property: DataMember(Order = 0)] bool CrashOnAnalyzerException = IdeAnalyzerOptions.DefaultCrashOnAnalyzerException, - [property: DataMember(Order = 1)] bool FadeOutUnusedImports = IdeAnalyzerOptions.DefaultFadeOutUnusedImports, - [property: DataMember(Order = 2)] bool FadeOutUnreachableCode = IdeAnalyzerOptions.DefaultFadeOutUnreachableCode, - [property: DataMember(Order = 3)] bool ReportInvalidPlaceholdersInStringDotFormatCalls = IdeAnalyzerOptions.DefaultReportInvalidPlaceholdersInStringDotFormatCalls, - [property: DataMember(Order = 4)] bool ReportInvalidRegexPatterns = IdeAnalyzerOptions.DefaultReportInvalidRegexPatterns, - [property: DataMember(Order = 5)] bool ReportInvalidJsonPatterns = IdeAnalyzerOptions.DefaultReportInvalidJsonPatterns, - [property: DataMember(Order = 6)] bool DetectAndOfferEditorFeaturesForProbableJsonStrings = IdeAnalyzerOptions.DefaultDetectAndOfferEditorFeaturesForProbableJsonStrings, - [property: DataMember(Order = 7)] CodeCleanupOptions? CleanupOptions = null) - { - public const bool DefaultCrashOnAnalyzerException = false; - public const bool DefaultFadeOutUnusedImports = true; - public const bool DefaultFadeOutUnreachableCode = true; - public const bool DefaultReportInvalidPlaceholdersInStringDotFormatCalls = true; - public const bool DefaultReportInvalidRegexPatterns = true; - public const bool DefaultReportInvalidJsonPatterns = true; - public const bool DefaultDetectAndOfferEditorFeaturesForProbableJsonStrings = true; - - public static readonly IdeAnalyzerOptions CodeStyleDefault = new( - CrashOnAnalyzerException: false, - FadeOutUnusedImports: false, - FadeOutUnreachableCode: false); - -#if !CODE_STYLE - public static IdeAnalyzerOptions GetDefault(HostLanguageServices languageServices) - => new(CleanupOptions: CodeCleanupOptions.GetDefault(languageServices)); -#endif - } - - internal static partial class AnalyzerOptionsExtensions - { - public static IdeAnalyzerOptions GetIdeOptions(this AnalyzerOptions options) -#if CODE_STYLE - => IdeAnalyzerOptions.CodeStyleDefault; -#else - => (options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.IdeOptions : IdeAnalyzerOptions.CodeStyleDefault; -#endif - - public static SyntaxFormattingOptions GetSyntaxFormattingOptions(this AnalyzerOptions options, SyntaxTree tree, ISyntaxFormatting formatting) - { -#if CODE_STYLE - var fallbackOptions = (SyntaxFormattingOptions?)null; -#else - var fallbackOptions = options.GetIdeOptions().CleanupOptions?.FormattingOptions; -#endif - return formatting.GetFormattingOptions(options.AnalyzerConfigOptionsProvider.GetOptions(tree), fallbackOptions); - } - - public static T GetOption(this SemanticModelAnalysisContext context, Option2 option) - { - var analyzerOptions = context.Options; - var syntaxTree = context.SemanticModel.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, syntaxTree, cancellationToken); - } - - public static T GetOption(this SyntaxNodeAnalysisContext context, Option2 option) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Node.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, syntaxTree, cancellationToken); - } - - public static T GetOption(this SyntaxTreeAnalysisContext context, Option2 option) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Tree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, syntaxTree, cancellationToken); - } - - public static T GetOption(this OperationAnalysisContext context, Option2 option) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Operation.Syntax.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, syntaxTree, cancellationToken); - } - - public static T GetOption(this SemanticModelAnalysisContext context, PerLanguageOption2 option, string? language) - { - var analyzerOptions = context.Options; - var syntaxTree = context.SemanticModel.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, language, syntaxTree, cancellationToken); - } - - public static T GetOption(this SyntaxNodeAnalysisContext context, PerLanguageOption2 option, string? language) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Node.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, language, syntaxTree, cancellationToken); - } - - public static T GetOption(this SyntaxTreeAnalysisContext context, PerLanguageOption2 option, string? language) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Tree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, language, syntaxTree, cancellationToken); - } - - public static T GetOption(this OperationAnalysisContext context, PerLanguageOption2 option, string? language) - { - var analyzerOptions = context.Options; - var syntaxTree = context.Operation.Syntax.SyntaxTree; - var cancellationToken = context.CancellationToken; - - return analyzerOptions.GetOption(option, language, syntaxTree, cancellationToken); - } - - public static bool TryGetEditorConfigOption(this AnalyzerOptions analyzerOptions, TOption option, SyntaxTree syntaxTree, [MaybeNullWhen(false)] out T value) - { - var configOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - return configOptions.TryGetEditorConfigOption(option, out value); - } - } -} diff --git a/src/Analyzers/Core/Analyzers/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs index e43a3d0071f43..59059cfe0fede 100644 --- a/src/Analyzers/Core/Analyzers/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs @@ -100,7 +100,7 @@ void OnSymbolEnd(SymbolAnalysisContext symbolEndContext) var (isCandidate, written) = value; if (isCandidate && !written) { - var option = GetCodeStyleOption(field, symbolEndContext.Options, symbolEndContext.CancellationToken); + var option = GetCodeStyleOption(field, symbolEndContext.Options); var diagnostic = DiagnosticHelper.Create( Descriptor, field.Locations[0], @@ -166,7 +166,7 @@ void UpdateFieldStateOnWrite(IFieldSymbol field) { Debug.Assert(IsCandidateField(field, threadStaticAttribute, dataContractAttribute, dataMemberAttribute)); - var option = GetCodeStyleOption(field, options, cancellationToken); + var option = GetCodeStyleOption(field, options); if (option == null || !option.Value) { return default; @@ -219,7 +219,7 @@ private static bool IsFieldWrite(IFieldReferenceOperation fieldReference, ISymbo return true; } - private static CodeStyleOption2 GetCodeStyleOption(IFieldSymbol field, AnalyzerOptions options, CancellationToken cancellationToken) - => options.GetOption(CodeStyleOptions2.PreferReadonly, field.Language, field.Locations[0].SourceTree, cancellationToken); + private static CodeStyleOption2 GetCodeStyleOption(IFieldSymbol field, AnalyzerOptions options) + => options.GetAnalyzerOptions(field.Locations[0].SourceTree).PreferReadonly; } } diff --git a/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs b/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs index f0884382b3d8e..d0654f0214c51 100644 --- a/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Analyzers/Core/Analyzers/NamingStyle/NamingStyleDiagnosticAnalyzerBase.cs @@ -128,12 +128,13 @@ void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) return null; } - var namingPreferences = GetNamingStylePreferences(compilation, symbol, options, cancellationToken); - if (namingPreferences == null) + var sourceTree = symbol.Locations.FirstOrDefault()?.SourceTree; + if (sourceTree == null) { return null; } + var namingPreferences = options.GetAnalyzerOptions(sourceTree).NamingPreferences; var namingStyleRules = namingPreferences.Rules; if (!namingStyleRules.TryGetApplicableRule(symbol, out var applicableRule) || @@ -167,21 +168,6 @@ void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext) return DiagnosticHelper.Create(Descriptor, symbol.Locations.First(), applicableRule.EnforcementLevel, additionalLocations: null, builder.ToImmutable(), failureReason); } - private static NamingStylePreferences? GetNamingStylePreferences( - Compilation compilation, - ISymbol symbol, - AnalyzerOptions options, - CancellationToken cancellationToken) - { - var sourceTree = symbol.Locations.FirstOrDefault()?.SourceTree; - if (sourceTree == null) - { - return null; - } - - return options.GetOption(NamingStyleOptions.NamingPreferences, compilation.Language, sourceTree, cancellationToken); - } - public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; } diff --git a/src/Analyzers/Core/Analyzers/NewLines/ConsecutiveStatementPlacement/AbstractConsecutiveStatementPlacementDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/NewLines/ConsecutiveStatementPlacement/AbstractConsecutiveStatementPlacementDiagnosticAnalyzer.cs index 23953de87f2b0..b1495b0f7d8bd 100644 --- a/src/Analyzers/Core/Analyzers/NewLines/ConsecutiveStatementPlacement/AbstractConsecutiveStatementPlacementDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/NewLines/ConsecutiveStatementPlacement/AbstractConsecutiveStatementPlacementDiagnosticAnalyzer.cs @@ -39,13 +39,14 @@ protected sealed override void InitializeWorker(AnalysisContext context) private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { - var cancellationToken = context.CancellationToken; - var tree = context.Tree; - var option = context.GetOption(CodeStyleOptions2.AllowStatementImmediatelyAfterBlock, tree.Options.Language); + var option = context.GetAnalyzerOptions().AllowStatementImmediatelyAfterBlock; if (option.Value) return; - Recurse(context, option.Notification.Severity, tree.GetRoot(cancellationToken), cancellationToken); + var cancellationToken = context.CancellationToken; + var root = context.Tree.GetRoot(cancellationToken); + + Recurse(context, option.Notification.Severity, root, cancellationToken); } private void Recurse(SyntaxTreeAnalysisContext context, ReportDiagnostic severity, SyntaxNode node, CancellationToken cancellationToken) diff --git a/src/Analyzers/Core/Analyzers/NewLines/MultipleBlankLines/AbstractMultipleBlankLinesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/NewLines/MultipleBlankLines/AbstractMultipleBlankLinesDiagnosticAnalyzer.cs index 68fe7dd278f87..aa547ccba89ad 100644 --- a/src/Analyzers/Core/Analyzers/NewLines/MultipleBlankLines/AbstractMultipleBlankLinesDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/NewLines/MultipleBlankLines/AbstractMultipleBlankLinesDiagnosticAnalyzer.cs @@ -35,13 +35,12 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeTree(SyntaxTreeAnalysisContext context) { - var option = context.GetOption(CodeStyleOptions2.AllowMultipleBlankLines, context.Tree.Options.Language); + var option = context.GetAnalyzerOptions().AllowMultipleBlankLines; if (option.Value) return; - var tree = context.Tree; var cancellationToken = context.CancellationToken; - var root = tree.GetRoot(cancellationToken); + var root = context.Tree.GetRoot(cancellationToken); Recurse(context, option.Notification.Severity, root, cancellationToken); } diff --git a/src/Analyzers/Core/Analyzers/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs index 4663d2ff4c60b..5dcbe9d0a1746 100644 --- a/src/Analyzers/Core/Analyzers/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/OrderModifiers/AbstractOrderModifiersDiagnosticAnalyzer.cs @@ -14,7 +14,6 @@ namespace Microsoft.CodeAnalysis.OrderModifiers internal abstract class AbstractOrderModifiersDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { private readonly ISyntaxFacts _syntaxFacts; - private readonly Option2> _option; private readonly AbstractOrderModifiersHelpers _helpers; protected AbstractOrderModifiersDiagnosticAnalyzer( @@ -30,7 +29,6 @@ protected AbstractOrderModifiersDiagnosticAnalyzer( new LocalizableResourceString(nameof(AnalyzersResources.Modifiers_are_not_ordered), AnalyzersResources.ResourceManager, typeof(AnalyzersResources))) { _syntaxFacts = syntaxFacts; - _option = option; _helpers = helpers; } @@ -40,9 +38,11 @@ public override DiagnosticAnalyzerCategory GetAnalyzerCategory() protected override void InitializeWorker(AnalysisContext context) => context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree); + protected abstract CodeStyleOption2 GetPreferredOrderStyle(SyntaxTreeAnalysisContext context); + private void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context) { - var option = context.GetOption(_option); + var option = GetPreferredOrderStyle(context); if (!_helpers.TryGetOrComputePreferredOrder(option.Value, out var preferredOrder)) { return; diff --git a/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs index a5e4bbd501530..8a4167e5ebce1 100644 --- a/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/QualifyMemberAccess/AbstractQualifyMemberAccessDiagnosticAnalyzer.cs @@ -10,22 +10,16 @@ using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#endif - namespace Microsoft.CodeAnalysis.QualifyMemberAccess { internal abstract class AbstractQualifyMemberAccessDiagnosticAnalyzer< TLanguageKindEnum, TExpressionSyntax, - TSimpleNameSyntax, - TSimplifierOptions> + TSimpleNameSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TSimpleNameSyntax : TExpressionSyntax - where TSimplifierOptions : SimplifierOptions { protected AbstractQualifyMemberAccessDiagnosticAnalyzer() : base(IDEDiagnosticIds.AddThisOrMeQualificationDiagnosticId, @@ -64,7 +58,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); + protected abstract ISimplification Simplification { get; } public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -127,7 +121,7 @@ private void AnalyzeOperation(OperationAnalysisContext context, IOperation opera _ => throw ExceptionUtilities.UnexpectedValue(operation), }; - var simplifierOptions = GetSimplifierOptions(context.Options, context.Operation.Syntax.SyntaxTree); + var simplifierOptions = context.GetAnalyzerOptions().GetSimplifierOptions(Simplification); if (!simplifierOptions.TryGetQualifyMemberAccessOption(symbolKind, out var optionValue)) return; diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs index 9b032c8a380d4..e5b9ea063f46d 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs @@ -137,7 +137,7 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) // for us appropriately. unnecessaryImports = MergeImports(unnecessaryImports); - var fadeOut = context.Options.GetIdeOptions().FadeOutUnusedImports; + var fadeOut = context.GetIdeAnalyzerOptions().FadeOutUnusedImports; DiagnosticDescriptor descriptor; if (GeneratedCodeUtilities.IsGeneratedCode(tree, IsRegularCommentOrDocComment, cancellationToken)) diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryParentheses/AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryParentheses/AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer.cs index 9179b2d43cc7b..8f96217e96f7a 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnnecessaryParentheses/AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessaryParentheses/AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer.cs @@ -81,8 +81,8 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) break; } - var option = GetLanguageOption(precedence); - var preference = context.GetOption(option, parenthesizedExpression.Language); + var options = context.GetAnalyzerOptions(); + var preference = GetLanguageOption(options, precedence); if (preference.Notification.Severity == ReportDiagnostic.Suppress) { diff --git a/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryPragmaSuppressionsDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryPragmaSuppressionsDiagnosticAnalyzer.cs index 95220efc83ae5..a487a3d60afc0 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryPragmaSuppressionsDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryPragmaSuppressionsDiagnosticAnalyzer.cs @@ -109,8 +109,7 @@ public async Task AnalyzeAsync( } // Bail out if analyzer has been turned off through options. - var option = compilationWithAnalyzers.AnalysisOptions.Options?.GetOption( - CodeStyleOptions2.RemoveUnnecessarySuppressionExclusions, tree, cancellationToken).Trim(); + var option = compilationWithAnalyzers.AnalysisOptions.Options?.GetAnalyzerOptions(tree).RemoveUnnecessarySuppressionExclusions.Trim(); var (userIdExclusions, userCategoryExclusions, analyzerDisabled) = ParseUserExclusions(option); if (analyzerDisabled) { diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs index 54e1f0deb591e..7ed12dc30871c 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs @@ -82,9 +82,7 @@ public static void Analyze(OperationBlockStartAnalysisContext context, SymbolSta // All operation blocks for a symbol belong to the same tree. var firstBlock = context.OperationBlocks[0]; if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree, - firstBlock.Language, context.Options, - context.CancellationToken, out var options)) { return; @@ -595,7 +593,7 @@ private void AnalyzeUnusedValueAssignments( if (shouldReport) { - _symbolStartAnalyzer.ReportUnusedParameterDiagnostic(unusedParameter, hasReference, context.ReportDiagnostic, context.Options, context.CancellationToken); + _symbolStartAnalyzer.ReportUnusedParameterDiagnostic(unusedParameter, hasReference, context.ReportDiagnostic, context.Options); } } diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs index fcb6875d21240..4c76ad200e6a1 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs @@ -121,7 +121,7 @@ private void OnSymbolEnd(SymbolAnalysisContext context) { foreach (var (parameter, hasReference) in _unusedParameters) { - ReportUnusedParameterDiagnostic(parameter, hasReference, context.ReportDiagnostic, context.Options, context.CancellationToken); + ReportUnusedParameterDiagnostic(parameter, hasReference, context.ReportDiagnostic, context.Options); } } @@ -129,8 +129,7 @@ private void ReportUnusedParameterDiagnostic( IParameterSymbol parameter, bool hasReference, Action reportDiagnostic, - AnalyzerOptions analyzerOptions, - CancellationToken cancellationToken) + AnalyzerOptions analyzerOptions) { if (!IsUnusedParameterCandidate(parameter)) { @@ -138,7 +137,7 @@ private void ReportUnusedParameterDiagnostic( } var location = parameter.Locations[0]; - var option = analyzerOptions.GetOption(CodeStyleOptions2.UnusedParameters, parameter.Language, location.SourceTree, cancellationToken); + var option = analyzerOptions.GetAnalyzerOptions(location.SourceTree).UnusedParameters; if (option.Notification.Severity == ReportDiagnostic.Suppress || !ShouldReportUnusedParameters(parameter.ContainingSymbol, option.Value, option.Notification.Severity)) { diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs index 58684220ca925..9e11f83d22ebc 100644 --- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs @@ -100,8 +100,6 @@ protected AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer( .Add(s_unusedParameterRule, CodeStyleOptions2.UnusedParameters), language) { - UnusedValueExpressionStatementOption = unusedValueExpressionStatementOption; - UnusedValueAssignmentOption = unusedValueAssignmentOption; } protected abstract bool IsRecordDeclaration(SyntaxNode node); @@ -109,8 +107,8 @@ protected AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer( protected abstract bool SupportsDiscard(SyntaxTree tree); protected abstract bool MethodHasHandlesClause(IMethodSymbol method); protected abstract bool IsIfConditionalDirective(SyntaxNode node); - private Option2> UnusedValueExpressionStatementOption { get; } - private Option2> UnusedValueAssignmentOption { get; } + protected abstract CodeStyleOption2 GetUnusedValueExpressionStatementOption(AnalyzerOptionsProvider provider); + protected abstract CodeStyleOption2 GetUnusedValueAssignmentOption(AnalyzerOptionsProvider provider); /// /// Indicates if we should bail from removable assignment analysis for the given @@ -196,18 +194,16 @@ protected sealed override void InitializeWorker(AnalysisContext context) compilationContext => SymbolStartAnalyzer.CreateAndRegisterActions(compilationContext, this)); } - private bool TryGetOptions( - SyntaxTree syntaxTree, - string language, - AnalyzerOptions analyzerOptions, - CancellationToken cancellationToken, - out Options options) + private bool TryGetOptions(SyntaxTree syntaxTree, AnalyzerOptions analyzerOptions, out Options options) { options = null; - var unusedParametersOption = analyzerOptions.GetOption(CodeStyleOptions2.UnusedParameters, language, syntaxTree, cancellationToken); - var (unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity) = GetPreferenceAndSeverity(UnusedValueExpressionStatementOption); - var (unusedValueAssignmentPreference, unusedValueAssignmentSeverity) = GetPreferenceAndSeverity(UnusedValueAssignmentOption); + var optionsProvider = analyzerOptions.GetAnalyzerOptions(syntaxTree); + + var unusedParametersOption = optionsProvider.UnusedParameters; + var (unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity) = GetPreferenceAndSeverity(GetUnusedValueExpressionStatementOption(optionsProvider)); + var (unusedValueAssignmentPreference, unusedValueAssignmentSeverity) = GetPreferenceAndSeverity(GetUnusedValueAssignmentOption(optionsProvider)); + if (unusedParametersOption.Notification.Severity == ReportDiagnostic.Suppress && unusedValueExpressionStatementSeverity == ReportDiagnostic.Suppress && unusedValueAssignmentSeverity == ReportDiagnostic.Suppress) @@ -221,10 +217,8 @@ private bool TryGetOptions( return true; // Local functions. - (UnusedValuePreference preference, ReportDiagnostic severity) GetPreferenceAndSeverity( - Option2> codeStyleOption) + (UnusedValuePreference preference, ReportDiagnostic severity) GetPreferenceAndSeverity(CodeStyleOption2 option) { - var option = analyzerOptions.GetOption(codeStyleOption, syntaxTree, cancellationToken); var preferenceOpt = option?.Value; if (preferenceOpt == null || option.Notification.Severity == ReportDiagnostic.Suppress) diff --git a/src/Analyzers/Core/Analyzers/SimplifyBooleanExpression/AbstractSimplifyConditionalDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/SimplifyBooleanExpression/AbstractSimplifyConditionalDiagnosticAnalyzer.cs index 400f515c55b20..59d2a0312030e 100644 --- a/src/Analyzers/Core/Analyzers/SimplifyBooleanExpression/AbstractSimplifyConditionalDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/SimplifyBooleanExpression/AbstractSimplifyConditionalDiagnosticAnalyzer.cs @@ -63,20 +63,15 @@ protected sealed override void InitializeWorker(AnalysisContext context) private void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context) { - var semanticModel = context.SemanticModel; - var syntaxTree = semanticModel.SyntaxTree; - var options = context.Options; - var cancellationToken = context.CancellationToken; - - var styleOption = options.GetOption( - CodeStyleOptions2.PreferSimplifiedBooleanExpressions, - semanticModel.Language, syntaxTree, cancellationToken); + var styleOption = context.GetAnalyzerOptions().PreferSimplifiedBooleanExpressions; if (!styleOption.Value) { // Bail immediately if the user has disabled this feature. return; } + var semanticModel = context.SemanticModel; + var cancellationToken = context.CancellationToken; var conditionalExpression = (TConditionalExpressionSyntax)context.Node; SyntaxFacts.GetPartsOfConditionalExpression( conditionalExpression, out var conditionNode, out var whenTrueNode, out var whenFalseNode); diff --git a/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs index 34cbe384700fd..dad44fac24a4f 100644 --- a/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs @@ -41,24 +41,14 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeInterpolation(OperationAnalysisContext context) { - var interpolation = (IInterpolationOperation)context.Operation; - - var syntaxTree = interpolation.Syntax.SyntaxTree; - var cancellationToken = context.CancellationToken; - var optionSet = context.Options.GetAnalyzerOptionSet(syntaxTree, cancellationToken); - if (optionSet == null) - { - return; - } - - var language = interpolation.Language; - var option = optionSet.GetOption(CodeStyleOptions2.PreferSimplifiedInterpolation, language); + var option = context.GetAnalyzerOptions().PreferSimplifiedInterpolation; if (!option.Value) { // No point in analyzing if the option is off. return; } + var interpolation = (IInterpolationOperation)context.Operation; GetHelpers().UnwrapInterpolation( GetVirtualCharService(), GetSyntaxFacts(), interpolation, out _, out var alignment, out _, out var formatString, out var unnecessaryLocations); diff --git a/src/Analyzers/Core/Analyzers/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs index d3b18fe7b3f34..1f998e87d2fa1 100644 --- a/src/Analyzers/Core/Analyzers/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseAutoProperty/AbstractUseAutoPropertyAnalyzer.cs @@ -55,7 +55,7 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context) var semanticModel = context.SemanticModel; // Don't even bother doing the analysis if the user doesn't even want auto-props. - var option = context.GetOption(CodeStyleOptions2.PreferAutoProperties, semanticModel.Language); + var option = context.GetAnalyzerOptions().PreferAutoProperties; if (!option.Value) { return; @@ -322,7 +322,7 @@ private void Process(AnalysisResult result, SemanticModelAnalysisContext context propertyDeclaration.GetLocation(), variableDeclarator.GetLocation()); - var option = context.GetOption(CodeStyleOptions2.PreferAutoProperties, propertyDeclaration.Language); + var option = context.GetAnalyzerOptions().PreferAutoProperties; if (option.Notification.Severity == ReportDiagnostic.Suppress) { // Avoid reporting diagnostics when the feature is disabled. This primarily avoids reporting the hidden diff --git a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs index aa1738669697e..f7436057827f1 100644 --- a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionDiagnosticAnalyzer.cs @@ -49,7 +49,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) var cancellationToken = context.CancellationToken; var conditionalExpression = (TConditionalExpressionSyntax)context.Node; - var option = context.GetOption(CodeStyleOptions2.PreferCoalesceExpression, conditionalExpression.Language); + var option = context.GetAnalyzerOptions().PreferCoalesceExpression; if (!option.Value) return; diff --git a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs index e6b08a4307230..b77d667770cf5 100644 --- a/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCoalesceExpression/AbstractUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs @@ -50,7 +50,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context) var cancellationToken = context.CancellationToken; - var option = context.GetOption(CodeStyleOptions2.PreferCoalesceExpression, conditionalExpression.Language); + var option = context.GetAnalyzerOptions().PreferCoalesceExpression; if (!option.Value) { return; diff --git a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs index af5705125fef7..db0614f7ebe0f 100644 --- a/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCollectionInitializer/AbstractUseCollectionInitializerDiagnosticAnalyzer.cs @@ -77,7 +77,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol ien var language = objectCreationExpression.Language; var cancellationToken = context.CancellationToken; - var option = context.GetOption(CodeStyleOptions2.PreferCollectionInitializer, language); + var option = context.GetAnalyzerOptions().PreferCollectionInitializer; if (!option.Value) { // not point in analyzing if the option is off. @@ -124,8 +124,7 @@ private void FadeOutCode( { var syntaxTree = context.Node.SyntaxTree; - var fadeOutCode = context.GetOption( - CodeStyleOptions2.PreferCollectionInitializer_FadeOutCode, context.Node.Language); + var fadeOutCode = context.GetIdeAnalyzerOptions().FadeOutComplexObjectInitialization; if (!fadeOutCode) return; diff --git a/src/Analyzers/Core/Analyzers/UseCompoundAssignment/AbstractUseCompoundAssignmentDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseCompoundAssignment/AbstractUseCompoundAssignmentDiagnosticAnalyzer.cs index af90b5a3c4339..4b5759f979934 100644 --- a/src/Analyzers/Core/Analyzers/UseCompoundAssignment/AbstractUseCompoundAssignmentDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseCompoundAssignment/AbstractUseCompoundAssignmentDiagnosticAnalyzer.cs @@ -73,7 +73,7 @@ private void AnalyzeAssignment(SyntaxNodeAnalysisContext context) var cancellationToken = context.CancellationToken; var syntaxTree = assignment.SyntaxTree; - var option = context.GetOption(CodeStyleOptions2.PreferCompoundAssignment, assignment.Language); + var option = context.GetAnalyzerOptions().PreferCompoundAssignment; if (!option.Value) { // Bail immediately if the user has disabled this feature. diff --git a/src/Analyzers/Core/Analyzers/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs index 8f9f90435ae0d..521e324487d55 100644 --- a/src/Analyzers/Core/Analyzers/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseConditionalExpression/AbstractUseConditionalExpressionDiagnosticAnalyzer.cs @@ -16,8 +16,6 @@ internal abstract class AbstractUseConditionalExpressionDiagnosticAnalyzer< : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TIfStatementSyntax : SyntaxNode { - private readonly PerLanguageOption2> _option; - public sealed override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -32,11 +30,11 @@ protected AbstractUseConditionalExpressionDiagnosticAnalyzer( new LocalizableResourceString(nameof(AnalyzersResources.Convert_to_conditional_expression), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)), message) { - _option = option; } protected abstract ISyntaxFacts GetSyntaxFacts(); protected abstract bool TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol); + protected abstract CodeStyleOption2 GetStylePreference(OperationAnalysisContext context); protected sealed override void InitializeWorker(AnalysisContext context) => context.RegisterOperationAction(AnalyzeOperation, OperationKind.Conditional); @@ -49,9 +47,7 @@ private void AnalyzeOperation(OperationAnalysisContext context) return; } - var language = ifStatement.Language; - - var option = context.GetOption(_option, language); + var option = GetStylePreference(context); if (!option.Value) { return; diff --git a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs index 95dc54f63bef9..28cadc2c712a2 100644 --- a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs @@ -22,6 +22,9 @@ protected AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer( { } + protected sealed override CodeStyleOption2 GetStylePreference(OperationAnalysisContext context) + => context.GetAnalyzerOptions().PreferConditionalExpressionOverAssignment; + protected override bool TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol) => UseConditionalExpressionForAssignmentHelpers.TryMatchPattern( GetSyntaxFacts(), ifOperation, out _, out _, out _, out _); diff --git a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs index 316b82c63e712..b291e7981cccd 100644 --- a/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer.cs @@ -22,6 +22,9 @@ protected AbstractUseConditionalExpressionForReturnDiagnosticAnalyzer( { } + protected sealed override CodeStyleOption2 GetStylePreference(OperationAnalysisContext context) + => context.GetAnalyzerOptions().PreferConditionalExpressionOverReturn; + protected override bool TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol) => UseConditionalExpressionForReturnHelpers.TryMatchPattern( GetSyntaxFacts(), ifOperation, containingSymbol, out _, out _, out _, out _); diff --git a/src/Analyzers/Core/Analyzers/UseConditionalExpression/UseConditionalExpressionOptions.cs b/src/Analyzers/Core/Analyzers/UseConditionalExpression/UseConditionalExpressionOptions.cs deleted file mode 100644 index f2ff3f2e8d263..0000000000000 --- a/src/Analyzers/Core/Analyzers/UseConditionalExpression/UseConditionalExpressionOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.UseConditionalExpression -{ - internal static class UseConditionalExpressionOptions - { - public static readonly PerLanguageOption2 ConditionalExpressionWrappingLength = new( - nameof(UseConditionalExpressionOptions), - nameof(ConditionalExpressionWrappingLength), defaultValue: 120, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(ConditionalExpressionWrappingLength)}")); - } -} diff --git a/src/Analyzers/Core/Analyzers/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs index 2c9f69c11ce95..ca2efb155e6e8 100644 --- a/src/Analyzers/Core/Analyzers/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseExplicitTupleName/UseExplicitTupleNameDiagnosticAnalyzer.cs @@ -33,7 +33,7 @@ protected override void InitializeWorker(AnalysisContext context) private void AnalyzeOperation(OperationAnalysisContext context) { // We only create a diagnostic if the option's value is set to true. - var option = context.GetOption(CodeStyleOptions2.PreferExplicitTupleNames, context.Compilation.Language); + var option = context.GetAnalyzerOptions().PreferExplicitTupleNames; if (!option.Value) { return; diff --git a/src/Analyzers/Core/Analyzers/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs index f657ef7d025f3..ab45495bbf6df 100644 --- a/src/Analyzers/Core/Analyzers/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseInferredMemberName/AbstractUseInferredMemberNameDiagnosticAnalyzer.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.UseInferredMemberName { internal abstract class AbstractUseInferredMemberNameDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { - protected abstract void LanguageSpecificAnalyzeSyntax(SyntaxNodeAnalysisContext context, SyntaxTree syntaxTree, AnalyzerOptions options, CancellationToken cancellationToken); + protected abstract void AnalyzeSyntax(SyntaxNodeAnalysisContext context); public AbstractUseInferredMemberNameDiagnosticAnalyzer() : base(IDEDiagnosticIds.UseInferredMemberNameDiagnosticId, @@ -25,15 +25,5 @@ public AbstractUseInferredMemberNameDiagnosticAnalyzer() public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; - - protected void AnalyzeSyntax(SyntaxNodeAnalysisContext context) - { - var cancellationToken = context.CancellationToken; - - var syntaxTree = context.Node.SyntaxTree; - var options = context.Options; - - LanguageSpecificAnalyzeSyntax(context, syntaxTree, options, cancellationToken); - } } } diff --git a/src/Analyzers/Core/Analyzers/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs index b842fa5fc362d..a666c4596ea1b 100644 --- a/src/Analyzers/Core/Analyzers/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseIsNullCheck/AbstractUseIsNullForReferenceEqualsDiagnosticAnalyzer.cs @@ -59,7 +59,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context, IMethodSymbol refe var semanticModel = context.SemanticModel; - var option = context.GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod, semanticModel.Language); + var option = context.GetAnalyzerOptions().PreferIsNullCheckOverReferenceEqualityMethod; if (!option.Value) { return; diff --git a/src/Analyzers/Core/Analyzers/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs index 6b1c9183d870d..611fb8b279530 100644 --- a/src/Analyzers/Core/Analyzers/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseNullPropagation/AbstractUseNullPropagationDiagnosticAnalyzer.cs @@ -89,7 +89,7 @@ private void AnalyzeSyntax( { var conditionalExpression = (TConditionalExpressionSyntax)context.Node; - var option = context.GetOption(CodeStyleOptions2.PreferNullPropagation, conditionalExpression.Language); + var option = context.GetAnalyzerOptions().PreferNullPropagation; if (!option.Value) { return; diff --git a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs index 1f6a416f68469..d7a659e87616c 100644 --- a/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseObjectInitializer/AbstractUseObjectInitializerDiagnosticAnalyzer.cs @@ -67,7 +67,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) { var objectCreationExpression = (TObjectCreationExpressionSyntax)context.Node; var language = objectCreationExpression.Language; - var option = context.GetOption(CodeStyleOptions2.PreferObjectInitializer, language); + var option = context.GetAnalyzerOptions().PreferObjectInitializer; if (!option.Value) { // not point in analyzing if the option is off. @@ -111,8 +111,7 @@ private void FadeOutCode( { var syntaxTree = context.Node.SyntaxTree; - var fadeOutCode = context.GetOption( - CodeStyleOptions2.PreferObjectInitializer_FadeOutCode, context.Node.Language); + var fadeOutCode = context.GetIdeAnalyzerOptions().FadeOutComplexObjectInitialization; if (!fadeOutCode) return; diff --git a/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs index 20ea5247730cd..906f807ee1c2a 100644 --- a/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs @@ -64,13 +64,11 @@ private void AnalyzeOperationBlock(Analyzer analyzer, OperationBlockAnalysisCont // We've got multiple members to hash, or multiple statements that can be reduced at this point. Debug.Assert(elementCount >= 2 || statements.Length >= 2); - var syntaxTree = operation.Syntax.SyntaxTree; - var cancellationToken = context.CancellationToken; - - var option = context.Options.GetOption(CodeStyleOptions2.PreferSystemHashCode, operation.Language, syntaxTree, cancellationToken); + var option = context.Options.GetIdeOptions().PreferSystemHashCode; if (option?.Value != true) return; + var cancellationToken = context.CancellationToken; var operationLocation = operation.Syntax.GetLocation(); var declarationLocation = context.OwningSymbol.DeclaringSyntaxReferences[0].GetSyntax(cancellationToken).GetLocation(); context.ReportDiagnostic(DiagnosticHelper.Create( diff --git a/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs index 22cd0fa3dffea..ac248ab899c67 100644 --- a/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs @@ -36,8 +36,6 @@ namespace Microsoft.CodeAnalysis.UseThrowExpression internal abstract class AbstractUseThrowExpressionDiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { - private readonly Option2> _preferThrowExpressionOption; - protected AbstractUseThrowExpressionDiagnosticAnalyzer(Option2> preferThrowExpressionOption, string language) : base(IDEDiagnosticIds.UseThrowExpressionDiagnosticId, EnforceOnBuildValues.UseThrowExpression, @@ -46,9 +44,10 @@ protected AbstractUseThrowExpressionDiagnosticAnalyzer(Option2 PreferThrowExpressionStyle(OperationAnalysisContext context); + public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticSpanAnalysis; @@ -95,7 +94,7 @@ private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol return; } - var option = context.GetOption(_preferThrowExpressionOption); + var option = PreferThrowExpressionStyle(context); if (!option.Value) return; diff --git a/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs b/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs index 1557eb566c449..72951a6fc3a12 100644 --- a/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs +++ b/src/Analyzers/Core/Analyzers/ValidateFormatString/AbstractValidateFormatStringDiagnosticAnalyzer.cs @@ -85,7 +85,7 @@ public override void Initialize(AnalysisContext context) [PerformanceSensitive( "https://github.com/dotnet/roslyn/issues/23583", - Constraint = nameof(AnalyzerOptionsExtensions.GetOption) + " is expensive and should be avoided if a syntax-based fast path exists.")] + Constraint = "Reading editorconfig options is expensive and should be avoided if a syntax-based fast path exists.")] private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol formatProviderType) { var syntaxFacts = GetSyntaxFacts(); @@ -96,7 +96,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context, INamedTypeSymbol for return; } - if (!context.Options.GetIdeOptions().ReportInvalidPlaceholdersInStringDotFormatCalls) + if (!context.GetIdeAnalyzerOptions().ReportInvalidPlaceholdersInStringDotFormatCalls) { return; } diff --git a/src/Analyzers/Core/CodeFixes/FileHeaders/AbstractFileHeaderCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/FileHeaders/AbstractFileHeaderCodeFixProvider.cs index 46e253db0c7c7..14d5fad49b431 100644 --- a/src/Analyzers/Core/CodeFixes/FileHeaders/AbstractFileHeaderCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/FileHeaders/AbstractFileHeaderCodeFixProvider.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FileHeaders { @@ -34,7 +35,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( CodeFixesResources.Add_file_header, - cancellationToken => GetTransformedDocumentAsync(context.Document, cancellationToken), + cancellationToken => GetTransformedDocumentAsync(context.Document, context.GetOptionsProvider(), cancellationToken), nameof(AbstractFileHeaderCodeFixProvider)), diagnostic); } @@ -42,21 +43,14 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) return Task.CompletedTask; } - private async Task GetTransformedDocumentAsync(Document document, CancellationToken cancellationToken) - => document.WithSyntaxRoot(await GetTransformedSyntaxRootAsync(document, cancellationToken).ConfigureAwait(false)); + private async Task GetTransformedDocumentAsync(Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + => document.WithSyntaxRoot(await GetTransformedSyntaxRootAsync(document, fallbackOptions, cancellationToken).ConfigureAwait(false)); - private async Task GetTransformedSyntaxRootAsync(Document document, CancellationToken cancellationToken) + private async Task GetTransformedSyntaxRootAsync(Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { -#if CODE_STYLE - var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(root.SyntaxTree, cancellationToken); -#else - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif - - var newLine = options.GetOption(FormattingOptions2.NewLine, document.Project.Language); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var generator = document.GetRequiredLanguageService(); - var newLineTrivia = generator.EndOfLine(newLine); + var newLineTrivia = generator.EndOfLine(options.NewLine); return await GetTransformedSyntaxRootAsync(generator.SyntaxFacts, FileHeaderHelper, newLineTrivia, document, fileHeaderTemplate: null, cancellationToken).ConfigureAwait(false); } @@ -68,13 +62,13 @@ internal static async Task GetTransformedSyntaxRootAsync(ISyntaxFact // If we weren't given a header lets get the one from editorconfig if (fileHeaderTemplate is null && - !document.Project.AnalyzerOptions.TryGetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, tree, out fileHeaderTemplate)) + !document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(tree).TryGetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, out fileHeaderTemplate)) { // No header supplied, no editorconfig setting, nothing to do return root; } - if (string.IsNullOrEmpty(fileHeaderTemplate)) + if (RoslynString.IsNullOrEmpty(fileHeaderTemplate)) { // Header template is empty, nothing to do. This shouldn't be possible if this method is called in // reaction to a diagnostic, but this method is also used when creating new documents so lets be defensive. @@ -238,7 +232,7 @@ public override FixAllProvider GetFixAllProvider() if (diagnostics.IsEmpty) return null; - return await this.GetTransformedDocumentAsync(document, context.CancellationToken).ConfigureAwait(false); + return await this.GetTransformedDocumentAsync(document, context.GetOptionsProvider(), context.CancellationToken).ConfigureAwait(false); }); } } diff --git a/src/Analyzers/Core/CodeFixes/Formatting/FormattingCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/Formatting/FormattingCodeFixProvider.cs index f88d08e1c244f..9739bc7cda65d 100644 --- a/src/Analyzers/Core/CodeFixes/Formatting/FormattingCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/Formatting/FormattingCodeFixProvider.cs @@ -40,7 +40,8 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) private async Task FixOneAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) { - var formattingOptions = await context.Document.GetSyntaxFormattingOptionsAsync(SyntaxFormatting, context.GetOptionsProvider(), cancellationToken).ConfigureAwait(false); + var options = await context.Document.GetCodeFixOptionsAsync(context.GetOptionsProvider(), cancellationToken).ConfigureAwait(false); + var formattingOptions = options.GetFormattingOptions(SyntaxFormatting); var tree = await context.Document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var updatedTree = await FormattingCodeFixHelper.FixOneAsync(tree, SyntaxFormatting, formattingOptions, diagnostic, cancellationToken).ConfigureAwait(false); return context.Document.WithText(await updatedTree.GetTextAsync(cancellationToken).ConfigureAwait(false)); @@ -48,7 +49,8 @@ private async Task FixOneAsync(CodeFixContext context, Diagnostic diag protected override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(SyntaxFormatting, fallbackOptions, cancellationToken).ConfigureAwait(false); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var formattingOptions = options.GetFormattingOptions(SyntaxFormatting); var updatedRoot = Formatter.Format(editor.OriginalRoot, SyntaxFormatting, formattingOptions, cancellationToken); editor.ReplaceNode(editor.OriginalRoot, updatedRoot); } diff --git a/src/Analyzers/Core/CodeFixes/NewLines/ConsecutiveStatementPlacement/ConsecutiveStatementPlacementCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/NewLines/ConsecutiveStatementPlacement/ConsecutiveStatementPlacementCodeFixProvider.cs index cdb10c3daf4ca..321d61a6991d8 100644 --- a/src/Analyzers/Core/CodeFixes/NewLines/ConsecutiveStatementPlacement/ConsecutiveStatementPlacementCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/NewLines/ConsecutiveStatementPlacement/ConsecutiveStatementPlacementCodeFixProvider.cs @@ -36,28 +36,22 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) var diagnostic = context.Diagnostics.First(); context.RegisterCodeFix(CodeAction.Create( CodeFixesResources.Add_blank_line_after_block, - c => UpdateDocumentAsync(document, diagnostic, c), + c => UpdateDocumentAsync(document, diagnostic, context.GetOptionsProvider(), c), nameof(CodeFixesResources.Add_blank_line_after_block)), context.Diagnostics); return Task.CompletedTask; } - private static Task UpdateDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) - => FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken); + private static Task UpdateDocumentAsync(Document document, Diagnostic diagnostic, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + => FixAllAsync(document, ImmutableArray.Create(diagnostic), fallbackOptions, cancellationToken); - public static async Task FixAllAsync(Document document, ImmutableArray diagnostics, CancellationToken cancellationToken) + public static async Task FixAllAsync(Document document, ImmutableArray diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); -#if CODE_STYLE - var options = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(root.SyntaxTree, cancellationToken); -#else - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); -#endif - - var newLine = options.GetOption(FormattingOptions2.NewLine, document.Project.Language); var generator = document.GetRequiredLanguageService(); - var endOfLineTrivia = generator.EndOfLine(newLine); + var endOfLineTrivia = generator.EndOfLine(options.NewLine); var nextTokens = diagnostics.Select(d => d.AdditionalLocations[0].FindToken(cancellationToken)); var newRoot = root.ReplaceTokens( @@ -68,6 +62,6 @@ public static async Task FixAllAsync(Document document, ImmutableArray } public override FixAllProvider GetFixAllProvider() - => FixAllProvider.Create(async (context, document, diagnostics) => await FixAllAsync(document, diagnostics, context.CancellationToken).ConfigureAwait(false)); + => FixAllProvider.Create(async (context, document, diagnostics) => await FixAllAsync(document, diagnostics, context.GetOptionsProvider(), context.CancellationToken).ConfigureAwait(false)); } } diff --git a/src/Analyzers/Core/CodeFixes/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs index b93529bbf9e35..f437f7d3d67ac 100644 --- a/src/Analyzers/Core/CodeFixes/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/OrderModifiers/AbstractOrderModifiersCodeFixProvider.cs @@ -22,20 +22,18 @@ namespace Microsoft.CodeAnalysis.OrderModifiers internal abstract class AbstractOrderModifiersCodeFixProvider : SyntaxEditorBasedCodeFixProvider { private readonly ISyntaxFacts _syntaxFacts; - private readonly Option2> _option; private readonly AbstractOrderModifiersHelpers _helpers; protected AbstractOrderModifiersCodeFixProvider( ISyntaxFacts syntaxFacts, - Option2> option, AbstractOrderModifiersHelpers helpers) { _syntaxFacts = syntaxFacts; - _option = option; _helpers = helpers; } protected abstract ImmutableArray FixableCompilerErrorIds { get; } + protected abstract CodeStyleOption2 GetCodeStyleOption(AnalyzerOptionsProvider options); public sealed override ImmutableArray FixableDiagnosticIds => FixableCompilerErrorIds.Add(IDEDiagnosticIds.OrderModifiersDiagnosticId); @@ -54,8 +52,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) protected override async Task FixAllAsync( Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var option = document.Project.AnalyzerOptions.GetOption(_option, tree, cancellationToken); + var options = await document.GetAnalyzerOptionsProviderAsync(cancellationToken).ConfigureAwait(false); + var option = GetCodeStyleOption(options); if (!_helpers.TryGetOrComputePreferredOrder(option.Value, out var preferredOrder)) { return; diff --git a/src/Analyzers/Core/CodeFixes/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsCodeFixProvider.cs index 1a70925b76634..ac0509bc82fb4 100644 --- a/src/Analyzers/Core/CodeFixes/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/RemoveUnnecessaryImports/AbstractRemoveUnnecessaryImportsCodeFixProvider.cs @@ -40,11 +40,13 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) private async Task RemoveUnnecessaryImportsAsync( Document document, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(GetSyntaxFormatting(), options, cancellationToken).ConfigureAwait(false); + + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var formattingOptions = options.GetFormattingOptions(GetSyntaxFormatting()); return await service.RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false); } } diff --git a/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs index dda8bfc7b1903..e27df4315b41c 100644 --- a/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/RemoveUnusedParametersAndValues/AbstractRemoveUnusedValuesCodeFixProvider.cs @@ -264,7 +264,8 @@ private static async Task PreprocessDocumentAsync(Document document, I protected sealed override async Task FixAllAsync(Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(GetSyntaxFormatting(), fallbackOptions, cancellationToken).ConfigureAwait(false); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var formattingOptions = options.GetFormattingOptions(GetSyntaxFormatting()); var preprocessedDocument = await PreprocessDocumentAsync(document, diagnostics, cancellationToken).ConfigureAwait(false); var newRoot = await GetNewRootAsync(preprocessedDocument, formattingOptions, diagnostics, cancellationToken).ConfigureAwait(false); editor.ReplaceNode(editor.OriginalRoot, newRoot); diff --git a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/AbstractUseConditionalExpressionCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/AbstractUseConditionalExpressionCodeFixProvider.cs index 60faa3c5db1fc..c92bb05cc1177 100644 --- a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/AbstractUseConditionalExpressionCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/AbstractUseConditionalExpressionCodeFixProvider.cs @@ -46,7 +46,7 @@ internal abstract class AbstractUseConditionalExpressionCodeFixProvider< protected abstract Task FixOneAsync( Document document, Diagnostic diagnostic, - SyntaxEditor editor, CancellationToken cancellationToken); + SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected override async Task FixAllAsync( Document document, ImmutableArray diagnostics, SyntaxEditor editor, @@ -62,7 +62,7 @@ protected override async Task FixAllAsync( foreach (var diagnostic in diagnostics) { await FixOneAsync( - document, diagnostic, nestedEditor, cancellationToken).ConfigureAwait(false); + document, diagnostic, nestedEditor, fallbackOptions, cancellationToken).ConfigureAwait(false); } var changedRoot = nestedEditor.GetChangedRoot(); @@ -78,7 +78,8 @@ await FixOneAsync( #else var provider = document.Project.Solution.Workspace.Services; #endif - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(GetSyntaxFormatting(), fallbackOptions, cancellationToken).ConfigureAwait(false); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var formattingOptions = options.GetFormattingOptions(GetSyntaxFormatting()); var formattedRoot = Formatter.Format(changedRoot, SpecializedFormattingAnnotation, provider, formattingOptions, rules, cancellationToken); changedRoot = formattedRoot; @@ -96,7 +97,7 @@ protected async Task CreateConditionalExpressionAsync( Document document, IConditionalOperation ifOperation, IOperation trueStatement, IOperation falseStatement, IOperation trueValue, IOperation falseValue, - bool isRef, CancellationToken cancellationToken) + bool isRef, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var generator = SyntaxGenerator.GetGenerator(document); var generatorInternal = document.GetRequiredLanguageService(); @@ -129,7 +130,7 @@ protected async Task CreateConditionalExpressionAsync( conditionalExpression = conditionalExpression.WithAdditionalAnnotations(Simplifier.Annotation); var makeMultiLine = await MakeMultiLineAsync( document, condition, - trueValue.Syntax, falseValue.Syntax, cancellationToken).ConfigureAwait(false); + trueValue.Syntax, falseValue.Syntax, fallbackOptions, cancellationToken).ConfigureAwait(false); if (makeMultiLine) { conditionalExpression = conditionalExpression.WithAdditionalAnnotations( @@ -157,7 +158,7 @@ private static TExpressionSyntax MakeRef(SyntaxGeneratorInternal generator, bool /// Checks if we should wrap the conditional expression over multiple lines. /// private static async Task MakeMultiLineAsync( - Document document, SyntaxNode condition, SyntaxNode trueSyntax, SyntaxNode falseSyntax, + Document document, SyntaxNode condition, SyntaxNode trueSyntax, SyntaxNode falseSyntax, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); @@ -168,13 +169,12 @@ private static async Task MakeMultiLineAsync( return true; } -#if CODE_STYLE - var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var wrappingLength = document.Project.AnalyzerOptions.GetOption(UseConditionalExpressionOptions.ConditionalExpressionWrappingLength, document.Project.Language, tree, cancellationToken); -#else - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var wrappingLength = options.GetOption(UseConditionalExpressionOptions.ConditionalExpressionWrappingLength); + // the option is currently not an editorconfig option, so not available in code style layer + var wrappingLength = +#if !CODE_STYLE + fallbackOptions.GetOptions(document.Project.LanguageServices)?.ConditionalExpressionWrappingLength ?? #endif + CodeActionOptions.DefaultConditionalExpressionWrappingLength; if (condition.Span.Length + trueSyntax.Span.Length + falseSyntax.Span.Length > wrappingLength) { diff --git a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs index b6384b2fb5506..22f9c9adc622d 100644 --- a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs @@ -55,7 +55,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) /// protected override async Task FixOneAsync( Document document, Diagnostic diagnostic, - SyntaxEditor editor, CancellationToken cancellationToken) + SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService(); var ifStatement = diagnostic.AdditionalLocations[0].FindNode(cancellationToken); @@ -76,7 +76,9 @@ protected override async Task FixOneAsync( trueStatement, falseStatement, trueAssignment?.Value ?? trueStatement, falseAssignment?.Value ?? falseStatement, - trueAssignment?.IsRef == true, cancellationToken).ConfigureAwait(false); + trueAssignment?.IsRef == true, + fallbackOptions, + cancellationToken).ConfigureAwait(false); // See if we're assigning to a variable declared directly above the if statement. If so, // try to inline the conditional directly into the initializer for that variable. diff --git a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs index 8996271183b81..888716d33eccc 100644 --- a/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs +++ b/src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs @@ -41,7 +41,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context) protected override async Task FixOneAsync( Document document, Diagnostic diagnostic, - SyntaxEditor editor, CancellationToken cancellationToken) + SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService(); var ifStatement = (TIfStatementSyntax)diagnostic.AdditionalLocations[0].FindNode(cancellationToken); @@ -64,7 +64,9 @@ protected override async Task FixOneAsync( trueStatement, falseStatement, trueReturn?.ReturnedValue ?? trueStatement, falseReturn?.ReturnedValue ?? falseStatement, - anyReturn.GetRefKind(containingSymbol) != RefKind.None, cancellationToken).ConfigureAwait(false); + anyReturn.GetRefKind(containingSymbol) != RefKind.None, + fallbackOptions, + cancellationToken).ConfigureAwait(false); var generatorInternal = document.GetRequiredLanguageService(); var returnStatement = anyReturn.Kind == OperationKind.YieldReturn diff --git a/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb b/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb new file mode 100644 index 0000000000000..f65569559fddf --- /dev/null +++ b/src/Analyzers/VisualBasic/Analyzers/CodeStyle/VisualBasicAnalyzerOptionsProvider.vb @@ -0,0 +1,120 @@ +' 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.CodeStyle +Imports Microsoft.CodeAnalysis.Options +Imports Microsoft.CodeAnalysis.VisualBasic.CodeStyle +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification + +Namespace Microsoft.CodeAnalysis.Diagnostics + ''' + ''' Provides Visual Basic analyzers a convenient access to editorconfig options with fallback to IDE default values. + ''' + Friend Structure VisualBasicAnalyzerOptionsProvider + ''' + ''' Document editorconfig options. + ''' + Private ReadOnly _options As AnalyzerConfigOptions + + ''' + ''' Fallback options - the default options in Code Style layer. + ''' + Private ReadOnly _fallbackOptions As IdeAnalyzerOptions + + Public Sub New(options As AnalyzerConfigOptions, fallbackOptions As IdeAnalyzerOptions) + _options = options + _fallbackOptions = fallbackOptions + End Sub + + Public Sub New(options As AnalyzerConfigOptions, fallbackOptions As AnalyzerOptions) + MyClass.New(options, fallbackOptions.GetIdeOptions()) + End Sub + + Public Function GetSimplifierOptions() As VisualBasicSimplifierOptions + Return _options.GetVisualBasicSimplifierOptions(FallbackSimplifierOptions) + End Function + + Public ReadOnly Property PreferredModifierOrder As CodeStyleOption2(Of String) + Get + Return GetOption(VisualBasicCodeStyleOptions.PreferredModifierOrder, FallbackCodeStyleOptions.PreferredModifierOrder) + End Get + End Property + + Public ReadOnly Property PreferIsNotExpression As CodeStyleOption2(Of Boolean) + Get + Return GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression, FallbackCodeStyleOptions.PreferIsNotExpression) + End Get + End Property + + Public ReadOnly Property PreferSimplifiedObjectCreation As CodeStyleOption2(Of Boolean) + Get + Return GetOption(VisualBasicCodeStyleOptions.PreferSimplifiedObjectCreation, FallbackCodeStyleOptions.PreferSimplifiedObjectCreation) + End Get + End Property + + Public ReadOnly Property UnusedValueExpressionStatement As CodeStyleOption2(Of UnusedValuePreference) + Get + Return GetOption(VisualBasicCodeStyleOptions.UnusedValueExpressionStatement, FallbackCodeStyleOptions.UnusedValueExpressionStatement) + End Get + End Property + + Public ReadOnly Property UnusedValueAssignment As CodeStyleOption2(Of UnusedValuePreference) + Get + Return GetOption(VisualBasicCodeStyleOptions.UnusedValueAssignment, FallbackCodeStyleOptions.UnusedValueAssignment) + End Get + End Property + + Private Function GetOption(Of TValue)([option] As Option2(Of CodeStyleOption2(Of TValue)), defaultValue As CodeStyleOption2(Of TValue)) As CodeStyleOption2(Of TValue) + Return _options.GetEditorConfigOption([option], defaultValue) + End Function + + Private ReadOnly Property FallbackSimplifierOptions As VisualBasicSimplifierOptions + Get + Return If(DirectCast(_fallbackOptions.CleanupOptions?.SimplifierOptions, VisualBasicSimplifierOptions), VisualBasicSimplifierOptions.Default) + End Get + End Property + + Private ReadOnly Property FallbackCodeStyleOptions As VisualBasicIdeCodeStyleOptions + Get + Return If(DirectCast(_fallbackOptions.CodeStyleOptions, VisualBasicIdeCodeStyleOptions), VisualBasicIdeCodeStyleOptions.Default) + End Get + End Property + + Public Shared Narrowing Operator CType(provider As AnalyzerOptionsProvider) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(provider.GetAnalyzerConfigOptions(), provider.GetFallbackOptions()) + End Operator + + Public Shared Widening Operator CType(provider As VisualBasicAnalyzerOptionsProvider) As AnalyzerOptionsProvider + Return New AnalyzerOptionsProvider(provider._options, provider._fallbackOptions) + End Operator + End Structure + + Friend Module VisualBasicAnalyzerOptionsProviders + + Public Function GetVisualBasicAnalyzerOptions(context As SemanticModelAnalysisContext) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.SemanticModel.SyntaxTree), context.Options) + End Function + + + Public Function GetVisualBasicAnalyzerOptions(context As SyntaxNodeAnalysisContext) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Node.SyntaxTree), context.Options) + End Function + + + Public Function GetVisualBasicAnalyzerOptions(context As SyntaxTreeAnalysisContext) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Tree), context.Options) + End Function + + + Public Function GetVisualBasicAnalyzerOptions(context As OperationAnalysisContext) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Operation.Syntax.SyntaxTree), context.Options) + End Function + + + Public Function GetVisualBasicAnalyzerOptions(context As CodeBlockAnalysisContext) As VisualBasicAnalyzerOptionsProvider + Return New VisualBasicAnalyzerOptionsProvider(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.SemanticModel.SyntaxTree), context.Options) + End Function + End Module +End Namespace diff --git a/src/Analyzers/VisualBasic/Analyzers/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb index 2fcc707c4c1f8..1b4c58c2d5a4c 100644 --- a/src/Analyzers/VisualBasic/Analyzers/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/OrderModifiers/VisualBasicOrderModifiersDiagnosticAnalyzer.vb @@ -2,6 +2,7 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.OrderModifiers Imports Microsoft.CodeAnalysis.VisualBasic.CodeStyle @@ -20,6 +21,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.OrderModifiers LanguageNames.VisualBasic) End Sub + Protected Overrides Function GetPreferredOrderStyle(context As SyntaxTreeAnalysisContext) As CodeStyleOption2(Of String) + Return context.GetVisualBasicAnalyzerOptions().PreferredModifierOrder + End Function + Protected Overrides Sub Recurse( context As SyntaxTreeAnalysisContext, preferredOrder As Dictionary(Of Integer, Integer), diff --git a/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb index 46aaf5e54f4c9..17140ff3275a1 100644 --- a/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/QualifyMemberAccess/VisualBasicQualifyMemberAccessDiagnosticAnalyzer.vb @@ -6,19 +6,22 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.QualifyMemberAccess Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Simplification +Imports Microsoft.CodeAnalysis.Simplification Namespace Microsoft.CodeAnalysis.VisualBasic.QualifyMemberAccess Friend NotInheritable Class VisualBasicQualifyMemberAccessDiagnosticAnalyzer - Inherits AbstractQualifyMemberAccessDiagnosticAnalyzer(Of SyntaxKind, ExpressionSyntax, SimpleNameSyntax, VisualBasicSimplifierOptions) + Inherits AbstractQualifyMemberAccessDiagnosticAnalyzer(Of SyntaxKind, ExpressionSyntax, SimpleNameSyntax) 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 ReadOnly Property Simplification As ISimplification + Get + Return VisualBasicSimplification.Instance + End Get + End Property Protected Overrides Function IsAlreadyQualifiedMemberAccess(node As ExpressionSyntax) As Boolean Return node.IsKind(SyntaxKind.MeExpression) diff --git a/src/Analyzers/VisualBasic/Analyzers/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb index 0793ef3ebc050..e39bf4080a7bb 100644 --- a/src/Analyzers/VisualBasic/Analyzers/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb @@ -2,6 +2,7 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Operations Imports Microsoft.CodeAnalysis.RemoveUnusedParametersAndValues @@ -20,6 +21,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedParametersAndValues LanguageNames.VisualBasic) End Sub + Protected Overrides Function GetUnusedValueExpressionStatementOption(provider As AnalyzerOptionsProvider) As CodeStyleOption2(Of UnusedValuePreference) + Return CType(provider, VisualBasicAnalyzerOptionsProvider).UnusedValueExpressionStatement + End Function + + Protected Overrides Function GetUnusedValueAssignmentOption(provider As AnalyzerOptionsProvider) As CodeStyleOption2(Of UnusedValuePreference) + Return CType(provider, VisualBasicAnalyzerOptionsProvider).UnusedValueAssignment + End Function + Protected Overrides Function IsRecordDeclaration(node As SyntaxNode) As Boolean Return False End Function diff --git a/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb b/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb deleted file mode 100644 index 34c589d637c12..0000000000000 --- a/src/Analyzers/VisualBasic/Analyzers/Simplification/VisualBasicSimplifierOptionsFactory.vb +++ /dev/null @@ -1,24 +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 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() - -#If CODE_STYLE Then - Dim fallbackOptions As VisualBasicSimplifierOptions = Nothing -#Else - Dim fallbackOptions = DirectCast(ideOptions.CleanupOptions?.SimplifierOptions, VisualBasicSimplifierOptions) -#End If - Return VisualBasicSimplifierOptions.Create(configOptions, fallbackOptions) - End Function - End Module -End Namespace - diff --git a/src/Analyzers/VisualBasic/Analyzers/SimplifyObjectCreation/VisualBasicSimplifyObjectCreationDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/SimplifyObjectCreation/VisualBasicSimplifyObjectCreationDiagnosticAnalyzer.vb index 047c0a2b797cf..1d3c7dab45686 100644 --- a/src/Analyzers/VisualBasic/Analyzers/SimplifyObjectCreation/VisualBasicSimplifyObjectCreationDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/SimplifyObjectCreation/VisualBasicSimplifyObjectCreationDiagnosticAnalyzer.vb @@ -35,15 +35,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyObjectCreation ' which can be simplified to ' Dim x As New SomeType() - Dim node = context.Node - Dim tree = node.SyntaxTree - Dim cancellationToken = context.CancellationToken - - Dim styleOption = context.Options.GetOption(VisualBasicCodeStyleOptions.PreferSimplifiedObjectCreation, tree, cancellationToken) + Dim styleOption = context.GetVisualBasicAnalyzerOptions().PreferSimplifiedObjectCreation If Not styleOption.Value Then Return End If + Dim node = context.Node Dim variableDeclarator = DirectCast(node, VariableDeclaratorSyntax) Dim asClauseType = variableDeclarator.AsClause?.Type() If asClauseType Is Nothing Then @@ -55,6 +52,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyObjectCreation Return End If + Dim cancellationToken = context.CancellationToken Dim symbolInfo = context.SemanticModel.GetTypeInfo(objectCreation, cancellationToken) If symbolInfo.Type IsNot Nothing AndAlso symbolInfo.Type.Equals(symbolInfo.ConvertedType, SymbolEqualityComparer.Default) Then context.ReportDiagnostic(DiagnosticHelper.Create(Descriptor, variableDeclarator.GetLocation(), styleOption.Notification.Severity, diff --git a/src/Analyzers/VisualBasic/Analyzers/UseInferredMemberName/VisualBasicUseInferredMemberNameDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseInferredMemberName/VisualBasicUseInferredMemberNameDiagnosticAnalyzer.vb index 18efec569d8d0..40bb8d0c8b8e5 100644 --- a/src/Analyzers/VisualBasic/Analyzers/UseInferredMemberName/VisualBasicUseInferredMemberNameDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/UseInferredMemberName/VisualBasicUseInferredMemberNameDiagnosticAnalyzer.vb @@ -24,37 +24,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseInferredMemberName SyntaxKind.NameColonEquals, SyntaxKind.NamedFieldInitializer) End Sub - Protected Overrides Sub LanguageSpecificAnalyzeSyntax(context As SyntaxNodeAnalysisContext, - syntaxTree As SyntaxTree, - options As AnalyzerOptions, - cancellationToken As CancellationToken) - Dim parseOptions = DirectCast(syntaxTree.Options, VisualBasicParseOptions) + Protected Overrides Sub AnalyzeSyntax(context As SyntaxNodeAnalysisContext) Select Case context.Node.Kind() Case SyntaxKind.NameColonEquals - ReportDiagnosticsIfNeeded(DirectCast(context.Node, NameColonEqualsSyntax), context, options, syntaxTree, parseOptions, cancellationToken) + ReportDiagnosticsIfNeeded(DirectCast(context.Node, NameColonEqualsSyntax), context) Exit Select Case SyntaxKind.NamedFieldInitializer - ReportDiagnosticsIfNeeded(DirectCast(context.Node, NamedFieldInitializerSyntax), context, options, syntaxTree, cancellationToken) + ReportDiagnosticsIfNeeded(DirectCast(context.Node, NamedFieldInitializerSyntax), context) Exit Select End Select End Sub - Private Sub ReportDiagnosticsIfNeeded(nameColonEquals As NameColonEqualsSyntax, - context As SyntaxNodeAnalysisContext, - options As AnalyzerOptions, - syntaxTree As SyntaxTree, - parseOptions As VisualBasicParseOptions, - cancellationToken As CancellationToken) + Private Sub ReportDiagnosticsIfNeeded(nameColonEquals As NameColonEqualsSyntax, context As SyntaxNodeAnalysisContext) If Not nameColonEquals.IsParentKind(SyntaxKind.SimpleArgument) Then Return End If + Dim syntaxTree = context.Node.SyntaxTree Dim argument = DirectCast(nameColonEquals.Parent, SimpleArgumentSyntax) - Dim preference = options.GetOption( - CodeStyleOptions2.PreferInferredTupleNames, context.Compilation.Language, syntaxTree, cancellationToken) - If Not preference.Value OrElse - Not CanSimplifyTupleName(argument, parseOptions) Then + Dim preference = context.GetAnalyzerOptions().PreferInferredTupleNames + If Not preference.Value OrElse Not CanSimplifyTupleName(argument, DirectCast(syntaxTree.Options, VisualBasicParseOptions)) Then Return End If @@ -69,27 +59,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseInferredMemberName additionalUnnecessaryLocations:=ImmutableArray.Create(syntaxTree.GetLocation(fadeSpan)))) End Sub - Private Sub ReportDiagnosticsIfNeeded( - fieldInitializer As NamedFieldInitializerSyntax, - context As SyntaxNodeAnalysisContext, - options As AnalyzerOptions, - syntaxTree As SyntaxTree, - cancellationToken As CancellationToken) + Private Sub ReportDiagnosticsIfNeeded(fieldInitializer As NamedFieldInitializerSyntax, context As SyntaxNodeAnalysisContext) If Not fieldInitializer.Parent.Parent.IsKind(SyntaxKind.AnonymousObjectCreationExpression) Then Return End If - Dim preference = options.GetOption( - CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames, context.Compilation.Language, syntaxTree, cancellationToken) - If Not preference.Value OrElse - Not CanSimplifyNamedFieldInitializer(fieldInitializer) Then - + Dim preference = context.GetAnalyzerOptions().PreferInferredAnonymousTypeMemberNames + If Not preference.Value OrElse Not CanSimplifyNamedFieldInitializer(fieldInitializer) Then Return End If Dim fadeSpan = TextSpan.FromBounds(fieldInitializer.Name.SpanStart, fieldInitializer.EqualsToken.Span.End) ' Create a normal diagnostic + Dim syntaxTree = context.Node.SyntaxTree context.ReportDiagnostic( DiagnosticHelper.CreateWithLocationTags( Descriptor, diff --git a/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb b/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb index 719a784d27b81..1d45d92b2af15 100644 --- a/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb +++ b/src/Analyzers/VisualBasic/Analyzers/UseIsNotExpression/VisualBasicUseIsNotDiagnosticAnalyzer.vb @@ -50,11 +50,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UseIsNotExpression Return End If - Dim options = syntaxContext.Options - Dim cancellationToken = syntaxContext.CancellationToken - ' Bail immediately if the user has disabled this feature. - Dim styleOption = options.GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression, syntaxTree, cancellationToken) + Dim styleOption = syntaxContext.GetVisualBasicAnalyzerOptions().PreferIsNotExpression If Not styleOption.Value Then Return End If diff --git a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems index 72e888f4bef43..070ab2de95fab 100644 --- a/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems +++ b/src/Analyzers/VisualBasic/Analyzers/VisualBasicAnalyzers.projitems @@ -16,6 +16,7 @@ + @@ -36,7 +37,6 @@ - diff --git a/src/Analyzers/VisualBasic/CodeFixes/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb b/src/Analyzers/VisualBasic/CodeFixes/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb index 56538b61ca959..30e17a46e3b1b 100644 --- a/src/Analyzers/VisualBasic/CodeFixes/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb +++ b/src/Analyzers/VisualBasic/CodeFixes/OrderModifiers/VisualBasicOrderModifiersCodeFixProvider.vb @@ -6,23 +6,28 @@ Imports System.Collections.Immutable Imports System.Composition Imports System.Diagnostics.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeFixes +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.OrderModifiers Imports Microsoft.CodeAnalysis.VisualBasic.CodeStyle Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.OrderModifiers - Friend Class VisualBasicOrderModifiersCodeFixProvider + Friend NotInheritable Class VisualBasicOrderModifiersCodeFixProvider Inherits AbstractOrderModifiersCodeFixProvider Public Sub New() MyBase.New(VisualBasicSyntaxFacts.Instance, - VisualBasicCodeStyleOptions.PreferredModifierOrder, VisualBasicOrderModifiersHelper.Instance) End Sub + Protected Overrides Function GetCodeStyleOption(options As AnalyzerOptionsProvider) As CodeStyleOption2(Of String) + Return CType(options, VisualBasicAnalyzerOptionsProvider).PreferredModifierOrder + End Function + Protected Overrides ReadOnly Property FixableCompilerErrorIds As ImmutableArray(Of String) = ImmutableArray(Of String).Empty End Class diff --git a/src/Analyzers/VisualBasic/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.vb b/src/Analyzers/VisualBasic/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.vb index f8296812fa0ae..a1121699eefb0 100644 --- a/src/Analyzers/VisualBasic/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.vb +++ b/src/Analyzers/VisualBasic/Tests/AddAccessibilityModifiers/AddAccessibilityModifiersTests.vb @@ -419,7 +419,7 @@ end namespace" Dim test As New VerifyVB.Test() test.TestCode = source test.FixedCode = fixedSource - test.Options.Add(CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault) + test.Options.Add(CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault) Await test.RunAsync() End Function diff --git a/src/CodeStyle/Core/Analyzers/Options/AnalyzerOptionsExtensions.cs b/src/CodeStyle/Core/Analyzers/Options/AnalyzerOptionsExtensions.cs deleted file mode 100644 index c3a38a3e69e64..0000000000000 --- a/src/CodeStyle/Core/Analyzers/Options/AnalyzerOptionsExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading; -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.Diagnostics -{ - internal static partial class AnalyzerOptionsExtensions - { -#pragma warning disable IDE0060 // Remove unused parameter - Needed to share this method signature between CodeStyle and Features layer. - public static T GetOption(this AnalyzerOptions analyzerOptions, IOption2 option, string? language, SyntaxTree syntaxTree, CancellationToken cancellationToken) -#pragma warning restore IDE0060 // Remove unused parameter - { - if (analyzerOptions.TryGetEditorConfigOption(option, syntaxTree, out var value)) - { - return value; - } - - return (T)option.DefaultValue!; - } - - public static T GetOption(this AnalyzerOptions analyzerOptions, Option2 option, SyntaxTree syntaxTree, CancellationToken cancellationToken) - => GetOption(analyzerOptions, option, language: null, syntaxTree, cancellationToken); - - public static T GetOption(this AnalyzerOptions analyzerOptions, PerLanguageOption2 option, string? language, SyntaxTree syntaxTree, CancellationToken cancellationToken) - => GetOption(analyzerOptions, (IOption2)option, language, syntaxTree, cancellationToken); - -#pragma warning disable IDE0060 // Remove unused parameter - Needed to share this method signature between CodeStyle and Features layer. - public static AnalyzerConfigOptions GetAnalyzerOptionSet(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree, CancellationToken cancellationToken) -#pragma warning restore IDE0060 // Remove unused parameter - => analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - } -} diff --git a/src/EditorFeatures/CSharp/AddImports/CSharpAddImportPlacementOptionsStorage.cs b/src/EditorFeatures/CSharp/AddImports/CSharpAddImportPlacementOptionsStorage.cs index ad0d107bfa788..dc0dd06280961 100644 --- a/src/EditorFeatures/CSharp/AddImports/CSharpAddImportPlacementOptionsStorage.cs +++ b/src/EditorFeatures/CSharp/AddImports/CSharpAddImportPlacementOptionsStorage.cs @@ -29,8 +29,10 @@ public AddImportPlacementOptions GetOptions(IGlobalOptionService globalOptions) } internal static AddImportPlacementOptions GetCSharpAddImportPlacementOptions(IGlobalOptionService globalOptions) - => new( - PlaceSystemNamespaceFirst: globalOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp), - PlaceImportsInsideNamespaces: globalOptions.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement).Value == AddImportPlacement.InsideNamespace, - AllowInHiddenRegions: false); // no global option available); + => new() + { + PlaceSystemNamespaceFirst = globalOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp), + UsingDirectivePlacement = globalOptions.GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement), + AllowInHiddenRegions = AddImportPlacementOptions.Default.AllowInHiddenRegions // no global option available); + }; } diff --git a/src/EditorFeatures/CSharp/CodeGeneration/CSharpCodeGenerationOptionsStorage.cs b/src/EditorFeatures/CSharp/CodeGeneration/CSharpCodeGenerationOptionsStorage.cs index bcc22b55fd833..6066335b7f7c0 100644 --- a/src/EditorFeatures/CSharp/CodeGeneration/CSharpCodeGenerationOptionsStorage.cs +++ b/src/EditorFeatures/CSharp/CodeGeneration/CSharpCodeGenerationOptionsStorage.cs @@ -27,15 +27,18 @@ public CodeGenerationOptions GetOptions(IGlobalOptionService globalOptions) } public static CSharpCodeGenerationOptions GetCSharpCodeGenerationOptions(this IGlobalOptionService globalOptions) - => new( - preferExpressionBodiedMethods: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods), - preferExpressionBodiedAccessors: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors), - preferExpressionBodiedProperties: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties), - preferExpressionBodiedIndexers: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers), - preferExpressionBodiedConstructors: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors), - preferExpressionBodiedOperators: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators), - preferExpressionBodiedLocalFunctions: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions), - preferExpressionBodiedLambdas: globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas), - preferStaticLocalFunction: globalOptions.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction), - namespaceDeclarations: globalOptions.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations)); + => new() + { + Common = globalOptions.GetCommonCodeGenerationOptions(LanguageNames.CSharp), + PreferExpressionBodiedMethods = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods), + PreferExpressionBodiedAccessors = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors), + PreferExpressionBodiedProperties = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties), + PreferExpressionBodiedIndexers = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers), + PreferExpressionBodiedConstructors = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors), + PreferExpressionBodiedOperators = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators), + PreferExpressionBodiedLocalFunctions = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions), + PreferExpressionBodiedLambdas = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas), + PreferStaticLocalFunction = globalOptions.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction), + NamespaceDeclarations = globalOptions.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations) + }; } diff --git a/src/EditorFeatures/CSharp/CodeStyle/CSharpCodeStyleOptionsStorage.cs b/src/EditorFeatures/CSharp/CodeStyle/CSharpCodeStyleOptionsStorage.cs new file mode 100644 index 0000000000000..310a71de65532 --- /dev/null +++ b/src/EditorFeatures/CSharp/CodeStyle/CSharpCodeStyleOptionsStorage.cs @@ -0,0 +1,59 @@ +// 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; + +namespace Microsoft.CodeAnalysis.CSharp.CodeStyle; + +internal static class CSharpCodeStyleOptionsStorage +{ + [ExportLanguageService(typeof(ICodeStyleOptionsStorage), LanguageNames.CSharp), Shared] + private sealed class Service : ICodeStyleOptionsStorage + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public Service() + { + } + + public IdeCodeStyleOptions GetOptions(IGlobalOptionService globalOptions) + => GetCSharpCodeStyleOptions(globalOptions); + } + + public static CSharpIdeCodeStyleOptions GetCSharpCodeStyleOptions(this IGlobalOptionService globalOptions) + => new() + { + Common = globalOptions.GetCommonCodeStyleOptions(LanguageNames.CSharp), + ImplicitObjectCreationWhenTypeIsApparent = globalOptions.GetOption(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent), + PreferNullCheckOverTypeCheck = globalOptions.GetOption(CSharpCodeStyleOptions.PreferNullCheckOverTypeCheck), + AllowBlankLinesBetweenConsecutiveBraces = globalOptions.GetOption(CSharpCodeStyleOptions.AllowBlankLinesBetweenConsecutiveBraces), + AllowBlankLineAfterColonInConstructorInitializer = globalOptions.GetOption(CSharpCodeStyleOptions.AllowBlankLineAfterColonInConstructorInitializer), + PreferConditionalDelegateCall = globalOptions.GetOption(CSharpCodeStyleOptions.PreferConditionalDelegateCall), + PreferSwitchExpression = globalOptions.GetOption(CSharpCodeStyleOptions.PreferSwitchExpression), + PreferPatternMatching = globalOptions.GetOption(CSharpCodeStyleOptions.PreferPatternMatching), + PreferPatternMatchingOverAsWithNullCheck = globalOptions.GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverAsWithNullCheck), + PreferPatternMatchingOverIsWithCastCheck = globalOptions.GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck), + PreferNotPattern = globalOptions.GetOption(CSharpCodeStyleOptions.PreferNotPattern), + PreferExtendedPropertyPattern = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern), + PreferInlinedVariableDeclaration = globalOptions.GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration), + PreferDeconstructedVariableDeclaration = globalOptions.GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration), + PreferIndexOperator = globalOptions.GetOption(CSharpCodeStyleOptions.PreferIndexOperator), + PreferRangeOperator = globalOptions.GetOption(CSharpCodeStyleOptions.PreferRangeOperator), + PreferUtf8StringLiterals = globalOptions.GetOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals), + PreferredModifierOrder = globalOptions.GetOption(CSharpCodeStyleOptions.PreferredModifierOrder), + PreferSimpleUsingStatement = globalOptions.GetOption(CSharpCodeStyleOptions.PreferSimpleUsingStatement), + PreferLocalOverAnonymousFunction = globalOptions.GetOption(CSharpCodeStyleOptions.PreferLocalOverAnonymousFunction), + PreferTupleSwap = globalOptions.GetOption(CSharpCodeStyleOptions.PreferTupleSwap), + UnusedValueExpressionStatement = globalOptions.GetOption(CSharpCodeStyleOptions.UnusedValueExpressionStatement), + UnusedValueAssignment = globalOptions.GetOption(CSharpCodeStyleOptions.UnusedValueAssignment), + PreferMethodGroupConversion = globalOptions.GetOption(CSharpCodeStyleOptions.PreferMethodGroupConversion), + PreferExpressionBodiedLambdas = globalOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas), + PreferStaticLocalFunction = globalOptions.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction) + }; +} diff --git a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs index c69e5095e5583..2dc085774397a 100644 --- a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs +++ b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs @@ -41,16 +41,12 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.CompleteStatement internal sealed class ConvertNamespaceCommandHandler : IChainedCommandHandler { /// - /// A fake option set where the 'use file scoped' namespace option is on. That way we can call into the helpers + /// Option setting 'use file scoped'. That way we can call into the helpers /// and have the results come back positive for converting to file-scoped regardless of the current option /// value. /// - private static readonly OptionSet s_optionSet = new OptionValueSet( - ImmutableDictionary.Empty.Add( - new OptionKey(CSharpCodeStyleOptions.NamespaceDeclarations.ToPublicOption()), - new CodeStyleOption2( - NamespaceDeclarationPreference.FileScoped, - NotificationOption2.Suggestion))); + private static readonly CodeStyleOption2 s_fileScopedNamespacePreferenceOption = + new(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Suggestion); private readonly ITextUndoHistoryRegistry _textUndoHistoryRegistry; private readonly IEditorOperationsFactoryService _editorOperationsFactoryService; @@ -148,7 +144,7 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler, return default; // Pass in our special options, and C#10 so that if we can convert this to file-scoped, we will. - if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(s_optionSet, root, namespaceDecl, forAnalyzer: true, LanguageVersion.CSharp10)) + if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(s_fileScopedNamespacePreferenceOption, root, namespaceDecl, forAnalyzer: true, LanguageVersion.CSharp10)) return default; var formattingOptions = document.GetSyntaxFormattingOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs index 5606d85163c18..c4ced23d2c59a 100644 --- a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs +++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Adornments; @@ -24,8 +25,9 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.EventHookup internal sealed partial class EventHookupSessionManager { public readonly IThreadingContext ThreadingContext; - private readonly IToolTipService _toolTipService; + private readonly IGlobalOptionService _globalOptions; + private IToolTipPresenter _toolTipPresenter; internal EventHookupSession CurrentSession { get; set; } @@ -35,10 +37,14 @@ internal sealed partial class EventHookupSessionManager [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public EventHookupSessionManager(IThreadingContext threadingContext, IToolTipService toolTipService) + public EventHookupSessionManager( + IThreadingContext threadingContext, + IToolTipService toolTipService, + IGlobalOptionService globalOptions) { ThreadingContext = threadingContext; _toolTipService = toolTipService; + _globalOptions = globalOptions; } internal void EventHookupFoundInSession(EventHookupSession analyzedSession) @@ -112,7 +118,7 @@ internal void BeginSession( IAsynchronousOperationListener asyncListener, Mutex testSessionHookupMutex) { - CurrentSession = new EventHookupSession(this, eventHookupCommandHandler, textView, subjectBuffer, asyncListener, testSessionHookupMutex); + CurrentSession = new EventHookupSession(this, eventHookupCommandHandler, textView, subjectBuffer, asyncListener, _globalOptions, testSessionHookupMutex); } internal void CancelAndDismissExistingSessions() diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs index 023e5695f872d..0b15a219962aa 100644 --- a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs +++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -46,6 +47,7 @@ internal class EventHookupSession private readonly ITrackingSpan _trackingSpan; private readonly ITextView _textView; private readonly ITextBuffer _subjectBuffer; + private readonly IGlobalOptionService _globalOptions; public event Action Dismissed = () => { }; @@ -100,12 +102,14 @@ public EventHookupSession( ITextView textView, ITextBuffer subjectBuffer, IAsynchronousOperationListener asyncListener, + IGlobalOptionService globalOptions, Mutex testSessionHookupMutex) { _threadingContext = eventHookupSessionManager.ThreadingContext; var cancellationToken = _cancellationTokenSource.Token; _textView = textView; _subjectBuffer = subjectBuffer; + _globalOptions = globalOptions; this.TESTSessionHookupMutex = testSessionHookupMutex; var document = textView.TextSnapshot.GetOpenDocumentInCurrentContextWithChanges(); @@ -180,7 +184,9 @@ private async Task DetermineIfEventHookupAndGetHandlerNameAsync(Document var namingRule = await document.GetApplicableNamingRuleAsync( new SymbolKindOrTypeKind(MethodKind.Ordinary), new DeclarationModifiers(isStatic: plusEqualsToken.Value.Parent.IsInStaticContext()), - Accessibility.Private, cancellationToken).ConfigureAwait(false); + Accessibility.Private, + _globalOptions.CreateProvider(), + cancellationToken).ConfigureAwait(false); return GetEventHandlerName( eventSymbol, plusEqualsToken.Value, semanticModel, diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs index 23f62b98e5281..71afe5236003f 100644 --- a/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs +++ b/src/EditorFeatures/CSharp/Formatting/CSharpFormattingInteractionService.cs @@ -121,10 +121,13 @@ public async Task> GetFormattingChangesAsync(Document if (await service.ShouldFormatOnTypedCharacterAsync(document, typedChar, position, cancellationToken).ConfigureAwait(false)) { var fallbackOptions = _globalOptions.GetCSharpSyntaxFormattingOptions(); - var autoFormattingOptions = _globalOptions.GetAutoFormattingOptions(LanguageNames.CSharp); - var indentStyle = _globalOptions.GetOption(IndentationOptionsStorage.SmartIndent, LanguageNames.CSharp); var formattingOptions = await _indentationManager.GetInferredFormattingOptionsAsync(document, fallbackOptions, explicitFormat: false, cancellationToken).ConfigureAwait(false); - var indentationOptions = new IndentationOptions(formattingOptions, autoFormattingOptions, indentStyle); + + var indentationOptions = new IndentationOptions(formattingOptions) + { + AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(LanguageNames.CSharp), + IndentStyle = _globalOptions.GetOption(IndentationOptionsStorage.SmartIndent, LanguageNames.CSharp) + }; return await service.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); } diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpSyntaxFormattingOptionsStorage.cs b/src/EditorFeatures/CSharp/Formatting/CSharpSyntaxFormattingOptionsStorage.cs index 46fbaea7a03eb..1fb25372b00e6 100644 --- a/src/EditorFeatures/CSharp/Formatting/CSharpSyntaxFormattingOptionsStorage.cs +++ b/src/EditorFeatures/CSharp/Formatting/CSharpSyntaxFormattingOptionsStorage.cs @@ -30,10 +30,10 @@ public SyntaxFormattingOptions GetOptions(IGlobalOptionService globalOptions) } public static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions(this IGlobalOptionService globalOptions) - => new( - lineFormatting: globalOptions.GetLineFormattingOptions(LanguageNames.CSharp), - separateImportDirectiveGroups: globalOptions.GetOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.CSharp), - spacing: + => new() + { + Common = globalOptions.GetCommonSyntaxFormattingOptions(LanguageNames.CSharp), + Spacing = (globalOptions.GetOption(CSharpFormattingOptions2.SpacesIgnoreAroundVariableDeclaration) ? SpacePlacement.IgnoreAroundVariableDeclaration : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.SpacingAfterMethodDeclarationName) ? SpacePlacement.AfterMethodDeclarationName : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.SpaceBetweenEmptyMethodDeclarationParentheses) ? SpacePlacement.BetweenEmptyMethodDeclarationParentheses : 0) | @@ -57,8 +57,8 @@ public static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions(thi (globalOptions.GetOption(CSharpFormattingOptions2.SpaceBeforeComma) ? SpacePlacement.BeforeComma : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.SpaceAfterDot) ? SpacePlacement.AfterDot : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.SpaceBeforeDot) ? SpacePlacement.BeforeDot : 0), - spacingAroundBinaryOperator: globalOptions.GetOption(CSharpFormattingOptions2.SpacingAroundBinaryOperator), - newLines: + SpacingAroundBinaryOperator = globalOptions.GetOption(CSharpFormattingOptions2.SpacingAroundBinaryOperator), + NewLines = (globalOptions.GetOption(CSharpFormattingOptions2.NewLineForMembersInObjectInit) ? NewLinePlacement.BeforeMembersInObjectInitializers : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.NewLineForMembersInAnonymousTypes) ? NewLinePlacement.BeforeMembersInAnonymousTypes : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.NewLineForElse) ? NewLinePlacement.BeforeElse : 0) | @@ -74,13 +74,16 @@ public static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions(thi (globalOptions.GetOption(CSharpFormattingOptions2.NewLinesForBracesInLambdaExpressionBody) ? NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.NewLinesForBracesInControlBlocks) ? NewLinePlacement.BeforeOpenBraceInControlBlocks : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.NewLineForClausesInQuery) ? NewLinePlacement.BetweenQueryExpressionClauses : 0), - labelPositioning: globalOptions.GetOption(CSharpFormattingOptions2.LabelPositioning), - indentation: + LabelPositioning = globalOptions.GetOption(CSharpFormattingOptions2.LabelPositioning), + Indentation = (globalOptions.GetOption(CSharpFormattingOptions2.IndentBraces) ? IndentationPlacement.Braces : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.IndentBlock) ? IndentationPlacement.BlockContents : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.IndentSwitchCaseSection) ? IndentationPlacement.SwitchCaseContents : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.IndentSwitchCaseSectionWhenBlock) ? IndentationPlacement.SwitchCaseContentsWhenBlock : 0) | (globalOptions.GetOption(CSharpFormattingOptions2.IndentSwitchSection) ? IndentationPlacement.SwitchSection : 0), - wrappingKeepStatementsOnSingleLine: globalOptions.GetOption(CSharpFormattingOptions2.WrappingKeepStatementsOnSingleLine), - wrappingPreserveSingleLine: globalOptions.GetOption(CSharpFormattingOptions2.WrappingPreserveSingleLine)); + WrappingKeepStatementsOnSingleLine = globalOptions.GetOption(CSharpFormattingOptions2.WrappingKeepStatementsOnSingleLine), + WrappingPreserveSingleLine = globalOptions.GetOption(CSharpFormattingOptions2.WrappingPreserveSingleLine), + NamespaceDeclarations = globalOptions.GetOption(CSharpCodeStyleOptions.NamespaceDeclarations), + PreferTopLevelStatements = globalOptions.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements) + }; } diff --git a/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs index 003bb8a6aa192..b182d031c8e5f 100644 --- a/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs +++ b/src/EditorFeatures/CSharp/Simplification/CSharpSimplifierOptionsStorage.cs @@ -28,16 +28,16 @@ public SimplifierOptions GetOptions(IGlobalOptionService 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)); + => new() + { + Common = globalOptions.GetCommonSimplifierOptions(LanguageNames.CSharp), + VarForBuiltInTypes = globalOptions.GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes), + VarWhenTypeIsApparent = globalOptions.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent), + VarElsewhere = globalOptions.GetOption(CSharpCodeStyleOptions.VarElsewhere), + PreferSimpleDefaultExpression = globalOptions.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression), + PreferParameterNullChecking = globalOptions.GetOption(CSharpCodeStyleOptions.PreferParameterNullChecking), + AllowEmbeddedStatementsOnSameLine = globalOptions.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine), + PreferBraces = globalOptions.GetOption(CSharpCodeStyleOptions.PreferBraces), + PreferThrowExpression = globalOptions.GetOption(CSharpCodeStyleOptions.PreferThrowExpression), + }; } diff --git a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralOptions.cs b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralOptions.cs index f7e7b9268100b..cb4a12bf858bb 100644 --- a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralOptions.cs +++ b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.SplitStringLiteral { - [ExportGlobalOptionProvider(LanguageNames.CSharp), Shared] - internal sealed class SplitStringLiteralOptions : IOptionProvider + internal sealed class SplitStringLiteralOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SplitStringLiteralOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - Enabled); - public static PerLanguageOption2 Enabled = new(nameof(SplitStringLiteralOptions), nameof(Enabled), defaultValue: true, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SplitStringLiterals")); diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs index 3016951f6643a..3061500938ecb 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs @@ -908,10 +908,7 @@ class Inner2 await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText, - onAfterWorkspaceCreated: w => - { - w.TryApplyChanges(w.CurrentSolution.WithOptions(w.CurrentSolution.Options.WithChangedOption(FormattingOptions2.InsertFinalNewLine, true))); - }); + options: Option(FormattingOptions2.InsertFinalNewLine, true)); } [WorkItem(17171, "https://github.com/dotnet/roslyn/issues/17171")] @@ -949,10 +946,7 @@ class Inner2 await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText, - onAfterWorkspaceCreated: w => - { - w.TryApplyChanges(w.CurrentSolution.WithOptions(w.CurrentSolution.Options.WithChangedOption(FormattingOptions2.InsertFinalNewLine, false))); - }); + options: Option(FormattingOptions2.InsertFinalNewLine, false)); } [WorkItem(16282, "https://github.com/dotnet/roslyn/issues/16282")] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs index b678981c1a3cd..dc5cb8036fe9d 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AbstractCSharpCompletionProviderTests.cs @@ -51,13 +51,14 @@ private protected override Task BaseVerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null, bool skipSpeculation = false) { return base.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, skipSpeculation: skipSpeculation); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options, skipSpeculation: skipSpeculation); } private protected override async Task VerifyWorkerAsync( @@ -66,19 +67,20 @@ private protected override async Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, - bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null, bool skipSpeculation = false) { - await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); - await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); - await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters); + await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options, skipSpeculation: skipSpeculation); + await VerifyInFrontOfCommentAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, options, skipSpeculation: skipSpeculation); + await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) if (!checkForAbsence && expectedItemOrNull != null) { - await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); - await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); - await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters); + await VerifyAtPosition_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options, skipSpeculation: skipSpeculation); + await VerifyInFrontOfComment_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, options, skipSpeculation: skipSpeculation); + await VerifyAtEndOfFile_ItemPartiallyWrittenAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options); } } @@ -90,7 +92,8 @@ private async Task VerifyInFrontOfCommentAsync( string expectedItemOrNull, string expectedDescriptionOrNull, SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, - string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, List matchingFilters, bool skipSpeculation = false) + string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, List matchingFilters, + CompletionOptions options, bool skipSpeculation = false) { code = code.Substring(0, position) + insertText + "/**/" + code.Substring(position); position += insertText.Length; @@ -99,7 +102,8 @@ await base.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, - inlineDescription, isComplexTextEdit, matchingFilters, flags: null, skipSpeculation: skipSpeculation); + inlineDescription, isComplexTextEdit, matchingFilters, flags: null, + options, skipSpeculation: skipSpeculation); } private async Task VerifyInFrontOfCommentAsync( @@ -108,13 +112,13 @@ private async Task VerifyInFrontOfCommentAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, bool skipSpeculation = false) + List matchingFilters, CompletionOptions options, bool skipSpeculation = false) { await VerifyInFrontOfCommentAsync( code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, options, skipSpeculation: skipSpeculation); } private protected async Task VerifyInFrontOfComment_ItemPartiallyWrittenAsync( @@ -123,13 +127,13 @@ private protected async Task VerifyInFrontOfComment_ItemPartiallyWrittenAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, bool skipSpeculation = false) + List matchingFilters, CompletionOptions options, bool skipSpeculation = false) { await VerifyInFrontOfCommentAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation: skipSpeculation); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, options, skipSpeculation: skipSpeculation); } protected static string AddInsideMethod(string text) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs index f528845711a88..1a4450dbb2d62 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs @@ -34,17 +34,17 @@ private protected override async Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { await VerifyAtPositionAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags); + isComplexTextEdit, matchingFilters, flags, options); await VerifyAtEndOfFileAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags); + isComplexTextEdit, matchingFilters, flags, options); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) @@ -53,12 +53,12 @@ await VerifyAtEndOfFileAsync( await VerifyAtPosition_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options); await VerifyAtEndOfFile_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags: null, options); } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/DeclarationNameCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/DeclarationNameCompletionProviderTests.cs index 72bf2ff1a344c..ba2b9fe1ddaae 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/DeclarationNameCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/DeclarationNameCompletionProviderTests.cs @@ -8,6 +8,8 @@ using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Completion.Providers; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; @@ -697,9 +699,11 @@ public async Task Parameter13() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - new OptionKey2(NamingStyleOptions.NamingPreferences, LanguageNames.CSharp), - ParameterCamelCaseWithPascalCaseFallback()))); + + var options = new CompletionOptions() + { + NamingStyleFallbackOptions = ParameterCamelCaseWithPascalCaseFallback() + }; var markup = @" using System.Threading; @@ -708,8 +712,8 @@ public class C void Goo(CancellationToken $$ } "; - await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter); - await VerifyItemIsAbsentAsync(markup, "CancellationToken"); + await VerifyItemExistsAsync(markup, "cancellationToken", glyph: (int)Glyph.Parameter, options: options); + await VerifyItemIsAbsentAsync(markup, "CancellationToken", options: options); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -2415,9 +2419,11 @@ public async Task CustomNamingStyleInsideClass() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - new OptionKey2(NamingStyleOptions.NamingPreferences, LanguageNames.CSharp), - NamesEndWithSuffixPreferences()))); + + var options = new CompletionOptions() + { + NamingStyleFallbackOptions = NamesEndWithSuffixPreferences() + }; var markup = @" class Configuration @@ -2426,13 +2432,13 @@ class Configuration } "; await VerifyItemExistsAsync(markup, "ConfigurationField", glyph: (int)Glyph.FieldPublic, - expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name); + expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name, options: options); await VerifyItemExistsAsync(markup, "ConfigurationProperty", glyph: (int)Glyph.PropertyPublic, - expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name); + expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name, options: options); await VerifyItemExistsAsync(markup, "ConfigurationMethod", glyph: (int)Glyph.MethodPublic, - expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name); - await VerifyItemIsAbsentAsync(markup, "ConfigurationLocal"); - await VerifyItemIsAbsentAsync(markup, "ConfigurationLocalFunction"); + expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name, options: options); + await VerifyItemIsAbsentAsync(markup, "ConfigurationLocal", options: options); + await VerifyItemIsAbsentAsync(markup, "ConfigurationLocalFunction", options: options); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -2441,9 +2447,11 @@ public async Task CustomNamingStyleInsideMethod() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - new OptionKey2(NamingStyleOptions.NamingPreferences, LanguageNames.CSharp), - NamesEndWithSuffixPreferences()))); + + var options = new CompletionOptions() + { + NamingStyleFallbackOptions = NamesEndWithSuffixPreferences() + }; var markup = @" class Configuration @@ -2455,12 +2463,12 @@ void M() } "; await VerifyItemExistsAsync(markup, "ConfigurationLocal", glyph: (int)Glyph.Local, - expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name); + expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name, options: options); await VerifyItemExistsAsync(markup, "ConfigurationLocalFunction", glyph: (int)Glyph.MethodPublic, - expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name); - await VerifyItemIsAbsentAsync(markup, "ConfigurationField"); - await VerifyItemIsAbsentAsync(markup, "ConfigurationMethod"); - await VerifyItemIsAbsentAsync(markup, "ConfigurationProperty"); + expectedDescriptionOrNull: CSharpFeaturesResources.Suggested_name, options: options); + await VerifyItemIsAbsentAsync(markup, "ConfigurationField", options: options); + await VerifyItemIsAbsentAsync(markup, "ConfigurationMethod", options: options); + await VerifyItemIsAbsentAsync(markup, "ConfigurationProperty", options: options); } [WorkItem(31304, "https://github.com/dotnet/roslyn/issues/31304")] @@ -2873,9 +2881,11 @@ public async Task ConflictingLocalVariable() using var workspaceFixture = GetOrCreateWorkspaceFixture(); var workspace = workspaceFixture.Target.GetWorkspace(ExportProvider); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options.WithChangedOption( - new OptionKey2(NamingStyleOptions.NamingPreferences, LanguageNames.CSharp), - MultipleCamelCaseLocalRules()))); + + var options = new CompletionOptions() + { + NamingStyleFallbackOptions = MultipleCamelCaseLocalRules() + }; var markup = @" public class MyClass @@ -2887,7 +2897,7 @@ void M() } } "; - await VerifyItemExistsAsync(markup, "myClass1", glyph: (int)Glyph.Local); + await VerifyItemExistsAsync(markup, "myClass1", glyph: (int)Glyph.Local, options: options); } private static NamingStylePreferences MultipleCamelCaseLocalRules() diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs index 64b49d5e68b12..cfde13317732a 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/LoadDirectiveCompletionProviderTests.cs @@ -35,13 +35,13 @@ private protected override Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { return BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } [Fact] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs index 01eeb2900f505..c6de0cddb6809 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ReferenceDirectiveCompletionProviderTests.cs @@ -38,7 +38,7 @@ private protected override Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { return BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs index 96782593c5ee6..5e50a3369668d 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests_NoInteractive.cs @@ -32,13 +32,13 @@ private protected override Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { return base.VerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, SourceCodeKind.Regular, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs index 3968c9abbeb8b..a39114becbcd7 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/XmlDocumentationCommentCompletionProviderTests.cs @@ -43,18 +43,18 @@ private protected override async Task VerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { // We don't need to try writing comments in from of items in doc comments. await VerifyAtPositionAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags); + isComplexTextEdit, matchingFilters, flags, options); await VerifyAtEndOfFileAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags); + isComplexTextEdit, matchingFilters, flags, options); // Items cannot be partially written if we're checking for their absence, // or if we're verifying that the list will show up (without specifying an actual item) @@ -63,12 +63,12 @@ await VerifyAtEndOfFileAsync( await VerifyAtPosition_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options); await VerifyAtEndOfFile_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } } diff --git a/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs b/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs index 6ab74c89276ad..a508282d1fc08 100644 --- a/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs +++ b/src/EditorFeatures/CSharpTest/ConvertAutoPropertyToFullProperty/ConvertAutoPropertyToFullPropertyTests_OptionSets.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; diff --git a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs index 838fc48d9e4f5..93a7bcb562ded 100644 --- a/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs +++ b/src/EditorFeatures/CSharpTest/ConvertProgram/ConvertToProgramMainAnalyzerTests.cs @@ -205,7 +205,7 @@ static void Main(string[] args) TestState = { OutputKind = OutputKind.ConsoleApplication }, Options = { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Never }, + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Never }, { CSharpCodeStyleOptions.PreferTopLevelStatements, false, NotificationOption2.Suggestion }, }, }.RunAsync(); diff --git a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs index 7948d86cd5920..11a9f08e8fa74 100644 --- a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs @@ -954,7 +954,7 @@ public void Goo() { } markup, LanguageNames.CSharp, options: new OptionsCollection(LanguageNames.CSharp) { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Always, NotificationOption2.Silent } + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Always, NotificationOption2.Silent } }); var result = await testState.ExtractViaCommandAsync(); diff --git a/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodBase.cs b/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodBase.cs index 19610dfd66bab..80e8731319772 100644 --- a/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodBase.cs +++ b/src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodBase.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.ExtractMethod; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; @@ -130,11 +131,10 @@ protected static async Task ExtractMethodAsync( var document = workspace.CurrentSolution.GetDocument(testDocument.Id); Assert.NotNull(document); - var options = new ExtractMethodGenerationOptions( - ExtractOptions: new ExtractMethodOptions(dontPutOutOrRefOnStruct), - CodeGenerationOptions: CodeGenerationOptions.GetDefault(document.Project.LanguageServices), - AddImportOptions: AddImportPlacementOptions.Default, - NamingPreferences: _ => NamingStylePreferences.Default); + var options = new ExtractMethodGenerationOptions(CodeGenerationOptions.GetDefault(document.Project.LanguageServices)) + { + ExtractOptions = new() { DontPutOutOrRefOnStruct = dontPutOutOrRefOnStruct } + }; var semanticDocument = await SemanticDocument.CreateAsync(document, CancellationToken.None); var validator = new CSharpSelectionValidator(semanticDocument, testDocument.SelectedSpans.Single(), options.ExtractOptions, localFunction: false); diff --git a/src/EditorFeatures/CSharpTest/Formatting/CSharpNewDocumentFormattingServiceTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CSharpNewDocumentFormattingServiceTests.cs index c0659745a7f1d..7ec2af1028a7f 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CSharpNewDocumentFormattingServiceTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CSharpNewDocumentFormattingServiceTests.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities.Formatting; @@ -37,9 +38,9 @@ namespace Goo; internal class C { }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error)) + { CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error) } }, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp10)); } @@ -59,9 +60,9 @@ namespace Bar await TestAsync( testCode: testCode, expected: testCode, - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error)) + { CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error) } }, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp10)); } @@ -80,9 +81,9 @@ internal class C await TestAsync( testCode: testCode, expected: testCode, - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error)) + { CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error) } }, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp9)); } @@ -104,9 +105,9 @@ internal class C { } }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Error)) + { CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Error) } }); } @@ -119,9 +120,9 @@ public async Task TestOrganizeUsingsWithNoUsings() await TestAsync( testCode: testCode, expected: testCode, - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, new CodeStyleOption2(AddImportPlacement.OutsideNamespace, NotificationOption2.Error)) + { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, new CodeStyleOption2(AddImportPlacement.OutsideNamespace, NotificationOption2.Error) } }); } @@ -140,9 +141,9 @@ namespace Goo namespace Goo { }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CodeStyleOptions2.FileHeaderTemplate, "This is a banner.") + { CodeStyleOptions2.FileHeaderTemplate, "This is a banner." } }); } @@ -165,9 +166,9 @@ internal class C { } }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CodeStyleOptions2.RequireAccessibilityModifiers, new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error)) + { CodeStyleOptions2.AccessibilityModifiersRequired, new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error) } }); } @@ -188,10 +189,10 @@ namespace Goo; internal class C { }", - options: new (OptionKey, object)[] + options: new OptionsCollection(LanguageNames.CSharp) { - (new OptionKey(CSharpCodeStyleOptions.NamespaceDeclarations), new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error)), - (new OptionKey(CodeStyleOptions2.RequireAccessibilityModifiers, Language), new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error)) + { CSharpCodeStyleOptions.NamespaceDeclarations, new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Error) }, + { CodeStyleOptions2.AccessibilityModifiersRequired, new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error) } }); } @@ -232,9 +233,9 @@ internal class D { } }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CodeStyleOptions2.RequireAccessibilityModifiers, new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error)) + { CodeStyleOptions2.AccessibilityModifiersRequired, new CodeStyleOption2(AccessibilityModifiersRequired.Always, NotificationOption2.Error) } }); } @@ -250,9 +251,9 @@ namespace Goo { using System; }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, new CodeStyleOption2(AddImportPlacement.InsideNamespace, NotificationOption2.Error)) + { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, new CodeStyleOption2(AddImportPlacement.InsideNamespace, NotificationOption2.Error) } }); } @@ -267,9 +268,9 @@ public async Task TestPreferTopLevelStatements() // See https://aka.ms/new-console-template for more information Console.WriteLine(""Hello, World!"");", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.PreferTopLevelStatements, new CodeStyleOption2(value: true, notification: NotificationOption2.Suggestion)) + { CSharpCodeStyleOptions.PreferTopLevelStatements, new CodeStyleOption2(value: true, notification: NotificationOption2.Suggestion) } }); } @@ -289,9 +290,9 @@ private static void Main(string[] args) Console.WriteLine(""Hello, World!""); } }", - options: new[] + options: new OptionsCollection(LanguageNames.CSharp) { - (CSharpCodeStyleOptions.PreferTopLevelStatements, new CodeStyleOption2(value: false, notification: NotificationOption2.Suggestion)) + { CSharpCodeStyleOptions.PreferTopLevelStatements, new CodeStyleOption2(value: false, notification: NotificationOption2.Suggestion) } }); } } diff --git a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs index 3dd3a6319fc83..1f80efedcdc8d 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/CodeCleanupTests.cs @@ -21,6 +21,7 @@ using Microsoft.CodeAnalysis.Editor.UnitTests; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Simplification; @@ -608,7 +609,7 @@ TestWorkspace GetTestWorkspaceForLanguage(string language) /// Indicates whether 'using' directives should be organized into separated groups. Default is true. /// The to test code cleanup. private protected static Task AssertCodeCleanupResult(string expected, string code, bool systemUsingsFirst = true, bool separateUsingGroups = false) - => AssertCodeCleanupResult(expected, code, CSharpCodeStyleOptions.PreferOutsidePlacementWithSilentEnforcement, systemUsingsFirst, separateUsingGroups); + => AssertCodeCleanupResult(expected, code, new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent), systemUsingsFirst, separateUsingGroups); /// /// Assert the expected code value equals the actual processed input . @@ -623,16 +624,17 @@ private protected static async Task AssertCodeCleanupResult(string expected, str { using var workspace = TestWorkspace.CreateCSharp(code, composition: EditorTestCompositions.EditorFeaturesWpf); - var solution = workspace.CurrentSolution - .WithOptions(workspace.Options - .WithChangedOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp, systemUsingsFirst) - .WithChangedOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.CSharp, separateUsingGroups) - .WithChangedOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, preferredImportPlacement)) - .WithAnalyzerReferences(new[] - { - new AnalyzerFileReference(typeof(CSharpCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), - new AnalyzerFileReference(typeof(UseExpressionBodyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile) - }); + // must set global options since incremental analyzer infra reads from global options + var globalOptions = workspace.GlobalOptions; + globalOptions.SetGlobalOption(new OptionKey(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.CSharp), separateUsingGroups); + globalOptions.SetGlobalOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp), systemUsingsFirst); + globalOptions.SetGlobalOption(new OptionKey(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement), preferredImportPlacement); + + var solution = workspace.CurrentSolution.WithAnalyzerReferences(new[] + { + new AnalyzerFileReference(typeof(CSharpCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), + new AnalyzerFileReference(typeof(UseExpressionBodyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile) + }); workspace.TryApplyChanges(solution); @@ -647,14 +649,8 @@ private protected static async Task AssertCodeCleanupResult(string expected, str var enabledDiagnostics = codeCleanupService.GetAllDiagnostics(); - var fallbackOptions = new CodeActionOptions( - CleanupOptions: CodeCleanupOptions.GetDefault(document.Project.LanguageServices) with - { - FormattingOptions = new CSharpSyntaxFormattingOptions(separateImportDirectiveGroups: separateUsingGroups) - }); - var newDoc = await codeCleanupService.CleanupAsync( - document, enabledDiagnostics, new ProgressTracker(), fallbackOptions.CreateProvider(), CancellationToken.None); + document, enabledDiagnostics, new ProgressTracker(), globalOptions.CreateProvider(), CancellationToken.None); var actual = await newDoc.GetTextAsync(); diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs index b60f6cc7f0286..50ce8977d91ae 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/CSharpFormatterTestsBase.cs @@ -10,6 +10,8 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Indentation; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editor.UnitTests; @@ -47,9 +49,10 @@ protected static async Task GetSmartTokenFormatterIndentationWorkerAsync( TestWorkspace workspace, ITextBuffer buffer, int indentationLine, - char ch) + char ch, + bool useTabs) { - await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch); + await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch, useTabs); return buffer.CurrentSnapshot.GetLineFromLineNumber(indentationLine).GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(TestEditorOptions.Instance); } @@ -58,14 +61,15 @@ protected static async Task TokenFormatAsync( TestWorkspace workspace, ITextBuffer buffer, int indentationLine, - char ch) + char ch, + bool useTabs) { - await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch); + await TokenFormatWorkerAsync(workspace, buffer, indentationLine, ch, useTabs); return buffer.CurrentSnapshot.GetText(); } - private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch) + private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch, bool useTabs) { var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First(); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(); @@ -84,8 +88,13 @@ private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextB var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(document, position)).AddRange(Formatter.GetDefaultFormattingRules(document)); var options = new IndentationOptions( - await document.GetSyntaxFormattingOptionsAsync(fallbackOptions: null, CancellationToken.None).ConfigureAwait(false), - AutoFormattingOptions.Default); + new CSharpSyntaxFormattingOptions + { + Common = new SyntaxFormattingOptions.CommonOptions() + { + LineFormatting = new LineFormattingOptions { UseTabs = useTabs } + } + }); var formatter = new CSharpSmartTokenFormatter(options, rules, root); var changes = await formatter.FormatTokenAsync(token, CancellationToken.None); @@ -114,8 +123,6 @@ protected static async Task GetSmartTokenFormatterIndentationAsync( { // create tree service using var workspace = TestWorkspace.CreateCSharp(code, composition: s_composition); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(FormattingOptions2.UseTabs, LanguageNames.CSharp, useTabs))); if (baseIndentation.HasValue) { @@ -125,7 +132,7 @@ protected static async Task GetSmartTokenFormatterIndentationAsync( } var buffer = workspace.Documents.First().GetTextBuffer(); - return await GetSmartTokenFormatterIndentationWorkerAsync(workspace, buffer, indentationLine, ch); + return await GetSmartTokenFormatterIndentationWorkerAsync(workspace, buffer, indentationLine, ch, useTabs); } } } diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs index 1c6364e60f59c..09d4e858cae60 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs @@ -1511,15 +1511,14 @@ private static async Task AssertIndentUsingSmartTokenFormatterAsync( var root = (await document.GetSyntaxRootAsync()) as CompilationUnitSyntax; var options = new IndentationOptions( - CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions(UseTabs: useTabs)), - AutoFormattingOptions.Default); + CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions { UseTabs = useTabs })); Assert.True( CSharpIndentationService.ShouldUseSmartTokenFormatterInsteadOfIndenter( Formatter.GetDefaultFormattingRules(document), root, line.AsTextLine(), options, out _)); - var actualIndentation = await GetSmartTokenFormatterIndentationWorkerAsync(workspace, buffer, indentationLine, ch); + var actualIndentation = await GetSmartTokenFormatterIndentationWorkerAsync(workspace, buffer, indentationLine, ch, useTabs); Assert.Equal(expectedIndentation.Value, actualIndentation); } @@ -1552,10 +1551,10 @@ private async Task AssertIndentNotUsingSmartTokenFormatterButUsingIndenterAsync( var root = (await document.GetSyntaxRootAsync()) as CompilationUnitSyntax; - var options = new IndentationOptions( - CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions(UseTabs: useTabs)), - AutoFormattingOptions.Default, - IndentStyle: indentStyle); + var options = new IndentationOptions(CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions { UseTabs = useTabs })) + { + IndentStyle = indentStyle + }; Assert.False( CSharpIndentationService.ShouldUseSmartTokenFormatterInsteadOfIndenter( diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs index ce659cca8ffc7..f00b8dab34c87 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatRangeTests.cs @@ -3588,8 +3588,7 @@ private static async Task AutoFormatOnMarkerAsync(string initialMarkup, string e Assert.Equal(tokenKind, endToken.Kind()); var options = new IndentationOptions( - CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions(UseTabs: useTabs)), - AutoFormattingOptions.Default); + CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions { UseTabs = useTabs })); var formatter = new CSharpSmartTokenFormatter(options, rules, root); diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs index 41b2146c86421..089c2de24cac8 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartTokenFormatterFormatTokenTests.cs @@ -645,12 +645,9 @@ private static async Task AssertSmartTokenFormatterOpenBraceAsync( // create tree service using var workspace = TestWorkspace.CreateCSharp(code); - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(FormattingOptions2.UseTabs, LanguageNames.CSharp, useTabs))); - var buffer = workspace.Documents.First().GetTextBuffer(); - var actual = await TokenFormatAsync(workspace, buffer, indentationLine, '{'); + var actual = await TokenFormatAsync(workspace, buffer, indentationLine, '{', useTabs); Assert.Equal(expected, actual); } diff --git a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs b/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs index 5c48b85324502..407f7edc844f3 100644 --- a/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/GenerateFromMembers/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersTests.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Editor.UnitTests; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers; using Microsoft.CodeAnalysis.PickMembers; @@ -30,7 +31,7 @@ public class GenerateEqualsAndGetHashCodeFromMembersTests private class TestWithDialog : VerifyCS.Test { private static readonly TestComposition s_composition = - FeaturesTestCompositions.Features.AddParts(typeof(TestPickMembersService)); + EditorTestCompositions.EditorFeatures.AddParts(typeof(TestPickMembersService)); public ImmutableArray MemberNames; public Action> OptionsCallback; diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs index 6f16ab5c1d2a3..23029296cb17d 100644 --- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs @@ -7287,10 +7287,10 @@ void M() { } public int Prop => throw new System.NotImplementedException(); }", - CodeActionOptions = CodeActionOptions.Default with + CodeActionOptions = (CSharpCodeActionOptions.Default with { - ImplementTypeOptions = new ImplementTypeOptions(InsertionBehavior: ImplementTypeInsertionBehavior.AtTheEnd) - } + ImplementTypeOptions = new() { InsertionBehavior = ImplementTypeInsertionBehavior.AtTheEnd } + }).CreateProvider() }.RunAsync(); } @@ -7462,10 +7462,10 @@ class Class : IInterface public int ReadWriteProp { get; set; } public int WriteOnlyProp { set => throw new System.NotImplementedException(); } }", - CodeActionOptions = CodeActionOptions.Default with + CodeActionOptions = (CSharpCodeActionOptions.Default with { - ImplementTypeOptions = new ImplementTypeOptions(PropertyGenerationBehavior: ImplementTypePropertyGenerationBehavior.PreferAutoProperties) - } + ImplementTypeOptions = new() { PropertyGenerationBehavior = ImplementTypePropertyGenerationBehavior.PreferAutoProperties } + }).CreateProvider() }.RunAsync(); } diff --git a/src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs b/src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs index 6f3f3177adf98..893f42386627d 100644 --- a/src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs +++ b/src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs @@ -1466,9 +1466,9 @@ public C([|string p__End, string p_test_t|]) }", parameters: new TestParameters(options: options.MergeStyles(options.PropertyNamesArePascalCase, options.ParameterNamesAreCamelCaseWithPUnderscorePrefixAndUnderscoreEndSuffix))); } - private TestParameters OmitIfDefault_Warning => new TestParameters(options: Option(CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption2.Warning)); - private TestParameters Never_Warning => new TestParameters(options: Option(CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Never, NotificationOption2.Warning)); - private TestParameters Always_Warning => new TestParameters(options: Option(CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Always, NotificationOption2.Warning)); + private TestParameters OmitIfDefault_Warning => new TestParameters(options: Option(CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption2.Warning)); + private TestParameters Never_Warning => new TestParameters(options: Option(CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Never, NotificationOption2.Warning)); + private TestParameters Always_Warning => new TestParameters(options: Option(CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Always, NotificationOption2.Warning)); [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInitializeParameter)] public async Task TestCreateFieldWithTopLevelNullability() diff --git a/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs b/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs index f30ccc97d11e1..49b11b7cca634 100644 --- a/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs +++ b/src/EditorFeatures/Core.Cocoa/Snippets/AbstractSnippetExpansionClient.cs @@ -147,8 +147,8 @@ private void CleanUpEndLocation(ITrackingSpan? endTrackingSpan) var document = this.SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { - var documentOptions = document.GetOptionsAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); - _indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, documentOptions.GetOption(FormattingOptions.TabSize)); + var lineFormattingOptions = document.GetLineFormattingOptionsAsync(GlobalOptions, CancellationToken.None).AsTask().WaitAndGetResult(CancellationToken.None); + _indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, lineFormattingOptions.TabSize); } else { diff --git a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsViewOptions.cs b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsViewOptions.cs index 5b5bc6ae4b7f6..6f2f8ac0dae9d 100644 --- a/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsViewOptions.cs +++ b/src/EditorFeatures/Core.Wpf/InlineHints/InlineHintsViewOptions.cs @@ -11,19 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.InlineHints { - [ExportGlobalOptionProvider, Shared] - internal sealed class InlineHintsViewOptions : IOptionProvider + internal sealed class InlineHintsViewOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public InlineHintsViewOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - DisplayAllHintsWhilePressingAltF1, - ColorHints); - private const string FeatureName = "InlineHintsOptions"; public static readonly Option2 DisplayAllHintsWhilePressingAltF1 = new( diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index facd6b6bfe102..bea932d165ace 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -270,7 +270,7 @@ protected static Task> GetCodeFixesAsy SnapshotSpan range, Func addOperationScope, CodeActionRequestPriority priority, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken) { @@ -283,7 +283,7 @@ protected static Task> GetCodeFixesAsy return UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync( workspace, state.Target.Owner._codeFixService, document, range.Span.ToTextSpan(), - priority, options, isBlocking, addOperationScope, cancellationToken).AsTask(); + priority, fallbackOptions, isBlocking, addOperationScope, cancellationToken).AsTask(); } private static string GetFixCategory(DiagnosticSeverity severity) @@ -311,7 +311,7 @@ protected static Task> GetRefactorings TextSpan? selection, Func addOperationScope, CodeActionRequestPriority priority, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken) { @@ -341,7 +341,7 @@ protected static Task> GetRefactorings var filterOutsideSelection = !requestedActionCategories.Contains(PredefinedSuggestedActionCategoryNames.Refactoring); return UnifiedSuggestedActionsSource.GetFilterAndOrderCodeRefactoringsAsync( - workspace, state.Target.Owner._codeRefactoringService, document, selection.Value, priority, options, isBlocking, + workspace, state.Target.Owner._codeRefactoringService, document, selection.Value, priority, fallbackOptions, isBlocking, addOperationScope, filterOutsideSelection, cancellationToken); } @@ -420,7 +420,7 @@ await InvokeBelowInputPriorityAsync(() => ReferenceCountedDisposable state, Document document, SnapshotSpan range, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { foreach (var order in Orderings) @@ -441,7 +441,7 @@ await InvokeBelowInputPriorityAsync(() => state.Target.SubjectBuffer.SupportsCodeFixes()) { var result = await state.Target.Owner._codeFixService.GetMostSevereFixAsync( - document, range.Span.ToTextSpan(), priority, options, isBlocking: false, cancellationToken).ConfigureAwait(false); + document, range.Span.ToTextSpan(), priority, fallbackOptions, isBlocking: false, cancellationToken).ConfigureAwait(false); if (result.HasFix) { @@ -464,7 +464,7 @@ await InvokeBelowInputPriorityAsync(() => private async Task TryGetRefactoringSuggestedActionCategoryAsync( Document document, TextSpan? selection, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { using var state = _state.TryAddReference(); @@ -483,7 +483,7 @@ await InvokeBelowInputPriorityAsync(() => state.Target.SubjectBuffer.SupportsRefactorings()) { if (await state.Target.Owner._codeRefactoringService.HasRefactoringsAsync( - document, selection.Value, options, cancellationToken).ConfigureAwait(false)) + document, selection.Value, fallbackOptions, cancellationToken).ConfigureAwait(false)) { return PredefinedSuggestedActionCategoryNames.Refactoring; } @@ -636,12 +636,12 @@ private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId? c if (document == null) return null; - var options = GlobalOptions.GetCodeActionOptionsProvider(); + var fallbackOptions = GlobalOptions.GetCodeActionOptionsProvider(); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var linkedToken = linkedTokenSource.Token; - var errorTask = Task.Run(() => GetFixLevelAsync(state, document, range, options, linkedToken), linkedToken); + var errorTask = Task.Run(() => GetFixLevelAsync(state, document, range, fallbackOptions, linkedToken), linkedToken); var selection = await GetSpanAsync(state, range, linkedToken).ConfigureAwait(false); @@ -649,7 +649,7 @@ private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId? c if (selection != null) { refactoringTask = Task.Run( - () => TryGetRefactoringSuggestedActionCategoryAsync(document, selection, options, linkedToken), linkedToken); + () => TryGetRefactoringSuggestedActionCategoryAsync(document, selection, fallbackOptions, linkedToken), linkedToken); } // If we happen to get the result of the error task before the refactoring task, diff --git a/src/EditorFeatures/Core/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs b/src/EditorFeatures/Core/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs index 968f3e3a85fd2..1f4e7eb6da94d 100644 --- a/src/EditorFeatures/Core/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs +++ b/src/EditorFeatures/Core/DocumentationComments/AbstractDocumentationCommentCommandHandler.cs @@ -94,8 +94,7 @@ private bool CompleteComment( var service = document.GetRequiredLanguageService(); var syntaxTree = document.GetRequiredSyntaxTreeSynchronously(cancellationToken); var text = syntaxTree.GetText(cancellationToken); - var documentOptions = document.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken); - var options = _globalOptions.GetDocumentationCommentOptions(documentOptions); + var options = document.GetDocumentationCommentOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); // Apply snippet in reverse order so that the first applied snippet doesn't affect span of next snippets. var snapshots = textView.Selection.GetSnapshotSpansOnBuffer(subjectBuffer).OrderByDescending(s => s.Span.Start); @@ -337,8 +336,7 @@ private void InsertExteriorTriviaIfNeeded(IDocumentationCommentSnippetService se return; } - var documentOptions = document.GetOptionsAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); - var options = _globalOptions.GetDocumentationCommentOptions(documentOptions); + var options = document.GetDocumentationCommentOptionsAsync(_globalOptions, CancellationToken.None).AsTask().WaitAndGetResult(CancellationToken.None); var snippet = service.GetDocumentationCommentSnippetFromPreviousLine(options, currentLine, previousLine); if (snippet != null) diff --git a/src/EditorFeatures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs b/src/EditorFeatures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs index 1974ed22ab9aa..a25b8e6233a30 100644 --- a/src/EditorFeatures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs +++ b/src/EditorFeatures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Data; @@ -35,15 +36,16 @@ protected override void UpdateOptions(AnalyzerConfigOptions _, OptionSet optionS return; } - var options = project.State.AnalyzerOptions; var document = project.Documents.FirstOrDefault(); if (document is null) { return; } - var sourceTree = document.GetRequiredSyntaxTreeSynchronously(default(CancellationToken)); - if (options.TryGetEditorConfigOption(NamingStyleOptions.NamingPreferences, sourceTree, out NamingStylePreferences? namingPreferences) && + var sourceTree = document.GetRequiredSyntaxTreeSynchronously(CancellationToken.None); + var configOptions = project.State.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(sourceTree); + + if (configOptions.TryGetEditorConfigOption(NamingStyleOptions.NamingPreferences, out NamingStylePreferences? namingPreferences) && namingPreferences is not null) { AddNamingStylePreferences(namingPreferences, isInEditorConfig: true); diff --git a/src/EditorFeatures/Core/EditorConfigSettings/Updater/NamingStyles/SourceTextExtensions.cs b/src/EditorFeatures/Core/EditorConfigSettings/Updater/NamingStyles/SourceTextExtensions.cs index 3cb5f64e19ff0..f259cfd32e0b7 100644 --- a/src/EditorFeatures/Core/EditorConfigSettings/Updater/NamingStyles/SourceTextExtensions.cs +++ b/src/EditorFeatures/Core/EditorConfigSettings/Updater/NamingStyles/SourceTextExtensions.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.EditorConfig; using Microsoft.CodeAnalysis.EditorConfig.Parsing; diff --git a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/IVSTypeScriptFormattingInteractionService.cs b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/IVSTypeScriptFormattingInteractionService.cs index 8b6f154e38c29..ed037254993fa 100644 --- a/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/IVSTypeScriptFormattingInteractionService.cs +++ b/src/EditorFeatures/Core/ExternalAccess/VSTypeScript/Api/IVSTypeScriptFormattingInteractionService.cs @@ -25,6 +25,7 @@ internal interface IVSTypeScriptFormattingInteractionService /// bool SupportsFormattingOnTypedCharacter(Document document, char ch); +#pragma warning disable RS0030 // Do not used banned APIs (backwards compat) /// /// Returns the text changes necessary to format the document. If "textSpan" is provided, /// only the text changes necessary to format that span are needed. @@ -47,5 +48,6 @@ internal interface IVSTypeScriptFormattingInteractionService /// Returns the text changes necessary to format the document after the user enters a Return /// The position provided is the position of the caret in the document after Return. Task> GetFormattingChangesOnReturnAsync(Document document, int position, DocumentOptionSet? documentOptions, CancellationToken cancellationToken); +#pragma warning restore } } diff --git a/src/EditorFeatures/Core/Formatting/IndentationManagerExtensions.cs b/src/EditorFeatures/Core/Formatting/IndentationManagerExtensions.cs index a7904a0edcaaf..da7fc9ca259ff 100644 --- a/src/EditorFeatures/Core/Formatting/IndentationManagerExtensions.cs +++ b/src/EditorFeatures/Core/Formatting/IndentationManagerExtensions.cs @@ -26,11 +26,13 @@ public static async Task GetInferredFormattingOptionsAs indentationManager.GetIndentation(snapshot.TextBuffer, explicitFormat, out var convertTabsToSpaces, out var tabSize, out var indentSize); - return options.With(new LineFormattingOptions( - UseTabs: !convertTabsToSpaces, - IndentationSize: indentSize, - TabSize: tabSize, - NewLine: options.NewLine)); + return options.With(new LineFormattingOptions() + { + UseTabs = !convertTabsToSpaces, + IndentationSize = indentSize, + TabSize = tabSize, + NewLine = options.NewLine + }); } } } diff --git a/src/EditorFeatures/Core/InlineDiagnostics/InlineDiagnosticsOptions.cs b/src/EditorFeatures/Core/InlineDiagnostics/InlineDiagnosticsOptions.cs index 7fdd27c56f116..6d490bb641834 100644 --- a/src/EditorFeatures/Core/InlineDiagnostics/InlineDiagnosticsOptions.cs +++ b/src/EditorFeatures/Core/InlineDiagnostics/InlineDiagnosticsOptions.cs @@ -11,19 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.InlineDiagnostics { - [ExportGlobalOptionProvider, Shared] - internal sealed class InlineDiagnosticsOptions : IOptionProvider + internal sealed class InlineDiagnosticsOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public InlineDiagnosticsOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - EnableInlineDiagnostics, - Location); - public static readonly PerLanguageOption2 EnableInlineDiagnostics = new("InlineDiagnosticsOptions", "EnableInlineDiagnostics", diff --git a/src/Features/Core/Portable/InlineHints/InlineHintsGlobalStateOption.cs b/src/EditorFeatures/Core/InlineHints/InlineHintsGlobalStateOption.cs similarity index 100% rename from src/Features/Core/Portable/InlineHints/InlineHintsGlobalStateOption.cs rename to src/EditorFeatures/Core/InlineHints/InlineHintsGlobalStateOption.cs diff --git a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs index 5c23208f8d35f..571cdda77f6b0 100644 --- a/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs +++ b/src/EditorFeatures/Core/LanguageServer/Handlers/CodeActions/CodeActionHelpers.cs @@ -35,13 +35,13 @@ public static async Task GetVSCodeActionsAsync( CodeActionParams request, CodeActionsCache codeActionsCache, Document document, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, CancellationToken cancellationToken) { var actionSets = await GetActionSetsAsync( - document, options, codeFixService, codeRefactoringService, request.Range, cancellationToken).ConfigureAwait(false); + document, fallbackOptions, codeFixService, codeRefactoringService, request.Range, cancellationToken).ConfigureAwait(false); if (actionSets.IsDefaultOrEmpty) return Array.Empty(); @@ -186,13 +186,13 @@ public static async Task> GetCodeActionsAsync( CodeActionsCache codeActionsCache, Document document, LSP.Range selection, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, CancellationToken cancellationToken) { var actionSets = await GetActionSetsAsync( - document, options, codeFixService, codeRefactoringService, selection, cancellationToken).ConfigureAwait(false); + document, fallbackOptions, codeFixService, codeRefactoringService, selection, cancellationToken).ConfigureAwait(false); if (actionSets.IsDefaultOrEmpty) return ImmutableArray.Empty; @@ -242,7 +242,7 @@ private static CodeAction GetNestedActionsFromActionSet(IUnifiedSuggestedAction private static async ValueTask> GetActionSetsAsync( Document document, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, LSP.Range selection, @@ -254,10 +254,10 @@ private static async ValueTask> GetAct var codeFixes = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeFixesAsync( document.Project.Solution.Workspace, codeFixService, document, textSpan, CodeActionRequestPriority.None, - options, isBlocking: false, addOperationScope: _ => null, cancellationToken).ConfigureAwait(false); + fallbackOptions, isBlocking: false, addOperationScope: _ => null, cancellationToken).ConfigureAwait(false); var codeRefactorings = await UnifiedSuggestedActionsSource.GetFilterAndOrderCodeRefactoringsAsync( - document.Project.Solution.Workspace, codeRefactoringService, document, textSpan, CodeActionRequestPriority.None, options, isBlocking: false, + document.Project.Solution.Workspace, codeRefactoringService, document, textSpan, CodeActionRequestPriority.None, fallbackOptions, isBlocking: false, addOperationScope: _ => null, filterOutsideSelection: false, cancellationToken).ConfigureAwait(false); var actionSets = UnifiedSuggestedActionsSource.FilterAndOrderActionSets( diff --git a/src/EditorFeatures/Core/Options/CompletionViewOptions.cs b/src/EditorFeatures/Core/Options/CompletionViewOptions.cs index 71bd290d76c9b..0666f6428af73 100644 --- a/src/EditorFeatures/Core/Options/CompletionViewOptions.cs +++ b/src/EditorFeatures/Core/Options/CompletionViewOptions.cs @@ -11,21 +11,8 @@ namespace Microsoft.CodeAnalysis.Completion { - [ExportGlobalOptionProvider, Shared] - internal sealed class CompletionViewOptions : IOptionProvider + internal sealed class CompletionViewOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CompletionViewOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - ShowCompletionItemFilters, - HighlightMatchingPortionsOfCompletionListItems, - EnableArgumentCompletionSnippets, - BlockForCompletionItems); - private const string FeatureName = "CompletionOptions"; public static readonly PerLanguageOption2 HighlightMatchingPortionsOfCompletionListItems = diff --git a/src/EditorFeatures/Core/Options/ExtensionManagerOptions.cs b/src/EditorFeatures/Core/Options/ExtensionManagerOptions.cs index 20b38e3a0c629..8e2fb3f1ae0dd 100644 --- a/src/EditorFeatures/Core/Options/ExtensionManagerOptions.cs +++ b/src/EditorFeatures/Core/Options/ExtensionManagerOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Options { - [ExportGlobalOptionProvider, Shared] - internal sealed class ExtensionManagerOptions : IOptionProvider + internal sealed class ExtensionManagerOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ExtensionManagerOptions() - { - } - - public ImmutableArray Options { get; } = ImmutableArray.Create( - DisableCrashingExtensions); - public static readonly Option2 DisableCrashingExtensions = new( nameof(ExtensionManagerOptions), nameof(DisableCrashingExtensions), defaultValue: true); } diff --git a/src/EditorFeatures/Core/Options/LegacyGlobalOptionsWorkspaceService.cs b/src/EditorFeatures/Core/Options/LegacyGlobalOptionsWorkspaceService.cs index 2b63d91443dbb..d7df3989986c8 100644 --- a/src/EditorFeatures/Core/Options/LegacyGlobalOptionsWorkspaceService.cs +++ b/src/EditorFeatures/Core/Options/LegacyGlobalOptionsWorkspaceService.cs @@ -5,7 +5,11 @@ using System; using System.Composition; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.InlineHints; namespace Microsoft.CodeAnalysis.Options { @@ -15,19 +19,85 @@ namespace Microsoft.CodeAnalysis.Options [ExportWorkspaceService(typeof(ILegacyGlobalOptionsWorkspaceService)), Shared] internal sealed class LegacyGlobalOptionsWorkspaceService : ILegacyGlobalOptionsWorkspaceService { - public IGlobalOptionService GlobalOptions { get; } + private readonly IGlobalOptionService _globalOptions; + private readonly CodeActionOptionsStorage.Provider _provider; + + private static readonly Option2 s_generateOverridesOption = new( + "GenerateOverridesOptions", "SelectAll", defaultValue: true, + storageLocation: new RoamingProfileStorageLocation($"TextEditor.Specific.GenerateOverridesOptions.SelectAll")); + + private static readonly PerLanguageOption2 s_generateOperators = new( + "GenerateEqualsAndGetHashCodeFromMembersOptions", + "GenerateOperators", defaultValue: false, + storageLocation: new RoamingProfileStorageLocation( + "TextEditor.%LANGUAGE%.Specific.GenerateEqualsAndGetHashCodeFromMembersOptions.GenerateOperators")); + + private static readonly PerLanguageOption2 s_implementIEquatable = new( + "GenerateEqualsAndGetHashCodeFromMembersOptions", + "ImplementIEquatable", defaultValue: false, + storageLocation: new RoamingProfileStorageLocation( + "TextEditor.%LANGUAGE%.Specific.GenerateEqualsAndGetHashCodeFromMembersOptions.ImplementIEquatable")); + + private static readonly PerLanguageOption2 s_addNullChecks = new( + "GenerateConstructorFromMembersOptions", + "AddNullChecks", defaultValue: false, + storageLocation: new RoamingProfileStorageLocation( + $"TextEditor.%LANGUAGE%.Specific.GenerateConstructorFromMembersOptions.AddNullChecks")); + + internal static readonly PerLanguageOption2 AddNullChecksToConstructorsGeneratedFromMembers = new( + "GenerateConstructorFromMembersOptions", + "AddNullChecks", defaultValue: false, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.GenerateConstructorFromMembersOptions.AddNullChecks")); [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public LegacyGlobalOptionsWorkspaceService(IGlobalOptionService globalOptions) { - GlobalOptions = globalOptions; + _globalOptions = globalOptions; + _provider = _globalOptions.CreateProvider(); + } + + public bool GenerateOverrides + { + get => _globalOptions.GetOption(s_generateOverridesOption); + set => _globalOptions.SetGlobalOption(new OptionKey(s_generateOverridesOption), value); } public bool RazorUseTabs - => GlobalOptions.GetOption(RazorLineFormattingOptionsStorage.UseTabs); + => _globalOptions.GetOption(RazorLineFormattingOptionsStorage.UseTabs); public int RazorTabSize - => GlobalOptions.GetOption(RazorLineFormattingOptionsStorage.TabSize); + => _globalOptions.GetOption(RazorLineFormattingOptionsStorage.TabSize); + + /// TODO: remove. https://github.com/dotnet/roslyn/issues/57283 + public bool InlineHintsOptionsDisplayAllOverride + { + get => _globalOptions.GetOption(InlineHintsGlobalStateOption.DisplayAllOverride); + set => _globalOptions.SetGlobalOption(new OptionKey(InlineHintsGlobalStateOption.DisplayAllOverride), value); + } + + public CleanCodeGenerationOptionsProvider CleanCodeGenerationOptionsProvider + => _provider; + + public AutoFormattingOptions GetAutoFormattingOptions(HostLanguageServices languageServices) + => _globalOptions.GetAutoFormattingOptions(languageServices.Language); + + public bool GetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(string language) + => _globalOptions.GetOption(s_implementIEquatable, language); + + public void SetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(string language, bool value) + => _globalOptions.SetGlobalOption(new OptionKey(s_generateOperators, language), value); + + public bool GetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(string language) + => _globalOptions.GetOption(s_implementIEquatable, language); + + public void SetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(string language, bool value) + => _globalOptions.SetGlobalOption(new OptionKey(s_implementIEquatable, language), value); + + public bool GetGenerateConstructorFromMembersOptionsAddNullChecks(string language) + => _globalOptions.GetOption(s_addNullChecks, language); + + public void SetGenerateConstructorFromMembersOptionsAddNullChecks(string language, bool value) + => _globalOptions.SetGlobalOption(new OptionKey(s_addNullChecks, language), value); } } diff --git a/src/EditorFeatures/Core/Options/NavigationBarViewOptions.cs b/src/EditorFeatures/Core/Options/NavigationBarViewOptions.cs index 3334ded376ec7..b0f41b0ab1f37 100644 --- a/src/EditorFeatures/Core/Options/NavigationBarViewOptions.cs +++ b/src/EditorFeatures/Core/Options/NavigationBarViewOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Options { - [ExportGlobalOptionProvider, Shared] - internal sealed class NavigationBarViewOptions : IOptionProvider + internal sealed class NavigationBarViewOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public NavigationBarViewOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - ShowNavigationBar); - private const string FeatureName = "NavigationBarOptions"; public static readonly PerLanguageOption ShowNavigationBar = new(FeatureName, nameof(ShowNavigationBar), defaultValue: true); diff --git a/src/EditorFeatures/Core/Options/SignatureHelpViewOptions.cs b/src/EditorFeatures/Core/Options/SignatureHelpViewOptions.cs index 027bc6995ca6f..0383174fb5338 100644 --- a/src/EditorFeatures/Core/Options/SignatureHelpViewOptions.cs +++ b/src/EditorFeatures/Core/Options/SignatureHelpViewOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Options { - [ExportGlobalOptionProvider, Shared] - internal sealed class SignatureHelpViewOptions : IOptionProvider + internal sealed class SignatureHelpViewOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SignatureHelpViewOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - ShowSignatureHelp); - private const string FeatureName = "SignatureHelpOptions"; public static readonly PerLanguageOption2 ShowSignatureHelp = new(FeatureName, nameof(ShowSignatureHelp), defaultValue: true); diff --git a/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs b/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs index 774f444b5b832..4f1ac82bfd641 100644 --- a/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs +++ b/src/EditorFeatures/Core/Organizing/OrganizeDocumentCommandHandler.cs @@ -133,13 +133,15 @@ public bool ExecuteCommand(SortAndRemoveUnnecessaryImportsCommandArgs args, Comm return true; } - private static void SortImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) + private void SortImports(ITextBuffer subjectBuffer, IUIThreadOperationContext operationContext) { var cancellationToken = operationContext.UserCancellationToken; var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { - var newDocument = Formatter.OrganizeImportsAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); + var organizeImportsService = document.GetRequiredLanguageService(); + var options = document.GetOrganizeImportsOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); + var newDocument = organizeImportsService.OrganizeImportsAsync(document, options, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); @@ -155,8 +157,10 @@ private void SortAndRemoveUnusedImports(ITextBuffer subjectBuffer, IUIThreadOper if (document != null) { var formattingOptions = document.SupportsSyntaxTree ? document.GetSyntaxFormattingOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken) : null; - var newDocument = document.GetLanguageService().RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken); - newDocument = Formatter.OrganizeImportsAsync(newDocument, cancellationToken).WaitAndGetResult(cancellationToken); + var newDocument = document.GetRequiredLanguageService().RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken); + var organizeImportsService = document.GetRequiredLanguageService(); + var options = document.GetOrganizeImportsOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken); + newDocument = organizeImportsService.OrganizeImportsAsync(newDocument, options, cancellationToken).WaitAndGetResult(cancellationToken); if (document != newDocument) { ApplyTextChange(document, newDocument); diff --git a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs index bcb8aa2c30ee9..5507591d18825 100644 --- a/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs +++ b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs @@ -12,8 +12,7 @@ namespace Microsoft.CodeAnalysis.Remote { - [ExportGlobalOptionProvider, Shared] - internal sealed class RemoteHostOptions : IOptionProvider + internal sealed class RemoteHostOptions { private const string LocalRegistryPath = @"Roslyn\Internal\OnOff\Features\"; private const string FeatureName = "InternalFeatureOnOffOptions"; @@ -41,17 +40,5 @@ internal sealed class RemoteHostOptions : IOptionProvider public static readonly Option2 OOPCoreClrFeatureFlag = new( FeatureName, nameof(OOPCoreClrFeatureFlag), defaultValue: false, new FeatureFlagStorageLocation("Roslyn.ServiceHubCore")); - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - SolutionChecksumMonitorBackOffTimeSpanInMS, - OOP64Bit, - OOPServerGCFeatureFlag, - OOPCoreClrFeatureFlag); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RemoteHostOptions() - { - } } } diff --git a/src/EditorFeatures/Core/Shared/Options/ComponentOnOffOptions.cs b/src/EditorFeatures/Core/Shared/Options/ComponentOnOffOptions.cs index 2f0fc7ff4f41c..ea6a7ae15209a 100644 --- a/src/EditorFeatures/Core/Shared/Options/ComponentOnOffOptions.cs +++ b/src/EditorFeatures/Core/Shared/Options/ComponentOnOffOptions.cs @@ -14,20 +14,8 @@ namespace Microsoft.CodeAnalysis.Editor.Shared.Options /// /// options to indicate whether a certain component in Roslyn is enabled or not /// - [ExportGlobalOptionProvider, Shared] - internal sealed class EditorComponentOnOffOptions : IOptionProvider + internal sealed class EditorComponentOnOffOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public EditorComponentOnOffOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - Adornment, - Tagger, - CodeRefactorings); - private const string LocalRegistryPath = @"Roslyn\Internal\OnOff\Components\"; private const string FeatureName = "EditorComponentOnOffOptions"; diff --git a/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs b/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs index 32d34894b342a..d6b62ab0819eb 100644 --- a/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs +++ b/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs @@ -11,35 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Shared.Options { - [ExportGlobalOptionProvider, Shared] - internal sealed class FeatureOnOffOptions : IOptionProvider + internal sealed class FeatureOnOffOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public FeatureOnOffOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - EndConstruct, - AutomaticInsertionOfAbstractOrInterfaceMembers, - LineSeparator, - Outlining, - KeywordHighlighting, - ReferenceHighlighting, - AutoInsertBlockCommentStartString, - PrettyListing, - RenameTrackingPreview, - RenameTracking, - RefactoringVerification, - AddImportsOnPaste, - OfferRemoveUnusedReferences, - OfferRemoveUnusedReferencesFeatureFlag, - ShowInheritanceMargin, - InheritanceMarginCombinedWithIndicatorMargin, - AutomaticallyCompleteStatementOnSemicolon, - SkipAnalyzersForImplicitlyTriggeredBuilds); - private const string FeatureName = "FeatureOnOffOptions"; public static readonly PerLanguageOption2 EndConstruct = new(FeatureName, "EndConstruct", defaultValue: true, diff --git a/src/EditorFeatures/Core/Shared/Options/InternalFeatureOnOffOptions.cs b/src/EditorFeatures/Core/Shared/Options/InternalFeatureOnOffOptions.cs index cba47eeb815c3..6c155b5490a5e 100644 --- a/src/EditorFeatures/Core/Shared/Options/InternalFeatureOnOffOptions.cs +++ b/src/EditorFeatures/Core/Shared/Options/InternalFeatureOnOffOptions.cs @@ -12,29 +12,8 @@ namespace Microsoft.CodeAnalysis.Editor.Shared.Options { - [ExportGlobalOptionProvider, Shared] - internal sealed class InternalFeatureOnOffOptions : IOptionProvider + internal sealed class InternalFeatureOnOffOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public InternalFeatureOnOffOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - BraceMatching, - Classification, - SemanticColorizer, - SyntacticColorizer, - AutomaticLineEnder, - SmartIndenter, - Squiggles, - FormatOnSave, - RenameTracking, - EventHookup, - Snippets, - BackgroundAnalysisMemoryMonitor); - private const string LocalRegistryPath = @"Roslyn\Internal\OnOff\Features\"; private const string FeatureName = "InternalFeatureOnOffOptions"; diff --git a/src/EditorFeatures/Core/SplitComment/SplitCommentCommandHandler.cs b/src/EditorFeatures/Core/SplitComment/SplitCommentCommandHandler.cs index 57d2a41895f51..20204663b8ed3 100644 --- a/src/EditorFeatures/Core/SplitComment/SplitCommentCommandHandler.cs +++ b/src/EditorFeatures/Core/SplitComment/SplitCommentCommandHandler.cs @@ -138,7 +138,7 @@ private static bool MatchesCommentStart(string commentStart, ITextSnapshotLine l return true; } - private static async Task<(Span replacementSpan, string replacementText)?> SplitCommentAsync( + private async Task<(Span replacementSpan, string replacementText)?> SplitCommentAsync( ITextView textView, Document document, SnapshotSpan selectionSpan, @@ -169,7 +169,7 @@ private static bool MatchesCommentStart(string commentStart, ITextSnapshotLine l var textSnapshot = selectionSpan.Snapshot; var triviaLine = textSnapshot.GetLineFromPosition(trivia.SpanStart); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var options = await document.GetLineFormattingOptionsAsync(_globalOptions, cancellationToken).ConfigureAwait(false); var replacementSpan = GetReplacementSpan(triviaLine, selectionSpan); var replacementText = GetReplacementText(textView, options, triviaLine, trivia, selectionSpan.Start); return (replacementSpan, replacementText); @@ -187,7 +187,7 @@ private static bool IsFollowedByComment(SnapshotPoint point, ISplitCommentServic } private static string GetReplacementText( - ITextView textView, DocumentOptionSet options, ITextSnapshotLine triviaLine, SyntaxTrivia trivia, int position) + ITextView textView, LineFormattingOptions options, ITextSnapshotLine triviaLine, SyntaxTrivia trivia, int position) { // We're inside a comment. Instead of inserting just a newline here, insert // 1. a newline @@ -199,12 +199,9 @@ private static string GetReplacementText( var commentStartColumn = triviaLine.GetColumnFromLineOffset(trivia.SpanStart - triviaLine.Start, textView.Options); - var useTabs = options.GetOption(FormattingOptions.UseTabs); - var tabSize = options.GetOption(FormattingOptions.TabSize); - var prefix = GetCommentPrefix(triviaLine.Snapshot, trivia, position); - var replacementText = options.GetOption(FormattingOptions.NewLine) + - commentStartColumn.CreateIndentationString(useTabs, tabSize) + + var replacementText = options.NewLine + + commentStartColumn.CreateIndentationString(options.UseTabs, options.TabSize) + prefix + GetWhitespaceAfterCommentPrefix(trivia, triviaLine, prefix, position); diff --git a/src/EditorFeatures/Core/SplitComment/SplitCommentOptions.cs b/src/EditorFeatures/Core/SplitComment/SplitCommentOptions.cs index e00bdc8b827f2..dd8d89b5be12c 100644 --- a/src/EditorFeatures/Core/SplitComment/SplitCommentOptions.cs +++ b/src/EditorFeatures/Core/SplitComment/SplitCommentOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.SplitComment { - [ExportGlobalOptionProvider, Shared] - internal sealed class SplitCommentOptions : IOptionProvider + internal sealed class SplitCommentOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SplitCommentOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - Enabled); - public static PerLanguageOption2 Enabled = new PerLanguageOption2(nameof(SplitCommentOptions), nameof(Enabled), defaultValue: true, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.SplitComments")); diff --git a/src/EditorFeatures/Core/Suggestions/SuggestionsOptions.cs b/src/EditorFeatures/Core/Suggestions/SuggestionsOptions.cs index b347b4c7a07e8..dde68b6524996 100644 --- a/src/EditorFeatures/Core/Suggestions/SuggestionsOptions.cs +++ b/src/EditorFeatures/Core/Suggestions/SuggestionsOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions { - [ExportGlobalOptionProvider, Shared] - internal sealed class SuggestionsOptions : IOptionProvider + internal sealed class SuggestionsOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SuggestionsOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - AsynchronousQuickActionsDisableFeatureFlag); - private const string FeatureName = "SuggestionsOptions"; public static readonly Option2 Asynchronous = new(FeatureName, nameof(Asynchronous), defaultValue: null, diff --git a/src/EditorFeatures/Core/Suggestions/SuggestionsOptionsProvider.cs b/src/EditorFeatures/Core/Suggestions/SuggestionsOptionsProvider.cs deleted file mode 100644 index 6fc82433450b6..0000000000000 --- a/src/EditorFeatures/Core/Suggestions/SuggestionsOptionsProvider.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Options.Providers; - -namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions -{ - [ExportGlobalOptionProvider, Shared] - internal sealed class SuggestionsOptionsProvider : IOptionProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public SuggestionsOptionsProvider() - { - } - - public ImmutableArray Options { get; } = ImmutableArray.Create( - SuggestionsOptions.Asynchronous, - SuggestionsOptions.AsynchronousQuickActionsDisableFeatureFlag); - } -} diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs index f2c748ac30d8c..2a9e0f8425070 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.VisualBasic; @@ -81,14 +82,14 @@ public TestChangeSignatureOptionsService TestChangeSignatureOptionsService public async Task ChangeSignatureAsync() { - var context = await ChangeSignatureService.GetChangeSignatureContextAsync(InvocationDocument, _testDocument.CursorPosition.Value, restrictToDeclarations: false, CodeActionOptions.DefaultProvider, CancellationToken.None).ConfigureAwait(false); + var context = await ChangeSignatureService.GetChangeSignatureContextAsync(InvocationDocument, _testDocument.CursorPosition.Value, restrictToDeclarations: false, Workspace.GlobalOptions.CreateProvider(), CancellationToken.None).ConfigureAwait(false); var options = AbstractChangeSignatureService.GetChangeSignatureOptions(context); return await ChangeSignatureService.ChangeSignatureWithContextAsync(context, options, CancellationToken.None); } public async Task GetParameterConfigurationAsync() { - var context = await ChangeSignatureService.GetChangeSignatureContextAsync(InvocationDocument, _testDocument.CursorPosition.Value, restrictToDeclarations: false, CodeActionOptions.DefaultProvider, CancellationToken.None); + var context = await ChangeSignatureService.GetChangeSignatureContextAsync(InvocationDocument, _testDocument.CursorPosition.Value, restrictToDeclarations: false, Workspace.GlobalOptions.CreateProvider(), CancellationToken.None); if (context is ChangeSignatureAnalysisSucceededContext changeSignatureAnalyzedSucceedContext) { return changeSignatureAnalyzedSucceedContext.ParameterConfiguration; diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index e1247941c7252..48b1f7fb7d9f0 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -185,13 +185,7 @@ protected TestWorkspace CreateWorkspaceFromOptions(string workspaceMarkupOrCode, } #if !CODE_STYLE - workspace.ApplyOptions(parameters.options); - - if (parameters.globalOptions != null) - { - workspace.ApplyOptions(parameters.globalOptions); - parameters.globalOptions.SetGlobalOptions(workspace.GlobalOptions); - } + parameters.globalOptions?.SetGlobalOptions(workspace.GlobalOptions); #endif return workspace; } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs index 237301cd76638..54e87a92da82d 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -76,7 +76,7 @@ public Test() internal OptionsCollection Options => _sharedState.Options; #if !CODE_STYLE - internal CodeActionOptions CodeActionOptions + internal CodeActionOptionsProvider CodeActionOptions { get => _sharedState.CodeActionOptions; set => _sharedState.CodeActionOptions = value; @@ -109,7 +109,7 @@ protected override AnalyzerOptions GetAnalyzerOptions(Project project) => new WorkspaceAnalyzerOptions(base.GetAnalyzerOptions(project), project.Solution, _sharedState.GetIdeAnalyzerOptions(project)); protected override CodeFixContext CreateCodeFixContext(Document document, TextSpan span, ImmutableArray diagnostics, Action> registerCodeFix, CancellationToken cancellationToken) - => new(document, span, diagnostics, registerCodeFix, new DelegatingCodeActionOptionsProvider(_ => _sharedState.CodeActionOptions), isBlocking: false, cancellationToken); + => new(document, span, diagnostics, registerCodeFix, _sharedState.CodeActionOptions, isBlocking: false, cancellationToken); protected override FixAllContext CreateFixAllContext( Document? document, @@ -130,7 +130,7 @@ protected override FixAllContext CreateFixAllContext( codeActionEquivalenceKey, diagnosticIds, fixAllDiagnosticProvider, - new DelegatingCodeActionOptionsProvider(_ => _sharedState.CodeActionOptions)), + _sharedState.CodeActionOptions), new ProgressTracker(), cancellationToken); #endif diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs index b5a4734c2b482..bbda01e197957 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/SharedVerifierState.cs @@ -48,7 +48,7 @@ public SharedVerifierState(AnalyzerTest test, string defaultFileE internal OptionsCollection Options { get; } #if !CODE_STYLE - internal CodeActionOptions CodeActionOptions { get; set; } = CodeActionOptions.Default; + internal CodeActionOptionsProvider CodeActionOptions { get; set; } = CodeAnalysis.CodeActions.CodeActionOptions.DefaultProvider; internal IdeAnalyzerOptions? IdeAnalyzerOptions { get; set; } internal IdeAnalyzerOptions GetIdeAnalyzerOptions(Project project) diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs index e36e580967cbf..435d68794fe4b 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs @@ -145,7 +145,7 @@ private async Task> TestOperationAsync( expectedChangedDocumentId: null); } - protected async Task TestMoveTypeToNewFileAsync( + private protected async Task TestMoveTypeToNewFileAsync( string originalCode, string expectedSourceTextAfterRefactoring, string expectedDocumentName, @@ -153,15 +153,13 @@ protected async Task TestMoveTypeToNewFileAsync( ImmutableArray destinationDocumentContainers = default, bool expectedCodeAction = true, int index = 0, - Action onAfterWorkspaceCreated = null) + OptionsCollection options = null) { - var testOptions = new TestParameters(index: index); + var testOptions = new TestParameters(index: index, options: options); if (expectedCodeAction) { using var workspace = CreateWorkspaceFromOptions(originalCode, testOptions); - onAfterWorkspaceCreated?.Invoke(workspace); - // replace with default values on null. destinationDocumentContainers = destinationDocumentContainers.NullToEmpty(); diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/NamingStyles/NamingStylesTestOptionSets.cs b/src/EditorFeatures/DiagnosticsTestUtilities/NamingStyles/NamingStylesTestOptionSets.cs index 36fc2c6eb2e45..0f6a3e7056eae 100644 --- a/src/EditorFeatures/DiagnosticsTestUtilities/NamingStyles/NamingStylesTestOptionSets.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/NamingStyles/NamingStylesTestOptionSets.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Immutable; using System.Linq; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.NamingStyles; diff --git a/src/EditorFeatures/Test/Formatting/InferredIndentationTests.cs b/src/EditorFeatures/Test/Formatting/InferredIndentationTests.cs index b736bf02f43fe..4d7f129f93f1d 100644 --- a/src/EditorFeatures/Test/Formatting/InferredIndentationTests.cs +++ b/src/EditorFeatures/Test/Formatting/InferredIndentationTests.cs @@ -5,6 +5,7 @@ #nullable disable using System.Linq; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; @@ -22,9 +23,9 @@ public async Task BlankFileMatchesWorkspaceSettings() { using var testWorkspace = CreateWithLines( ""); - var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetOptionsAsync(); + var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetLineFormattingOptionsAsync(testWorkspace.GlobalOptions, CancellationToken.None); - Assert.Equal(FormattingOptions.UseTabs.DefaultValue, options.GetOption(FormattingOptions.UseTabs)); + Assert.Equal(FormattingOptions.UseTabs.DefaultValue, options.UseTabs); } [Fact] @@ -35,9 +36,9 @@ public async Task SingleLineWithTab() "{", "\tvoid M() { }", "}"); - var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetOptionsAsync(); + var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetLineFormattingOptionsAsync(testWorkspace.GlobalOptions, CancellationToken.None); - Assert.True(options.GetOption(FormattingOptions.UseTabs)); + Assert.True(options.UseTabs); } [Fact] @@ -48,10 +49,10 @@ public async Task SingleLineWithFourSpaces() "{", " void M() { }", "}"); - var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetOptionsAsync(); + var options = await testWorkspace.CurrentSolution.Projects.Single().Documents.Single().GetLineFormattingOptionsAsync(testWorkspace.GlobalOptions, CancellationToken.None); - Assert.False(options.GetOption(FormattingOptions.UseTabs)); - Assert.Equal(4, options.GetOption(FormattingOptions.IndentationSize)); + Assert.False(options.UseTabs); + Assert.Equal(4, options.IndentationSize); } private static TestWorkspace CreateWithLines(params string[] lines) diff --git a/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs b/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs index 60c41b52ea6e9..2b9987550081d 100644 --- a/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs +++ b/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs @@ -10,6 +10,8 @@ using System.Security; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.Editor.CSharp.DecompiledSource; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.MetadataAsSource; @@ -78,7 +80,11 @@ public Task GenerateSourceAsync(ISymbol symbol, Project? p return _metadataAsSourceService.GetGeneratedFileAsync(project, symbol, signaturesOnly, MetadataAsSourceOptions.GetDefault(project.LanguageServices)); } - public async Task GenerateSourceAsync(string? symbolMetadataName = null, Project? project = null, bool signaturesOnly = true) + public async Task GenerateSourceAsync( + string? symbolMetadataName = null, + Project? project = null, + bool signaturesOnly = true, + bool fileScopedNamespaces = false) { symbolMetadataName ??= AbstractMetadataAsSourceTests.DefaultSymbolMetadataName; project ??= this.DefaultProject; @@ -112,8 +118,24 @@ public async Task GenerateSourceAsync(string? symbolMetada } } + var options = MetadataAsSourceOptions.GetDefault(project.LanguageServices); + + if (fileScopedNamespaces) + { + options = options with + { + GenerationOptions = options.GenerationOptions with + { + GenerationOptions = new CSharpCodeGenerationOptions + { + NamespaceDeclarations = new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Silent) + } + } + }; + } + // Generate and hold onto the result so it can be disposed of with this context - var result = await _metadataAsSourceService.GetGeneratedFileAsync(project, symbol, signaturesOnly, MetadataAsSourceOptions.GetDefault(project.LanguageServices)); + var result = await _metadataAsSourceService.GetGeneratedFileAsync(project, symbol, signaturesOnly, options); return result; } @@ -131,9 +153,9 @@ public static void VerifyResult(MetadataAsSourceFile file, string expected) Assert.Equal(expectedSpan.End, actualSpan.End); } - public async Task GenerateAndVerifySourceAsync(string symbolMetadataName, string expected, Project? project = null, bool signaturesOnly = true) + public async Task GenerateAndVerifySourceAsync(string symbolMetadataName, string expected, Project? project = null, bool signaturesOnly = true, bool fileScopedNamespaces = false) { - var result = await GenerateSourceAsync(symbolMetadataName, project, signaturesOnly); + var result = await GenerateSourceAsync(symbolMetadataName, project, signaturesOnly, fileScopedNamespaces); VerifyResult(result, expected); } diff --git a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs index 017800d47dcef..a90d5d8174946 100644 --- a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs +++ b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs @@ -19,6 +19,9 @@ using VB = Microsoft.CodeAnalysis.VisualBasic; using Microsoft.CodeAnalysis.CSharp.Formatting; using System.Threading; +using Microsoft.CodeAnalysis.MetadataAsSource; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; +using Microsoft.CodeAnalysis.CodeCleanup; namespace Microsoft.CodeAnalysis.Editor.UnitTests.MetadataAsSource { @@ -984,10 +987,6 @@ public async Task TestTypeInFileScopedNamespace1() using var context = TestContext.Create( LanguageNames.CSharp, SpecializedCollections.SingletonEnumerable(metadataSource), languageVersion: "10"); - context.Workspace.SetOptions(context.Workspace.Options.WithChangedOption( - CSharpCodeStyleOptions.NamespaceDeclarations, - new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Silent))); - await context.GenerateAndVerifySourceAsync("N.C", $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // {CodeAnalysisResources.InMemoryAssembly} @@ -998,7 +997,8 @@ namespace N; public class [|C|] {{ public C(); -}}"); +}}", + fileScopedNamespaces: true); } [WorkItem(546198, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546198")] @@ -1010,10 +1010,6 @@ public async Task TestTypeInFileScopedNamespace2() using var context = TestContext.Create( LanguageNames.CSharp, SpecializedCollections.SingletonEnumerable(metadataSource), languageVersion: "9"); - context.Workspace.SetOptions(context.Workspace.Options.WithChangedOption( - CSharpCodeStyleOptions.NamespaceDeclarations, - new CodeStyleOption2(NamespaceDeclarationPreference.FileScoped, NotificationOption2.Silent))); - await context.GenerateAndVerifySourceAsync("N.C", $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // {CodeAnalysisResources.InMemoryAssembly} @@ -1025,7 +1021,7 @@ public class [|C|] {{ public C(); }} -}}"); +}}", fileScopedNamespaces: true); } [WorkItem(546198, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546198")] @@ -1037,10 +1033,6 @@ public async Task TestTypeInFileScopedNamespace3() using var context = TestContext.Create( LanguageNames.CSharp, SpecializedCollections.SingletonEnumerable(metadataSource), languageVersion: "10"); - context.Workspace.SetOptions(context.Workspace.Options.WithChangedOption( - CSharpCodeStyleOptions.NamespaceDeclarations, - new CodeStyleOption2(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Silent))); - await context.GenerateAndVerifySourceAsync("N.C", $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // {CodeAnalysisResources.InMemoryAssembly} diff --git a/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb b/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb index 3f8c543568135..ebdb2c335fe71 100644 --- a/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb +++ b/src/EditorFeatures/Test2/Expansion/AbstractExpansionTest.vb @@ -4,6 +4,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces @@ -28,7 +29,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Expansion Dim root = Await document.GetSyntaxRootAsync() - Dim cleanupOptions = Await document.GetCodeCleanupOptionsAsync(fallbackOptions:=Nothing, CancellationToken.None) + Dim cleanupOptions = CodeCleanupOptions.GetDefault(document.Project.LanguageServices) If hostDocument.AnnotatedSpans.ContainsKey("Expand") Then For Each span In hostDocument.AnnotatedSpans("Expand") diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs index ac23d353e45b4..222c32d6dc623 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractArgumentProviderTests`1.cs @@ -73,12 +73,11 @@ private protected async Task VerifyDefaultValueAsync( Assert.IsType(GetArgumentProviderType(), provider); var root = await document.GetRequiredSyntaxRootAsync(CancellationToken.None); - var documentOptions = await document.GetOptionsAsync(CancellationToken.None); var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None); var parameter = GetParameterSymbolInfo(workspace, semanticModel, root, position, CancellationToken.None); Contract.ThrowIfNull(parameter); - var context = new ArgumentContext(provider, documentOptions, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None); + var context = new ArgumentContext(provider, semanticModel, position, parameter, previousDefaultValue, CancellationToken.None); await provider.ProvideArgumentAsync(context); Assert.Equal(expectedDefaultValue, context.DefaultValue); diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index c11adfcd4ee34..36fa5d9e91d55 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -14,6 +14,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncCompletion; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Host.Mef; @@ -127,14 +128,15 @@ private protected abstract Task BaseVerifyWorkerAsync( SourceCodeKind sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, CompletionItemFlags? flags, bool skipSpeculation = false); + List matchingFilters, CompletionItemFlags? flags, CompletionOptions options, + bool skipSpeculation = false); internal Task GetCompletionListAsync( CompletionService service, Document document, int position, RoslynCompletion.CompletionTrigger triggerInfo, - CompletionOptions? options = null) + CompletionOptions options = null) => service.GetCompletionsAsync(document, position, options ?? GetCompletionOptions(), OptionValueSet.Empty, triggerInfo, GetRoles(document)); private protected async Task CheckResultsAsync( @@ -144,8 +146,12 @@ private protected async Task CheckResultsAsync( bool? hasSuggestionModeItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, CompletionItemFlags? flags) + List matchingFilters, + CompletionItemFlags? flags, + CompletionOptions options) { + options ??= GetCompletionOptions(); + var code = (await document.GetTextAsync()).ToString(); var trigger = RoslynCompletion.CompletionTrigger.Invoke; @@ -155,7 +161,6 @@ private protected async Task CheckResultsAsync( trigger = RoslynCompletion.CompletionTrigger.CreateInsertionTrigger(insertedCharacter: code.ElementAt(position - 1)); } - var options = GetCompletionOptions(); var displayOptions = SymbolDescriptionOptions.Default; var completionService = GetCompletionService(document.Project); var completionList = await GetCompletionListAsync(completionService, document, position, trigger, options); @@ -241,7 +246,7 @@ private async Task VerifyAsync( SourceCodeKind? sourceCodeKind, bool usePreviousCharAsTrigger, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionModeItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, - List matchingFilters, CompletionItemFlags? flags, bool skipSpeculation = false) + List matchingFilters, CompletionItemFlags? flags, CompletionOptions options, bool skipSpeculation = false) { foreach (var sourceKind in sourceCodeKind.HasValue ? new[] { sourceCodeKind.Value } : new[] { SourceCodeKind.Regular, SourceCodeKind.Script }) { @@ -259,7 +264,7 @@ await VerifyWorkerAsync( sourceKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionModeItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, - skipSpeculation: skipSpeculation).ConfigureAwait(false); + options, skipSpeculation: skipSpeculation).ConfigureAwait(false); } } @@ -336,7 +341,7 @@ private protected async Task VerifyItemExistsAsync( int? glyph = null, int? matchPriority = null, bool? hasSuggestionModeItem = null, string displayTextSuffix = null, string displayTextPrefix = null, string inlineDescription = null, bool? isComplexTextEdit = null, List matchingFilters = null, - CompletionItemFlags? flags = null, bool skipSpeculation = false) + CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence: false, @@ -344,7 +349,7 @@ await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix, displayTextPrefix: displayTextPrefix, inlineDescription: inlineDescription, isComplexTextEdit: isComplexTextEdit, matchingFilters: matchingFilters, - flags: flags, skipSpeculation: skipSpeculation); + flags: flags, options, skipSpeculation: skipSpeculation); } private protected async Task VerifyItemIsAbsentAsync( @@ -352,32 +357,33 @@ private protected async Task VerifyItemIsAbsentAsync( SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool? hasSuggestionModeItem = null, string displayTextSuffix = null, string displayTextPrefix = null, string inlineDescription = null, - bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null) + bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null) { await VerifyAsync(markup, expectedItem, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix, displayTextPrefix: displayTextPrefix, inlineDescription: inlineDescription, - isComplexTextEdit: isComplexTextEdit, matchingFilters: matchingFilters, flags: flags); + isComplexTextEdit: isComplexTextEdit, matchingFilters: matchingFilters, flags: flags, options); } - protected async Task VerifyAnyItemExistsAsync( + private protected async Task VerifyAnyItemExistsAsync( string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool? hasSuggestionModeItem = null, string displayTextSuffix = null, string displayTextPrefix = null, - string inlineDescription = null) + string inlineDescription = null, CompletionOptions options = null) { await VerifyAsync(markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, sourceCodeKind, usePreviousCharAsTrigger: usePreviousCharAsTrigger, checkForAbsence: false, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix, displayTextPrefix: displayTextPrefix, inlineDescription: inlineDescription, - isComplexTextEdit: null, matchingFilters: null, flags: null); + isComplexTextEdit: null, matchingFilters: null, flags: null, options); } - protected async Task VerifyNoItemsExistAsync( + private protected async Task VerifyNoItemsExistAsync( string markup, SourceCodeKind? sourceCodeKind = null, bool usePreviousCharAsTrigger = false, bool? hasSuggestionModeItem = null, - string displayTextSuffix = null, string inlineDescription = null) + string displayTextSuffix = null, string inlineDescription = null, CompletionOptions options = null) { await VerifyAsync( markup, expectedItemOrNull: null, expectedDescriptionOrNull: null, @@ -385,7 +391,7 @@ await VerifyAsync( checkForAbsence: true, glyph: null, matchPriority: null, hasSuggestionModeItem: hasSuggestionModeItem, displayTextSuffix: displayTextSuffix, displayTextPrefix: null, inlineDescription: inlineDescription, - isComplexTextEdit: null, matchingFilters: null, flags: null); + isComplexTextEdit: null, matchingFilters: null, flags: null, options); } internal abstract Type GetCompletionProviderType(); @@ -407,6 +413,7 @@ private protected virtual async Task VerifyWorkerAsync( string displayTextSuffix, string displayTextPrefix, string inlineDescription, bool? isComplexTextEdit, List matchingFilters, CompletionItemFlags? flags, + CompletionOptions options, bool skipSpeculation = false) { using var workspaceFixture = GetOrCreateWorkspaceFixture(); @@ -419,7 +426,7 @@ await CheckResultsAsync( expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionModeItem, displayTextSuffix, displayTextPrefix, - inlineDescription, isComplexTextEdit, matchingFilters, flags); + inlineDescription, isComplexTextEdit, matchingFilters, flags, options); if (!skipSpeculation && await CanUseSpeculativeSemanticModelAsync(document1, position)) { @@ -428,7 +435,7 @@ await CheckResultsAsync( document2, position, expectedItemOrNull, expectedDescriptionOrNull, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionModeItem, displayTextSuffix, displayTextPrefix, - inlineDescription, isComplexTextEdit, matchingFilters, flags); + inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } } @@ -914,7 +921,7 @@ private protected async Task VerifyAtPositionAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, - bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + bool? isComplexTextEdit = null, List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { code = code.Substring(0, position) + insertText + code.Substring(position); position += insertText.Length; @@ -923,7 +930,7 @@ await BaseVerifyWorkerAsync(code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, skipSpeculation: skipSpeculation); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options, skipSpeculation: skipSpeculation); } private protected async Task VerifyAtPositionAsync( @@ -932,13 +939,13 @@ private protected async Task VerifyAtPositionAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, CompletionOptions options = null, bool skipSpeculation = false) { await VerifyAtPositionAsync( code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, - inlineDescription, isComplexTextEdit, matchingFilters, flags, skipSpeculation: skipSpeculation); + inlineDescription, isComplexTextEdit, matchingFilters, flags, options, skipSpeculation: skipSpeculation); } private protected async Task VerifyAtEndOfFileAsync( @@ -947,7 +954,8 @@ private protected async Task VerifyAtEndOfFileAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null) + List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null) { // only do this if the placeholder was at the end of the text. if (code.Length != position) @@ -962,7 +970,7 @@ await BaseVerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, - inlineDescription, isComplexTextEdit, matchingFilters, flags); + inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } private protected async Task VerifyAtPosition_ItemPartiallyWrittenAsync( @@ -971,13 +979,15 @@ private protected async Task VerifyAtPosition_ItemPartiallyWrittenAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null, bool skipSpeculation = false) + List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null, bool skipSpeculation = false) { await VerifyAtPositionAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, skipSpeculation: skipSpeculation); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options, + skipSpeculation: skipSpeculation); } private protected async Task VerifyAtEndOfFileAsync( @@ -986,12 +996,13 @@ private protected async Task VerifyAtEndOfFileAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null) + List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null) { await VerifyAtEndOfFileAsync(code, position, string.Empty, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, - displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags); + displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options); } private protected async Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( @@ -1000,13 +1011,14 @@ private protected async Task VerifyAtEndOfFile_ItemPartiallyWrittenAsync( SourceCodeKind sourceCodeKind, bool checkForAbsence, int? glyph, int? matchPriority, bool? hasSuggestionItem, string displayTextSuffix, string displayTextPrefix, string inlineDescription = null, bool? isComplexTextEdit = null, - List matchingFilters = null, CompletionItemFlags? flags = null) + List matchingFilters = null, CompletionItemFlags? flags = null, + CompletionOptions options = null) { await VerifyAtEndOfFileAsync( code, position, ItemPartiallyWritten(expectedItemOrNull), usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags); + isComplexTextEdit, matchingFilters, flags, options); } protected void VerifyTextualTriggerCharacter( diff --git a/src/EditorFeatures/TestUtilities/ExtractInterface/AbstractExtractInterfaceTests.cs b/src/EditorFeatures/TestUtilities/ExtractInterface/AbstractExtractInterfaceTests.cs index fdc228081db66..a78b7a2ffe961 100644 --- a/src/EditorFeatures/TestUtilities/ExtractInterface/AbstractExtractInterfaceTests.cs +++ b/src/EditorFeatures/TestUtilities/ExtractInterface/AbstractExtractInterfaceTests.cs @@ -98,7 +98,7 @@ private static async Task TestExtractInterfaceCommandAsync( using var testState = ExtractInterfaceTestState.Create(markup, languageName, compilationOptions, options: new OptionsCollection(languageName) { - { CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Never, NotificationOption2.Silent } + { CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Never, NotificationOption2.Silent } }); var result = await testState.ExtractViaCommandAsync(); diff --git a/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs b/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs index 3ec9a60bec796..da77cb8bc205f 100644 --- a/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs +++ b/src/EditorFeatures/TestUtilities/ExtractInterface/ExtractInterfaceTestState.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.ExtractInterface; using Microsoft.CodeAnalysis.Notification; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -85,7 +86,7 @@ public Task GetTypeAnalysisResultAsync(TypeD ExtractFromDocument, _testDocument.CursorPosition.Value, typeDiscoveryRule, - CodeActionOptions.DefaultProvider, + Workspace.GlobalOptions.CreateProvider(), CancellationToken.None); } @@ -94,7 +95,7 @@ public Task ExtractViaCommandAsync() return ExtractInterfaceService.ExtractInterfaceAsync( ExtractFromDocument, _testDocument.CursorPosition.Value, - CodeActionOptions.DefaultProvider, + Workspace.GlobalOptions.CreateProvider(), (errorMessage, severity) => { this.ErrorMessage = errorMessage; @@ -108,7 +109,7 @@ public async Task ExtractViaCodeAction() var actions = await ExtractInterfaceService.GetExtractInterfaceCodeActionAsync( ExtractFromDocument, new TextSpan(_testDocument.CursorPosition.Value, 1), - CodeActionOptions.DefaultProvider, + Workspace.GlobalOptions.CreateProvider(), CancellationToken.None); var action = actions.Single(); diff --git a/src/EditorFeatures/TestUtilities/ExtractInterface/TestExtractInterfaceOptions.cs b/src/EditorFeatures/TestUtilities/ExtractInterface/TestExtractInterfaceOptions.cs index f9aff7552cbe8..1db5a8c70d8bf 100644 --- a/src/EditorFeatures/TestUtilities/ExtractInterface/TestExtractInterfaceOptions.cs +++ b/src/EditorFeatures/TestUtilities/ExtractInterface/TestExtractInterfaceOptions.cs @@ -50,6 +50,7 @@ public Task GetExtractInterfaceOptionsAsync( string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { this.AllExtractableMembers = extractableMembers; @@ -66,7 +67,7 @@ public Task GetExtractInterfaceOptionsAsync( interfaceName: ChosenInterfaceName ?? defaultInterfaceName, fileName: ChosenFileName ?? defaultInterfaceName, location: SameFile ? ExtractInterfaceOptionsResult.ExtractLocation.SameFile : ExtractInterfaceOptionsResult.ExtractLocation.NewFile, - CodeActionOptions.DefaultProvider); + fallbackOptions); return Task.FromResult(result); } diff --git a/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs b/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs index 83c83a9ba035a..e22b231b1aab5 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/AbstractNewDocumentFormattingServiceTests.cs @@ -5,7 +5,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -20,59 +22,25 @@ public abstract class AbstractNewDocumentFormattingServiceTests protected abstract string Language { get; } protected abstract TestWorkspace CreateTestWorkspace(string testCode, ParseOptions? parseOptions); - internal Task TestAsync(string testCode, string expected) + internal async Task TestAsync(string testCode, string expected, OptionsCollection? options = null, ParseOptions? parseOptions = null) { - return TestCoreAsync(testCode, expected, options: null, parseOptions: null); - } - - internal Task TestAsync(string testCode, string expected, (PerLanguageOption2, T)[]? options = null, ParseOptions? parseOptions = null) - { - return TestCoreAsync(testCode, - expected, - options.Select(o => (new OptionKey(o.Item1, Language), o.Item2)).ToArray(), - parseOptions); - } + using var workspace = CreateTestWorkspace(testCode, parseOptions); + options?.SetGlobalOptions(workspace.GlobalOptions); - internal Task TestAsync(string testCode, string expected, (Option2, T)[]? options = null, ParseOptions? parseOptions = null) - { - return TestCoreAsync(testCode, - expected, - options.Select(o => (new OptionKey(o.Item1), o.Item2)).ToArray(), - parseOptions); - } - - internal Task TestAsync(string testCode, string expected, (OptionKey, object)[]? options = null, ParseOptions? parseOptions = null) - { - return TestCoreAsync(testCode, - expected, - options, - parseOptions); - } - - private async Task TestCoreAsync(string testCode, string expected, (OptionKey, T)[]? options, ParseOptions? parseOptions) - { - using (var workspace = CreateTestWorkspace(testCode, parseOptions)) - { - if (options is not null) - { - var workspaceOptions = workspace.Options; - foreach (var option in options) - { - workspaceOptions = workspaceOptions.WithChangedOption(option.Item1, option.Item2); - } + var solution = workspace.CurrentSolution; - workspace.SetOptions(workspaceOptions); - } + var document = workspace.CurrentSolution.Projects.First().Documents.First(); + var languageServices = document.Project.LanguageServices; - var document = workspace.CurrentSolution.Projects.First().Documents.First(); + var cleanupOptions = + options?.ToAnalyzerConfigOptions(languageServices).GetCodeCleanupOptions(allowImportsInHiddenRegions: false, fallbackOptions: null, languageServices) ?? + CodeCleanupOptions.GetDefault(languageServices); - var formattingService = document.GetRequiredLanguageService(); - var cleanupOptions = await document.GetCodeCleanupOptionsAsync(fallbackOptions: null, CancellationToken.None).ConfigureAwait(false); - var formattedDocument = await formattingService.FormatNewDocumentAsync(document, hintDocument: null, cleanupOptions, CancellationToken.None); + var formattingService = document.GetRequiredLanguageService(); + var formattedDocument = await formattingService.FormatNewDocumentAsync(document, hintDocument: null, cleanupOptions, CancellationToken.None); - var actual = await formattedDocument.GetTextAsync(); - AssertEx.EqualOrDiff(expected, actual.ToString()); - } + var actual = await formattedDocument.GetTextAsync(); + AssertEx.EqualOrDiff(expected, actual.ToString()); } } } diff --git a/src/EditorFeatures/TestUtilities/Utilities/CSharpCodeActionOptions.cs b/src/EditorFeatures/TestUtilities/Utilities/CSharpCodeActionOptions.cs new file mode 100644 index 0000000000000..9766f13ab2af8 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/Utilities/CSharpCodeActionOptions.cs @@ -0,0 +1,29 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; +using Microsoft.CodeAnalysis.Formatting; + +namespace Microsoft.CodeAnalysis.Test.Utilities; + +internal static class CSharpCodeActionOptions +{ + public static CodeActionOptions Default = new( + new CodeCleanupOptions( + CSharpSyntaxFormattingOptions.Default, + CSharpSimplifierOptions.Default), + CSharpCodeGenerationOptions.Default, + CSharpIdeCodeStyleOptions.Default); +} diff --git a/src/EditorFeatures/TestUtilities/Utilities/VisualBasicCodeActionOptions.cs b/src/EditorFeatures/TestUtilities/Utilities/VisualBasicCodeActionOptions.cs new file mode 100644 index 0000000000000..c6be069c144d4 --- /dev/null +++ b/src/EditorFeatures/TestUtilities/Utilities/VisualBasicCodeActionOptions.cs @@ -0,0 +1,39 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.ImplementType; +using Microsoft.CodeAnalysis.VisualBasic.CodeGeneration; +using Microsoft.CodeAnalysis.VisualBasic.CodeStyle; +using Microsoft.CodeAnalysis.VisualBasic.Formatting; +using Microsoft.CodeAnalysis.VisualBasic.Simplification; + +namespace Microsoft.CodeAnalysis.Test.Utilities; + +internal static class VisualBasicCodeActionOptions +{ + public static CodeActionOptions Default = new( + new CodeCleanupOptions( + VisualBasicSyntaxFormattingOptions.Default, + VisualBasicSimplifierOptions.Default), + VisualBasicCodeGenerationOptions.Default, + VisualBasicIdeCodeStyleOptions.Default); + + public static CodeActionOptions WithWrappingColumn(this CodeActionOptions options, int value) + => options with { WrappingColumn = value }; + + public static CodeActionOptions With(this CodeActionOptions options, VisualBasicSyntaxFormattingOptions value) + => options with { CleanupOptions = options.CleanupOptions with { FormattingOptions = value } }; + + public static CodeActionOptions With(this CodeActionOptions options, ImplementTypeOptions value) + => options with { ImplementTypeOptions = value }; +} diff --git a/src/EditorFeatures/VisualBasic/AddImports/VisualBasicAddImportPlacementOptionsStorage.vb b/src/EditorFeatures/VisualBasic/AddImports/VisualBasicAddImportPlacementOptionsStorage.vb index 2718d8415b900..df0ba04561ecc 100644 --- a/src/EditorFeatures/VisualBasic/AddImports/VisualBasicAddImportPlacementOptionsStorage.vb +++ b/src/EditorFeatures/VisualBasic/AddImports/VisualBasicAddImportPlacementOptionsStorage.vb @@ -29,10 +29,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport Public Function GetVisualBasicAddImportPlacementOptions(globalOptions As IGlobalOptionService) As AddImportPlacementOptions - Return New AddImportPlacementOptions( - PlaceSystemNamespaceFirst:=globalOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.VisualBasic), - PlaceImportsInsideNamespaces:=False, ' VB does not support imports in namespace declarations - AllowInHiddenRegions:=False) ' no global option available + Return New AddImportPlacementOptions() With + { + .PlaceSystemNamespaceFirst = globalOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.VisualBasic), + .UsingDirectivePlacement = AddImportPlacementOptions.Default.UsingDirectivePlacement, ' VB does not support imports in namespace declarations + .AllowInHiddenRegions = AddImportPlacementOptions.Default.AllowInHiddenRegions ' no global option available + } End Function End Module End Namespace diff --git a/src/EditorFeatures/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptionsStorage.vb b/src/EditorFeatures/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptionsStorage.vb index f106b2b29d82a..dc0106755be9a 100644 --- a/src/EditorFeatures/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptionsStorage.vb +++ b/src/EditorFeatures/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptionsStorage.vb @@ -25,7 +25,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration End Sub Public Function GetOptions(globalOptions As IGlobalOptionService) As CodeGenerationOptions Implements ICodeGenerationOptionsStorage.GetOptions - Return VisualBasicCodeGenerationOptions.Default + Return New VisualBasicCodeGenerationOptions() With + { + .Common = globalOptions.GetCommonCodeGenerationOptions(LanguageNames.VisualBasic) + } End Function End Class End Module diff --git a/src/EditorFeatures/VisualBasic/CodeStyle/VisualBasicCodeStyleOptionsStorage.vb b/src/EditorFeatures/VisualBasic/CodeStyle/VisualBasicCodeStyleOptionsStorage.vb new file mode 100644 index 0000000000000..2febc0582443f --- /dev/null +++ b/src/EditorFeatures/VisualBasic/CodeStyle/VisualBasicCodeStyleOptionsStorage.vb @@ -0,0 +1,39 @@ +' 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 +Imports System.Composition +Imports System.Runtime.CompilerServices +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.Options + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle + Friend Module VisualBasicCodeStyleOptionsStorage + + Private NotInheritable Class Service + Implements ICodeStyleOptionsStorage + + + + Public Sub New() + End Sub + + Public Function GetOptions(globalOptions As IGlobalOptionService) As IdeCodeStyleOptions Implements ICodeStyleOptionsStorage.GetOptions + Return GetVisualBasicCodeStyleOptions(globalOptions) + End Function + End Class + + + Public Function GetVisualBasicCodeStyleOptions(globalOptions As IGlobalOptionService) As VisualBasicIdeCodeStyleOptions + Return New VisualBasicIdeCodeStyleOptions( + Common:=globalOptions.GetCommonCodeStyleOptions(LanguageNames.VisualBasic), + PreferredModifierOrder:=globalOptions.GetOption(VisualBasicCodeStyleOptions.PreferredModifierOrder), + PreferIsNotExpression:=globalOptions.GetOption(VisualBasicCodeStyleOptions.PreferIsNotExpression), + PreferSimplifiedObjectCreation:=globalOptions.GetOption(VisualBasicCodeStyleOptions.PreferSimplifiedObjectCreation), + UnusedValueExpressionStatement:=globalOptions.GetOption(VisualBasicCodeStyleOptions.UnusedValueExpressionStatement), + UnusedValueAssignment:=globalOptions.GetOption(VisualBasicCodeStyleOptions.UnusedValueAssignment)) + End Function + End Module +End Namespace diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb index fca0dc6fa43f6..0c01dad43f02d 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb @@ -139,7 +139,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Return p.Name = PredefinedCodeCleanupProviderNames.NormalizeModifiersOrOperators End Function) - Dim cleanDocument = CodeCleaner.CleanupAsync(document, GetSpanToCleanup(statement), codeCleanups, cancellationToken:=cancellationToken).WaitAndGetResult(cancellationToken) + Dim options = document.GetCodeCleanupOptionsAsync(_globalOptions, cancellationToken).AsTask().WaitAndGetResult(cancellationToken) + Dim cleanDocument = CodeCleaner.CleanupAsync(document, GetSpanToCleanup(statement), Options, codeCleanups, cancellationToken:=cancellationToken).WaitAndGetResult(cancellationToken) Using transaction = New CaretPreservingEditTransaction(VBEditorResources.End_Construct, view, _undoHistoryRegistry, _editorOperationsFactoryService) transaction.MergePolicy = AutomaticCodeChangeMergePolicy.Instance diff --git a/src/EditorFeatures/VisualBasic/Formatting/VisualBasicSyntaxFormattingOptionsStorage.vb b/src/EditorFeatures/VisualBasic/Formatting/VisualBasicSyntaxFormattingOptionsStorage.vb index 75432d9fc27e5..8e67f5b869016 100644 --- a/src/EditorFeatures/VisualBasic/Formatting/VisualBasicSyntaxFormattingOptionsStorage.vb +++ b/src/EditorFeatures/VisualBasic/Formatting/VisualBasicSyntaxFormattingOptionsStorage.vb @@ -31,9 +31,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Public Function GetVisualBasicSyntaxFormattingOptions(globalOptions As IGlobalOptionService) As VisualBasicSyntaxFormattingOptions - Return New VisualBasicSyntaxFormattingOptions( - lineFormatting:=globalOptions.GetLineFormattingOptions(LanguageNames.VisualBasic), - separateImportDirectiveGroups:=globalOptions.GetOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.VisualBasic)) + Return New VisualBasicSyntaxFormattingOptions() With + { + .Common = globalOptions.GetCommonSyntaxFormattingOptions(LanguageNames.VisualBasic) + } End Function End Module End Namespace diff --git a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb index b38d38c123c84..6bbca6ad95202 100644 --- a/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb +++ b/src/EditorFeatures/VisualBasic/NavigationBar/VisualBasicEditorNavigationBarItemService_CodeGeneration.vb @@ -29,8 +29,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.NavigationBar Dim generatedTree = Await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Dim generatedNode = generatedTree.GetAnnotatedNodes(GeneratedSymbolAnnotation).Single().FirstAncestorOrSelf(Of MethodBlockBaseSyntax) - Dim documentOptions = Await document.GetOptionsAsync(cancellationToken).ConfigureAwait(False) - Dim indentSize = documentOptions.GetOption(FormattingOptions.IndentationSize) + Dim formattingOptions = Await document.GetLineFormattingOptionsAsync(_globalOptions, cancellationToken).ConfigureAwait(False) + Dim indentSize = formattingOptions.IndentationSize Dim navigationPoint = NavigationPointHelpers.GetNavigationPoint(generatedTree.GetText(text.Encoding), indentSize, generatedNode) diff --git a/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb b/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb index 20c7e5db4f821..fc9f85d897d6d 100644 --- a/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb +++ b/src/EditorFeatures/VisualBasic/Simplification/VisualBasicSimplifierOptionsStorage.vb @@ -28,13 +28,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification 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)) + Return New VisualBasicSimplifierOptions() With + { + .Common = globalOptions.GetCommonSimplifierOptions(LanguageNames.VisualBasic) + } End Function End Module End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb b/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb index 55f8dbfb3712f..1035780279cb6 100644 --- a/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CaseCorrecting/CaseCorrectionServiceTests.vb @@ -5,6 +5,7 @@ Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis +Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.CodeCleanup.Providers Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions @@ -33,7 +34,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CaseCorrecting Dim document = workspace.CurrentSolution.GetDocument(hostDocument.Id) Dim span = (Await document.GetSyntaxRootAsync()).FullSpan - Dim options = Await document.GetCodeCleanupOptionsAsync(fallbackOptions:=Nothing, CancellationToken.None) + Dim options = CodeCleanupOptions.GetDefault(document.Project.LanguageServices) Dim service = document.GetLanguageService(Of ICodeCleanerService) Dim newDocument = Await service.CleanupAsync( diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb index e60b5230e4d03..c687277d1c677 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/AbstractVisualBasicCompletionProviderTests.vb @@ -29,12 +29,12 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, hasSuggestionItem As Boolean?, displayTextSuffix As String, displayTextPrefix As String, inlineDescription As String, - isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, Optional skipSpeculation As Boolean = False) As Task + isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, options As CompletionOptions, Optional skipSpeculation As Boolean = False) As Task Return MyBase.VerifyWorkerAsync( code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags, skipSpeculation) + isComplexTextEdit, matchingFilters, flags, options, skipSpeculation) End Function Private Protected Overrides Async Function VerifyWorkerAsync( @@ -43,22 +43,22 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, hasSuggestionItem As Boolean?, displayTextSuffix As String, displayTextPrefix As String, inlineDescription As String, - isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, Optional skipSpeculation As Boolean = False) As Task + isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, options As CompletionOptions, Optional skipSpeculation As Boolean = False) As Task ' Script/interactive support removed for now. ' TODO: Re-enable these when interactive is back in the product. - If sourceCodeKind <> Microsoft.CodeAnalysis.SourceCodeKind.Regular Then + If sourceCodeKind <> SourceCodeKind.Regular Then Return End If Await VerifyAtPositionAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags, skipSpeculation) + isComplexTextEdit, matchingFilters, flags, options, skipSpeculation) Await VerifyAtEndOfFileAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags) + isComplexTextEdit, matchingFilters, flags, options) ' Items cannot be partially written if we're checking for their absence, ' or if we're verifying that the list will show up (without specifying an actual item) @@ -66,12 +66,12 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet Await VerifyAtPosition_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, - displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, skipSpeculation:=skipSpeculation) + displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags:=Nothing, options, skipSpeculation:=skipSpeculation) Await VerifyAtEndOfFile_ItemPartiallyWrittenAsync( code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, - displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters) + displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags:=Nothing, options) End If End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb index 8ff02da37852f..f76720939b514 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/ObjectInitializerCompletionProviderTests.vb @@ -18,7 +18,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, hasSuggestionItem As Boolean?, displayTextSuffix As String, displayTextPrefix As String, inlineDescription As String, - isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, Optional skipSpeculation As Boolean = False) As Task + isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, + options As CompletionOptions, Optional skipSpeculation As Boolean = False) As Task ' Script/interactive support removed for now. ' TODO: Re-enable these when interactive is back in the product. If sourceCodeKind <> SourceCodeKind.Regular Then @@ -29,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet code, position, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, usePreviousCharAsTrigger, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, - isComplexTextEdit, matchingFilters, flags, skipSpeculation) + isComplexTextEdit, matchingFilters, flags, options, skipSpeculation) End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb index a3264cc94b7e8..11c3c97434da6 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/OverrideCompletionProviderTests.vb @@ -564,7 +564,7 @@ End Class.Value Dim position As Integer MarkupTestFile.GetPosition(markup.NormalizeLineEndings(), code, position) - Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing) + Await BaseVerifyWorkerAsync(code, position, "[Class]()", "Sub CBase.Class()", SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing) End Function @@ -585,7 +585,7 @@ End Class.Value Await BaseVerifyWorkerAsync( code, position, "[Class]", "Property CBase.Class As Integer", - SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing) + SourceCodeKind.Regular, False, False, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing) End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.vb index 6921e1eab8687..05cd53b9cb175 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SuggestionModeCompletionProviderTests.vb @@ -378,7 +378,11 @@ End Class Dim options As CompletionOptions If useDebuggerOptions Then - options = New CompletionOptions(FilterOutOfScopeLocals:=False, ShowXmlDocCommentCompletion:=False) + options = New CompletionOptions() With + { + .FilterOutOfScopeLocals = False, + .ShowXmlDocCommentCompletion = False + } Else options = CompletionOptions.Default End If diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb index 382f497ae5b2f..0de9b1055857f 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb @@ -7874,10 +7874,10 @@ End Namespace Dim position = workspace.DocumentWithCursor.CursorPosition.Value Await CheckResultsAsync(document, position, "InstanceMethod", expectedDescriptionOrNull:=Nothing, usePreviousCharAsTrigger:=False, checkForAbsence:=False, glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing, displayTextSuffix:=Nothing, displayTextPrefix:=Nothing, inlineDescription:=Nothing, - isComplexTextEdit:=Nothing, matchingFilters:=Nothing, flags:=Nothing) + isComplexTextEdit:=Nothing, matchingFilters:=Nothing, flags:=Nothing, options:=Nothing) Await CheckResultsAsync(document, position, "SharedMethod", expectedDescriptionOrNull:=Nothing, usePreviousCharAsTrigger:=False, checkForAbsence:=False, glyph:=Nothing, matchPriority:=Nothing, hasSuggestionModeItem:=Nothing, displayTextSuffix:=Nothing, displayTextPrefix:=Nothing, inlineDescription:=Nothing, - isComplexTextEdit:=Nothing, matchingFilters:=Nothing, flags:=Nothing) + isComplexTextEdit:=Nothing, matchingFilters:=Nothing, flags:=Nothing, options:=Nothing) End Using End Function diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb index 36456f3d3fb50..c235437c9a418 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/XmlDocCommentCompletionProviderTests.vb @@ -22,9 +22,11 @@ Namespace Tests sourceCodeKind As SourceCodeKind, usePreviousCharAsTrigger As Boolean, checkForAbsence As Boolean, glyph As Integer?, matchPriority As Integer?, hasSuggestionItem As Boolean?, displayTextSuffix As String, displayTextPrefix As String, inlineDescription As String, - isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, Optional skipSpeculation As Boolean = False) As Task - Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, skipSpeculation) - Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags) + isComplexTextEdit As Boolean?, matchingFilters As List(Of CompletionFilter), flags As CompletionItemFlags?, + options As CompletionOptions, Optional skipSpeculation As Boolean = False) As Task + + Await VerifyAtPositionAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options, skipSpeculation) + Await VerifyAtEndOfFileAsync(code, position, usePreviousCharAsTrigger, expectedItemOrNull, expectedDescriptionOrNull, sourceCodeKind, checkForAbsence, glyph, matchPriority, hasSuggestionItem, displayTextSuffix, displayTextPrefix, inlineDescription, isComplexTextEdit, matchingFilters, flags, options) End Function Private Async Function VerifyItemsExistAsync(markup As String, ParamArray items() As String) As Task diff --git a/src/EditorFeatures/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb b/src/EditorFeatures/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb index 6cbec31d92ab9..721209aebfd9a 100644 --- a/src/EditorFeatures/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb +++ b/src/EditorFeatures/VisualBasicTest/ExtractMethod/ExtractMethodTests.vb @@ -12,6 +12,7 @@ Imports Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.ExtractMethod +Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.Text.Shared.Extensions Imports Microsoft.CodeAnalysis.VisualBasic.ExtractMethod @@ -100,7 +101,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ExtractMethod Dim document = workspace.CurrentSolution.GetDocument(testDocument.Id) Assert.NotNull(document) - Dim extractOptions = New ExtractMethodOptions(DontPutOutOrRefOnStruct:=dontPutOutOrRefOnStruct) + Dim extractOptions = New ExtractMethodOptions() With {.DontPutOutOrRefOnStruct = dontPutOutOrRefOnStruct} Dim cleanupOptions = CodeCleanupOptions.GetDefault(document.Project.LanguageServices) Dim sdocument = Await SemanticDocument.CreateAsync(document, CancellationToken.None) @@ -114,11 +115,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ExtractMethod Assert.True(selectedCode.ContainsValidContext) ' extract method - Dim extractGenerationOptions = New ExtractMethodGenerationOptions( - extractOptions, - CodeGenerationOptions.GetDefault(document.Project.LanguageServices), - AddImportPlacementOptions.Default, - Function() NamingStylePreferences.Default) + Dim extractGenerationOptions = New ExtractMethodGenerationOptions(CodeGenerationOptions.GetDefault(document.Project.LanguageServices)) With + { + .ExtractOptions = extractOptions + } Dim extractor = New VisualBasicMethodExtractor(CType(selectedCode, VisualBasicSelectionResult), extractGenerationOptions) Dim result = Await extractor.ExtractMethodAsync(CancellationToken.None) diff --git a/src/EditorFeatures/VisualBasicTest/Formatting/CodeCleanUpTests.vb b/src/EditorFeatures/VisualBasicTest/Formatting/CodeCleanUpTests.vb index 15d349032adad..1e57fc9d05efa 100644 --- a/src/EditorFeatures/VisualBasicTest/Formatting/CodeCleanUpTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Formatting/CodeCleanUpTests.vb @@ -6,6 +6,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.AddImport Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeCleanup +Imports Microsoft.CodeAnalysis.CodeGeneration Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Diagnostics.VisualBasic Imports Microsoft.CodeAnalysis.Editing @@ -13,8 +14,10 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.MakeFieldReadonly +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Shared.Utilities Imports Microsoft.CodeAnalysis.SolutionCrawler +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.Analyzers Imports Microsoft.CodeAnalysis.VisualBasic.Formatting Imports Microsoft.CodeAnalysis.VisualBasic.Simplification @@ -334,16 +337,17 @@ End Class Optional separateImportsGroups As Boolean = False) As Task Using workspace = TestWorkspace.CreateVisualBasic(code, composition:=EditorTestCompositions.EditorFeaturesWpf) - Dim solution = workspace.CurrentSolution. - WithOptions(workspace.Options. - WithChangedOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.VisualBasic, systemImportsFirst). - WithChangedOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.VisualBasic, separateImportsGroups)). - WithAnalyzerReferences( - { - New AnalyzerFileReference(GetType(VisualBasicCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), - New AnalyzerFileReference(GetType(MakeFieldReadonlyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), - New AnalyzerFileReference(GetType(VisualBasicPreferFrameworkTypeDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile) - }) + ' must set global options since incremental analyzer infra reads from global options + Dim globalOptions = workspace.GlobalOptions + globalOptions.SetGlobalOption(New OptionKey(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.VisualBasic), separateImportsGroups) + globalOptions.SetGlobalOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.VisualBasic), systemImportsFirst) + + Dim solution = workspace.CurrentSolution.WithAnalyzerReferences( + { + New AnalyzerFileReference(GetType(VisualBasicCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), + New AnalyzerFileReference(GetType(MakeFieldReadonlyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile), + New AnalyzerFileReference(GetType(VisualBasicPreferFrameworkTypeDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile) + }) workspace.TryApplyChanges(solution) @@ -358,19 +362,11 @@ End Class Dim enabledDiagnostics = codeCleanupService.GetAllDiagnostics() - Dim options = New CodeActionOptions( - CleanupOptions:=New CodeCleanupOptions( - FormattingOptions:=New VisualBasicSyntaxFormattingOptions( - LineFormattingOptions.Default, - separateImportDirectiveGroups:=separateImportsGroups), - SimplifierOptions:=VisualBasicSimplifierOptions.Default, - AddImportOptions:=AddImportPlacementOptions.Default)) - Dim newDoc = Await codeCleanupService.CleanupAsync( document, enabledDiagnostics, New ProgressTracker, - options.CreateProvider(), + globalOptions.CreateProvider(), CancellationToken.None) Dim actual = Await newDoc.GetTextAsync() diff --git a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicNewDocumentFormattingServiceTests.vb b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicNewDocumentFormattingServiceTests.vb index fc5c9bfa31a53..091928d524e2e 100644 --- a/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicNewDocumentFormattingServiceTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Formatting/VisualBasicNewDocumentFormattingServiceTests.vb @@ -3,6 +3,7 @@ ' See the LICENSE file in the project root for more information. Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Test.Utilities.Formatting @@ -32,7 +33,9 @@ Imports System Namespace Goo End Namespace", - options:={(CodeStyleOptions2.FileHeaderTemplate, "This is a banner.")}) + options:=New OptionsCollection(LanguageNames.VisualBasic) From { + {CodeStyleOptions2.FileHeaderTemplate, "This is a banner."} + }) End Function diff --git a/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb b/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb index c32dc36ebddfd..8feef3f964476 100644 --- a/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb +++ b/src/EditorFeatures/VisualBasicTest/GenerateConstructorFromMembers/GenerateConstructorFromMembersTests.vb @@ -6,6 +6,7 @@ Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings Imports Microsoft.CodeAnalysis.GenerateConstructorFromMembers +Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.PickMembers Imports Microsoft.CodeAnalysis.VisualBasic.GenerateConstructorFromMembers @@ -367,10 +368,10 @@ End Class", chosenSymbols:={"i"}) Public Async Function TestWithDialog1WithNullCheck() As Task Dim options = New OptionsCollection(LanguageNames.VisualBasic) - options.Add(GenerateConstructorFromMembersOptions.AddNullChecks, True) + options.Add(LegacyGlobalOptionsWorkspaceService.AddNullChecksToConstructorsGeneratedFromMembers, True) Dim parameters = New TestParameters() - parameters = parameters.WithOptions(options) + parameters = parameters.WithGlobalOptions(options) Await TestWithPickMembersDialogAsync( "Class Program diff --git a/src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb b/src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb index 88bf57d3971e1..3e230b48629dc 100644 --- a/src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb +++ b/src/EditorFeatures/VisualBasicTest/InitializeParameter/InitializeMemberFromParameterTests.vb @@ -902,19 +902,19 @@ end class", index:=3) Private ReadOnly Property OmitIfDefault_Warning As TestParameters Get - Return New TestParameters(options:=[Option](CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption2.Warning)) + Return New TestParameters(options:=[Option](CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.OmitIfDefault, NotificationOption2.Warning)) End Get End Property Private ReadOnly Property Never_Warning As TestParameters Get - Return New TestParameters(options:=[Option](CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Never, NotificationOption2.Warning)) + Return New TestParameters(options:=[Option](CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Never, NotificationOption2.Warning)) End Get End Property Private ReadOnly Property Always_Warning As TestParameters Get - Return New TestParameters(options:=[Option](CodeStyleOptions2.RequireAccessibilityModifiers, AccessibilityModifiersRequired.Always, NotificationOption2.Warning)) + Return New TestParameters(options:=[Option](CodeStyleOptions2.AccessibilityModifiersRequired, AccessibilityModifiersRequired.Always, NotificationOption2.Warning)) End Get End Property End Class diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.cs index e78454a629baf..4a49b332b1a40 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.cs @@ -36,7 +36,7 @@ public override ImmutableArray FixableDiagnosticIds get { return ImmutableArray.Create(CS0117); } } - protected override Task> GetCodeActionsAsync(Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + protected override Task> GetCodeActionsAsync(Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetLanguageService(); return service.GenerateEnumMemberAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs index f22c1a9d68609..2ed1889f504a0 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateConversionCodeFixProvider.cs @@ -59,7 +59,7 @@ node is SimpleNameSyntax || } protected override Task> GetCodeActionsAsync( - Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); return service.GenerateConversionAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs index b0c7106671855..6bf7cabab630f 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateMethod/GenerateMethodCodeFixProvider.cs @@ -91,7 +91,7 @@ node is SimpleNameSyntax || } protected override Task> GetCodeActionsAsync( - Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); return service.GenerateMethodAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs b/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs index 9121c0a7537cb..6b1ebb4a37cf5 100644 --- a/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.cs @@ -62,7 +62,7 @@ protected override bool IsCandidate(SyntaxNode node, SyntaxToken token, Diagnost => ((ExpressionSyntax)node).GetRightmostName(); protected override Task> GetCodeActionsAsync( - Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService(); return service.GenerateTypeAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs index 7d79b413f7714..38ed0969d46e8 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/EnableNullable/EnableNullableCodeRefactoringProvider.cs @@ -59,10 +59,10 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte } context.RegisterRefactoring( - new CustomCodeAction((purpose, cancellationToken) => EnableNullableReferenceTypesAsync(document.Project, purpose, cancellationToken))); + new CustomCodeAction((purpose, cancellationToken) => EnableNullableReferenceTypesAsync(document.Project, purpose, context.Options, cancellationToken))); } - private static async Task EnableNullableReferenceTypesAsync(Project project, CodeActionPurpose purpose, CancellationToken cancellationToken) + private static async Task EnableNullableReferenceTypesAsync(Project project, CodeActionPurpose purpose, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var solution = project.Solution; foreach (var document in project.Documents) @@ -70,7 +70,7 @@ private static async Task EnableNullableReferenceTypesAsync(Project pr if (await document.IsGeneratedCodeAsync(cancellationToken).ConfigureAwait(false)) continue; - var updatedDocumentRoot = await EnableNullableReferenceTypesAsync(document, cancellationToken).ConfigureAwait(false); + var updatedDocumentRoot = await EnableNullableReferenceTypesAsync(document, fallbackOptions, cancellationToken).ConfigureAwait(false); solution = solution.WithDocumentSyntaxRoot(document.Id, updatedDocumentRoot); } @@ -83,7 +83,7 @@ private static async Task EnableNullableReferenceTypesAsync(Project pr return solution; } - private static async Task EnableNullableReferenceTypesAsync(Document document, CancellationToken cancellationToken) + private static async Task EnableNullableReferenceTypesAsync(Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var firstToken = GetFirstTokenOfInterest(root); @@ -101,7 +101,7 @@ private static async Task EnableNullableReferenceTypesAsync(Document // * Add '#nullable disable' if the document didn't specify other semantics // * Remove leading '#nullable restore' (was '#nullable enable' prior to rewrite in the previous step) // * Otherwise, leave existing '#nullable' directive since it will control the initial semantics for the document - return await DisableNullableReferenceTypesInExistingDocumentIfNecessaryAsync(document, root, firstToken, cancellationToken).ConfigureAwait(false); + return await DisableNullableReferenceTypesInExistingDocumentIfNecessaryAsync(document, root, firstToken, fallbackOptions, cancellationToken).ConfigureAwait(false); } private static (SyntaxNode root, SyntaxToken firstToken) RewriteExistingDirectives(SyntaxNode root, SyntaxToken firstToken) @@ -148,10 +148,10 @@ private static (SyntaxNode root, SyntaxToken firstToken) RewriteExistingDirectiv return (updatedRoot, GetFirstTokenOfInterest(updatedRoot)); } - private static async Task DisableNullableReferenceTypesInExistingDocumentIfNecessaryAsync(Document document, SyntaxNode root, SyntaxToken firstToken, CancellationToken cancellationToken) + private static async Task DisableNullableReferenceTypesInExistingDocumentIfNecessaryAsync(Document document, SyntaxNode root, SyntaxToken firstToken, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var newLine = SyntaxFactory.EndOfLine(options.GetOption(FormattingOptions2.NewLine)); + var options = await document.GetCSharpCodeFixOptionsProviderAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var newLine = SyntaxFactory.EndOfLine(options.NewLine); // Add a new '#nullable disable' to the top of each file if (!HasLeadingNullableDirective(root, out var leadingDirective)) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index b4275f66224d0..70f1939a24d0f 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; @@ -87,7 +88,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext completionC var baseNames = GetBaseNames(context.SemanticModel, nameInfo); if (baseNames != default) { - await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, result, cancellationToken).ConfigureAwait(false); + var namingStyleOptions = await document.GetNamingStylePreferencesAsync(completionContext.CompletionOptions.NamingStyleFallbackOptions, cancellationToken).ConfigureAwait(false); + GetRecommendedNames(baseNames, nameInfo, context, result, namingStyleOptions, cancellationToken); } var recommendedNames = result.ToImmutable(); @@ -252,15 +254,16 @@ private static Glyph GetGlyph(SymbolKind kind, Accessibility? declaredAccessibil return (type, wasPlural); } - private static async Task GetRecommendedNamesAsync( + private static void GetRecommendedNames( ImmutableArray> baseNames, NameDeclarationInfo declarationInfo, CSharpSyntaxContext context, - Document document, ArrayBuilder<(string name, SymbolKind kind)> result, + NamingStylePreferences namingStyleOptions, CancellationToken cancellationToken) { - var rules = await document.GetNamingRulesAsync(FallbackNamingRules.CompletionFallbackRules, cancellationToken).ConfigureAwait(false); + var rules = namingStyleOptions.CreateRules().NamingRules.AddRange(FallbackNamingRules.CompletionFallbackRules); + var supplementaryRules = FallbackNamingRules.CompletionSupplementaryRules; var semanticFactsService = context.GetRequiredLanguageService(); diff --git a/src/Features/CSharp/Portable/ConvertAutoPropertyToFullProperty/CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertAutoPropertyToFullProperty/CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs index c495d3b67ff18..ba5d2eaa22426 100644 --- a/src/Features/CSharp/Portable/ConvertAutoPropertyToFullProperty/CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertAutoPropertyToFullProperty/CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs @@ -13,14 +13,13 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.ConvertAutoPropertyToFullProperty; using Microsoft.CodeAnalysis.CSharp.CodeGeneration; -using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; -using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; namespace Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty { @@ -33,12 +32,13 @@ public CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider() { } - internal override async Task GetFieldNameAsync(Document document, IPropertySymbol property, CancellationToken cancellationToken) + internal override async Task GetFieldNameAsync(Document document, IPropertySymbol property, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { var rule = await document.GetApplicableNamingRuleAsync( - new SymbolKindOrTypeKind(SymbolKind.Field), + new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Field), property.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None, Accessibility.Private, + fallbackOptions, cancellationToken).ConfigureAwait(false); var fieldName = rule.NamingStyle.MakeCompliant(property.Name).First(); diff --git a/src/Features/CSharp/Portable/ConvertForToForEach/CSharpConvertForToForEachCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertForToForEach/CSharpConvertForToForEachCodeRefactoringProvider.cs index d3c05daeacaaa..f92d6b4360311 100644 --- a/src/Features/CSharp/Portable/ConvertForToForEach/CSharpConvertForToForEachCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertForToForEach/CSharpConvertForToForEachCodeRefactoringProvider.cs @@ -124,7 +124,7 @@ private static bool TryGetStepValue( protected override SyntaxNode ConvertForNode( ForStatementSyntax forStatement, TypeSyntax typeNode, SyntaxToken foreachIdentifier, ExpressionSyntax collectionExpression, - ITypeSymbol iterationVariableType, OptionSet optionSet) + ITypeSymbol iterationVariableType) { typeNode ??= iterationVariableType.GenerateTypeSyntax(); diff --git a/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeRefactoringProvider.cs index 3c178f167981c..f9307a45f90e9 100644 --- a/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeRefactoringProvider.cs @@ -45,18 +45,17 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (!IsValidPosition(namespaceDecl, position)) return; - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.Options, cancellationToken).ConfigureAwait(false); + var info = - CanOfferUseBlockScoped(optionSet, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.BlockScoped) : - CanOfferUseFileScoped(optionSet, root, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.FileScoped) : + CanOfferUseBlockScoped(options.NamespaceDeclarations, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.BlockScoped) : + CanOfferUseFileScoped(options.NamespaceDeclarations, root, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.FileScoped) : ((string title, string equivalenceKey)?)null; if (info == null) return; - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(context.Options, cancellationToken).ConfigureAwait(false); - context.RegisterRefactoring(CodeAction.Create( - info.Value.title, c => ConvertAsync(document, namespaceDecl, formattingOptions, c), info.Value.equivalenceKey)); + info.Value.title, c => ConvertAsync(document, namespaceDecl, options.GetFormattingOptions(), c), info.Value.equivalenceKey)); } private static bool IsValidPosition(BaseNamespaceDeclarationSyntax baseDeclaration, int position) diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs index a00688a7a6027..85f94a9f779d6 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertProgramTransform_ProgramMain.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -23,7 +24,7 @@ namespace Microsoft.CodeAnalysis.CSharp.ConvertProgram internal static partial class ConvertProgramTransform { - public static async Task ConvertToProgramMainAsync(Document document, CancellationToken cancellationToken) + public static async Task ConvertToProgramMainAsync(Document document, AccessibilityModifiersRequired accessibilityModifiersRequired, CancellationToken cancellationToken) { // While the analyze and refactoring check ensure we're in a well formed state for their needs, the 'new // template' code just calls directly into this if the user prefers Program.Main. So check and make sure @@ -39,7 +40,7 @@ public static async Task ConvertToProgramMainAsync(Document document, if (programType.GetMembers(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName).FirstOrDefault() is IMethodSymbol mainMethod) { var classDeclaration = await GenerateProgramClassAsync( - document, programType, mainMethod, cancellationToken).ConfigureAwait(false); + document, programType, mainMethod, accessibilityModifiersRequired, cancellationToken).ConfigureAwait(false); var newRoot = root.RemoveNodes(root.Members.OfType().Skip(1), SyntaxGenerator.DefaultRemoveOptions); Contract.ThrowIfNull(newRoot); @@ -59,13 +60,11 @@ private static async Task GenerateProgramClassAsync( Document document, INamedTypeSymbol programType, IMethodSymbol mainMethod, + AccessibilityModifiersRequired accessibilityModifiersRequired, CancellationToken cancellationToken) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - // Respect user settings on if they want explicit or implicit accessibility modifiers. - var option = options.GetOption(CodeStyleOptions2.RequireAccessibilityModifiers); - var accessibilityModifiersRequired = option.Value is AccessibilityModifiersRequired.ForNonInterfaceMembers or AccessibilityModifiersRequired.Always; + var useDeclaredAccessibity = accessibilityModifiersRequired is AccessibilityModifiersRequired.ForNonInterfaceMembers or AccessibilityModifiersRequired.Always; var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var generator = document.GetRequiredLanguageService(); @@ -78,7 +77,7 @@ private static async Task GenerateProgramClassAsync( GenerateProgramMainStatements(root, out var leadingTrivia)); method = method.WithReturnType(method.ReturnType.WithAdditionalAnnotations(Simplifier.AddImportsAnnotation)); method = (MethodDeclarationSyntax)generator.WithAccessibility( - method, accessibilityModifiersRequired ? mainMethod.DeclaredAccessibility : Accessibility.NotApplicable); + method, useDeclaredAccessibity ? mainMethod.DeclaredAccessibility : Accessibility.NotApplicable); // Workaround for simplification not being ready when we generate a new file. Substitute System.String[] // with string[]. @@ -87,7 +86,7 @@ private static async Task GenerateProgramClassAsync( return FixupComments(generator.ClassDeclaration( WellKnownMemberNames.TopLevelStatementsEntryPointTypeName, - accessibility: accessibilityModifiersRequired ? programType.DeclaredAccessibility : Accessibility.NotApplicable, + accessibility: useDeclaredAccessibity ? programType.DeclaredAccessibility : Accessibility.NotApplicable, modifiers: hasExistingPart ? DeclarationModifiers.Partial : DeclarationModifiers.None, members: new[] { method }).WithLeadingTrivia(leadingTrivia)); } diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs index 42c8bb5b5abc4..7ded9a3a0b0ae 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeFixProvider.cs @@ -36,9 +36,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) var document = context.Document; var cancellationToken = context.CancellationToken; - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var option = options.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); - var priority = option.Notification.Severity == ReportDiagnostic.Hidden + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.Options, cancellationToken).ConfigureAwait(false); + var priority = options.PreferTopLevelStatements.Notification.Severity == ReportDiagnostic.Hidden ? CodeActionPriority.Low : CodeActionPriority.Medium; @@ -48,7 +47,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) protected override async Task FixAllAsync( Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var fixedDocument = await ConvertToProgramMainAsync(document, cancellationToken).ConfigureAwait(false); + var options = await document.GetCodeFixOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var fixedDocument = await ConvertToProgramMainAsync(document, options.AccessibilityModifiersRequired, cancellationToken).ConfigureAwait(false); var fixedRoot = await fixedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); editor.ReplaceNode(editor.OriginalRoot, fixedRoot); diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeRefactoringProvider.cs index b9abd701ffcf9..7acbdd3dcbb1c 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertToProgramMainCodeRefactoringProvider.cs @@ -49,17 +49,16 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (!acceptableLocation.SourceSpan.IntersectsWith(position)) return; - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.Options, cancellationToken).ConfigureAwait(false); var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); - if (!CanOfferUseProgramMain(option, root, compilation, forAnalyzer: false)) + if (!CanOfferUseProgramMain(options.PreferTopLevelStatements, root, compilation, forAnalyzer: false)) return; context.RegisterRefactoring(CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpAnalyzersResources.Convert_to_Program_Main_style_program, - c => ConvertToProgramMainAsync(document, c), + c => ConvertToProgramMainAsync(document, options.AccessibilityModifiersRequired.Value, c), nameof(CSharpAnalyzersResources.Convert_to_Program_Main_style_program))); } } diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeFixProvider.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeFixProvider.cs index ae2f17192632e..6735aae2ba74d 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeFixProvider.cs @@ -38,9 +38,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) var document = context.Document; var cancellationToken = context.CancellationToken; - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var option = options.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); - var priority = option.Notification.Severity == ReportDiagnostic.Hidden + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.Options, cancellationToken).ConfigureAwait(false); + var priority = options.PreferTopLevelStatements.Notification.Severity == ReportDiagnostic.Hidden ? CodeActionPriority.Low : CodeActionPriority.Medium; diff --git a/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeRefactoringProvider.cs index 162d37ca62a9b..60f998d137dae 100644 --- a/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertProgram/ConvertToTopLevelStatementsCodeRefactoringProvider.cs @@ -45,9 +45,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (methodDeclaration is null) return; - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var option = options.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); - if (!CanOfferUseTopLevelStatements(option, forAnalyzer: false)) + var options = await document.GetCSharpCodeFixOptionsProviderAsync(context.Options, cancellationToken).ConfigureAwait(false); + if (!CanOfferUseTopLevelStatements(options.PreferTopLevelStatements, forAnalyzer: false)) return; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Features/CSharp/Portable/ConvertToRawString/ConvertRegularStringToRawStringCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ConvertToRawString/ConvertRegularStringToRawStringCodeRefactoringProvider.cs index b14b4a669e311..c409bc37868ef 100644 --- a/src/Features/CSharp/Portable/ConvertToRawString/ConvertRegularStringToRawStringCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ConvertToRawString/ConvertRegularStringToRawStringCodeRefactoringProvider.cs @@ -391,7 +391,7 @@ private static SyntaxToken ConvertToMultiLineRawIndentedString( var quoteDelimeterCount = Math.Max(3, longestQuoteSequence + 1); // Auto-formatting options are not relevant since they only control behavior on typing. - var indentationOptions = new IndentationOptions(formattingOptions, AutoFormattingOptions.Default); + var indentationOptions = new IndentationOptions(formattingOptions); var indentation = token.GetPreferredIndentation(document, indentationOptions, cancellationToken); using var _ = PooledStringBuilder.GetInstance(out var builder); diff --git a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs index 86314de1e9435..95d61768bb852 100644 --- a/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs @@ -52,8 +52,7 @@ protected override ImmutableArray AnalyzeCodeBlock(CodeBlockAnalysis var semanticModel = context.SemanticModel; var cancellationToken = context.CancellationToken; - var syntaxTree = semanticModel.SyntaxTree; - var options = context.Options.GetCSharpSimplifierOptions(syntaxTree); + var options = context.GetCSharpAnalyzerOptions().GetSimplifierOptions(); using var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, options, ignoredSpans: null, cancellationToken); simplifier.Visit(context.CodeBlock); return simplifier.Diagnostics; @@ -64,11 +63,10 @@ protected override ImmutableArray AnalyzeSemanticModel(SemanticModel var semanticModel = context.SemanticModel; var cancellationToken = context.CancellationToken; - var syntaxTree = semanticModel.SyntaxTree; - var simplifierOptions = context.Options.GetCSharpSimplifierOptions(syntaxTree); - var root = syntaxTree.GetRoot(cancellationToken); + var options = context.GetCSharpAnalyzerOptions().GetSimplifierOptions(); + var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); - var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, simplifierOptions, ignoredSpans: codeBlockIntervalTree, cancellationToken); + var simplifier = new TypeSyntaxSimplifierWalker(this, semanticModel, options, ignoredSpans: codeBlockIntervalTree, cancellationToken); simplifier.Visit(root); return simplifier.Diagnostics; } diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs index ba0d4ab4ae0a5..764ae1e5b3de7 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.ExpressionCodeGenerator.cs @@ -31,9 +31,8 @@ public ExpressionCodeGenerator( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction) - : base(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction) + : base(insertionPoint, selectionResult, analyzerResult, options, localFunction) { } diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs index 00be04464a1a0..d2dd6cdbd06de 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.MultipleStatementsCodeGenerator.cs @@ -32,9 +32,8 @@ public MultipleStatementsCodeGenerator( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction) - : base(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction) + : base(insertionPoint, selectionResult, analyzerResult, options, localFunction) { } diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs index 46dc4d01988b1..2f177a8e9f314 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.SingleStatementCodeGenerator.cs @@ -28,9 +28,8 @@ public SingleStatementCodeGenerator( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction) - : base(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction) + : base(insertionPoint, selectionResult, analyzerResult, options, localFunction) { } diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs index 7b70d87102002..3eb7e69ae6d3a 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.CSharpCodeGenerator.cs @@ -28,7 +28,6 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; -using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; namespace Microsoft.CodeAnalysis.CSharp.ExtractMethod { @@ -46,11 +45,10 @@ public static Task GenerateAsync( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction, CancellationToken cancellationToken) { - var codeGenerator = Create(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction); + var codeGenerator = Create(insertionPoint, selectionResult, analyzerResult, options, localFunction); return codeGenerator.GenerateAsync(cancellationToken); } @@ -59,22 +57,21 @@ private static CSharpCodeGenerator Create( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction) { if (ExpressionCodeGenerator.IsExtractMethodOnExpression(selectionResult)) { - return new ExpressionCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction); + return new ExpressionCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, localFunction); } if (SingleStatementCodeGenerator.IsExtractMethodOnSingleStatement(selectionResult)) { - return new SingleStatementCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction); + return new SingleStatementCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, localFunction); } if (MultipleStatementsCodeGenerator.IsExtractMethodOnMultipleStatements(selectionResult)) { - return new MultipleStatementsCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction); + return new MultipleStatementsCodeGenerator(insertionPoint, selectionResult, analyzerResult, options, localFunction); } throw ExceptionUtilities.UnexpectedValue(selectionResult); @@ -85,9 +82,8 @@ protected CSharpCodeGenerator( SelectionResult selectionResult, AnalyzerResult analyzerResult, CSharpCodeGenerationOptions options, - NamingStylePreferencesProvider namingPreferences, bool localFunction) - : base(insertionPoint, selectionResult, analyzerResult, options, namingPreferences, localFunction) + : base(insertionPoint, selectionResult, analyzerResult, options, localFunction) { Contract.ThrowIfFalse(SemanticDocument == selectionResult.SemanticDocument); @@ -852,11 +848,10 @@ protected string GenerateMethodNameFromUserPreference() } // For local functions, pascal case and camel case should be the most common and therefore we only consider those cases. - var namingPreferences = NamingPreferences(SemanticDocument.Document.Project.LanguageServices); - var localFunctionPreferences = namingPreferences.SymbolSpecifications.Where(symbol => symbol.AppliesTo(new SymbolKindOrTypeKind(MethodKind.LocalFunction), CreateMethodModifiers(), null)); + var localFunctionPreferences = Options.NamingStyle.SymbolSpecifications.Where(symbol => symbol.AppliesTo(new SymbolSpecification.SymbolKindOrTypeKind(MethodKind.LocalFunction), CreateMethodModifiers(), null)); - var namingRules = namingPreferences.Rules.NamingRules; - var localFunctionKind = new SymbolKindOrTypeKind(MethodKind.LocalFunction); + var namingRules = Options.NamingStyle.Rules.NamingRules; + var localFunctionKind = new SymbolSpecification.SymbolKindOrTypeKind(MethodKind.LocalFunction); if (LocalFunction) { if (namingRules.Any(rule => rule.NamingStyle.CapitalizationScheme.Equals(Capitalization.CamelCase) && rule.SymbolSpecification.AppliesTo(localFunctionKind, CreateMethodModifiers(), null))) diff --git a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs index 8e5e92b8072c0..10629b4ebe93c 100644 --- a/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs +++ b/src/Features/CSharp/Portable/ExtractMethod/CSharpMethodExtractor.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -102,8 +103,8 @@ protected override async Task ExpandAsync(SelectionResult sele return await selection.SemanticDocument.WithSyntaxRootAsync(selection.SemanticDocument.Root.ReplaceNode(lastExpression, newExpression), cancellationToken).ConfigureAwait(false); } - protected override Task GenerateCodeAsync(InsertionPoint insertionPoint, SelectionResult selectionResult, AnalyzerResult analyzeResult, CodeGenerationOptions options, NamingStylePreferencesProvider namingPreferences, CancellationToken cancellationToken) - => CSharpCodeGenerator.GenerateAsync(insertionPoint, selectionResult, analyzeResult, (CSharpCodeGenerationOptions)options, namingPreferences, LocalFunction, cancellationToken); + protected override Task GenerateCodeAsync(InsertionPoint insertionPoint, SelectionResult selectionResult, AnalyzerResult analyzeResult, CodeGenerationOptions options, CancellationToken cancellationToken) + => CSharpCodeGenerator.GenerateAsync(insertionPoint, selectionResult, analyzeResult, (CSharpCodeGenerationOptions)options, LocalFunction, cancellationToken); protected override ImmutableArray GetCustomFormattingRules(Document document) => ImmutableArray.Create(new FormattingRule()); @@ -162,13 +163,13 @@ protected override async Task CheckTypeAsync( if (!leadingTrivia.Any(t => t.IsKind(SyntaxKind.EndOfLineTrivia)) && !methodDefinition.FindTokenOnLeftOfPosition(methodDefinition.SpanStart).IsKind(SyntaxKind.OpenBraceToken)) { var originalMethodDefinition = methodDefinition; - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - methodDefinition = methodDefinition.WithPrependedLeadingTrivia(SpecializedCollections.SingletonEnumerable(SyntaxFactory.EndOfLine(options.GetOption(FormattingOptions2.NewLine)))); + var newLine = Options.LineFormattingOptions.NewLine; + methodDefinition = methodDefinition.WithPrependedLeadingTrivia(SpecializedCollections.SingletonEnumerable(SyntaxFactory.EndOfLine(newLine))); if (!originalMethodDefinition.FindTokenOnLeftOfPosition(originalMethodDefinition.SpanStart).TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia)) { // Add a second new line since there were no line endings in the original form - methodDefinition = methodDefinition.WithPrependedLeadingTrivia(SpecializedCollections.SingletonEnumerable(SyntaxFactory.EndOfLine(options.GetOption(FormattingOptions2.NewLine)))); + methodDefinition = methodDefinition.WithPrependedLeadingTrivia(SpecializedCollections.SingletonEnumerable(SyntaxFactory.EndOfLine(newLine))); } // Generating the new document and associated variables. diff --git a/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs index 2c6ac1de5ab38..542c08b79d270 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpAccessibilityModifiersNewDocumentFormattingProvider.cs @@ -29,9 +29,8 @@ public CSharpAccessibilityModifiersNewDocumentFormattingProvider() 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); - if (accessibilityPreferences.Value == AccessibilityModifiersRequired.Never) + var accessibilityPreferences = options.FormattingOptions.AccessibilityModifiersRequired; + if (accessibilityPreferences == AccessibilityModifiersRequired.Never) { return document; } @@ -46,7 +45,7 @@ public async Task FormatNewDocumentAsync(Document document, Document? foreach (var declaration in typeDeclarations) { - if (!service.ShouldUpdateAccessibilityModifier(CSharpAccessibilityFacts.Instance, declaration, accessibilityPreferences.Value, out _)) + if (!service.ShouldUpdateAccessibilityModifier(CSharpAccessibilityFacts.Instance, declaration, accessibilityPreferences, out _)) continue; // Since we format each document as they are added to a project we can't assume we know about all diff --git a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs index 428db28a1c04a..bd21844b93a22 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs @@ -9,6 +9,8 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.ConvertNamespace; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; @@ -30,17 +32,18 @@ public CSharpNamespaceDeclarationNewDocumentFormattingProvider() 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); - var namespaces = GetNamespacesToReplace(document, root, optionSet).ToList(); + var formattingOptions = (CSharpSyntaxFormattingOptions)options.FormattingOptions; + + var namespaces = GetNamespacesToReplace(document, root, formattingOptions.NamespaceDeclarations).ToList(); if (namespaces.Count != 1) return document; return await ConvertNamespaceTransform.ConvertAsync(document, namespaces[0], options.FormattingOptions, cancellationToken).ConfigureAwait(false); } - private static IEnumerable GetNamespacesToReplace(Document document, CompilationUnitSyntax root, DocumentOptionSet optionSet) + private static IEnumerable GetNamespacesToReplace(Document document, CompilationUnitSyntax root, CodeStyleOption2 option) { var syntaxFacts = document.GetRequiredLanguageService(); var declarations = root.DescendantNodes().OfType(); @@ -48,8 +51,8 @@ private static IEnumerable GetNamespacesToReplac foreach (var declaration in declarations) { // Passing in forAnalyzer: true means we'll only get a result if the declaration doesn't match the preferences - if (ConvertNamespaceAnalysis.CanOfferUseBlockScoped(optionSet, declaration, forAnalyzer: true) || - ConvertNamespaceAnalysis.CanOfferUseFileScoped(optionSet, root, declaration, forAnalyzer: true)) + if (ConvertNamespaceAnalysis.CanOfferUseBlockScoped(option, declaration, forAnalyzer: true) || + ConvertNamespaceAnalysis.CanOfferUseFileScoped(option, root, declaration, forAnalyzer: true)) { yield return declaration; } diff --git a/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs index 4bfbf176acb6c..ca50ae5aed207 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpOrganizeUsingsNewDocumentFormattingProvider.cs @@ -29,14 +29,10 @@ public CSharpOrganizeUsingsNewDocumentFormattingProvider() public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { var organizeImportsService = document.GetRequiredLanguageService(); + var organizedDocument = await organizeImportsService.OrganizeImportsAsync(document, options.GetOrganizeImportsOptions(), cancellationToken).ConfigureAwait(false); - 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); + return await MisplacedUsingDirectivesCodeFixProvider.TransformDocumentIfRequiredAsync( + organizedDocument, options.SimplifierOptions, options.AddImportOptions.UsingDirectivePlacement, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs index 128f258cc56f6..42e8f5892490c 100644 --- a/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs +++ b/src/Features/CSharp/Portable/Formatting/CSharpUseProgramMainNewDocumentFormattingProvider.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.CodeStyle; namespace Microsoft.CodeAnalysis.CSharp.Formatting { @@ -25,15 +26,13 @@ public CSharpUseProgramMainNewDocumentFormattingProvider() public async Task FormatNewDocumentAsync(Document document, Document? hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken) { - 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 = documentOptions.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); + var option = ((CSharpSyntaxFormattingOptions)options.FormattingOptions).PreferTopLevelStatements; if (option.Value) return document; - return await ConvertProgramTransform.ConvertToProgramMainAsync(document, cancellationToken).ConfigureAwait(false); + return await ConvertProgramTransform.ConvertToProgramMainAsync(document, options.FormattingOptions.AccessibilityModifiersRequired, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs b/src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs index 67c6a9eee7b74..e1a0542678183 100644 --- a/src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs @@ -65,7 +65,7 @@ public GenerateConstructorCodeFixProvider() public override ImmutableArray FixableDiagnosticIds => GenerateConstructorDiagnosticIds.AllDiagnosticIds; protected override Task> GetCodeActionsAsync( - Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetLanguageService(); return service.GenerateConstructorAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/GenerateConstructorFromMembers/CSharpGenerateConstructorFromMembersCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/GenerateConstructorFromMembers/CSharpGenerateConstructorFromMembersCodeRefactoringProvider.cs index e4b33eb706dd6..ef5ec9234eba4 100644 --- a/src/Features/CSharp/Portable/GenerateConstructorFromMembers/CSharpGenerateConstructorFromMembersCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/GenerateConstructorFromMembers/CSharpGenerateConstructorFromMembersCodeRefactoringProvider.cs @@ -7,14 +7,20 @@ using System; using System.Composition; using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.Features.Intents; using Microsoft.CodeAnalysis.GenerateConstructorFromMembers; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PickMembers; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.CSharp.Simplification; namespace Microsoft.CodeAnalysis.CSharp.GenerateConstructorFromMembers { @@ -45,7 +51,10 @@ protected override bool ContainingTypesOrSelfHasUnsafeKeyword(INamedTypeSymbol c protected override string ToDisplayString(IParameterSymbol parameter, SymbolDisplayFormat format) => SymbolDisplay.ToDisplayString(parameter, format); - protected override bool PrefersThrowExpression(DocumentOptionSet options) - => options.GetOption(CSharpCodeStyleOptions.PreferThrowExpression).Value; + protected override async ValueTask PrefersThrowExpressionAsync(Document document, SimplifierOptionsProvider fallbackOptions, CancellationToken cancellationToken) + { + var options = (CSharpSimplifierOptions)await document.GetSimplifierOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + return options.PreferThrowExpression.Value; + } } } diff --git a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs index cb9223e83645a..7e920ff11d961 100644 --- a/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs +++ b/src/Features/CSharp/Portable/GenerateType/CSharpGenerateTypeService.cs @@ -12,6 +12,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; @@ -767,7 +768,8 @@ internal override bool IsGenericName(SimpleNameSyntax simpleName) internal override bool IsSimpleName(ExpressionSyntax expression) => expression is SimpleNameSyntax; - internal override async Task TryAddUsingsOrImportToDocumentAsync(Solution updatedSolution, SyntaxNode modifiedRoot, Document document, SimpleNameSyntax simpleName, string includeUsingsOrImports, CancellationToken cancellationToken) + internal override async Task TryAddUsingsOrImportToDocumentAsync( + Solution updatedSolution, SyntaxNode modifiedRoot, Document document, SimpleNameSyntax simpleName, string includeUsingsOrImports, AddImportPlacementOptionsProvider fallbackOptions, CancellationToken cancellationToken) { // Nothing to include if (string.IsNullOrWhiteSpace(includeUsingsOrImports)) @@ -803,9 +805,8 @@ internal override async Task TryAddUsingsOrImportToDocumentAsync(Solut return updatedSolution; } - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var placeSystemNamespaceFirst = documentOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst); - var addedCompilationRoot = compilationRoot.AddUsingDirectives(new[] { usingDirective }, placeSystemNamespaceFirst, Formatter.Annotation); + var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var addedCompilationRoot = compilationRoot.AddUsingDirectives(new[] { usingDirective }, addImportOptions.PlaceSystemNamespaceFirst, Formatter.Annotation); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, addedCompilationRoot, PreservationMode.PreserveIdentity); } diff --git a/src/Features/CSharp/Portable/GenerateVariable/CSharpGenerateVariableCodeFixProvider.cs b/src/Features/CSharp/Portable/GenerateVariable/CSharpGenerateVariableCodeFixProvider.cs index 6224e5c056cd8..7f0fc1440ad4d 100644 --- a/src/Features/CSharp/Portable/GenerateVariable/CSharpGenerateVariableCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/GenerateVariable/CSharpGenerateVariableCodeFixProvider.cs @@ -59,7 +59,7 @@ protected override SyntaxNode GetTargetNode(SyntaxNode node) } protected override Task> GetCodeActionsAsync( - Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var service = document.GetLanguageService(); return service.GenerateVariableAsync(document, node, fallbackOptions, cancellationToken); diff --git a/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs index 50021c5381471..95528dae3a4d1 100644 --- a/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs @@ -6,17 +6,21 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.LanguageServices; using Microsoft.CodeAnalysis.CSharp.Shared.Extensions; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.InitializeParameter; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.CodeAnalysis.CSharp.InitializeParameter @@ -29,7 +33,8 @@ internal class CSharpAddParameterCheckCodeRefactoringProvider : ParameterSyntax, StatementSyntax, ExpressionSyntax, - BinaryExpressionSyntax> + BinaryExpressionSyntax, + CSharpSimplifierOptions> { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -69,16 +74,16 @@ protected override bool CanOffer(SyntaxNode body) return true; } - protected override bool PrefersThrowExpression(DocumentOptionSet options) - => options.GetOption(CSharpCodeStyleOptions.PreferThrowExpression).Value; + protected override bool PrefersThrowExpression(CSharpSimplifierOptions options) + => options.PreferThrowExpression.Value; protected override string EscapeResourceString(string input) => input.Replace("\\", "\\\\").Replace("\"", "\\\""); - protected override StatementSyntax CreateParameterCheckIfStatement(DocumentOptionSet options, ExpressionSyntax condition, StatementSyntax ifTrueStatement) + protected override StatementSyntax CreateParameterCheckIfStatement(ExpressionSyntax condition, StatementSyntax ifTrueStatement, CSharpSimplifierOptions options) { - var withBlock = options.GetOption(CSharpCodeStyleOptions.PreferBraces).Value == CodeAnalysis.CodeStyle.PreferBracesPreference.Always; - var singleLine = options.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine).Value; + var withBlock = options.PreferBraces.Value == CodeAnalysis.CodeStyle.PreferBracesPreference.Always; + var singleLine = options.AllowEmbeddedStatementsOnSameLine.Value; var closeParenToken = Token(SyntaxKind.CloseParenToken); if (withBlock) { @@ -103,14 +108,13 @@ protected override StatementSyntax CreateParameterCheckIfStatement(DocumentOptio @else: null); } - protected override async Task TryAddNullCheckToParameterDeclarationAsync(Document document, ParameterSyntax parameterSyntax, CancellationToken cancellationToken) + protected override async Task TryAddNullCheckToParameterDeclarationAsync(Document document, ParameterSyntax parameterSyntax, CSharpSimplifierOptions options, CancellationToken cancellationToken) { var tree = parameterSyntax.SyntaxTree; if (!tree.Options.LanguageVersion().IsCSharp11OrAbove()) return null; - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - if (!options.GetOption(CSharpCodeStyleOptions.PreferParameterNullChecking).Value) + if (!options.PreferParameterNullChecking.Value) return null; // We expect the syntax tree to already be in memory since we already have a node from the tree diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs index 366070320f75e..ab01b5ad833dd 100644 --- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs +++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineParameterNameHintsService.cs @@ -26,8 +26,7 @@ internal class CSharpInlineParameterNameHintsService : AbstractInlineParameterNa { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpInlineParameterNameHintsService(IGlobalOptionService globalOptions) - : base(globalOptions) + public CSharpInlineParameterNameHintsService() { } diff --git a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs index 8456ce3f2449e..c90655abf0378 100644 --- a/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs +++ b/src/Features/CSharp/Portable/InlineHints/CSharpInlineTypeHintsService.cs @@ -20,8 +20,7 @@ internal sealed class CSharpInlineTypeHintsService : AbstractInlineTypeHintsServ { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpInlineTypeHintsService(IGlobalOptionService globalOptions) - : base(globalOptions) + public CSharpInlineTypeHintsService() { } diff --git a/src/Features/CSharp/Portable/ReplaceMethodWithProperty/CSharpReplaceMethodWithPropertyService.cs b/src/Features/CSharp/Portable/ReplaceMethodWithProperty/CSharpReplaceMethodWithPropertyService.cs index a25d904041c76..473163bdb76f3 100644 --- a/src/Features/CSharp/Portable/ReplaceMethodWithProperty/CSharpReplaceMethodWithPropertyService.cs +++ b/src/Features/CSharp/Portable/ReplaceMethodWithProperty/CSharpReplaceMethodWithPropertyService.cs @@ -7,7 +7,9 @@ using System; using System.Composition; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.LanguageServices; @@ -33,7 +35,7 @@ public void RemoveSetMethod(SyntaxEditor editor, SyntaxNode setMethodDeclaration => editor.RemoveNode(setMethodDeclaration); public void ReplaceGetMethodWithProperty( - DocumentOptionSet documentOptions, + CodeGenerationOptions options, ParseOptions parseOptions, SyntaxEditor editor, SemanticModel semanticModel, @@ -47,7 +49,7 @@ public void ReplaceGetMethodWithProperty( var languageVersion = parseOptions.LanguageVersion(); var newProperty = ConvertMethodsToProperty( - documentOptions, languageVersion, + (CSharpCodeGenerationOptions)options, languageVersion, semanticModel, editor.Generator, getAndSetMethods, propertyName, nameChanged); @@ -55,15 +57,15 @@ public void ReplaceGetMethodWithProperty( } public static SyntaxNode ConvertMethodsToProperty( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, + CSharpCodeGenerationOptions options, LanguageVersion languageVersion, SemanticModel semanticModel, SyntaxGenerator generator, GetAndSetMethods getAndSetMethods, string propertyName, bool nameChanged) { var propertyDeclaration = ConvertMethodsToPropertyWorker( - documentOptions, languageVersion, semanticModel, + options, languageVersion, semanticModel, generator, getAndSetMethods, propertyName, nameChanged); - var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value; + var expressionBodyPreference = options.PreferExpressionBodiedProperties.Value; if (expressionBodyPreference != ExpressionBodyPreference.Never) { if (propertyDeclaration.AccessorList?.Accessors.Count == 1 && @@ -110,14 +112,14 @@ public static SyntaxNode ConvertMethodsToProperty( } public static PropertyDeclarationSyntax ConvertMethodsToPropertyWorker( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, + CSharpCodeGenerationOptions options, LanguageVersion languageVersion, SemanticModel semanticModel, SyntaxGenerator generator, GetAndSetMethods getAndSetMethods, string propertyName, bool nameChanged) { var getMethodDeclaration = (MethodDeclarationSyntax)getAndSetMethods.GetMethodDeclaration; var setMethodDeclaration = getAndSetMethods.SetMethodDeclaration as MethodDeclarationSyntax; - var getAccessor = CreateGetAccessor(getAndSetMethods, documentOptions, languageVersion); - var setAccessor = CreateSetAccessor(semanticModel, generator, getAndSetMethods, documentOptions, languageVersion); + var getAccessor = CreateGetAccessor(getAndSetMethods, options, languageVersion); + var setAccessor = CreateSetAccessor(semanticModel, generator, getAndSetMethods, options, languageVersion); var nameToken = GetPropertyName(getMethodDeclaration.Identifier, propertyName, nameChanged); var warning = GetWarning(getAndSetMethods); @@ -160,19 +162,19 @@ private static SyntaxToken GetPropertyName(SyntaxToken identifier, string proper } private static AccessorDeclarationSyntax CreateGetAccessor( - GetAndSetMethods getAndSetMethods, DocumentOptionSet documentOptions, LanguageVersion languageVersion) + GetAndSetMethods getAndSetMethods, CSharpCodeGenerationOptions options, LanguageVersion languageVersion) { var accessorDeclaration = CreateGetAccessorWorker(getAndSetMethods); return UseExpressionOrBlockBodyIfDesired( - documentOptions, languageVersion, accessorDeclaration); + options, languageVersion, accessorDeclaration); } private static AccessorDeclarationSyntax UseExpressionOrBlockBodyIfDesired( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, + CSharpCodeGenerationOptions options, LanguageVersion languageVersion, AccessorDeclarationSyntax accessorDeclaration) { - var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value; + var expressionBodyPreference = options.PreferExpressionBodiedAccessors.Value; if (accessorDeclaration?.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never) { if (accessorDeclaration.Body.TryConvertToArrowExpressionBody( @@ -229,10 +231,10 @@ private static AccessorDeclarationSyntax CreateGetAccessorWorker(GetAndSetMethod private static AccessorDeclarationSyntax CreateSetAccessor( SemanticModel semanticModel, SyntaxGenerator generator, GetAndSetMethods getAndSetMethods, - DocumentOptionSet documentOptions, LanguageVersion languageVersion) + CSharpCodeGenerationOptions options, LanguageVersion languageVersion) { var accessorDeclaration = CreateSetAccessorWorker(semanticModel, generator, getAndSetMethods); - return UseExpressionOrBlockBodyIfDesired(documentOptions, languageVersion, accessorDeclaration); + return UseExpressionOrBlockBodyIfDesired(options, languageVersion, accessorDeclaration); } private static AccessorDeclarationSyntax CreateSetAccessorWorker( diff --git a/src/Features/CSharp/Portable/ReplacePropertyWithMethods/CSharpReplacePropertyWithMethodsService.cs b/src/Features/CSharp/Portable/ReplacePropertyWithMethods/CSharpReplacePropertyWithMethodsService.cs index 9d9c92bf78400..81958ae34dd91 100644 --- a/src/Features/CSharp/Portable/ReplacePropertyWithMethods/CSharpReplacePropertyWithMethodsService.cs +++ b/src/Features/CSharp/Portable/ReplacePropertyWithMethods/CSharpReplacePropertyWithMethodsService.cs @@ -8,7 +8,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -40,30 +42,31 @@ public override async Task> GetReplacementMembersAsyn IFieldSymbol propertyBackingField, string desiredGetMethodName, string desiredSetMethodName, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { if (propertyDeclarationNode is not PropertyDeclarationSyntax propertyDeclaration) return ImmutableArray.Empty; - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var languageVersion = syntaxTree.Options.LanguageVersion(); return ConvertPropertyToMembers( - documentOptions, languageVersion, + languageVersion, SyntaxGenerator.GetGenerator(document), property, propertyDeclaration, propertyBackingField, - desiredGetMethodName, desiredSetMethodName, + options.PreferExpressionBodiedMethods.Value, desiredGetMethodName, desiredSetMethodName, cancellationToken); } private static ImmutableArray ConvertPropertyToMembers( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, SyntaxGenerator generator, IPropertySymbol property, PropertyDeclarationSyntax propertyDeclaration, IFieldSymbol? propertyBackingField, + ExpressionBodyPreference expressionBodyPreference, string desiredGetMethodName, string desiredSetMethodName, CancellationToken cancellationToken) @@ -80,33 +83,33 @@ private static ImmutableArray ConvertPropertyToMembers( if (getMethod != null) { result.Add(GetGetMethod( - documentOptions, languageVersion, + languageVersion, generator, propertyDeclaration, propertyBackingField, - getMethod, desiredGetMethodName, - cancellationToken: cancellationToken)); + getMethod, desiredGetMethodName, expressionBodyPreference, + cancellationToken)); } var setMethod = property.SetMethod; if (setMethod != null) { result.Add(GetSetMethod( - documentOptions, languageVersion, + languageVersion, generator, propertyDeclaration, propertyBackingField, - setMethod, desiredSetMethodName, - cancellationToken: cancellationToken)); + setMethod, desiredSetMethodName, expressionBodyPreference, + cancellationToken)); } return result.ToImmutable(); } private static SyntaxNode GetSetMethod( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, SyntaxGenerator generator, PropertyDeclarationSyntax propertyDeclaration, IFieldSymbol? propertyBackingField, IMethodSymbol setMethod, string desiredSetMethodName, + ExpressionBodyPreference expressionBodyPreference, CancellationToken cancellationToken) { var methodDeclaration = GetSetMethodWorker( @@ -118,7 +121,7 @@ private static SyntaxNode GetSetMethod( methodDeclaration = CopyLeadingTrivia(propertyDeclaration, methodDeclaration, ConvertValueToParamRewriter.Instance); return UseExpressionOrBlockBodyIfDesired( - documentOptions, languageVersion, methodDeclaration, + languageVersion, methodDeclaration, expressionBodyPreference, createReturnStatementForExpression: false); } @@ -164,13 +167,13 @@ private static MethodDeclarationSyntax GetSetMethodWorker( } private static SyntaxNode GetGetMethod( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, SyntaxGenerator generator, PropertyDeclarationSyntax propertyDeclaration, IFieldSymbol? propertyBackingField, IMethodSymbol getMethod, string desiredGetMethodName, + ExpressionBodyPreference expressionBodyPreference, CancellationToken cancellationToken) { var methodDeclaration = GetGetMethodWorker( @@ -180,7 +183,7 @@ private static SyntaxNode GetGetMethod( methodDeclaration = CopyLeadingTrivia(propertyDeclaration, methodDeclaration, ConvertValueToReturnsRewriter.Instance); return UseExpressionOrBlockBodyIfDesired( - documentOptions, languageVersion, methodDeclaration, + languageVersion, methodDeclaration, expressionBodyPreference, createReturnStatementForExpression: true); } @@ -213,10 +216,11 @@ private static SyntaxTrivia ConvertDocumentationComment(SyntaxTrivia trivia, CSh } private static SyntaxNode UseExpressionOrBlockBodyIfDesired( - DocumentOptionSet documentOptions, LanguageVersion languageVersion, - MethodDeclarationSyntax methodDeclaration, bool createReturnStatementForExpression) + LanguageVersion languageVersion, + MethodDeclarationSyntax methodDeclaration, + ExpressionBodyPreference expressionBodyPreference, + bool createReturnStatementForExpression) { - var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; if (methodDeclaration.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never) { if (methodDeclaration.Body.TryConvertToArrowExpressionBody( diff --git a/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs index 202d25fcea7d7..006f3bdf70f9c 100644 --- a/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/SimplifyThisOrMe/CSharpSimplifyThisOrMeDiagnosticAnalyzer.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Simplification.Simplifiers; using Microsoft.CodeAnalysis.SimplifyThisOrMe; @@ -19,13 +20,12 @@ internal sealed class CSharpSimplifyThisOrMeDiagnosticAnalyzer SyntaxKind, ExpressionSyntax, ThisExpressionSyntax, - MemberAccessExpressionSyntax, - CSharpSimplifierOptions> + MemberAccessExpressionSyntax> { protected override ISyntaxKinds SyntaxKinds => CSharpSyntaxKinds.Instance; - protected override CSharpSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree) - => options.GetCSharpSimplifierOptions(syntaxTree); + protected override ISimplification Simplification + => CSharpSimplification.Instance; protected override AbstractMemberAccessExpressionSimplifier Simplifier => MemberAccessExpressionSimplifier.Instance; diff --git a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs index 1cc8e801fa3b0..3630036ceea40 100644 --- a/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/UseExpressionBody/UseExpressionBodyCodeRefactoringProvider.cs @@ -10,7 +10,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Formatting; @@ -54,7 +56,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(context.Options, cancellationToken).ConfigureAwait(false); foreach (var helper in _helpers) { @@ -62,7 +64,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (declaration == null) continue; - var succeeded = TryComputeRefactoring(context, root, declaration, optionSet, helper); + var succeeded = TryComputeRefactoring(context, root, declaration, options, helper); if (succeeded) return; } @@ -90,12 +92,13 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte private static bool TryComputeRefactoring( CodeRefactoringContext context, SyntaxNode root, SyntaxNode declaration, - OptionSet optionSet, UseExpressionBodyHelper helper) + CSharpCodeGenerationOptions options, UseExpressionBodyHelper helper) { var document = context.Document; + var preference = helper.GetExpressionBodyPreference(options); var succeeded = false; - if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: false)) + if (helper.CanOfferUseExpressionBody(preference, declaration, forAnalyzer: false)) { var title = helper.UseExpressionBodyTitle.ToString(); context.RegisterRefactoring( @@ -109,7 +112,7 @@ private static bool TryComputeRefactoring( succeeded = true; } - if (helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: false, out _, out _)) + if (helper.CanOfferUseBlockBody(preference, declaration, forAnalyzer: false, out _, out _)) { var title = helper.UseBlockBodyTitle.ToString(); context.RegisterRefactoring( diff --git a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider.cs b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider.cs index 8dc2edf4352dc..ac7591f83de49 100644 --- a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider.cs +++ b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider.cs @@ -42,6 +42,9 @@ public UseExpressionBodyForLambdaCodeStyleProvider() // Shared code needed by all parts of the style provider for this feature. + protected override CodeStyleOption2 GetCodeStyleOption(AnalyzerOptionsProvider provider) + => ((CSharpAnalyzerOptionsProvider)provider).PreferExpressionBodiedLambdas; + private static ExpressionSyntax GetBodyAsExpression(LambdaExpressionSyntax declaration) => declaration.Body as ExpressionSyntax; diff --git a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider_Refactoring.cs b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider_Refactoring.cs index d398f5c9cbe12..1e0aabb93d3b1 100644 --- a/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider_Refactoring.cs +++ b/src/Features/CSharp/Portable/UseExpressionBodyForLambda/UseExpressionBodyForLambdaCodeStyleProvider_Refactoring.cs @@ -104,7 +104,6 @@ private static async Task> ComputeRefactoringsAsync( } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); using var resultDisposer = ArrayBuilder.GetInstance(out var result); if (CanOfferUseExpressionBody(option, lambdaNode, root.GetLanguageVersion())) diff --git a/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs b/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs index 4a12669472e76..3001b9e3aecfc 100644 --- a/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs @@ -14,6 +14,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Extensions; @@ -85,10 +86,18 @@ protected override async Task FixAllAsync( var root = editor.OriginalRoot; var currentRoot = root.TrackNodes(nodesToTrack); - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var languageVersion = semanticModel.SyntaxTree.Options.LanguageVersion(); - var makeStaticIfPossible = languageVersion >= LanguageVersion.CSharp8 && - optionSet.GetOption(CSharpCodeStyleOptions.PreferStaticLocalFunction).Value; + bool makeStaticIfPossible; + + if (languageVersion >= LanguageVersion.CSharp8) + { + var options = (CSharpCodeGenerationOptions)await document.GetCodeGenerationOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + makeStaticIfPossible = options.PreferStaticLocalFunction.Value; + } + else + { + makeStaticIfPossible = false; + } // Process declarations in reverse order so that we see the effects of nested // declarations befor processing the outer decls. diff --git a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs index 650cf7cd252d3..b212581d79c91 100644 --- a/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCheckWithoutNameDiagnosticAnalyzer.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; @@ -76,7 +77,7 @@ private void SyntaxNodeAction( return; } - var styleOption = context.GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck); + var styleOption = context.GetCSharpAnalyzerOptions().PreferPatternMatchingOverIsWithCastCheck; if (!styleOption.Value) { // User has disabled this feature. diff --git a/src/Features/CSharp/Portable/Wrapping/CSharpSyntaxWrappingOptions.cs b/src/Features/CSharp/Portable/Wrapping/CSharpSyntaxWrappingOptions.cs index 6be11821d36cd..08a617128b300 100644 --- a/src/Features/CSharp/Portable/Wrapping/CSharpSyntaxWrappingOptions.cs +++ b/src/Features/CSharp/Portable/Wrapping/CSharpSyntaxWrappingOptions.cs @@ -23,12 +23,15 @@ public CSharpSyntaxWrappingOptions( { NewLinesForBracesInObjectCollectionArrayInitializers = newLinesForBracesInObjectCollectionArrayInitializers; } + } - public static CSharpSyntaxWrappingOptions Create(AnalyzerConfigOptions options, CodeActionOptions ideOptions) + internal static class CSharpSyntaxWrappingOptionsProviders + { + public static CSharpSyntaxWrappingOptions GetCSharpSyntaxWrappingOptions(this AnalyzerConfigOptions options, CodeActionOptions fallbackOptions) => new( - CSharpSyntaxFormattingOptions.Create(options, (CSharpSyntaxFormattingOptions?)ideOptions.CleanupOptions?.FormattingOptions), + options.GetCSharpSyntaxFormattingOptions((CSharpSyntaxFormattingOptions)fallbackOptions.CleanupOptions.FormattingOptions), operatorPlacement: options.GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping), - wrappingColumn: ideOptions.WrappingColumn, + wrappingColumn: fallbackOptions.WrappingColumn, newLinesForBracesInObjectCollectionArrayInitializers: options.GetOption(CSharpFormattingOptions2.NewLinesForBracesInObjectCollectionArrayInitializers)); } } diff --git a/src/Features/CSharp/Portable/Wrapping/CSharpWrappingCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/Wrapping/CSharpWrappingCodeRefactoringProvider.cs index 31cb4b66cacb4..5bcadd7293cb4 100644 --- a/src/Features/CSharp/Portable/Wrapping/CSharpWrappingCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/Wrapping/CSharpWrappingCodeRefactoringProvider.cs @@ -34,6 +34,6 @@ public CSharpWrappingCodeRefactoringProvider() } protected override SyntaxWrappingOptions GetWrappingOptions(AnalyzerConfigOptions options, CodeActionOptions ideOptions) - => CSharpSyntaxWrappingOptions.Create(options, ideOptions); + => options.GetCSharpSyntaxWrappingOptions(ideOptions); } } diff --git a/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.State.cs b/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.State.cs index 07598618f853f..2bde78fdc4611 100644 --- a/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.State.cs +++ b/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.State.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -26,11 +27,12 @@ private class State public static async Task GenerateAsync( ImmutableArray selectedMembers, Document document, + NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { var state = new State(); if (!await state.TryInitializeAsync( - selectedMembers, document, cancellationToken).ConfigureAwait(false)) + selectedMembers, document, fallbackOptions, cancellationToken).ConfigureAwait(false)) { return null; } @@ -41,11 +43,12 @@ private class State private async Task TryInitializeAsync( ImmutableArray selectedMembers, Document document, + NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { ContainingType = selectedMembers[0].ContainingType; - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var parametersForSelectedMembers = DetermineParameters(selectedMembers, rules); if (!selectedMembers.All(IsWritableInstanceFieldOrProperty) || diff --git a/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.cs b/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.cs index 0d22a883f31d8..fdca6a31fbaf6 100644 --- a/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/AddConstructorParametersFromMembers/AddConstructorParametersFromMembersCodeRefactoringProvider.cs @@ -67,7 +67,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (info != null) { - var state = await State.GenerateAsync(info.SelectedMembers, document, cancellationToken).ConfigureAwait(false); + var state = await State.GenerateAsync(info.SelectedMembers, document, fallbackOptions, cancellationToken).ConfigureAwait(false); if (state?.ConstructorCandidates != null && !state.ConstructorCandidates.IsEmpty) { var codeGenOptions = await document.GetCodeGenerationOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerCodeRefactoringProvider.cs b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerCodeRefactoringProvider.cs index 28e7dd07d03b0..1698a948c4ff0 100644 --- a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerCodeRefactoringProvider.cs @@ -43,15 +43,14 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte return; } - var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - - if (document.Project.AnalyzerOptions.TryGetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, tree, out var fileHeaderTemplate) - && !string.IsNullOrEmpty(fileHeaderTemplate)) + var formattingOptions = await document.GetDocumentFormattingOptionsAsync(context.Options, cancellationToken).ConfigureAwait(false); + if (!string.IsNullOrEmpty(formattingOptions.FileHeaderTemplate)) { // If we have a defined file header template, allow the analyzer and code fix to handle it return; } + var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var position = span.Start; diff --git a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs index ef1f1a6f61d04..f431af511fc40 100644 --- a/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs +++ b/src/Features/Core/Portable/AddFileBanner/AbstractAddFileBannerNewDocumentFormattingProvider.cs @@ -23,10 +23,9 @@ internal abstract class AbstractAddFileBannerNewDocumentFormattingProvider : INe 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); // Apply file header preferences - var fileHeaderTemplate = documentOptions.GetOption(CodeStyleOptions2.FileHeaderTemplate); + var fileHeaderTemplate = options.DocumentFormattingOptions.FileHeaderTemplate; if (!string.IsNullOrEmpty(fileHeaderTemplate)) { var newLineTrivia = SyntaxGeneratorInternal.EndOfLine(options.FormattingOptions.NewLine); diff --git a/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs index 37532bfb73285..8ac8abfbba279 100644 --- a/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs +++ b/src/Features/Core/Portable/CodeFixes/GenerateMember/AbstractGenerateMemberCodeFixProvider.cs @@ -24,7 +24,7 @@ internal abstract class AbstractGenerateMemberCodeFixProvider : CodeFixProvider return null; } - protected abstract Task> GetCodeActionsAsync(Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); + protected abstract Task> GetCodeActionsAsync(Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected abstract bool IsCandidate(SyntaxNode node, SyntaxToken token, Diagnostic diagnostic); public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) diff --git a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs index 0f7d9347885e4..309980851f6be 100644 --- a/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/AddMissingImports/AbstractAddMissingImportsFeatureService.cs @@ -61,7 +61,7 @@ public async Task AnalyzeAsync(Document documen var packageSources = ImmutableArray.Empty; var addImportOptions = new AddImportOptions( - SearchOptions: new(SearchReferenceAssemblies: true, SearchNuGetPackages: false), + SearchOptions: new() { SearchReferenceAssemblies = true, SearchNuGetPackages = false }, CleanupOptions: options.CleanupOptions, HideAdvancedMembers: options.HideAdvancedMembers); diff --git a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs index 118d0365b9ad2..e5d22fc10a7fa 100644 --- a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs +++ b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; @@ -21,7 +22,7 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings.MoveType { internal abstract partial class AbstractMoveTypeService { - private class MoveTypeEditor : Editor + private sealed class MoveTypeEditor : Editor { public MoveTypeEditor( TService service, @@ -161,8 +162,8 @@ private async Task AddNewDocumentWithSingleTypeDeclarationAsync(Docume /// private async Task AddFinalNewLineIfDesiredAsync(Document document, SyntaxNode modifiedRoot) { - var options = await document.GetOptionsAsync(CancellationToken).ConfigureAwait(false); - var insertFinalNewLine = options.GetOption(FormattingOptions2.InsertFinalNewLine); + var documentFormattingOptions = await document.GetDocumentFormattingOptionsAsync(State.FallbackOptions, CancellationToken).ConfigureAwait(false); + var insertFinalNewLine = documentFormattingOptions.InsertFinalNewLine; if (insertFinalNewLine) { var endOfFileToken = ((ICompilationUnitSyntax)modifiedRoot).EndOfFileToken; @@ -172,8 +173,9 @@ private async Task AddFinalNewLineIfDesiredAsync(Document document, if (endOfFileToken.LeadingTrivia.IsEmpty() && !previousToken.TrailingTrivia.Any(syntaxFacts.IsEndOfLineTrivia)) { + var lineFormattingOptions = await document.GetLineFormattingOptionsAsync(State.FallbackOptions, CancellationToken).ConfigureAwait(false); var generator = document.GetRequiredLanguageService(); - var endOfLine = generator.EndOfLine(options.GetOption(FormattingOptions.NewLine)); + var endOfLine = generator.EndOfLine(lineFormattingOptions.NewLine); return modifiedRoot.ReplaceToken( previousToken, previousToken.WithAppendedTrailingTrivia(endOfLine)); } diff --git a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.State.cs b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.State.cs index 80ea5e3e2d3be..4606e94f3d4a8 100644 --- a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.State.cs +++ b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.State.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -18,21 +19,21 @@ internal abstract partial class AbstractMoveTypeService public static SyntaxAnnotation NamespaceScopeMovedAnnotation = new(nameof(MoveTypeOperationKind.MoveTypeNamespaceScope)); - public abstract Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken); - public abstract Task> GetRefactoringAsync(Document document, TextSpan textSpan, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken); + public abstract Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken); + public abstract Task> GetRefactoringAsync(Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken); } internal abstract partial class AbstractMoveTypeService : @@ -42,7 +43,7 @@ internal abstract partial class AbstractMoveTypeService> GetRefactoringAsync( - Document document, TextSpan textSpan, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var state = await CreateStateAsync(document, textSpan, fallbackOptions, cancellationToken).ConfigureAwait(false); @@ -55,7 +56,7 @@ public override async Task> GetRefactoringAsync( return actions; } - public override async Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken) + public override async Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var state = await CreateStateAsync(document, textSpan, fallbackOptions, cancellationToken).ConfigureAwait(false); @@ -79,7 +80,7 @@ public override async Task GetModifiedSolutionAsync(Document document, protected abstract Task GetRelevantNodeAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken); - private async Task CreateStateAsync(Document document, TextSpan textSpan, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken) + private async Task CreateStateAsync(Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var nodeToAnalyze = await GetRelevantNodeAsync(document, textSpan, cancellationToken).ConfigureAwait(false); if (nodeToAnalyze == null) diff --git a/src/Features/Core/Portable/CodeRefactorings/MoveType/IMoveTypeService.cs b/src/Features/Core/Portable/CodeRefactorings/MoveType/IMoveTypeService.cs index 9898a6ffc9fe1..a30bb92fe86c5 100644 --- a/src/Features/Core/Portable/CodeRefactorings/MoveType/IMoveTypeService.cs +++ b/src/Features/Core/Portable/CodeRefactorings/MoveType/IMoveTypeService.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Text; @@ -16,8 +17,8 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings.MoveType { internal interface IMoveTypeService : ILanguageService { - Task> GetRefactoringAsync(Document document, TextSpan textSpan, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken); + Task> GetRefactoringAsync(Document document, TextSpan textSpan, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken); - Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, SyntaxFormattingOptionsProvider fallbackOptions, CancellationToken cancellationToken); + Task GetModifiedSolutionAsync(Document document, TextSpan textSpan, MoveTypeOperationKind operationKind, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Analysis.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Analysis.cs index 0fd657dad7665..48f5757bbd797 100644 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Analysis.cs +++ b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Analysis.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.CodeStyle // subclasses cannot change anything. All code relevant to subclasses relating to analysis // is contained in AbstractCodeStyleProvider.cs - internal abstract partial class AbstractCodeStyleProvider + internal abstract partial class AbstractCodeStyleProvider { public abstract class DiagnosticAnalyzer : AbstractBuiltInCodeStyleDiagnosticAnalyzer { @@ -76,52 +76,52 @@ public void RegisterCompilationStartAction(Action c => analyze(c.Compilation, _this)); } - public void RegisterCodeBlockAction(Action> analyze) + public void RegisterCodeBlockAction(Action> analyze) { var provider = _codeStyleProvider; _context.RegisterCodeBlockAction( - c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree, c.CancellationToken)); + c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree)); } - public void RegisterSemanticModelAction(Action> analyze) + public void RegisterSemanticModelAction(Action> analyze) { var provider = _codeStyleProvider; _context.RegisterSemanticModelAction( - c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree, c.CancellationToken)); + c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree)); } - public void RegisterSyntaxTreeAction(Action> analyze) + public void RegisterSyntaxTreeAction(Action> analyze) { var provider = _codeStyleProvider; _context.RegisterSyntaxTreeAction( - c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.Tree, c.CancellationToken)); + c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.Tree)); } public void RegisterOperationAction( - Action> analyze, + Action> analyze, params OperationKind[] operationKinds) { var provider = _codeStyleProvider; _context.RegisterOperationAction( - c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.Operation.SemanticModel.SyntaxTree, c.CancellationToken), + c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.Operation.SemanticModel.SyntaxTree), operationKinds); } public void RegisterSyntaxNodeAction( - Action> analyze, + Action> analyze, params TSyntaxKind[] syntaxKinds) where TSyntaxKind : struct { var provider = _codeStyleProvider; _context.RegisterSyntaxNodeAction( - c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree, c.CancellationToken), + c => AnalyzeIfEnabled(provider, c, analyze, c.Options, c.SemanticModel.SyntaxTree), syntaxKinds); } private static void AnalyzeIfEnabled( - TCodeStyleProvider provider, TContext context, Action> analyze, - AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken) + TCodeStyleProvider provider, TContext context, Action> analyze, + AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree) { - var optionValue = options.GetOption(provider._option, syntaxTree, cancellationToken); + var optionValue = provider.GetCodeStyleOption(analyzerOptions.GetAnalyzerOptions(syntaxTree)); var severity = GetOptionSeverity(optionValue); switch (severity) { diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Fixing.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Fixing.cs index 631ee701b3225..6481f90b5f7bb 100644 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Fixing.cs +++ b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Fixing.cs @@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.CodeStyle // subclasses cannot change anything. All code relevant to subclasses relating to fixing is // contained in AbstractCodeStyleProvider.cs - internal abstract partial class AbstractCodeStyleProvider + internal abstract partial class AbstractCodeStyleProvider { private async Task RegisterCodeFixesAsync(CodeFixContext context) { diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Refactoring.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Refactoring.cs index cb279f6c80918..fe2711b81fe16 100644 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Refactoring.cs +++ b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.Refactoring.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.CodeAnalysis.CodeStyle { @@ -14,14 +15,14 @@ namespace Microsoft.CodeAnalysis.CodeStyle // subclasses cannot change anything. All code relevant to subclasses relating to refactorings // is contained in AbstractCodeStyleProvider.cs - internal abstract partial class AbstractCodeStyleProvider + internal abstract partial class AbstractCodeStyleProvider { private async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var (document, _, cancellationToken) = context; - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var optionValue = optionSet.GetOption(_option); + var optionProvider = await document.GetAnalyzerOptionsProviderAsync(cancellationToken).ConfigureAwait(false); + var optionValue = GetCodeStyleOption(optionProvider); var severity = GetOptionSeverity(optionValue); switch (severity) @@ -62,7 +63,7 @@ private async Task ComputeRefactoringsAsync(CodeRefactoringContext context) } private async Task ComputeRefactoringsAsync( - CodeRefactoringContext context, TOptionKind option, bool analyzerActive) + CodeRefactoringContext context, TOptionValue option, bool analyzerActive) { var (document, span, cancellationToken) = context; diff --git a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.cs b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.cs index b3b5c112a983a..2b1722f568b48 100644 --- a/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.cs +++ b/src/Features/Core/Portable/CodeStyle/AbstractCodeStyleProvider.cs @@ -29,11 +29,10 @@ namespace Microsoft.CodeAnalysis.CodeStyle /// only', it will not bother running any of the DiagnosticAnalyzer codepaths, and will only run /// the CodeRefactoringProvider codepaths. /// - internal abstract partial class AbstractCodeStyleProvider< - TOptionKind, TCodeStyleProvider> - where TCodeStyleProvider : AbstractCodeStyleProvider, new() + internal abstract partial class AbstractCodeStyleProvider + where TCodeStyleProvider : AbstractCodeStyleProvider, new() { - private readonly Option2> _option; + private readonly Option2> _option; private readonly string _language; private readonly string _descriptorId; private readonly EnforceOnBuild _enforceOnBuild; @@ -41,7 +40,7 @@ internal abstract partial class AbstractCodeStyleProvider< private readonly LocalizableString _message; protected AbstractCodeStyleProvider( - Option2> option, + Option2> option, string language, string descriptorId, EnforceOnBuild enforceOnBuild, @@ -61,7 +60,7 @@ protected AbstractCodeStyleProvider( /// handle ReportDiagnostic.Default and will map that back to the appropriate value in that /// case. /// - protected static ReportDiagnostic GetOptionSeverity(CodeStyleOption2 optionValue) + protected static ReportDiagnostic GetOptionSeverity(CodeStyleOption2 optionValue) { var severity = optionValue.Notification.Severity; return severity == ReportDiagnostic.Default @@ -69,6 +68,8 @@ protected static ReportDiagnostic GetOptionSeverity(CodeStyleOption2 GetCodeStyleOption(AnalyzerOptionsProvider provider); + #region analysis protected abstract void DiagnosticAnalyzerInitialize(AnalysisContext context); @@ -141,7 +142,7 @@ protected abstract Task> ComputeAllRefactoringsWhenAn /// expression body already. /// protected abstract Task> ComputeOpposingRefactoringsWhenAnalyzerActiveAsync( - Document document, TextSpan span, TOptionKind option, CancellationToken cancellationToken); + Document document, TextSpan span, TOptionValue option, CancellationToken cancellationToken); #endregion } diff --git a/src/Features/Core/Portable/Completion/ArgumentContext.cs b/src/Features/Core/Portable/Completion/ArgumentContext.cs index 7f88525a5139a..54c3efcf746af 100644 --- a/src/Features/Core/Portable/Completion/ArgumentContext.cs +++ b/src/Features/Core/Portable/Completion/ArgumentContext.cs @@ -15,7 +15,6 @@ internal sealed class ArgumentContext { public ArgumentContext( ArgumentProvider provider, - OptionSet options, SemanticModel semanticModel, int position, IParameterSymbol parameter, @@ -23,7 +22,6 @@ public ArgumentContext( CancellationToken cancellationToken) { Provider = provider ?? throw new ArgumentNullException(nameof(provider)); - Options = options ?? throw new ArgumentNullException(nameof(options)); SemanticModel = semanticModel ?? throw new ArgumentNullException(nameof(semanticModel)); Position = position; Parameter = parameter ?? throw new ArgumentNullException(nameof(parameter)); @@ -33,11 +31,6 @@ public ArgumentContext( internal ArgumentProvider Provider { get; } - /// - /// Gets the effective options where argument completion is requested. - /// - public OptionSet Options { get; } - /// /// Gets the semantic model where argument completion is requested. /// diff --git a/src/Features/Core/Portable/Completion/CompletionOptions.cs b/src/Features/Core/Portable/Completion/CompletionOptions.cs index d63cc37cea030..7642ccd08faa0 100644 --- a/src/Features/Core/Portable/Completion/CompletionOptions.cs +++ b/src/Features/Core/Portable/Completion/CompletionOptions.cs @@ -2,33 +2,35 @@ // 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.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Recommendations; namespace Microsoft.CodeAnalysis.Completion { - internal readonly record struct CompletionOptions( - bool TriggerOnTyping = true, - bool TriggerOnTypingLetters = true, - bool? TriggerOnDeletion = null, - bool TriggerInArgumentLists = true, - EnterKeyRule EnterKeyBehavior = EnterKeyRule.Default, - SnippetsRule SnippetsBehavior = SnippetsRule.Default, - bool HideAdvancedMembers = false, - bool ShowNameSuggestions = true, - bool? ShowItemsFromUnimportedNamespaces = null, - bool UnnamedSymbolCompletionDisabled = false, - bool TargetTypedCompletionFilter = false, - bool TypeImportCompletion = false, - bool ProvideDateAndTimeCompletions = true, - bool ProvideRegexCompletions = true, - bool ForceExpandedCompletionIndexCreation = false, - bool UpdateImportCompletionCacheInBackground = false, - bool FilterOutOfScopeLocals = true, - bool ShowXmlDocCommentCompletion = true, - ExpandedCompletionMode ExpandedCompletionBehavior = ExpandedCompletionMode.AllItems) + internal sealed record class CompletionOptions { - // note: must pass at least one parameter to avoid calling default ctor: - public static readonly CompletionOptions Default = new(TriggerOnTyping: true); + public bool TriggerOnTyping { get; init; } = true; + public bool TriggerOnTypingLetters { get; init; } = true; + public bool? TriggerOnDeletion { get; init; } = null; + public bool TriggerInArgumentLists { get; init; } = true; + public EnterKeyRule EnterKeyBehavior { get; init; } = EnterKeyRule.Default; + public SnippetsRule SnippetsBehavior { get; init; } = SnippetsRule.Default; + public bool HideAdvancedMembers { get; init; } = false; + public bool ShowNameSuggestions { get; init; } = true; + public bool? ShowItemsFromUnimportedNamespaces { get; init; } = null; + public bool UnnamedSymbolCompletionDisabled { get; init; } = false; + public bool TargetTypedCompletionFilter { get; init; } = false; + public bool TypeImportCompletion { get; init; } = false; + public bool ProvideDateAndTimeCompletions { get; init; } = true; + public bool ProvideRegexCompletions { get; init; } = true; + public bool ForceExpandedCompletionIndexCreation { get; init; } = false; + public bool UpdateImportCompletionCacheInBackground { get; init; } = false; + public bool FilterOutOfScopeLocals { get; init; } = true; + public bool ShowXmlDocCommentCompletion { get; init; } = true; + public ExpandedCompletionMode ExpandedCompletionBehavior { get; init; } = ExpandedCompletionMode.AllItems; + public NamingStylePreferences? NamingStyleFallbackOptions { get; init; } = null; + + public static readonly CompletionOptions Default = new(); public RecommendationServiceOptions ToRecommendationServiceOptions() => new( diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs index dbc458f414f01..aa5ab7753f104 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; @@ -37,7 +38,8 @@ public AbstractMemberInsertingCompletionProvider() public override async Task GetChangeAsync(Document document, CompletionItem item, char? commitKey = null, CancellationToken cancellationToken = default) { // TODO: pass fallback options: https://github.com/dotnet/roslyn/issues/60786 - var fallbackOptions = CodeActionOptions.DefaultProvider; + var globalOptions = document.Project.Solution.Workspace.Services.GetService(); + var fallbackOptions = globalOptions?.CleanCodeGenerationOptionsProvider ?? CodeActionOptions.DefaultProvider; var newDocument = await DetermineNewDocumentAsync(document, item, fallbackOptions, cancellationToken).ConfigureAwait(false); var newText = await newDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs index dbe8cf1fd1535..649dcf21f7199 100644 --- a/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/AbstractImportCompletionProvider.cs @@ -7,10 +7,12 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Completion.Log; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -128,8 +130,11 @@ public override async Task GetChangeAsync( var generator = document.GetRequiredLanguageService(); // TODO: fallback options https://github.com/dotnet/roslyn/issues/60786 - var addImportsOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var globalOptions = document.Project.Solution.Workspace.Services.GetService(); + var fallbackOptions = globalOptions?.CleanCodeGenerationOptionsProvider ?? CodeActionOptions.DefaultProvider; + + var addImportsOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var importNode = CreateImport(document, containingNamespace); diff --git a/src/Features/Core/Portable/ConvertAutoPropertyToFullProperty/AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs b/src/Features/Core/Portable/ConvertAutoPropertyToFullProperty/AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs index e62b1a4ff2da6..6f62db9b11fc8 100644 --- a/src/Features/Core/Portable/ConvertAutoPropertyToFullProperty/AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertAutoPropertyToFullProperty/AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -22,7 +23,7 @@ internal abstract class AbstractConvertAutoPropertyToFullPropertyCodeRefactoring where TTypeDeclarationNode : SyntaxNode where TCodeGenerationContextInfo : CodeGenerationContextInfo { - internal abstract Task GetFieldNameAsync(Document document, IPropertySymbol propertySymbol, CancellationToken cancellationToken); + internal abstract Task GetFieldNameAsync(Document document, IPropertySymbol propertySymbol, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken); internal abstract (SyntaxNode newGetAccessor, SyntaxNode newSetAccessor) GetNewAccessors( TCodeGenerationContextInfo info, SyntaxNode property, string fieldName, SyntaxGenerator generator); internal abstract SyntaxNode GetPropertyWithoutInitializer(SyntaxNode property); @@ -98,7 +99,7 @@ private async Task ExpandToFullPropertyAsync( // Create full property. If the auto property had an initial value // we need to remove it and later add it to the backing field - var fieldName = await GetFieldNameAsync(document, propertySymbol, cancellationToken).ConfigureAwait(false); + var fieldName = await GetFieldNameAsync(document, propertySymbol, fallbackOptions, cancellationToken).ConfigureAwait(false); var (newGetAccessor, newSetAccessor) = GetNewAccessors(info, property, fieldName, generator); var fullProperty = generator .WithAccessorDeclarations( diff --git a/src/Features/Core/Portable/ConvertForEachToFor/AbstractConvertForEachToForCodeRefactoringProvider.cs b/src/Features/Core/Portable/ConvertForEachToFor/AbstractConvertForEachToForCodeRefactoringProvider.cs index 53ce1b98fb5d7..144462a133bbd 100644 --- a/src/Features/Core/Portable/ConvertForEachToFor/AbstractConvertForEachToForCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertForEachToFor/AbstractConvertForEachToForCodeRefactoringProvider.cs @@ -68,7 +68,6 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticFact = document.GetRequiredLanguageService(); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var foreachInfo = GetForeachInfo(semanticFact, model, foreachStatement, cancellationToken); if (foreachInfo == null || !ValidLocation(foreachInfo)) { diff --git a/src/Features/Core/Portable/ConvertForToForEach/AbstractConvertForToForEachCodeRefactoringProvider.cs b/src/Features/Core/Portable/ConvertForToForEach/AbstractConvertForToForEachCodeRefactoringProvider.cs index 84360293befc9..31fa13385caed 100644 --- a/src/Features/Core/Portable/ConvertForToForEach/AbstractConvertForToForEachCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertForToForEach/AbstractConvertForToForEachCodeRefactoringProvider.cs @@ -47,7 +47,7 @@ protected abstract bool TryGetForStatementComponents( protected abstract SyntaxNode ConvertForNode( TForStatementSyntax currentFor, TTypeNode? typeNode, SyntaxToken foreachIdentifier, - TExpressionSyntax collectionExpression, ITypeSymbol iterationVariableType, OptionSet options); + TExpressionSyntax collectionExpression, ITypeSymbol iterationVariableType); public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { @@ -350,12 +350,11 @@ private async Task ConvertForToForEachAsync( SyntaxGenerator.DefaultRemoveOptions | SyntaxRemoveOptions.KeepLeadingTrivia); } - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); editor.ReplaceNode( forStatement, (currentFor, _) => ConvertForNode( (TForStatementSyntax)currentFor, typeNode, foreachIdentifier, - collectionExpression, iterationType, options)); + collectionExpression, iterationType)); return document.WithSyntaxRoot(editor.GetChangedRoot()); diff --git a/src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs b/src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs index 19b4bec1073bf..84adcc67a4516 100644 --- a/src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs @@ -284,7 +284,7 @@ private async Task ConvertToStructInCurrentProcessAsync( // (and importantly not any of the documents where we change the call sites, below) // For records we don't use this however, but rather leave the parameters exactly as the tuple elements // were defined, since they function as both the parameters and the property names. - var parameterNamingRule = await document.GetApplicableNamingRuleAsync(SymbolKind.Parameter, Accessibility.NotApplicable, cancellationToken).ConfigureAwait(false); + var parameterNamingRule = await document.GetApplicableNamingRuleAsync(SymbolKind.Parameter, Accessibility.NotApplicable, fallbackOptions, cancellationToken).ConfigureAwait(false); // Next, generate the full struct that will be used to replace all instances of this // tuple type. diff --git a/src/Features/Core/Portable/Diagnostics/AnalyzerOptionsExtensions.cs b/src/Features/Core/Portable/Diagnostics/AnalyzerOptionsExtensions.cs deleted file mode 100644 index 4c2a177ec5ca2..0000000000000 --- a/src/Features/Core/Portable/Diagnostics/AnalyzerOptionsExtensions.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Options; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.Diagnostics -{ - internal static partial class AnalyzerOptionsExtensions - { - public static OptionSet GetAnalyzerOptionSet(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - var optionSetAsync = GetAnalyzerOptionSetAsync(analyzerOptions, syntaxTree, cancellationToken); - if (optionSetAsync.IsCompleted) - return optionSetAsync.Result; - - return optionSetAsync.AsTask().GetAwaiter().GetResult(); - } - - public static async ValueTask GetAnalyzerOptionSetAsync(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - var configOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); -#pragma warning disable CS0612 // Type or member is obsolete - var optionSet = await GetDocumentOptionSetAsync(analyzerOptions, syntaxTree, cancellationToken).ConfigureAwait(false); -#pragma warning restore CS0612 // Type or member is obsolete - - return new AnalyzerConfigOptionSet(configOptions, optionSet); - } - - public static T GetOption(this AnalyzerOptions analyzerOptions, ILanguageSpecificOption option, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - var optionAsync = GetOptionAsync(analyzerOptions, option, language: null, syntaxTree, cancellationToken); - if (optionAsync.IsCompleted) - return optionAsync.Result; - - return optionAsync.AsTask().GetAwaiter().GetResult(); - } - - public static T GetOption(this AnalyzerOptions analyzerOptions, IPerLanguageOption option, string? language, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - var optionAsync = GetOptionAsync(analyzerOptions, option, language, syntaxTree, cancellationToken); - if (optionAsync.IsCompleted) - return optionAsync.Result; - - return optionAsync.AsTask().GetAwaiter().GetResult(); - } - - public static async ValueTask GetOptionAsync(this AnalyzerOptions analyzerOptions, IOption option, string? language, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - if (analyzerOptions.TryGetEditorConfigOption(option, syntaxTree, out var value)) - { - return value; - } - -#pragma warning disable CS0612 // Type or member is obsolete - var optionSet = await analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).ConfigureAwait(false); -#pragma warning restore CS0612 // Type or member is obsolete - - if (optionSet != null) - { - value = optionSet.GetOption(new OptionKey(option, language)); - } - - return value ?? (T)option.DefaultValue!; - } - - [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/23582", OftenCompletesSynchronously = true)] - public static ValueTask GetDocumentOptionSetAsync(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - if (analyzerOptions is not WorkspaceAnalyzerOptions workspaceAnalyzerOptions) - { - return ValueTaskFactory.FromResult((OptionSet?)null); - } - - return workspaceAnalyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken); - } - } -} diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticOptions.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticOptions.cs index 7dc0d10d79f35..1422e927ed734 100644 --- a/src/Features/Core/Portable/Diagnostics/DiagnosticOptions.cs +++ b/src/Features/Core/Portable/Diagnostics/DiagnosticOptions.cs @@ -11,8 +11,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics { - [ExportSolutionOptionProvider, Shared] - internal sealed class DiagnosticOptions : IOptionProvider + internal sealed class DiagnosticOptions { private const string FeatureName = "DiagnosticOptions"; @@ -23,15 +22,5 @@ internal sealed class DiagnosticOptions : IOptionProvider public static readonly Option2 LogTelemetryForBackgroundAnalyzerExecution = new( FeatureName, nameof(LogTelemetryForBackgroundAnalyzerExecution), defaultValue: false, new FeatureFlagStorageLocation($"Roslyn.LogTelemetryForBackgroundAnalyzerExecution")); - - public ImmutableArray Options { get; } = ImmutableArray.Create( - LspPullDiagnosticsFeatureFlag, - LogTelemetryForBackgroundAnalyzerExecution); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public DiagnosticOptions() - { - } } } diff --git a/src/Features/Core/Portable/DocumentHighlighting/HighlightingOptions.cs b/src/Features/Core/Portable/DocumentHighlighting/HighlightingOptions.cs index a5c6bee28db66..867e8dbca91ff 100644 --- a/src/Features/Core/Portable/DocumentHighlighting/HighlightingOptions.cs +++ b/src/Features/Core/Portable/DocumentHighlighting/HighlightingOptions.cs @@ -7,12 +7,12 @@ namespace Microsoft.CodeAnalysis.DocumentHighlighting; [DataContract] -internal readonly record struct HighlightingOptions( - [property: DataMember(Order = 0)] bool HighlightRelatedRegexComponentsUnderCursor = true, - [property: DataMember(Order = 1)] bool HighlightRelatedJsonComponentsUnderCursor = true) +internal readonly record struct HighlightingOptions { + [DataMember] public bool HighlightRelatedRegexComponentsUnderCursor { get; init; } = true; + [DataMember] public bool HighlightRelatedJsonComponentsUnderCursor { get; init; } = true; + public HighlightingOptions() - : this(HighlightRelatedRegexComponentsUnderCursor: true) { } diff --git a/src/Features/Core/Portable/DocumentationComments/DocumentationCommentOptions.cs b/src/Features/Core/Portable/DocumentationComments/DocumentationCommentOptions.cs index e29ba4043d6f9..d2d145e439d65 100644 --- a/src/Features/Core/Portable/DocumentationComments/DocumentationCommentOptions.cs +++ b/src/Features/Core/Portable/DocumentationComments/DocumentationCommentOptions.cs @@ -3,12 +3,23 @@ // See the LICENSE file in the project root for more information. using System.Runtime.Serialization; +using Microsoft.CodeAnalysis.Formatting; namespace Microsoft.CodeAnalysis.DocumentationComments; [DataContract] -internal readonly record struct DocumentationCommentOptions( - [property: DataMember(Order = 0)] bool AutoXmlDocCommentGeneration, - [property: DataMember(Order = 1)] int TabSize, - [property: DataMember(Order = 2)] bool UseTabs, - [property: DataMember(Order = 3)] string NewLine); +internal readonly record struct DocumentationCommentOptions +{ + public static readonly DocumentationCommentOptions Default = new(); + + [DataMember] public LineFormattingOptions LineFormatting { get; init; } = LineFormattingOptions.Default; + [DataMember] public bool AutoXmlDocCommentGeneration { get; init; } = true; + + public DocumentationCommentOptions() + { + } + + public bool UseTabs => LineFormatting.UseTabs; + public int TabSize => LineFormatting.TabSize; + public string NewLine => LineFormatting.NewLine; +} diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDetectionAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDetectionAnalyzer.cs index 6e7401e66f657..e8b43d92325da 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDetectionAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDetectionAnalyzer.cs @@ -50,7 +50,7 @@ public void Analyze(SemanticModelAnalysisContext context) var syntaxTree = semanticModel.SyntaxTree; var cancellationToken = context.CancellationToken; - if (!context.Options.GetIdeOptions().DetectAndOfferEditorFeaturesForProbableJsonStrings) + if (!context.GetIdeAnalyzerOptions().DetectAndOfferEditorFeaturesForProbableJsonStrings) return; var detector = JsonLanguageDetector.GetOrCreate(semanticModel.Compilation, _info); diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDiagnosticAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDiagnosticAnalyzer.cs index 7c3196334f009..ba5902fcdaa03 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonDiagnosticAnalyzer.cs @@ -44,7 +44,7 @@ public void Analyze(SemanticModelAnalysisContext context) var syntaxTree = semanticModel.SyntaxTree; var cancellationToken = context.CancellationToken; - var option = context.Options.GetIdeOptions().ReportInvalidJsonPatterns; + var option = context.GetIdeAnalyzerOptions().ReportInvalidJsonPatterns; if (!option) return; diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs index 813b75b6aa458..2e2a2deaf4fae 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDiagnosticAnalyzer.cs @@ -43,7 +43,7 @@ public void Analyze(SemanticModelAnalysisContext context) var syntaxTree = semanticModel.SyntaxTree; var cancellationToken = context.CancellationToken; - var option = context.Options.GetIdeOptions().ReportInvalidRegexPatterns; + var option = context.GetIdeAnalyzerOptions().ReportInvalidRegexPatterns; if (!option) return; diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/IUnitTestingSolutionCrawlerRegistrationServiceAccessor.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/IUnitTestingSolutionCrawlerRegistrationServiceAccessor.cs deleted file mode 100644 index 585489b622fda..0000000000000 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/API/IUnitTestingSolutionCrawlerRegistrationServiceAccessor.cs +++ /dev/null @@ -1,20 +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. - -#nullable disable - -using System; -using System.Collections.Generic; -using Microsoft.CodeAnalysis.Host; - -namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api -{ - [Obsolete] - internal interface IUnitTestingSolutionCrawlerServiceAccessor : IWorkspaceService - { - void Reanalyze(Workspace workspace, IEnumerable projectIds = null, IEnumerable documentIds = null, bool highPriority = false); - - void AddAnalyzerProvider(IUnitTestingIncrementalAnalyzerProviderImplementation provider, UnitTestingIncrementalAnalyzerProviderMetadataWrapper metadata); - } -} diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessor.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessor.cs deleted file mode 100644 index 7de58bc2714ef..0000000000000 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessor.cs +++ /dev/null @@ -1,70 +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. - -#nullable disable - -using System; -using System.Collections.Generic; -using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.SolutionCrawler; - -namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting -{ - [Obsolete] - internal sealed class UnitTestingSolutionCrawlerServiceAccessor : IUnitTestingSolutionCrawlerServiceAccessor - { - private readonly ISolutionCrawlerRegistrationService _registrationService; - private readonly ISolutionCrawlerService _solutionCrawlerService; - private readonly IGlobalOptionService _globalOptions; - - private UnitTestingIncrementalAnalyzerProvider _analyzerProvider; - - [Obsolete(MefConstruction.FactoryMethodMessage, error: true)] - public UnitTestingSolutionCrawlerServiceAccessor( - ISolutionCrawlerRegistrationService registrationService, - ISolutionCrawlerService solutionCrawlerService, - IGlobalOptionService globalOptions) - { - _registrationService = registrationService; - _solutionCrawlerService = solutionCrawlerService; - _globalOptions = globalOptions; - } - - public void AddAnalyzerProvider(IUnitTestingIncrementalAnalyzerProviderImplementation provider, UnitTestingIncrementalAnalyzerProviderMetadataWrapper metadata) - { - if (_analyzerProvider != null) - { - // NOTE: We expect the analyzer to be a singleton, therefore this method should be called just once. - throw new InvalidOperationException(); - } - - _analyzerProvider = new UnitTestingIncrementalAnalyzerProvider(provider); - _registrationService.AddAnalyzerProvider(_analyzerProvider, metadata.UnderlyingObject); - } - - // NOTE: For the Reanalyze method to work correctly, the analyzer passed into the Reanalyze method, - // must be the same as created when we call the AddAnalyzerProvider method. - // As such the analyzer provider instance caches a single instance of the analyzer. - public void Reanalyze(Workspace workspace, IEnumerable projectIds = null, IEnumerable documentIds = null, bool highPriority = false) - { - // NOTE: this method must be called after AddAnalyzerProvider was called previously. - if (_analyzerProvider == null) - { - throw new InvalidOperationException(); - } - - _solutionCrawlerService.Reanalyze(workspace, _analyzerProvider.CreateIncrementalAnalyzer(workspace), projectIds, documentIds, highPriority); - } - - public void Register(Workspace workspace) - { - if (_globalOptions.GetOption(SolutionCrawlerRegistrationService.EnableSolutionCrawler)) - { - _registrationService.Register(workspace); - } - } - } -} diff --git a/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessorFactory.cs b/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessorFactory.cs deleted file mode 100644 index d9d39d1e51b9f..0000000000000 --- a/src/Features/Core/Portable/ExternalAccess/UnitTesting/UnitTestingSolutionCrawlerServiceAccessorFactory.cs +++ /dev/null @@ -1,39 +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. - -#nullable disable - -using System; -using System.Composition; -using Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.SolutionCrawler; - -namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting -{ - [Obsolete] - [ExportWorkspaceServiceFactory(typeof(IUnitTestingSolutionCrawlerServiceAccessor))] - [Shared] - internal sealed class UnitTestingSolutionCrawlerServiceAccessorFactory : IWorkspaceServiceFactory - { - private readonly IGlobalOptionService _globalOptions; - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public UnitTestingSolutionCrawlerServiceAccessorFactory(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - - [Obsolete(MefConstruction.FactoryMethodMessage, error: true)] - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - { - var solutionCrawlerRegistrationService = workspaceServices.GetRequiredService(); - var solutionCrawlerService = workspaceServices.GetRequiredService(); - return new UnitTestingSolutionCrawlerServiceAccessor(solutionCrawlerRegistrationService, solutionCrawlerService, _globalOptions); - } - } -} diff --git a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs index d81aee62cc072..4b02de155e62f 100644 --- a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs +++ b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs @@ -48,7 +48,7 @@ protected abstract Task UpdateMembersWithExplicitImplementationsAsync( internal abstract bool ShouldIncludeAccessibilityModifier(SyntaxNode typeNode); - public async Task> GetExtractInterfaceCodeActionAsync(Document document, TextSpan span, CodeCleanupOptionsProvider fallbackOptions, CancellationToken cancellationToken) + public async Task> GetExtractInterfaceCodeActionAsync(Document document, TextSpan span, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var typeAnalysisResult = await AnalyzeTypeAtPositionAsync(document, span.Start, TypeDiscoveryRule.TypeNameOnly, fallbackOptions, cancellationToken).ConfigureAwait(false); @@ -84,7 +84,7 @@ public async Task AnalyzeTypeAtPositionAsync Document document, int position, TypeDiscoveryRule typeDiscoveryRule, - CodeCleanupOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var typeNode = await GetTypeDeclarationAsync(document, position, typeDiscoveryRule, cancellationToken).ConfigureAwait(false); @@ -265,7 +265,7 @@ internal static async Task GetExtractInterfaceOpt INamedTypeSymbol type, IEnumerable extractableMembers, string containingNamespace, - CodeCleanupOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var conflictingTypeNames = type.ContainingNamespace.GetAllTypes(cancellationToken).Select(t => t.Name); @@ -286,6 +286,7 @@ internal static async Task GetExtractInterfaceOpt containingNamespace, generatedNameTypeParameterSuffix, document.Project.Language, + fallbackOptions, cancellationToken).ConfigureAwait(false); } diff --git a/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceTypeAnalysisResult.cs b/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceTypeAnalysisResult.cs index f6c2879e042f7..f23667c0e35f2 100644 --- a/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceTypeAnalysisResult.cs +++ b/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceTypeAnalysisResult.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeGeneration; namespace Microsoft.CodeAnalysis.ExtractInterface { @@ -16,7 +17,7 @@ internal sealed class ExtractInterfaceTypeAnalysisResult public readonly SyntaxNode TypeNode; public readonly INamedTypeSymbol TypeToExtractFrom; public readonly IEnumerable ExtractableMembers; - public readonly CodeCleanupOptionsProvider FallbackOptions; + public readonly CleanCodeGenerationOptionsProvider FallbackOptions; public readonly string ErrorMessage; public ExtractInterfaceTypeAnalysisResult( @@ -24,7 +25,7 @@ public ExtractInterfaceTypeAnalysisResult( SyntaxNode typeNode, INamedTypeSymbol typeToExtractFrom, IEnumerable extractableMembers, - CodeCleanupOptionsProvider fallbackOptions) + CleanCodeGenerationOptionsProvider fallbackOptions) { CanExtractInterface = true; DocumentToExtractFrom = documentToExtractFrom; diff --git a/src/Features/Core/Portable/ExtractInterface/IExtractInterfaceOptionsService.cs b/src/Features/Core/Portable/ExtractInterface/IExtractInterfaceOptionsService.cs index 025edd6135834..01cb1c345bd04 100644 --- a/src/Features/Core/Portable/ExtractInterface/IExtractInterfaceOptionsService.cs +++ b/src/Features/Core/Portable/ExtractInterface/IExtractInterfaceOptionsService.cs @@ -7,6 +7,8 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Notification; @@ -24,6 +26,7 @@ Task GetExtractInterfaceOptionsAsync( string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs b/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs index 3bca31182a429..a4b6851e90720 100644 --- a/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs +++ b/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs @@ -11,12 +11,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.ExtractMethod @@ -39,10 +37,9 @@ protected abstract partial class CodeGenerator PreserveTriviaAsync(SelectionResult selectionResult, CancellationToken cancellationToken); protected abstract Task ExpandAsync(SelectionResult selection, CancellationToken cancellationToken); - protected abstract Task GenerateCodeAsync(InsertionPoint insertionPoint, SelectionResult selectionResult, AnalyzerResult analyzeResult, CodeGenerationOptions options, NamingStylePreferencesProvider namingPreferences, CancellationToken cancellationToken); + protected abstract Task GenerateCodeAsync(InsertionPoint insertionPoint, SelectionResult selectionResult, AnalyzerResult analyzeResult, CodeGenerationOptions options, CancellationToken cancellationToken); protected abstract SyntaxToken GetMethodNameAtInvocation(IEnumerable methodNames); protected abstract ImmutableArray GetCustomFormattingRules(Document document); @@ -77,7 +75,6 @@ public async Task ExtractMethodAsync(CancellationToken canc OriginalSelectionResult.With(expandedDocument), analyzeResult.With(expandedDocument), Options.CodeGenerationOptions, - Options.NamingPreferences, cancellationToken).ConfigureAwait(false); var applied = await triviaResult.ApplyAsync(generatedCode, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.ConstructorDelegatingCodeAction.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.ConstructorDelegatingCodeAction.cs index 27887169d59d8..74980c692d0d7 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.ConstructorDelegatingCodeAction.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.ConstructorDelegatingCodeAction.cs @@ -18,20 +18,20 @@ namespace Microsoft.CodeAnalysis.GenerateConstructorFromMembers { internal abstract partial class AbstractGenerateConstructorFromMembersCodeRefactoringProvider { - private class ConstructorDelegatingCodeAction : CodeAction + private sealed class ConstructorDelegatingCodeAction : CodeAction { private readonly AbstractGenerateConstructorFromMembersCodeRefactoringProvider _service; private readonly Document _document; private readonly State _state; private readonly bool _addNullChecks; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; public ConstructorDelegatingCodeAction( AbstractGenerateConstructorFromMembersCodeRefactoringProvider service, Document document, State state, bool addNullChecks, - CodeAndImportGenerationOptionsProvider fallbackOptions) + CleanCodeGenerationOptionsProvider fallbackOptions) { _service = service; _document = document; @@ -62,8 +62,7 @@ protected override async Task GetChangedDocumentAsync(CancellationToke using var _1 = ArrayBuilder.GetInstance(out var nullCheckStatements); using var _2 = ArrayBuilder.GetInstance(out var assignStatements); - var options = await _document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var useThrowExpressions = _service.PrefersThrowExpression(options); + var useThrowExpressions = await _service.PrefersThrowExpressionAsync(_document, _fallbackOptions, cancellationToken).ConfigureAwait(false); for (var i = _state.DelegatedConstructor.Parameters.Length; i < _state.Parameters.Length; i++) { diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.FieldDelegatingCodeAction.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.FieldDelegatingCodeAction.cs index 38240d68d50bc..c6373eeb51a88 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.FieldDelegatingCodeAction.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.FieldDelegatingCodeAction.cs @@ -21,14 +21,14 @@ private sealed class FieldDelegatingCodeAction : CodeAction private readonly Document _document; private readonly State _state; private readonly bool _addNullChecks; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; public FieldDelegatingCodeAction( AbstractGenerateConstructorFromMembersCodeRefactoringProvider service, Document document, State state, bool addNullChecks, - CodeAndImportGenerationOptionsProvider fallbackOptions) + CleanCodeGenerationOptionsProvider fallbackOptions) { _service = service; _document = document; @@ -53,8 +53,7 @@ protected override async Task GetChangedDocumentAsync(CancellationToke var semanticModel = await _document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; - var options = await _document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var preferThrowExpression = _service.PrefersThrowExpression(options); + var preferThrowExpression = await _service.PrefersThrowExpressionAsync(_document, _fallbackOptions, cancellationToken).ConfigureAwait(false); var members = factory.CreateMemberDelegatingConstructor( semanticModel, diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.GenerateConstructorWithDialogCodeAction.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.GenerateConstructorWithDialogCodeAction.cs index b5fc10b9f221e..ab6876731adfc 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.GenerateConstructorWithDialogCodeAction.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.GenerateConstructorWithDialogCodeAction.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.GenerateFromMembers; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PickMembers; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -26,8 +27,7 @@ private class GenerateConstructorWithDialogCodeAction : CodeActionWithOptions private readonly Accessibility? _desiredAccessibility; private readonly AbstractGenerateConstructorFromMembersCodeRefactoringProvider _service; private readonly TextSpan _textSpan; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; - private bool? _addNullCheckOptionValue; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; internal ImmutableArray ViableMembers { get; } internal ImmutableArray PickMembersOptions { get; } @@ -42,7 +42,7 @@ public GenerateConstructorWithDialogCodeAction( Accessibility? desiredAccessibility, ImmutableArray viableMembers, ImmutableArray pickMembersOptions, - CodeAndImportGenerationOptionsProvider fallbackOptions) + CleanCodeGenerationOptionsProvider fallbackOptions) { _service = service; _document = document; @@ -79,13 +79,14 @@ protected override async Task> ComputeOperation // If we presented the 'Add null check' option, then persist whatever value // the user chose. That way we'll keep that as the default for the next time // the user opens the dialog. - _addNullCheckOptionValue = addNullChecksOption.Value; + var globalOptions = _document.Project.Solution.Workspace.Services.GetRequiredService(); + globalOptions.SetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(_document.Project.Language, addNullChecksOption.Value); } var addNullChecks = (addNullChecksOption?.Value ?? false); var state = await State.TryGenerateAsync( _service, _document, _textSpan, _containingType, _desiredAccessibility, - result.Members, cancellationToken).ConfigureAwait(false); + result.Members, _fallbackOptions, cancellationToken).ConfigureAwait(false); if (state == null) { @@ -119,21 +120,6 @@ protected override async Task> ComputeOperation return await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false); } } - - protected override async Task GetChangedSolutionAsync(CancellationToken cancellationToken) - { - var solution = await base.GetChangedSolutionAsync(cancellationToken).ConfigureAwait(false); - - if (_addNullCheckOptionValue.HasValue) - { - solution = solution?.WithOptions(solution.Options.WithChangedOption( - GenerateConstructorFromMembersOptions.AddNullChecks, - _document.Project.Language, - _addNullCheckOptionValue.Value)); - } - - return solution; - } } } } diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.State.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.State.cs index 058df987d2470..5339f8858b1dd 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.State.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.State.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -35,10 +36,11 @@ private class State INamedTypeSymbol containingType, Accessibility? desiredAccessibility, ImmutableArray selectedMembers, + NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { var state = new State(); - if (!await state.TryInitializeAsync(service, document, textSpan, containingType, desiredAccessibility, selectedMembers, cancellationToken).ConfigureAwait(false)) + if (!await state.TryInitializeAsync(service, document, textSpan, containingType, desiredAccessibility, selectedMembers, fallbackOptions, cancellationToken).ConfigureAwait(false)) { return null; } @@ -53,6 +55,7 @@ private async Task TryInitializeAsync( INamedTypeSymbol containingType, Accessibility? desiredAccessibility, ImmutableArray selectedMembers, + NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { if (!selectedMembers.All(IsWritableInstanceFieldOrProperty)) @@ -71,7 +74,7 @@ private async Task TryInitializeAsync( IsContainedInUnsafeType = service.ContainingTypesOrSelfHasUnsafeKeyword(containingType); - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); Parameters = DetermineParameters(selectedMembers, rules); MatchingConstructor = GetMatchingConstructorBasedOnParameterTypes(ContainingType, Parameters); // We are going to create a new contructor and pass part of the parameters into DelegatedConstructor, diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.cs index d2233dee59288..508e3ceff4677 100644 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/GenerateConstructorFromMembers/AbstractGenerateConstructorFromMembersCodeRefactoringProvider.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.PickMembers; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -55,7 +56,7 @@ protected AbstractGenerateConstructorFromMembersCodeRefactoringProvider(IPickMem protected abstract bool ContainingTypesOrSelfHasUnsafeKeyword(INamedTypeSymbol containingType); protected abstract string ToDisplayString(IParameterSymbol parameter, SymbolDisplayFormat format); - protected abstract bool PrefersThrowExpression(DocumentOptionSet options); + protected abstract ValueTask PrefersThrowExpressionAsync(Document document, SimplifierOptionsProvider fallbackOptions, CancellationToken cancellationToken); public override Task ComputeRefactoringsAsync(CodeRefactoringContext context) { @@ -139,7 +140,7 @@ private async Task ComputeRefactoringsAsync( Action registerSingleAction, Action> registerMultipleActions, Accessibility? desiredAccessibility, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) @@ -168,7 +169,7 @@ private async Task ComputeRefactoringsAsync( Document document, TextSpan textSpan, Accessibility? desiredAccessibility, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var helpers = document.GetRequiredLanguageService(); @@ -221,8 +222,8 @@ private async Task ComputeRefactoringsAsync( if (canAddNullCheck) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var optionValue = options.GetOption(GenerateConstructorFromMembersOptions.AddNullChecks); + var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService(); + var optionValue = globalOptions.GetGenerateConstructorFromMembersOptionsAddNullChecks(document.Project.Language); pickMemberOptions.Add(new PickMembersOption( AddNullChecksId, @@ -236,14 +237,14 @@ private async Task ComputeRefactoringsAsync( } public async Task> GenerateConstructorFromMembersAsync( - Document document, TextSpan textSpan, bool addNullChecks, Accessibility? desiredAccessibility, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) + Document document, TextSpan textSpan, bool addNullChecks, Accessibility? desiredAccessibility, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Refactoring_GenerateFromMembers_GenerateConstructorFromMembers, cancellationToken)) { var info = await GetSelectedMemberInfoAsync(document, textSpan, allowPartialSelection: true, cancellationToken).ConfigureAwait(false); if (info != null) { - var state = await State.TryGenerateAsync(this, document, textSpan, info.ContainingType, desiredAccessibility, info.SelectedMembers, cancellationToken).ConfigureAwait(false); + var state = await State.TryGenerateAsync(this, document, textSpan, info.ContainingType, desiredAccessibility, info.SelectedMembers, fallbackOptions, cancellationToken).ConfigureAwait(false); if (state != null && state.MatchingConstructor == null) { return GetCodeActions(document, state, addNullChecks, fallbackOptions); @@ -254,7 +255,7 @@ public async Task> GenerateConstructorFromMembersAsyn } } - private ImmutableArray GetCodeActions(Document document, State state, bool addNullChecks, CodeAndImportGenerationOptionsProvider fallbackOptions) + private ImmutableArray GetCodeActions(Document document, State state, bool addNullChecks, CleanCodeGenerationOptionsProvider fallbackOptions) { using var _ = ArrayBuilder.GetInstance(out var result); diff --git a/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersOptions.cs b/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersOptions.cs deleted file mode 100644 index 71b86839fe97b..0000000000000 --- a/src/Features/Core/Portable/GenerateConstructorFromMembers/GenerateConstructorFromMembersOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.GenerateConstructorFromMembers -{ - internal static class GenerateConstructorFromMembersOptions - { - public static readonly PerLanguageOption2 AddNullChecks = new( - nameof(GenerateConstructorFromMembersOptions), - nameof(AddNullChecks), defaultValue: false, - storageLocation: new RoamingProfileStorageLocation( - $"TextEditor.%LANGUAGE%.Specific.{nameof(GenerateConstructorFromMembersOptions)}.{nameof(AddNullChecks)}")); - } -} diff --git a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeAction.cs b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeAction.cs index 4562c81084fcb..790575149aa6c 100644 --- a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeAction.cs +++ b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeAction.cs @@ -135,9 +135,7 @@ private async Task UpdateDocumentAndAddImportsAsync(SyntaxNode oldType { var oldRoot = await _document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newDocument = _document.WithSyntaxRoot(oldRoot.ReplaceNode(oldType, newType)); - - // fallback options: https://github.com/dotnet/roslyn/issues/60794 - var addImportOptions = await _document.GetAddImportPlacementOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var addImportOptions = await _document.GetAddImportPlacementOptionsAsync(_fallbackOptions, cancellationToken).ConfigureAwait(false); newDocument = await ImportAdder.AddImportsFromSymbolAnnotationAsync(newDocument, addImportOptions, cancellationToken).ConfigureAwait(false); return newDocument; diff --git a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs index 04b50bc7ec963..2380d81fe6903 100644 --- a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PickMembers; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -253,13 +254,13 @@ private async Task CreateCodeActionWithDialogAsync( bool generateEquals, bool generateGetHashCode, CancellationToken cancellationToken) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); using var _ = ArrayBuilder.GetInstance(out var pickMembersOptions); if (CanImplementIEquatable(semanticModel, containingType, out var equatableTypeOpt)) { - var value = options.GetOption(GenerateEqualsAndGetHashCodeFromMembersOptions.ImplementIEquatable); + var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService(); + var value = globalOptions.GetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(document.Project.Language); var displayName = equatableTypeOpt.ToDisplayString(new SymbolDisplayFormat( typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly, @@ -273,7 +274,9 @@ private async Task CreateCodeActionWithDialogAsync( if (!HasOperators(containingType)) { - var value = options.GetOption(GenerateEqualsAndGetHashCodeFromMembersOptions.GenerateOperators); + var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService(); + var value = globalOptions.GetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(document.Project.Language); + pickMembersOptions.Add(new PickMembersOption( GenerateOperatorsId, FeaturesResources.Generate_operators, diff --git a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersOptions.cs b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersOptions.cs deleted file mode 100644 index 83db4893e6937..0000000000000 --- a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndGetHashCodeFromMembersOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers -{ - internal static class GenerateEqualsAndGetHashCodeFromMembersOptions - { - public static readonly PerLanguageOption2 GenerateOperators = new( - nameof(GenerateEqualsAndGetHashCodeFromMembersOptions), - nameof(GenerateOperators), defaultValue: false, - storageLocation: new RoamingProfileStorageLocation( - $"TextEditor.%LANGUAGE%.Specific.{nameof(GenerateEqualsAndGetHashCodeFromMembersOptions)}.{nameof(GenerateOperators)}")); - - public static readonly PerLanguageOption2 ImplementIEquatable = new( - nameof(GenerateEqualsAndGetHashCodeFromMembersOptions), - nameof(ImplementIEquatable), defaultValue: false, - storageLocation: new RoamingProfileStorageLocation( - $"TextEditor.%LANGUAGE%.Specific.{nameof(GenerateEqualsAndGetHashCodeFromMembersOptions)}.{nameof(ImplementIEquatable)}")); - } -} diff --git a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndHashWithDialogCodeAction.cs b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndHashWithDialogCodeAction.cs index 679fb5d5da50c..10f96c842ec61 100644 --- a/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndHashWithDialogCodeAction.cs +++ b/src/Features/Core/Portable/GenerateEqualsAndGetHashCodeFromMembers/GenerateEqualsAndHashWithDialogCodeAction.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PickMembers; using Roslyn.Utilities; @@ -27,8 +28,6 @@ private class GenerateEqualsAndGetHashCodeWithDialogCodeAction : CodeActionWithO private readonly ImmutableArray _viableMembers; private readonly ImmutableArray _pickMembersOptions; private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; - private bool? _implementIEqutableOptionValue; - private bool? _generateOperatorsOptionValue; public GenerateEqualsAndGetHashCodeWithDialogCodeAction( GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider service, @@ -70,22 +69,27 @@ protected override async Task> ComputeOperation } // If we presented the user any options, then persist whatever values - // the user chose. That way we'll keep that as the default for the + // the user chose to the global options. That way we'll keep that as the default for the // next time the user opens the dialog. var implementIEqutableOption = result.Options.FirstOrDefault(o => o.Id == ImplementIEquatableId); - if (implementIEqutableOption != null) - { - _implementIEqutableOptionValue = implementIEqutableOption.Value; - } - var generateOperatorsOption = result.Options.FirstOrDefault(o => o.Id == GenerateOperatorsId); - if (generateOperatorsOption != null) + if (generateOperatorsOption != null || implementIEqutableOption != null) { - _generateOperatorsOptionValue = generateOperatorsOption.Value; + var globalOptions = _document.Project.Solution.Workspace.Services.GetRequiredService(); + + if (generateOperatorsOption != null) + { + globalOptions.SetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(_document.Project.Language, generateOperatorsOption.Value); + } + + if (implementIEqutableOption != null) + { + globalOptions.SetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(_document.Project.Language, implementIEqutableOption.Value); + } } - var implementIEquatable = (implementIEqutableOption?.Value ?? false); - var generatorOperators = (generateOperatorsOption?.Value ?? false); + var implementIEquatable = implementIEqutableOption?.Value ?? false; + var generatorOperators = generateOperatorsOption?.Value ?? false; var action = new GenerateEqualsAndGetHashCodeAction( _document, _typeDeclaration, _containingType, result.Members, _fallbackOptions, @@ -95,29 +99,6 @@ protected override async Task> ComputeOperation public override string Title => GenerateEqualsAndGetHashCodeAction.GetTitle(_generateEquals, _generateGetHashCode) + "..."; - - protected override async Task GetChangedSolutionAsync(CancellationToken cancellationToken) - { - var solution = await base.GetChangedSolutionAsync(cancellationToken).ConfigureAwait(false); - - if (_implementIEqutableOptionValue.HasValue) - { - solution = solution?.WithOptions(solution.Options.WithChangedOption( - GenerateEqualsAndGetHashCodeFromMembersOptions.ImplementIEquatable, - _document.Project.Language, - _implementIEqutableOptionValue.Value)); - } - - if (_generateOperatorsOptionValue.HasValue) - { - solution = solution?.WithOptions(solution.Options.WithChangedOption( - GenerateEqualsAndGetHashCodeFromMembersOptions.GenerateOperators, - _document.Project.Language, - _generateOperatorsOptionValue.Value)); - } - - return solution; - } } } } diff --git a/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.State.cs b/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.State.cs index b9e2eed7ec695..7e8eee563164c 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.State.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateConstructor/AbstractGenerateConstructorService.State.cs @@ -75,9 +75,9 @@ private State(TService service, SemanticDocument document, NamingRule fieldNamin CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - var fieldNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Field, Accessibility.Private, cancellationToken).ConfigureAwait(false); - var propertyNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Property, Accessibility.Public, cancellationToken).ConfigureAwait(false); - var parameterNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Parameter, Accessibility.NotApplicable, cancellationToken).ConfigureAwait(false); + var fieldNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Field, Accessibility.Private, fallbackOptions, cancellationToken).ConfigureAwait(false); + var propertyNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Property, Accessibility.Public, fallbackOptions, cancellationToken).ConfigureAwait(false); + var parameterNamingRule = await document.Document.GetApplicableNamingRuleAsync(SymbolKind.Parameter, Accessibility.NotApplicable, fallbackOptions, cancellationToken).ConfigureAwait(false); var state = new State(service, document, fieldNamingRule, propertyNamingRule, parameterNamingRule, fallbackOptions); if (!await state.TryInitializeAsync(node, cancellationToken).ConfigureAwait(false)) diff --git a/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.cs b/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.cs index 378f0fe0b93a7..42a68e67158d8 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateVariable/AbstractGenerateVariableService.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.AddParameter; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -74,7 +75,7 @@ public async Task> GenerateVariableAsync( } await AddLocalCodeActionsAsync(actions, document, state, fallbackOptions, cancellationToken).ConfigureAwait(false); - await AddParameterCodeActionsAsync(actions, document, state, cancellationToken).ConfigureAwait(false); + await AddParameterCodeActionsAsync(actions, document, state, fallbackOptions, cancellationToken).ConfigureAwait(false); if (actions.Count > 1) { @@ -107,7 +108,7 @@ private static async Task AddPropertyCodeActionsAsync( // Don't generate properties with a `_` prefix unless that's what the user really wants as their naming style. if (await NameIsHighlyUnlikelyToWarrantSymbolAsync( - document.Document, state, SymbolKind.Property, state.DetermineMaximalAccessibility(), cancellationToken).ConfigureAwait(false)) + document.Document, state, SymbolKind.Property, state.DetermineMaximalAccessibility(), fallbackOptions, cancellationToken).ConfigureAwait(false)) { return; } @@ -123,13 +124,13 @@ private static async Task AddPropertyCodeActionsAsync( } private static async Task NameIsHighlyUnlikelyToWarrantSymbolAsync( - Document document, State state, SymbolKind kind, Accessibility accessibility, CancellationToken cancellationToken) + Document document, State state, SymbolKind kind, Accessibility accessibility, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { // Check If the user explicitly used _ as the start of the name they're generating. Don't offer to generate // a non-field symbol unless that's genuinely the naming style they have setup. if (state.IdentifierToken.ValueText.StartsWith("_")) { - var namingStyle = await document.GetApplicableNamingRuleAsync(kind, accessibility, cancellationToken).ConfigureAwait(false); + var namingStyle = await document.GetApplicableNamingRuleAsync(kind, accessibility, fallbackOptions, cancellationToken).ConfigureAwait(false); if (namingStyle.NamingStyle.Prefix != "_") return true; } @@ -189,7 +190,7 @@ private async Task AddLocalCodeActionsAsync( { // Don't generate locals with a `_` prefix unless that's what the user really wants as their naming style. if (await NameIsHighlyUnlikelyToWarrantSymbolAsync( - document, state, SymbolKind.Local, Accessibility.NotApplicable, cancellationToken).ConfigureAwait(false)) + document, state, SymbolKind.Local, Accessibility.NotApplicable, fallbackOptions, cancellationToken).ConfigureAwait(false)) { return; } @@ -199,13 +200,13 @@ private async Task AddLocalCodeActionsAsync( } private static async Task AddParameterCodeActionsAsync( - ArrayBuilder result, Document document, State state, CancellationToken cancellationToken) + ArrayBuilder result, Document document, State state, CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { if (state.CanGenerateParameter()) { // Don't generate parameters with a `_` prefix unless that's what the user really wants as their naming style. if (await NameIsHighlyUnlikelyToWarrantSymbolAsync( - document, state, SymbolKind.Parameter, Accessibility.NotApplicable, cancellationToken).ConfigureAwait(false)) + document, state, SymbolKind.Parameter, Accessibility.NotApplicable, fallbackOptions, cancellationToken).ConfigureAwait(false)) { return; } diff --git a/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs b/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs index fdff7c0ff852d..f7dc65e2ca56f 100644 --- a/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs +++ b/src/Features/Core/Portable/GenerateOverrides/GenerateOverridesWithDialogCodeAction.cs @@ -21,10 +21,6 @@ internal partial class GenerateOverridesCodeRefactoringProvider { private sealed class GenerateOverridesWithDialogCodeAction : CodeActionWithOptions { - public static readonly Option2 s_globalOption = new( - "GenerateOverridesOptions", "SelectAll", defaultValue: true, - storageLocation: new RoamingProfileStorageLocation($"TextEditor.Specific.GenerateOverridesOptions.SelectAll")); - private readonly GenerateOverridesCodeRefactoringProvider _service; private readonly Document _document; private readonly INamedTypeSymbol _containingType; @@ -59,7 +55,7 @@ public override object GetOptions(CancellationToken cancellationToken) return pickMembersService.PickMembers( FeaturesResources.Pick_members_to_override, _viableMembers, - selectAll: globalOptionService?.GlobalOptions.GetOption(s_globalOption) ?? s_globalOption.DefaultValue); + selectAll: globalOptionService?.GenerateOverrides ?? true); } protected override async Task> ComputeOperationsAsync(object options, CancellationToken cancellationToken) @@ -120,7 +116,10 @@ public ChangeOptionValueOperation(bool selectedAll) public override void Apply(Workspace workspace, CancellationToken cancellationToken) { var service = workspace.Services.GetService(); - service?.GlobalOptions.SetGlobalOption(new OptionKey(s_globalOption), _selectedAll); + if (service != null) + { + service.GenerateOverrides = _selectedAll; + } } } } diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs index 0f1c9ae0bffc3..1634966b324f1 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.CodeAction.cs @@ -25,13 +25,13 @@ private class GenerateTypeCodeAction : CodeAction private readonly Document _document; private readonly State _state; private readonly string _equivalenceKey; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; public GenerateTypeCodeAction( TService service, Document document, State state, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, bool intoNamespace, bool inNewFile) { @@ -85,9 +85,9 @@ private sealed class GenerateTypeCodeActionWithOption : CodeActionWithOptions private readonly TService _service; private readonly Document _document; private readonly State _state; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; - internal GenerateTypeCodeActionWithOption(TService service, Document document, State state, CodeAndImportGenerationOptionsProvider fallbackOptions) + internal GenerateTypeCodeActionWithOption(TService service, Document document, State state, CleanCodeGenerationOptionsProvider fallbackOptions) { _service = service; _document = document; diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs index acc61e80518f8..285c551d9fd3b 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.Editor.cs @@ -41,13 +41,13 @@ private partial class Editor private readonly bool _fromDialog; private readonly GenerateTypeOptionsResult _generateTypeOptionsResult; private readonly CancellationToken _cancellationToken; - private readonly CodeAndImportGenerationOptionsProvider _fallbackOptions; + private readonly CleanCodeGenerationOptionsProvider _fallbackOptions; public Editor( TService service, SemanticDocument document, State state, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, bool intoNamespace, bool inNewFile, CancellationToken cancellationToken) @@ -65,7 +65,7 @@ public Editor( TService service, SemanticDocument document, State state, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, bool fromDialog, GenerateTypeOptionsResult generateTypeOptionsResult, CancellationToken cancellationToken) @@ -320,8 +320,7 @@ private async Task> GetGenerateInNewFileOperati var formattingService = newDocument.GetLanguageService(); if (formattingService is not null) { - // TODO: fallback options: https://github.com/dotnet/roslyn/issues/60794 - var cleanupOptions = await codeGenResult.GetCodeCleanupOptionsAsync(fallbackOptions: null, _cancellationToken).ConfigureAwait(false); + var cleanupOptions = await codeGenResult.GetCodeCleanupOptionsAsync(_fallbackOptions, _cancellationToken).ConfigureAwait(false); codeGenResult = await formattingService.FormatNewDocumentAsync(codeGenResult, _semanticDocument.Document, cleanupOptions, _cancellationToken).ConfigureAwait(false); } } @@ -365,7 +364,9 @@ private async Task> CreateAddDocumentAndUpdateU // Update the Generating Document with a using if required if (includeUsingsOrImports != null) { - updatedSolution = await _service.TryAddUsingsOrImportToDocumentAsync(updatedSolution, null, _semanticDocument.Document, _state.SimpleName, includeUsingsOrImports, cancellationToken).ConfigureAwait(false); + updatedSolution = await _service.TryAddUsingsOrImportToDocumentAsync( + updatedSolution, modifiedRoot: null, _semanticDocument.Document, _state.SimpleName, + includeUsingsOrImports, _fallbackOptions, cancellationToken).ConfigureAwait(false); } // Add reference of the updated project to the triggering Project if they are 2 different projects @@ -460,6 +461,7 @@ private async Task> GetGenerateIntoExistingDocu _semanticDocument.Document, _state.SimpleName, includeUsingsOrImports, + _fallbackOptions, _cancellationToken).ConfigureAwait(false); } @@ -615,7 +617,7 @@ where IsViableFieldOrProperty(parameterType, m) } } - var fieldNamingRule = await _semanticDocument.Document.GetApplicableNamingRuleAsync(SymbolKind.Field, Accessibility.Private, _cancellationToken).ConfigureAwait(false); + var fieldNamingRule = await _semanticDocument.Document.GetApplicableNamingRuleAsync(SymbolKind.Field, Accessibility.Private, _fallbackOptions, _cancellationToken).ConfigureAwait(false); var nameToUse = fieldNamingRule.NamingStyle.MakeCompliant(parameterName.NameBasedOnArgument).First(); parameterToNewFieldMap[parameterName.BestNameForParameter] = nameToUse; return false; diff --git a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs index 5a31f253b0136..597bc6ed94bac 100644 --- a/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs +++ b/src/Features/Core/Portable/GenerateType/AbstractGenerateTypeService.cs @@ -11,8 +11,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.LanguageServices.ProjectInfoService; @@ -58,7 +60,9 @@ protected AbstractGenerateTypeService() internal abstract bool IsPublicOnlyAccessibility(TExpressionSyntax expression, Project project); internal abstract bool IsGenericName(TSimpleNameSyntax simpleName); internal abstract bool IsSimpleName(TExpressionSyntax expression); - internal abstract Task TryAddUsingsOrImportToDocumentAsync(Solution updatedSolution, SyntaxNode modifiedRoot, Document document, TSimpleNameSyntax simpleName, string includeUsingsOrImports, CancellationToken cancellationToken); + + internal abstract Task TryAddUsingsOrImportToDocumentAsync( + Solution updatedSolution, SyntaxNode modifiedRoot, Document document, TSimpleNameSyntax simpleName, string includeUsingsOrImports, AddImportPlacementOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected abstract bool TryGetNameParts(TExpressionSyntax expression, out IList nameParts); @@ -69,7 +73,7 @@ protected AbstractGenerateTypeService() public async Task> GenerateTypeAsync( Document document, SyntaxNode node, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Refactoring_GenerateType, cancellationToken)) @@ -103,7 +107,7 @@ private ImmutableArray GetActions( SemanticDocument document, SyntaxNode node, State state, - CodeAndImportGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { using var _ = ArrayBuilder.GetInstance(out var result); diff --git a/src/Features/Core/Portable/GenerateType/IGenerateTypeService.cs b/src/Features/Core/Portable/GenerateType/IGenerateTypeService.cs index 9deb8e1089d37..6524f29c24d76 100644 --- a/src/Features/Core/Portable/GenerateType/IGenerateTypeService.cs +++ b/src/Features/Core/Portable/GenerateType/IGenerateTypeService.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.GenerateType { internal interface IGenerateTypeService : ILanguageService { - Task> GenerateTypeAsync(Document document, SyntaxNode node, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); + Task> GenerateTypeAsync(Document document, SyntaxNode node, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); Task<(INamespaceSymbol, INamespaceOrTypeSymbol, Location)> GetOrGenerateEnclosingNamespaceSymbolAsync(INamedTypeSymbol namedTypeSymbol, string[] containers, Document selectedDocument, SyntaxNode selectedDocumentRoot, CancellationToken cancellationToken); string GetRootNamespace(CompilationOptions options); } diff --git a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs index 17f2f09c5e0cc..74db13a35fbbe 100644 --- a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs +++ b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.DisposePatternCodeAction.cs @@ -8,10 +8,12 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; @@ -323,19 +325,39 @@ private IMethodSymbol CreateDisposeInterfaceMethod( return result; } - private static async Task CreateDisposedValueFieldAsync( + /// + /// This helper is implementing access to the editorconfig option. This would usually be done via but + /// we do not have access to here since the code action implementation is also used to implement . + /// TODO: remove - see https://github.com/dotnet/roslyn/issues/60990. + /// + public async ValueTask GetAccessibilityModifiersRequiredAsync(Document document, CancellationToken cancellationToken) + { + var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var configOptions = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); + + if (configOptions.TryGetEditorConfigOption>(CodeStyleOptions2.AccessibilityModifiersRequired, out var value)) + { + return value.Value; + } + + var fallbackFormattingOptions = await ((OptionsProvider)Options.FallbackOptions).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false); + + return fallbackFormattingOptions.AccessibilityModifiersRequired; + } + + private async Task CreateDisposedValueFieldAsync( Document document, INamedTypeSymbol containingType, CancellationToken cancellationToken) { var rule = await document.GetApplicableNamingRuleAsync( - SymbolKind.Field, Accessibility.Private, cancellationToken).ConfigureAwait(false); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var requireAccessiblity = options.GetOption(CodeStyleOptions2.RequireAccessibilityModifiers); + SymbolKind.Field, Accessibility.Private, Options.FallbackOptions, cancellationToken).ConfigureAwait(false); + + var requireAccessiblity = await GetAccessibilityModifiersRequiredAsync(document, cancellationToken).ConfigureAwait(false); var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); var boolType = compilation.GetSpecialType(SpecialType.System_Boolean); - var accessibilityLevel = requireAccessiblity.Value is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault + var accessibilityLevel = requireAccessiblity is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault ? Accessibility.NotApplicable : Accessibility.Private; diff --git a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.cs b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.cs index 0e36ab9be8275..010becc3a25c3 100644 --- a/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.cs +++ b/src/Features/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.cs @@ -47,6 +47,7 @@ public async Task ImplementInterfaceAsync(Document document, Implement return document; } + // TODO: https://github.com/dotnet/roslyn/issues/60990 // While implementing just one default action, like in the case of pressing enter after interface name in VB, // choose to implement with the dispose pattern as that's the Dev12 behavior. var action = ShouldImplementDisposePattern(state, explicitly: false) diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs index 286e2d0584a47..1f113616adba4 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs @@ -18,17 +18,19 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Collections; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.InitializeParameter { - internal abstract partial class AbstractAddParameterCheckCodeRefactoringProvider< + internal abstract class AbstractAddParameterCheckCodeRefactoringProvider< TTypeDeclarationSyntax, TParameterSyntax, TStatementSyntax, TExpressionSyntax, - TBinaryExpressionSyntax> : AbstractInitializeParameterCodeRefactoringProvider< + TBinaryExpressionSyntax, + TSimplifierOptions> : AbstractInitializeParameterCodeRefactoringProvider< TTypeDeclarationSyntax, TParameterSyntax, TStatementSyntax, @@ -38,12 +40,13 @@ internal abstract partial class AbstractAddParameterCheckCodeRefactoringProvider where TStatementSyntax : SyntaxNode where TExpressionSyntax : SyntaxNode where TBinaryExpressionSyntax : TExpressionSyntax + where TSimplifierOptions : SimplifierOptions { protected abstract bool CanOffer(SyntaxNode body); - protected abstract bool PrefersThrowExpression(DocumentOptionSet options); + protected abstract bool PrefersThrowExpression(TSimplifierOptions options); protected abstract string EscapeResourceString(string input); - protected abstract TStatementSyntax CreateParameterCheckIfStatement(DocumentOptionSet options, TExpressionSyntax condition, TStatementSyntax ifTrueStatement); - protected abstract Task TryAddNullCheckToParameterDeclarationAsync(Document document, TParameterSyntax parameterSyntax, CancellationToken cancellationToken); + protected abstract TStatementSyntax CreateParameterCheckIfStatement(TExpressionSyntax condition, TStatementSyntax ifTrueStatement, TSimplifierOptions options); + protected abstract Task TryAddNullCheckToParameterDeclarationAsync(Document document, TParameterSyntax parameterSyntax, TSimplifierOptions options, CancellationToken cancellationToken); protected override async Task> GetRefactoringsForAllParametersAsync( Document document, @@ -52,6 +55,7 @@ protected override async Task> GetRefactoringsForAllP IBlockOperation? blockStatementOpt, ImmutableArray listOfParameterNodes, TextSpan parameterSpan, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { // List to keep track of the valid parameters @@ -72,7 +76,7 @@ protected override async Task> GetRefactoringsForAllP // Great. The list has parameters that need null checks. Offer to add null checks for all. return ImmutableArray.Create(CodeAction.Create( FeaturesResources.Add_null_checks_for_all_parameters, - c => UpdateDocumentForRefactoringAsync(document, blockStatementOpt, listOfParametersOrdinals, parameterSpan, c), + c => UpdateDocumentForRefactoringAsync(document, blockStatementOpt, listOfParametersOrdinals, parameterSpan, fallbackOptions, c), nameof(FeaturesResources.Add_null_checks_for_all_parameters))); } @@ -83,7 +87,7 @@ protected override async Task> GetRefactoringsForSing SyntaxNode funcOrRecord, IMethodSymbol methodSymbol, IBlockOperation? blockStatementOpt, - CodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); @@ -92,11 +96,13 @@ protected override async Task> GetRefactoringsForSing if (!ParameterValidForNullCheck(document, parameter, semanticModel, blockStatementOpt, cancellationToken)) return ImmutableArray.Empty; + var simplifierOptions = (TSimplifierOptions)await document.GetSimplifierOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + // Great. There was no null check. Offer to add one. using var result = TemporaryArray.Empty; result.Add(CodeAction.Create( FeaturesResources.Add_null_check, - c => AddNullCheckAsync(document, parameterSyntax, parameter, funcOrRecord, methodSymbol, blockStatementOpt, c), + c => AddNullCheckAsync(document, parameterSyntax, parameter, funcOrRecord, methodSymbol, blockStatementOpt, simplifierOptions, c), nameof(FeaturesResources.Add_null_check))); // Also, if this was a string, offer to add the special checks to string.IsNullOrEmpty and @@ -106,12 +112,12 @@ protected override async Task> GetRefactoringsForSing { result.Add(CodeAction.Create( FeaturesResources.Add_string_IsNullOrEmpty_check, - c => AddStringCheckAsync(document, parameter, funcOrRecord, methodSymbol, blockStatementOpt, nameof(string.IsNullOrEmpty), c), + c => AddStringCheckAsync(document, parameter, funcOrRecord, methodSymbol, blockStatementOpt, nameof(string.IsNullOrEmpty), simplifierOptions, c), nameof(FeaturesResources.Add_string_IsNullOrEmpty_check))); result.Add(CodeAction.Create( FeaturesResources.Add_string_IsNullOrWhiteSpace_check, - c => AddStringCheckAsync(document, parameter, funcOrRecord, methodSymbol, blockStatementOpt, nameof(string.IsNullOrWhiteSpace), c), + c => AddStringCheckAsync(document, parameter, funcOrRecord, methodSymbol, blockStatementOpt, nameof(string.IsNullOrWhiteSpace), simplifierOptions, c), nameof(FeaturesResources.Add_string_IsNullOrWhiteSpace_check))); } @@ -123,8 +129,11 @@ private async Task UpdateDocumentForRefactoringAsync( IBlockOperation? blockStatementOpt, List listOfParametersOrdinals, TextSpan parameterSpan, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { + TSimplifierOptions? lazySimplifierOptions = null; + foreach (var index in listOfParametersOrdinals) { // Updates functionDeclaration and uses it to get the first valid ParameterNode using the ordinals (index). @@ -149,17 +158,19 @@ private async Task UpdateDocumentForRefactoringAsync( if (!CanOfferRefactoring(funcOrRecord, semanticModel, syntaxFacts, cancellationToken, out blockStatementOpt)) continue; + lazySimplifierOptions ??= (TSimplifierOptions)await document.GetSimplifierOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + // If parameter is a string, default check would be IsNullOrEmpty. This is because IsNullOrEmpty is more // commonly used in this regard according to telemetry and UX testing. if (parameter.Type.SpecialType == SpecialType.System_String && !IsRecordDeclaration(funcOrRecord)) { - document = await AddStringCheckAsync(document, parameter, funcOrRecord, (IMethodSymbol)parameter.ContainingSymbol, blockStatementOpt, nameof(string.IsNullOrEmpty), cancellationToken).ConfigureAwait(false); + document = await AddStringCheckAsync(document, parameter, funcOrRecord, (IMethodSymbol)parameter.ContainingSymbol, blockStatementOpt, nameof(string.IsNullOrEmpty), lazySimplifierOptions, cancellationToken).ConfigureAwait(false); continue; } // For all other parameters, add null check - updates document document = await AddNullCheckAsync(document, parameterSyntax, parameter, funcOrRecord, - (IMethodSymbol)parameter.ContainingSymbol, blockStatementOpt, cancellationToken).ConfigureAwait(false); + (IMethodSymbol)parameter.ContainingSymbol, blockStatementOpt, lazySimplifierOptions, cancellationToken).ConfigureAwait(false); } return document; @@ -330,10 +341,11 @@ private async Task AddNullCheckAsync( SyntaxNode functionDeclaration, IMethodSymbol method, IBlockOperation? blockStatementOpt, + TSimplifierOptions options, CancellationToken cancellationToken) { // First see if we can adopt the '!!' parameter null checking syntax. - var modifiedDocument = await TryAddNullCheckToParameterDeclarationAsync(document, parameterSyntax, cancellationToken).ConfigureAwait(false); + var modifiedDocument = await TryAddNullCheckToParameterDeclarationAsync(document, parameterSyntax, options, cancellationToken).ConfigureAwait(false); if (modifiedDocument != null) { return modifiedDocument; @@ -341,7 +353,7 @@ private async Task AddNullCheckAsync( // Then see if we can convert a statement of the form "this.s = s" into "this.s = s ?? throw ...". modifiedDocument = await TryAddNullCheckToAssignmentAsync( - document, parameter, blockStatementOpt, cancellationToken).ConfigureAwait(false); + document, parameter, blockStatementOpt, options, cancellationToken).ConfigureAwait(false); if (modifiedDocument != null) { @@ -349,10 +361,9 @@ private async Task AddNullCheckAsync( } // If we can't, then just offer to add an "if (s == null)" statement. - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); return await AddNullCheckStatementAsync( document, parameter, functionDeclaration, method, blockStatementOpt, - (s, g) => CreateNullCheckStatement(optionSet, s, g, parameter), + (s, g) => CreateNullCheckStatement(s, g, parameter, options), cancellationToken).ConfigureAwait(false); } @@ -363,12 +374,12 @@ private async Task AddStringCheckAsync( IMethodSymbol method, IBlockOperation? blockStatementOpt, string methodName, + TSimplifierOptions options, CancellationToken cancellationToken) { - var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); return await AddNullCheckStatementAsync( document, parameter, functionDeclaration, method, blockStatementOpt, - (s, g) => CreateStringCheckStatement(optionSet, s.Compilation, g, parameter, methodName), + (s, g) => CreateStringCheckStatement(s.Compilation, g, parameter, methodName, options), cancellationToken).ConfigureAwait(false); } @@ -405,15 +416,14 @@ private async Task AddNullCheckStatementAsync( return document.WithSyntaxRoot(newRoot); } - private TStatementSyntax CreateNullCheckStatement(DocumentOptionSet optionSet, SemanticModel semanticModel, SyntaxGenerator generator, IParameterSymbol parameter) + private TStatementSyntax CreateNullCheckStatement(SemanticModel semanticModel, SyntaxGenerator generator, IParameterSymbol parameter, TSimplifierOptions options) => CreateParameterCheckIfStatement( - optionSet, (TExpressionSyntax)generator.CreateNullCheckExpression(semanticModel, parameter.Name), - (TStatementSyntax)generator.CreateThrowArgumentNullExceptionStatement(semanticModel.Compilation, parameter)); + (TStatementSyntax)generator.CreateThrowArgumentNullExceptionStatement(semanticModel.Compilation, parameter), + options); private TStatementSyntax CreateStringCheckStatement( - DocumentOptionSet optionSet, Compilation compilation, SyntaxGenerator generator, - IParameterSymbol parameter, string methodName) + Compilation compilation, SyntaxGenerator generator, IParameterSymbol parameter, string methodName, TSimplifierOptions options) { var stringType = compilation.GetSpecialType(SpecialType.System_String); @@ -425,7 +435,7 @@ private TStatementSyntax CreateStringCheckStatement( generator.Argument(generator.IdentifierName(parameter.Name))); var throwStatement = (TStatementSyntax)generator.ThrowStatement(CreateArgumentException(compilation, generator, parameter, methodName)); - return CreateParameterCheckIfStatement(optionSet, condition, throwStatement); + return CreateParameterCheckIfStatement(condition, throwStatement, options); } private static SyntaxNode? GetStatementToAddNullCheckAfter( @@ -508,6 +518,7 @@ private TStatementSyntax CreateStringCheckStatement( Document document, IParameterSymbol parameter, IBlockOperation? blockStatementOpt, + TSimplifierOptions options, CancellationToken cancellationToken) { // tries to convert "this.s = s" into "this.s = s ?? throw ...". Only supported @@ -526,7 +537,6 @@ private TStatementSyntax CreateStringCheckStatement( return null; } - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); if (!PrefersThrowExpression(options)) { return null; diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs index 9ea3c91ffca48..fcd16b9173052 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs @@ -14,12 +14,14 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Naming; using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -48,7 +50,8 @@ protected override bool SupportsRecords(ParseOptions options) protected override Task> GetRefactoringsForAllParametersAsync( Document document, SyntaxNode functionDeclaration, IMethodSymbol method, IBlockOperation? blockStatementOpt, - ImmutableArray listOfParameterNodes, TextSpan parameterSpan, CancellationToken cancellationToken) + ImmutableArray listOfParameterNodes, TextSpan parameterSpan, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { return SpecializedTasks.EmptyImmutableArray(); } @@ -60,7 +63,7 @@ protected override async Task> GetRefactoringsForSing SyntaxNode constructorDeclaration, IMethodSymbol method, IBlockOperation? blockStatementOpt, - CodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { // Only supported for constructor parameters. @@ -81,7 +84,7 @@ protected override async Task> GetRefactoringsForSing // to an existing matching field/prop if we can find one, or add a new field/prop // if we can't. - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var parameterNameParts = IdentifierNameParts.CreateIdentifierNameParts(parameter, rules); if (parameterNameParts.BaseName == "") return ImmutableArray.Empty; @@ -108,17 +111,17 @@ private async Task> HandleNoExistingFieldOrPropertyAs IMethodSymbol method, IBlockOperation? blockStatementOpt, ImmutableArray rules, - CodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { // Didn't find a field/prop that this parameter could be assigned to. // Offer to create new one and assign to that. using var _ = ArrayBuilder.GetInstance(out var allActions); - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var (fieldAction, propertyAction) = AddSpecificParameterInitializationActions( - document, parameter, constructorDeclaration, blockStatementOpt, rules, options, fallbackOptions); + document, parameter, constructorDeclaration, blockStatementOpt, rules, formattingOptions.AccessibilityModifiersRequired, fallbackOptions); // Check if the surrounding parameters are assigned to another field in this class. If so, offer to // make this parameter into a field as well. Otherwise, default to generating a property @@ -135,7 +138,7 @@ private async Task> HandleNoExistingFieldOrPropertyAs } var (allFieldsAction, allPropertiesAction) = AddAllParameterInitializationActions( - document, constructorDeclaration, method, blockStatementOpt, rules, options, fallbackOptions); + document, constructorDeclaration, method, blockStatementOpt, rules, formattingOptions.AccessibilityModifiersRequired, fallbackOptions); if (allFieldsAction != null && allPropertiesAction != null) { @@ -160,7 +163,7 @@ private async Task> HandleNoExistingFieldOrPropertyAs IMethodSymbol method, IBlockOperation? blockStatementOpt, ImmutableArray rules, - DocumentOptionSet options, + AccessibilityModifiersRequired accessibilityModifiersRequired, CodeGenerationOptionsProvider fallbackOptions) { if (blockStatementOpt == null) @@ -171,8 +174,8 @@ private async Task> HandleNoExistingFieldOrPropertyAs if (parameters.Length < 2) return default; - var fields = parameters.SelectAsArray(p => (ISymbol)CreateField(p, options, rules)); - var properties = parameters.SelectAsArray(p => (ISymbol)CreateProperty(p, options, rules)); + var fields = parameters.SelectAsArray(p => (ISymbol)CreateField(p, accessibilityModifiersRequired, rules)); + var properties = parameters.SelectAsArray(p => (ISymbol)CreateProperty(p, accessibilityModifiersRequired, rules)); var allFieldsAction = CodeAction.Create( FeaturesResources.Create_and_assign_remaining_as_fields, @@ -194,11 +197,11 @@ private async Task> HandleNoExistingFieldOrPropertyAs SyntaxNode constructorDeclaration, IBlockOperation? blockStatementOpt, ImmutableArray rules, - DocumentOptionSet options, + AccessibilityModifiersRequired accessibilityModifiersRequired, CodeGenerationOptionsProvider fallbackOptions) { - var field = CreateField(parameter, options, rules); - var property = CreateProperty(parameter, options, rules); + var field = CreateField(parameter, accessibilityModifiersRequired, rules); + var property = CreateProperty(parameter, accessibilityModifiersRequired, rules); var fieldAction = CodeAction.Create( string.Format(FeaturesResources.Create_and_assign_field_0, field.Name), c => AddSingleSymbolInitializationAsync(document, constructorDeclaration, blockStatementOpt, parameter, field, fallbackOptions, c), @@ -267,10 +270,9 @@ private ImmutableArray HandleExistingFieldOrProperty( private IFieldSymbol CreateField( IParameterSymbol parameter, - DocumentOptionSet options, + AccessibilityModifiersRequired accessibilityModifiersRequired, ImmutableArray rules) { - var requireAccessibilityModifiers = options.GetOption(CodeStyleOptions2.RequireAccessibilityModifiers); var parameterNameParts = IdentifierNameParts.CreateIdentifierNameParts(parameter, rules).BaseNameParts; foreach (var rule in rules) @@ -280,7 +282,7 @@ private IFieldSymbol CreateField( var uniqueName = GenerateUniqueName(parameter, parameterNameParts, rule); var accessibilityLevel = Accessibility.Private; - if (requireAccessibilityModifiers.Value is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault) + if (accessibilityModifiersRequired is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault) { var defaultAccessibility = DetermineDefaultFieldAccessibility(parameter.ContainingType); if (defaultAccessibility == Accessibility.Private) @@ -317,10 +319,9 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr private IPropertySymbol CreateProperty( IParameterSymbol parameter, - DocumentOptionSet options, + AccessibilityModifiersRequired accessibilityModifiersRequired, ImmutableArray rules) { - var requireAccessibilityModifiers = options.GetOption(CodeStyleOptions2.RequireAccessibilityModifiers); var parameterNameParts = IdentifierNameParts.CreateIdentifierNameParts(parameter, rules).BaseNameParts; foreach (var rule in rules) @@ -330,7 +331,7 @@ private IPropertySymbol CreateProperty( var uniqueName = GenerateUniqueName(parameter, parameterNameParts, rule); var accessibilityLevel = Accessibility.Public; - if (requireAccessibilityModifiers.Value is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault) + if (accessibilityModifiersRequired is AccessibilityModifiersRequired.Never or AccessibilityModifiersRequired.OmitIfDefault) { var defaultAccessibility = DetermineDefaultPropertyAccessibility(); if (defaultAccessibility == Accessibility.Public) diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs index d61ca08e6813c..4d527d0befb76 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs @@ -16,6 +16,7 @@ using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.InitializeParameter @@ -58,6 +59,7 @@ protected abstract Task> GetRefactoringsForAllParamet IBlockOperation? blockStatementOpt, ImmutableArray listOfParameterNodes, TextSpan parameterSpan, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected abstract Task> GetRefactoringsForSingleParameterAsync( @@ -67,7 +69,7 @@ protected abstract Task> GetRefactoringsForSinglePara SyntaxNode functionDeclaration, IMethodSymbol methodSymbol, IBlockOperation? blockStatementOpt, - CodeGenerationOptionsProvider fallbackOptions, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected abstract void InsertStatement( @@ -145,7 +147,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte // actually determine if there are any viable refactorings here. var refactorings = await GetRefactoringsForAllParametersAsync( document, funcOrRecord, methodSymbol, blockStatementOpt, - listOfPotentiallyValidParametersNodes.ToImmutable(), selectedParameter.Span, cancellationToken).ConfigureAwait(false); + listOfPotentiallyValidParametersNodes.ToImmutable(), selectedParameter.Span, context.Options, cancellationToken).ConfigureAwait(false); context.RegisterRefactorings(refactorings, context.Span); } diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs index 14cd9a45ab867..763e2b8b65b1d 100644 --- a/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs +++ b/src/Features/Core/Portable/InlineHints/AbstractInlineParameterNameHintsService.cs @@ -18,8 +18,6 @@ namespace Microsoft.CodeAnalysis.InlineHints { internal abstract class AbstractInlineParameterNameHintsService : IInlineParameterNameHintsService { - private readonly IGlobalOptionService _globalOptions; - protected enum HintKind { Literal, @@ -27,11 +25,6 @@ protected enum HintKind Other } - public AbstractInlineParameterNameHintsService(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - protected abstract void AddAllParameterNameHintLocations( SemanticModel semanticModel, ISyntaxFactsService syntaxFacts, @@ -44,7 +37,9 @@ protected abstract void AddAllParameterNameHintLocations( public async Task> GetInlineHintsAsync(Document document, TextSpan textSpan, InlineParameterHintsOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken) { - var displayAllOverride = _globalOptions.GetOption(InlineHintsGlobalStateOption.DisplayAllOverride); + // TODO: https://github.com/dotnet/roslyn/issues/57283 + var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService(); + var displayAllOverride = globalOptions.InlineHintsOptionsDisplayAllOverride; var enabledForParameters = displayAllOverride || options.EnabledForParameters; if (!enabledForParameters) diff --git a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs index 26916f2dea196..fcc4e9e6bfb8e 100644 --- a/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs +++ b/src/Features/Core/Portable/InlineHints/AbstractInlineTypeHintsService.cs @@ -22,13 +22,6 @@ internal abstract class AbstractInlineTypeHintsService : IInlineTypeHintsService genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); - private readonly IGlobalOptionService _globalOptions; - - public AbstractInlineTypeHintsService(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - protected abstract TypeHint? TryGetTypeHint( SemanticModel semanticModel, SyntaxNode node, bool displayAllOverride, @@ -40,7 +33,9 @@ public AbstractInlineTypeHintsService(IGlobalOptionService globalOptions) public async Task> GetInlineHintsAsync( Document document, TextSpan textSpan, InlineTypeHintsOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken) { - var displayAllOverride = _globalOptions.GetOption(InlineHintsGlobalStateOption.DisplayAllOverride); + // TODO: https://github.com/dotnet/roslyn/issues/57283 + var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService(); + var displayAllOverride = globalOptions.InlineHintsOptionsDisplayAllOverride; var enabledForTypes = options.EnabledForTypes; if (!enabledForTypes && !displayAllOverride) diff --git a/src/Features/Core/Portable/Intents/IntentDataProvider.cs b/src/Features/Core/Portable/Intents/IntentDataProvider.cs index 64cb421654ad4..7737f8a837505 100644 --- a/src/Features/Core/Portable/Intents/IntentDataProvider.cs +++ b/src/Features/Core/Portable/Intents/IntentDataProvider.cs @@ -23,13 +23,13 @@ internal sealed class IntentDataProvider return serializerOptions; }); - public readonly CodeAndImportGenerationOptionsProvider FallbackOptions; + public readonly CleanCodeGenerationOptionsProvider FallbackOptions; private readonly string? _serializedIntentData; public IntentDataProvider( string? serializedIntentData, - CodeAndImportGenerationOptionsProvider fallbackOptions) + CleanCodeGenerationOptionsProvider fallbackOptions) { _serializedIntentData = serializedIntentData; FallbackOptions = fallbackOptions; diff --git a/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs index 24b4fdcceb9f2..8b716e5e9f08d 100644 --- a/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/PreferFrameworkType/PreferFrameworkTypeDiagnosticAnalyzerBase.cs @@ -26,12 +26,6 @@ protected PreferFrameworkTypeDiagnosticAnalyzerBase() { } - private static PerLanguageOption2> GetOptionForDeclarationContext - => CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration; - - private static PerLanguageOption2> GetOptionForMemberAccessContext - => CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess; - public override bool OpenFileOnly(SimplifierOptions? options) { // analyzer is only active in C# and VB projects @@ -55,12 +49,12 @@ protected sealed override void InitializeWorker(AnalysisContext context) protected void AnalyzeNode(SyntaxNodeAnalysisContext context) { - var semanticModel = context.SemanticModel; - var language = semanticModel.Language; + var options = context.GetAnalyzerOptions(); // if the user never prefers this style, do not analyze at all. // we don't know the context of the node yet, so check all predefined type option preferences and bail early. - if (!IsStylePreferred(context, language)) + if (!IsFrameworkTypePreferred(options.PreferPredefinedTypeKeywordInDeclaration) && + !IsFrameworkTypePreferred(options.PreferPredefinedTypeKeywordInMemberAccess)) { return; } @@ -74,63 +68,27 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context) } // check we have a symbol so that the fixer can generate the right type syntax from it. - if (semanticModel.GetSymbolInfo(predefinedTypeNode, context.CancellationToken).Symbol is not ITypeSymbol) + if (context.SemanticModel.GetSymbolInfo(predefinedTypeNode, context.CancellationToken).Symbol is not ITypeSymbol) { return; } // earlier we did a context insensitive check to see if this style was preferred in *any* context at all. // now, we have to make a context sensitive check to see if options settings for our context requires us to report a diagnostic. - if (ShouldReportDiagnostic(predefinedTypeNode, context, language, - out var diagnosticSeverity)) + var optionValue = IsInMemberAccessOrCrefReferenceContext(predefinedTypeNode) ? + options.PreferPredefinedTypeKeywordInMemberAccess : + options.PreferPredefinedTypeKeywordInDeclaration; + + if (IsFrameworkTypePreferred(optionValue)) { context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, predefinedTypeNode.GetLocation(), - diagnosticSeverity, additionalLocations: null, + optionValue.Notification.Severity, additionalLocations: null, PreferFrameworkTypeConstants.Properties)); } - } - - /// - /// Detects the context of this occurrence of predefined type and determines if we should report it. - /// - private bool ShouldReportDiagnostic( - TPredefinedTypeSyntax predefinedTypeNode, - SyntaxNodeAnalysisContext context, - string language, - out ReportDiagnostic severity) - { - // we have a predefined type syntax that is either in a member access context or a declaration context. - // check the appropriate option and determine if we should report a diagnostic. - var isMemberAccessOrCref = IsInMemberAccessOrCrefReferenceContext(predefinedTypeNode); - var option = isMemberAccessOrCref ? GetOptionForMemberAccessContext : GetOptionForDeclarationContext; - var optionValue = context.GetOption(option, language); - - severity = optionValue.Notification.Severity; - return OptionSettingPrefersFrameworkType(optionValue, severity); - } - - private static bool IsStylePreferred( - SyntaxNodeAnalysisContext context, - string language) - => IsFrameworkTypePreferred(context, GetOptionForDeclarationContext, language) || - IsFrameworkTypePreferred(context, GetOptionForMemberAccessContext, language); - - private static bool IsFrameworkTypePreferred( - SyntaxNodeAnalysisContext context, - PerLanguageOption2> option, - string language) - { - var optionValue = context.GetOption(option, language); - return OptionSettingPrefersFrameworkType(optionValue, optionValue.Notification.Severity); + static bool IsFrameworkTypePreferred(CodeStyleOption2 optionValue) + => !optionValue.Value && optionValue.Notification.Severity != ReportDiagnostic.Suppress; } - - /// - /// checks if style is preferred and the enforcement is not None. - /// - /// if predefined type is not preferred, it implies the preference is framework type. - private static bool OptionSettingPrefersFrameworkType(CodeStyleOption2 optionValue, ReportDiagnostic severity) - => !optionValue.Value && severity != ReportDiagnostic.Suppress; } } diff --git a/src/Features/Core/Portable/ReplaceMethodWithProperty/IReplaceMethodWithPropertyService.cs b/src/Features/Core/Portable/ReplaceMethodWithProperty/IReplaceMethodWithPropertyService.cs index a777ac6101c3a..09bd4a87ef861 100644 --- a/src/Features/Core/Portable/ReplaceMethodWithProperty/IReplaceMethodWithPropertyService.cs +++ b/src/Features/Core/Portable/ReplaceMethodWithProperty/IReplaceMethodWithPropertyService.cs @@ -5,6 +5,7 @@ #nullable disable using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host; @@ -20,7 +21,7 @@ internal interface IReplaceMethodWithPropertyService : ILanguageService void ReplaceSetReference(SyntaxEditor editor, SyntaxToken nameToken, string propertyName, bool nameChanged); void ReplaceGetMethodWithProperty( - DocumentOptionSet documentOptions, ParseOptions parseOptions, + CodeGenerationOptions options, ParseOptions parseOptions, SyntaxEditor editor, SemanticModel semanticModel, GetAndSetMethods getAndSetMethods, string propertyName, bool nameChanged); diff --git a/src/Features/Core/Portable/ReplaceMethodWithProperty/ReplaceMethodWithPropertyCodeRefactoringProvider.cs b/src/Features/Core/Portable/ReplaceMethodWithProperty/ReplaceMethodWithPropertyCodeRefactoringProvider.cs index 5524959b6dad8..f70b36b4c957e 100644 --- a/src/Features/Core/Portable/ReplaceMethodWithProperty/ReplaceMethodWithPropertyCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ReplaceMethodWithProperty/ReplaceMethodWithPropertyCodeRefactoringProvider.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.FindSymbols; @@ -74,7 +75,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte // Looks good! context.RegisterRefactoring(CodeAction.Create( string.Format(FeaturesResources.Replace_0_with_property, methodName), - c => ReplaceMethodsWithPropertyAsync(document, propertyName, nameChanged, methodSymbol, setMethod: null, cancellationToken: c), + c => ReplaceMethodsWithPropertyAsync(document, propertyName, nameChanged, methodSymbol, setMethod: null, context.Options, cancellationToken: c), methodName), methodDeclaration.Span); @@ -87,7 +88,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte { context.RegisterRefactoring(CodeAction.Create( string.Format(FeaturesResources.Replace_0_and_1_with_property, methodName, setMethod.Name), - c => ReplaceMethodsWithPropertyAsync(document, propertyName, nameChanged, methodSymbol, setMethod, cancellationToken: c), + c => ReplaceMethodsWithPropertyAsync(document, propertyName, nameChanged, methodSymbol, setMethod, context.Options, cancellationToken: c), methodName + "-get/set"), methodDeclaration.Span); } @@ -161,6 +162,7 @@ private async Task ReplaceMethodsWithPropertyAsync( bool nameChanged, IMethodSymbol getMethod, IMethodSymbol? setMethod, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); @@ -187,7 +189,7 @@ private async Task ReplaceMethodsWithPropertyAsync( var updatedSolution = originalSolution; updatedSolution = await UpdateReferencesAsync(updatedSolution, propertyName, nameChanged, getReferencesByDocument, setReferencesByDocument, cancellationToken).ConfigureAwait(false); - updatedSolution = await ReplaceGetMethodsAndRemoveSetMethodsAsync(originalSolution, updatedSolution, propertyName, nameChanged, getMethodReferences, setMethodReferences, updateSetMethod: setMethod != null, cancellationToken: cancellationToken).ConfigureAwait(false); + updatedSolution = await ReplaceGetMethodsAndRemoveSetMethodsAsync(originalSolution, updatedSolution, propertyName, nameChanged, getMethodReferences, setMethodReferences, updateSetMethod: setMethod != null, fallbackOptions, cancellationToken).ConfigureAwait(false); return updatedSolution; } @@ -319,6 +321,7 @@ private static async Task ReplaceGetMethodsAndRemoveSetMethodsAsync( IEnumerable getMethodReferences, IEnumerable setMethodReferences, bool updateSetMethod, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var getDefinitionsByDocumentId = await GetDefinitionsByDocumentIdAsync(originalSolution, getMethodReferences, cancellationToken).ConfigureAwait(false); @@ -333,7 +336,7 @@ private static async Task ReplaceGetMethodsAndRemoveSetMethodsAsync( var setDefinitions = setDefinitionsByDocumentId[documentId]; updatedSolution = await ReplaceGetMethodsAndRemoveSetMethodsAsync( - propertyName, nameChanged, updatedSolution, documentId, getDefinitions, setDefinitions, updateSetMethod, cancellationToken).ConfigureAwait(false); + propertyName, nameChanged, updatedSolution, documentId, getDefinitions, setDefinitions, updateSetMethod, fallbackOptions, cancellationToken).ConfigureAwait(false); } return updatedSolution; @@ -347,6 +350,7 @@ private static async Task ReplaceGetMethodsAndRemoveSetMethodsAsync( MultiDictionary.ValueSet originalGetDefinitions, MultiDictionary.ValueSet originalSetDefinitions, bool updateSetMethod, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var updatedDocument = updatedSolution.GetRequiredDocument(documentId); @@ -365,7 +369,7 @@ private static async Task ReplaceGetMethodsAndRemoveSetMethodsAsync( var editor = new SyntaxEditor(root, updatedSolution.Workspace.Services); - var documentOptions = await updatedDocument.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var codeGenerationOptions = await updatedDocument.GetCodeGenerationOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var parseOptions = syntaxTree.Options; // First replace all the get methods with properties. @@ -374,7 +378,7 @@ private static async Task ReplaceGetMethodsAndRemoveSetMethodsAsync( cancellationToken.ThrowIfCancellationRequested(); service.ReplaceGetMethodWithProperty( - documentOptions, parseOptions, editor, semanticModel, + codeGenerationOptions, parseOptions, editor, semanticModel, getSetPair, propertyName, nameChanged); } diff --git a/src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs b/src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs index a600272b26b9e..a05462248be0a 100644 --- a/src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs +++ b/src/Features/Core/Portable/ReplacePropertyWithMethods/AbstractReplacePropertyWithMethodsService.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.LanguageServices; @@ -25,7 +26,8 @@ internal abstract class AbstractReplacePropertyWithMethodsService> GetReplacementMembersAsync(Document document, IPropertySymbol property, SyntaxNode propertyDeclaration, IFieldSymbol propertyBackingField, string desiredGetMethodName, string desiredSetMethodName, CancellationToken cancellationToken); + public abstract Task> GetReplacementMembersAsync( + Document document, IPropertySymbol property, SyntaxNode propertyDeclaration, IFieldSymbol propertyBackingField, string desiredGetMethodName, string desiredSetMethodName, CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); protected abstract TCrefSyntax? TryGetCrefSyntax(TIdentifierNameSyntax identifierName); protected abstract TCrefSyntax CreateCrefSyntax(TCrefSyntax originalCref, SyntaxToken identifierToken, SyntaxNode? parameterType); diff --git a/src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs b/src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs index 1e2e36f52211b..50fea616fbd3f 100644 --- a/src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs +++ b/src/Features/Core/Portable/ReplacePropertyWithMethods/IReplacePropertyWithMethodsService.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host; @@ -30,6 +31,7 @@ Task> GetReplacementMembersAsync( IFieldSymbol propertyBackingField, string desiredGetMethodName, string desiredSetMethodName, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken); SyntaxNode GetPropertyNodeToReplace(SyntaxNode propertyDeclaration); diff --git a/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs b/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs index 033f941ead4e3..faf980fd7d5a9 100644 --- a/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ReplacePropertyWithMethods/ReplacePropertyWithMethodsCodeRefactoringProvider.cs @@ -67,7 +67,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte context.RegisterRefactoring( CodeAction.Create( string.Format(resourceString, propertyName), - c => ReplacePropertyWithMethodsAsync(document, propertySymbol, c), + c => ReplacePropertyWithMethodsAsync(document, propertySymbol, context.Options, c), propertyName), propertyDeclaration.Span); } @@ -75,6 +75,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte private async Task ReplacePropertyWithMethodsAsync( Document document, IPropertySymbol propertySymbol, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var desiredMethodSuffix = NameGenerator.GenerateUniqueName(propertySymbol.Name, @@ -111,7 +112,7 @@ from loc in r.Locations updatedSolution = await ReplaceDefinitionsWithMethodsAsync( originalSolution, updatedSolution, propertyReferences, definitionToBackingField, - desiredGetMethodName, desiredSetMethodName, cancellationToken).ConfigureAwait(false); + desiredGetMethodName, desiredSetMethodName, fallbackOptions, cancellationToken).ConfigureAwait(false); return updatedSolution; } @@ -287,12 +288,14 @@ await service.ReplaceReferenceAsync( } } } + private static async Task ReplaceDefinitionsWithMethodsAsync( Solution originalSolution, Solution updatedSolution, IEnumerable references, ImmutableDictionary definitionToBackingField, string desiredGetMethodName, string desiredSetMethodName, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var definitionsByDocumentId = await GetDefinitionsByDocumentIdAsync(originalSolution, references, cancellationToken).ConfigureAwait(false); @@ -303,7 +306,7 @@ private static async Task ReplaceDefinitionsWithMethodsAsync( updatedSolution = await ReplaceDefinitionsWithMethodsAsync( updatedSolution, documentId, definitions, definitionToBackingField, - desiredGetMethodName, desiredSetMethodName, cancellationToken).ConfigureAwait(false); + desiredGetMethodName, desiredSetMethodName, fallbackOptions, cancellationToken).ConfigureAwait(false); } return updatedSolution; @@ -343,6 +346,7 @@ private static async Task ReplaceDefinitionsWithMethodsAsync( MultiDictionary.ValueSet originalDefinitions, IDictionary definitionToBackingField, string desiredGetMethodName, string desiredSetMethodName, + CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var updatedDocument = updatedSolution.GetRequiredDocument(documentId); @@ -369,6 +373,7 @@ private static async Task ReplaceDefinitionsWithMethodsAsync( property, declaration, definitionToBackingField.GetValueOrDefault(property), desiredGetMethodName, desiredSetMethodName, + fallbackOptions, cancellationToken).ConfigureAwait(false); // Properly make the members fit within an interface if that's what diff --git a/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs b/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs index a56b7566f9e0f..c979f14a96e80 100644 --- a/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs +++ b/src/Features/Core/Portable/Shared/Extensions/DocumentExtensions.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editing; @@ -102,26 +103,16 @@ public static async Task IsValidContextForDocumentOrLinkedDocumentsAsync( /// that match if the user hasn't specified any for a particular symbol type. The are added at the end so they /// will only be used if the user hasn't specified a preference. /// - public static Task> GetNamingRulesAsync( - this Document document, CancellationToken cancellationToken) - => document.GetNamingRulesAsync(FallbackNamingRules.Default, cancellationToken); - - /// - /// Get the user-specified naming rules, with the added . - /// - public static async Task> GetNamingRulesAsync(this Document document, - ImmutableArray defaultRules, CancellationToken cancellationToken) + public static async Task> GetNamingRulesAsync( + this Document document, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var namingStyleOptions = options.GetOption(NamingStyleOptions.NamingPreferences); - var rules = namingStyleOptions.CreateRules().NamingRules; - - return defaultRules.IsDefaultOrEmpty ? rules : rules.AddRange(defaultRules); + var options = await document.GetNamingStylePreferencesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + return options.CreateRules().NamingRules.AddRange(FallbackNamingRules.Default); } - public static async Task GetApplicableNamingRuleAsync(this Document document, ISymbol symbol, CancellationToken cancellationToken) + public static async Task GetApplicableNamingRuleAsync(this Document document, ISymbol symbol, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); foreach (var rule in rules) { if (rule.SymbolSpecification.AppliesTo(symbol)) @@ -132,9 +123,9 @@ public static async Task GetApplicableNamingRuleAsync(this Document } public static async Task GetApplicableNamingRuleAsync( - this Document document, SymbolKind symbolKind, Accessibility accessibility, CancellationToken cancellationToken) + this Document document, SymbolKind symbolKind, Accessibility accessibility, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); foreach (var rule in rules) { if (rule.SymbolSpecification.AppliesTo(symbolKind, accessibility)) @@ -145,9 +136,9 @@ public static async Task GetApplicableNamingRuleAsync( } public static async Task GetApplicableNamingRuleAsync( - this Document document, SymbolKindOrTypeKind kind, DeclarationModifiers modifiers, Accessibility? accessibility, CancellationToken cancellationToken) + this Document document, SymbolKindOrTypeKind kind, DeclarationModifiers modifiers, Accessibility? accessibility, NamingStylePreferencesProvider fallbackOptions, CancellationToken cancellationToken) { - var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false); + var rules = await document.GetNamingRulesAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); foreach (var rule in rules) { if (rule.SymbolSpecification.AppliesTo(kind, modifiers, accessibility)) diff --git a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeCodeFixProvider.cs b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeCodeFixProvider.cs index f9d482283912a..cacc384398b07 100644 --- a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeCodeFixProvider.cs +++ b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeCodeFixProvider.cs @@ -45,7 +45,6 @@ protected sealed override async Task FixAllAsync( SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService(); var memberAccessNodes = diagnostics.Select( diff --git a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs index 3903a1a4217f0..27b8cde332b52 100644 --- a/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/SimplifyThisOrMe/AbstractSimplifyThisOrMeDiagnosticAnalyzer.cs @@ -20,14 +20,12 @@ internal abstract class AbstractSimplifyThisOrMeDiagnosticAnalyzer< TLanguageKindEnum, TExpressionSyntax, TThisExpressionSyntax, - TMemberAccessExpressionSyntax, - TSimplifierOptions> : + TMemberAccessExpressionSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer where TLanguageKindEnum : struct where TExpressionSyntax : SyntaxNode where TThisExpressionSyntax : TExpressionSyntax where TMemberAccessExpressionSyntax : TExpressionSyntax - where TSimplifierOptions : SimplifierOptions { protected AbstractSimplifyThisOrMeDiagnosticAnalyzer() : base(IDEDiagnosticIds.RemoveThisOrMeQualificationDiagnosticId, @@ -40,7 +38,7 @@ protected AbstractSimplifyThisOrMeDiagnosticAnalyzer() } protected abstract ISyntaxKinds SyntaxKinds { get; } - protected abstract TSimplifierOptions GetSimplifierOptions(AnalyzerOptions options, SyntaxTree syntaxTree); + protected abstract ISimplification Simplification { get; } protected abstract AbstractMemberAccessExpressionSimplifier Simplifier { get; } @@ -59,8 +57,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context) if (node.Parent is not TMemberAccessExpressionSyntax memberAccessExpression) return; - var syntaxTree = node.SyntaxTree; - var simplifierOptions = GetSimplifierOptions(context.Options, syntaxTree); + var simplifierOptions = context.GetAnalyzerOptions().GetSimplifierOptions(Simplification); if (!this.Simplifier.ShouldSimplifyThisMemberAccessExpression( memberAccessExpression, semanticModel, simplifierOptions, out var thisExpression, out var severity, cancellationToken)) diff --git a/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs b/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs index 4fd4894216703..597bc7130a7a7 100644 --- a/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs +++ b/src/Features/Core/Portable/Wrapping/AbstractCodeActionComputer.cs @@ -96,10 +96,7 @@ protected string GetIndentationAfter(SyntaxNodeOrToken nodeOrToken, FormattingOp var newDocument = OriginalDocument.WithText(newSourceText); // The only auto-formatting option that's relevant is indent style. Others only control behavior on typing. - var indentationOptions = new IndentationOptions( - Options.FormattingOptions, - AutoFormattingOptions.Default, - IndentStyle: indentStyle); + var indentationOptions = new IndentationOptions(Options.FormattingOptions) { IndentStyle = indentStyle }; var indentationService = Wrapper.IndentationService; var originalLineNumber = newSourceText.Lines.GetLineFromPosition(nodeOrToken.Span.End).LineNumber; diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index 8ca5de4f61e73..21762764f6b94 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -672,11 +672,13 @@ public static async Task GetFormattingOptionsAsync( { // LSP doesn't currently support indent size as an option. However, except in special // circumstances, indent size is usually equivalent to tab size, so we'll just set it. - formattingOptions = formattingOptions.With(new LineFormattingOptions( - UseTabs: !options.InsertSpaces, - TabSize: options.TabSize, - IndentationSize: options.TabSize, - NewLine: formattingOptions.NewLine)); + formattingOptions = formattingOptions.With(new LineFormattingOptions() + { + UseTabs = !options.InsertSpaces, + TabSize = options.TabSize, + IndentationSize = options.TabSize, + NewLine = formattingOptions.NewLine + }); } return formattingOptions; diff --git a/src/Features/LanguageServer/Protocol/Features/CodeCleanup/AbstractCodeCleanupService.cs b/src/Features/LanguageServer/Protocol/Features/CodeCleanup/AbstractCodeCleanupService.cs index 00bbd0827567a..910c5c28e0331 100644 --- a/src/Features/LanguageServer/Protocol/Features/CodeCleanup/AbstractCodeCleanupService.cs +++ b/src/Features/LanguageServer/Protocol/Features/CodeCleanup/AbstractCodeCleanupService.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CodeFixesAndRefactorings; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.RemoveUnnecessaryImports; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -57,11 +58,9 @@ public async Task CleanupAsync( // do the remove usings after code fix, as code fix might remove some code which can results in unused usings. if (organizeUsings) { - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); - progressTracker.Description = this.OrganizeImportsDescription; document = await RemoveSortUsingsAsync( - document, enabledDiagnostics.OrganizeUsings, formattingOptions, cancellationToken).ConfigureAwait(false); + document, enabledDiagnostics.OrganizeUsings, fallbackOptions, cancellationToken).ConfigureAwait(false); progressTracker.ItemCompleted(); } @@ -81,25 +80,25 @@ public async Task CleanupAsync( } private static async Task RemoveSortUsingsAsync( - Document document, OrganizeUsingsSet organizeUsingsSet, SyntaxFormattingOptions formattingOptions, CancellationToken cancellationToken) + Document document, OrganizeUsingsSet organizeUsingsSet, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { - if (organizeUsingsSet.IsRemoveUnusedImportEnabled) + if (organizeUsingsSet.IsRemoveUnusedImportEnabled && + document.GetLanguageService() is { } removeUsingsService) { - var removeUsingsService = document.GetLanguageService(); - if (removeUsingsService != null) + using (Logger.LogBlock(FunctionId.CodeCleanup_RemoveUnusedImports, cancellationToken)) { - using (Logger.LogBlock(FunctionId.CodeCleanup_RemoveUnusedImports, cancellationToken)) - { - document = await removeUsingsService.RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false); - } + var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + document = await removeUsingsService.RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false); } } - if (organizeUsingsSet.IsSortImportsEnabled) + if (organizeUsingsSet.IsSortImportsEnabled && + document.GetLanguageService() is { } organizeImportsService) { using (Logger.LogBlock(FunctionId.CodeCleanup_SortImports, cancellationToken)) { - document = await Formatter.OrganizeImportsAsync(document, cancellationToken).ConfigureAwait(false); + var organizeOptions = await document.GetOrganizeImportsOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); + document = await organizeImportsService.OrganizeImportsAsync(document, organizeOptions, cancellationToken).ConfigureAwait(false); } } diff --git a/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs b/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs index 80a9ccef1f916..773cf0a989ddb 100644 --- a/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs +++ b/src/Features/LanguageServer/Protocol/Features/CodeFixes/ICodeFixService.cs @@ -31,13 +31,13 @@ internal interface ICodeFixService internal static class ICodeFixServiceExtensions { - public static IAsyncEnumerable StreamFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider options, bool isBlocking, CancellationToken cancellationToken) - => service.StreamFixesAsync(document, range, CodeActionRequestPriority.None, options, isBlocking, addOperationScope: _ => null, cancellationToken); + public static IAsyncEnumerable StreamFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken) + => service.StreamFixesAsync(document, range, CodeActionRequestPriority.None, fallbackOptions, isBlocking, addOperationScope: _ => null, cancellationToken); - public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider options, bool isBlocking, CancellationToken cancellationToken) - => service.StreamFixesAsync(document, range, options, isBlocking, cancellationToken).ToImmutableArrayAsync(cancellationToken); + public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken) + => service.StreamFixesAsync(document, range, fallbackOptions, isBlocking, cancellationToken).ToImmutableArrayAsync(cancellationToken); - public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider options, bool isBlocking, Func addOperationScope, CancellationToken cancellationToken) - => service.StreamFixesAsync(document, textSpan, priority, options, isBlocking, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken); + public static Task> GetFixesAsync(this ICodeFixService service, Document document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider fallbackOptions, bool isBlocking, Func addOperationScope, CancellationToken cancellationToken) + => service.StreamFixesAsync(document, textSpan, priority, fallbackOptions, isBlocking, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken); } } 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 33b6e4642e081..8e1c453365cba 100644 --- a/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs +++ b/src/Features/LanguageServer/Protocol/Features/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer_IncrementalAnalyzer.cs @@ -84,7 +84,7 @@ private async Task AnalyzeDocumentForKindAsync(TextDocument document, AnalysisKi { var analysisScope = new DocumentAnalysisScope(document, span: null, nonCachedStateSets.SelectAsArray(s => s.Analyzer), kind); var executor = new DocumentAnalysisExecutor(analysisScope, compilationWithAnalyzers, _diagnosticAnalyzerRunner, logPerformanceInfo: true, onAnalysisException: OnAnalysisException); - var logTelemetry = document.Project.Solution.Options.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution); + var logTelemetry = GlobalOptions.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution); foreach (var stateSet in nonCachedStateSets) { var computedData = await ComputeDocumentAnalysisDataAsync(executor, stateSet, logTelemetry, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs index 92bf0bd3401c6..ebb32d1132da0 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/AutoFormattingOptionsStorage.cs @@ -9,11 +9,13 @@ namespace Microsoft.CodeAnalysis.Formatting; internal static class AutoFormattingOptionsStorage { public static AutoFormattingOptions GetAutoFormattingOptions(this IGlobalOptionService globalOptions, string language) - => new( - FormatOnReturn: globalOptions.GetOption(FormatOnReturn, language), - FormatOnTyping: globalOptions.GetOption(FormatOnTyping, language), - FormatOnSemicolon: globalOptions.GetOption(FormatOnSemicolon, language), - FormatOnCloseBrace: globalOptions.GetOption(FormatOnCloseBrace, language)); + => new() + { + FormatOnReturn = globalOptions.GetOption(FormatOnReturn, language), + FormatOnTyping = globalOptions.GetOption(FormatOnTyping, language), + FormatOnSemicolon = globalOptions.GetOption(FormatOnSemicolon, language), + FormatOnCloseBrace = globalOptions.GetOption(FormatOnCloseBrace, language) + }; internal static readonly PerLanguageOption2 FormatOnReturn = new( "FormattingOptions", OptionGroup.Default, "AutoFormattingOnReturn", AutoFormattingOptions.Default.FormatOnReturn, diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CodeActionOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CodeActionOptionsStorage.cs index 75334f139fb34..f2edcf9f4f9d7 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/CodeActionOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/CodeActionOptionsStorage.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.ExtractMethod; using Microsoft.CodeAnalysis.Formatting; @@ -23,29 +24,27 @@ internal static class CodeActionOptionsStorage public static CodeActionOptions GetCodeActionOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) => new( - SearchOptions: globalOptions.GetSymbolSearchOptions(languageServices.Language), - ImplementTypeOptions: globalOptions.GetImplementTypeOptions(languageServices.Language), - ExtractMethodOptions: globalOptions.GetExtractMethodOptions(languageServices.Language), - CleanupOptions: globalOptions.GetCodeCleanupOptions(languageServices), - CodeGenerationOptions: globalOptions.GetCodeGenerationOptions(languageServices), - HideAdvancedMembers: globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, languageServices.Language), - WrappingColumn: globalOptions.GetOption(WrappingColumn, languageServices.Language)); + cleanupOptions: globalOptions.GetCodeCleanupOptions(languageServices), + codeGenerationOptions: globalOptions.GetCodeGenerationOptions(languageServices), + codeStyleOptions: globalOptions.GetCodeStyleOptions(languageServices)) + { + SearchOptions = globalOptions.GetSymbolSearchOptions(languageServices.Language), + ImplementTypeOptions = globalOptions.GetImplementTypeOptions(languageServices.Language), + ExtractMethodOptions = globalOptions.GetExtractMethodOptions(languageServices.Language), + HideAdvancedMembers = globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, languageServices.Language), + WrappingColumn = globalOptions.GetOption(WrappingColumn, languageServices.Language), + ConditionalExpressionWrappingLength = globalOptions.GetOption(ConditionalExpressionWrappingLength, languageServices.Language) + }; internal static CodeActionOptionsProvider GetCodeActionOptionsProvider(this IGlobalOptionService globalOptions) - => new CachingCodeActionsOptionsProvider(globalOptions); - - private sealed class CachingCodeActionsOptionsProvider : AbstractCodeActionOptionsProvider { - private readonly IGlobalOptionService _globalOptions; - private ImmutableDictionary _cache = ImmutableDictionary.Empty; - - public CachingCodeActionsOptionsProvider(IGlobalOptionService globalOptions) - { - _globalOptions = globalOptions; - } - - public override CodeActionOptions GetOptions(HostLanguageServices languageService) - => ImmutableInterlocked.GetOrAdd(ref _cache, languageService.Language, (language, options) => GetCodeActionOptions(options, languageService), _globalOptions); + var cache = ImmutableDictionary.Empty; + return new DelegatingCodeActionOptionsProvider(languageService => ImmutableInterlocked.GetOrAdd(ref cache, languageService.Language, (_, options) => GetCodeActionOptions(options, languageService), globalOptions)); } + + public static readonly PerLanguageOption2 ConditionalExpressionWrappingLength = new( + "UseConditionalExpressionOptions", + "ConditionalExpressionWrappingLength", CodeActionOptions.DefaultConditionalExpressionWrappingLength, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ConditionalExpressionWrappingLength")); } } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CodeCleanupOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CodeCleanupOptionsStorage.cs index 1e61d699b09d7..9db899dda6381 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/CodeCleanupOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/CodeCleanupOptionsStorage.cs @@ -20,7 +20,10 @@ public static ValueTask GetCodeCleanupOptionsAsync(this Docu public static CodeCleanupOptions GetCodeCleanupOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) => new( - FormattingOptions: globalOptions.GetSyntaxFormattingOptions(languageServices), - SimplifierOptions: globalOptions.GetSimplifierOptions(languageServices), - AddImportOptions: AddImportPlacementOptions.Default); + globalOptions.GetSyntaxFormattingOptions(languageServices), + globalOptions.GetSimplifierOptions(languageServices)) + { + AddImportOptions = globalOptions.GetAddImportPlacementOptions(languageServices), + DocumentFormattingOptions = globalOptions.GetDocumentFormattingOptions(languageServices.Language) + }; } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CodeGenerationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CodeGenerationOptionsStorage.cs index cd38b5748a05f..58a41a595d1c3 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/CodeGenerationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/CodeGenerationOptionsStorage.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; using Roslyn.Utilities; @@ -25,6 +26,12 @@ public static ValueTask GetCodeGenerationOptionsAsync(thi public static ValueTask GetCleanCodeGenerationOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) => document.GetCleanCodeGenerationOptionsAsync(globalOptions.GetCleanCodeGenerationOptions(document.Project.LanguageServices), cancellationToken); + public static CodeGenerationOptions.CommonOptions GetCommonCodeGenerationOptions(this IGlobalOptionService globalOptions, string language) + => new() + { + NamingStyle = globalOptions.GetNamingStylePreferences(language) + }; + public static CodeGenerationOptions GetCodeGenerationOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) => languageServices.GetRequiredService().GetOptions(globalOptions); diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CodeStyleOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CodeStyleOptionsStorage.cs new file mode 100644 index 0000000000000..3d02d3c650b76 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Features/Options/CodeStyleOptionsStorage.cs @@ -0,0 +1,58 @@ +// 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.CodeStyle; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.AddImport; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CodeStyle; + +internal interface ICodeStyleOptionsStorage : ILanguageService +{ + IdeCodeStyleOptions GetOptions(IGlobalOptionService globalOptions); +} + +internal static class CodeStyleOptionsStorage +{ + public static IdeCodeStyleOptions GetCodeStyleOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) + => languageServices.GetRequiredService().GetOptions(globalOptions); + + public static IdeCodeStyleOptions.CommonOptions GetCommonCodeStyleOptions(this IGlobalOptionService globalOptions, string language) + => new() + { + PreferObjectInitializer = globalOptions.GetOption(CodeStyleOptions2.PreferObjectInitializer, language), + PreferCollectionInitializer = globalOptions.GetOption(CodeStyleOptions2.PreferCollectionInitializer, language), + PreferSimplifiedBooleanExpressions = globalOptions.GetOption(CodeStyleOptions2.PreferSimplifiedBooleanExpressions, language), + OperatorPlacementWhenWrapping = globalOptions.GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping, language), + PreferCoalesceExpression = globalOptions.GetOption(CodeStyleOptions2.PreferCoalesceExpression, language), + PreferNullPropagation = globalOptions.GetOption(CodeStyleOptions2.PreferNullPropagation, language), + PreferExplicitTupleNames = globalOptions.GetOption(CodeStyleOptions2.PreferExplicitTupleNames, language), + PreferAutoProperties = globalOptions.GetOption(CodeStyleOptions2.PreferAutoProperties, language), + PreferInferredTupleNames = globalOptions.GetOption(CodeStyleOptions2.PreferInferredTupleNames, language), + PreferInferredAnonymousTypeMemberNames = globalOptions.GetOption(CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames, language), + PreferIsNullCheckOverReferenceEqualityMethod = globalOptions.GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod, language), + PreferConditionalExpressionOverAssignment = globalOptions.GetOption(CodeStyleOptions2.PreferConditionalExpressionOverAssignment, language), + PreferConditionalExpressionOverReturn = globalOptions.GetOption(CodeStyleOptions2.PreferConditionalExpressionOverReturn, language), + PreferCompoundAssignment = globalOptions.GetOption(CodeStyleOptions2.PreferCompoundAssignment, language), + PreferSimplifiedInterpolation = globalOptions.GetOption(CodeStyleOptions2.PreferSimplifiedInterpolation, language), + UnusedParameters = globalOptions.GetOption(CodeStyleOptions2.UnusedParameters, language), + AccessibilityModifiersRequired = globalOptions.GetOption(CodeStyleOptions2.AccessibilityModifiersRequired, language), + PreferReadonly = globalOptions.GetOption(CodeStyleOptions2.PreferReadonly, language), + ArithmeticBinaryParentheses = globalOptions.GetOption(CodeStyleOptions2.ArithmeticBinaryParentheses, language), + OtherBinaryParentheses = globalOptions.GetOption(CodeStyleOptions2.OtherBinaryParentheses, language), + RelationalBinaryParentheses = globalOptions.GetOption(CodeStyleOptions2.RelationalBinaryParentheses, language), + OtherParentheses = globalOptions.GetOption(CodeStyleOptions2.OtherParentheses, language), + ForEachExplicitCastInSource = globalOptions.GetOption(CodeStyleOptions2.ForEachExplicitCastInSource, language), + PreferNamespaceAndFolderMatchStructure = globalOptions.GetOption(CodeStyleOptions2.PreferNamespaceAndFolderMatchStructure, language), + AllowMultipleBlankLines = globalOptions.GetOption(CodeStyleOptions2.AllowMultipleBlankLines, language), + AllowStatementImmediatelyAfterBlock = globalOptions.GetOption(CodeStyleOptions2.AllowStatementImmediatelyAfterBlock, language), + RemoveUnnecessarySuppressionExclusions = globalOptions.GetOption(CodeStyleOptions2.RemoveUnnecessarySuppressionExclusions) + }; +} diff --git a/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs index 90e9c1145c703..6468b9b373b7f 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/CompletionOptionsStorage.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.Completion; @@ -9,23 +10,26 @@ namespace Microsoft.CodeAnalysis.Completion; 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)); + => 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), + NamingStyleFallbackOptions = options.GetNamingStylePreferences(language) + }; // feature flags diff --git a/src/Features/LanguageServer/Protocol/Features/Options/DocumentFormattingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/DocumentFormattingOptionsStorage.cs new file mode 100644 index 0000000000000..9f19bc0c22841 --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Features/Options/DocumentFormattingOptionsStorage.cs @@ -0,0 +1,29 @@ +// 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.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Formatting; + +internal static class DocumentFormattingOptionsStorage +{ + public static ValueTask GetDocumentFormattingOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) + => document.GetDocumentFormattingOptionsAsync(globalOptions.GetDocumentFormattingOptions(document.Project.Language), cancellationToken); + +#pragma warning disable IDE0060 // Unused parameters to match common pattern + public static DocumentFormattingOptions GetDocumentFormattingOptions(this IGlobalOptionService globalOptions, string language) + => new( + // FileHeaderTemplate not stored in global options (does not have a storage other than editorconfig) + // InsertFinalNewLine not stored in global options (does not have a storage other than editorconfig) + ); +#pragma warning restore +} + diff --git a/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs index d8018e8553bfd..296cbd2d7bddf 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/DocumentationCommentOptionsStorage.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 System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; @@ -9,22 +11,25 @@ namespace Microsoft.CodeAnalysis.DocumentationComments; internal static class DocumentationCommentOptionsStorage { - public static DocumentationCommentOptions GetDocumentationCommentOptions(this IGlobalOptionService globalOptions, DocumentOptionSet documentOptions) - => new( - AutoXmlDocCommentGeneration: globalOptions.GetOption(AutoXmlDocCommentGeneration, documentOptions.Language), - TabSize: documentOptions.GetOption(FormattingOptions.TabSize), - UseTabs: documentOptions.GetOption(FormattingOptions.UseTabs), - NewLine: documentOptions.GetOption(FormattingOptions.NewLine)); + public static async ValueTask GetDocumentationCommentOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) + { + var lineFormattingOptions = await document.GetLineFormattingOptionsAsync(globalOptions, cancellationToken).ConfigureAwait(false); + return new() + { + LineFormatting = lineFormattingOptions, + AutoXmlDocCommentGeneration = globalOptions.GetOption(AutoXmlDocCommentGeneration, document.Project.Language) + }; + } public static DocumentationCommentOptions GetDocumentationCommentOptions(this IGlobalOptionService globalOptions, SyntaxFormattingOptions formattingOptions, string language) - => new( - AutoXmlDocCommentGeneration: globalOptions.GetOption(AutoXmlDocCommentGeneration, language), - TabSize: formattingOptions.TabSize, - UseTabs: formattingOptions.UseTabs, - NewLine: formattingOptions.NewLine); + => new() + { + LineFormatting = formattingOptions.LineFormatting, + AutoXmlDocCommentGeneration = globalOptions.GetOption(AutoXmlDocCommentGeneration, language) + }; public static readonly PerLanguageOption2 AutoXmlDocCommentGeneration = new( - "DocumentationCommentOptions", "AutoXmlDocCommentGeneration", defaultValue: true, + "DocumentationCommentOptions", "AutoXmlDocCommentGeneration", DocumentationCommentOptions.Default.AutoXmlDocCommentGeneration, storageLocation: new RoamingProfileStorageLocation(language => language == LanguageNames.VisualBasic ? "TextEditor.%LANGUAGE%.Specific.AutoComment" : "TextEditor.%LANGUAGE%.Specific.Automatic XML Doc Comment Generation")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs index ee6de6c55232f..b8f6ced181941 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/ExtractMethodOptionsStorage.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; @@ -15,14 +16,18 @@ namespace Microsoft.CodeAnalysis.ExtractMethod; internal static class ExtractMethodOptionsStorage { public static ExtractMethodOptions GetExtractMethodOptions(this IGlobalOptionService globalOptions, string language) - => new( - DontPutOutOrRefOnStruct: globalOptions.GetOption(DontPutOutOrRefOnStruct, language)); + => new() + { + DontPutOutOrRefOnStruct = globalOptions.GetOption(DontPutOutOrRefOnStruct, language) + }; public static ExtractMethodGenerationOptions GetExtractMethodGenerationOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) - => new(globalOptions.GetExtractMethodOptions(languageServices.Language), - globalOptions.GetCodeGenerationOptions(languageServices), - globalOptions.GetAddImportPlacementOptions(languageServices), - globalOptions.GetNamingStylePreferencesProvider()); + => new(globalOptions.GetCodeGenerationOptions(languageServices)) + { + ExtractOptions = globalOptions.GetExtractMethodOptions(languageServices.Language), + AddImportOptions = globalOptions.GetAddImportPlacementOptions(languageServices), + LineFormattingOptions = globalOptions.GetLineFormattingOptions(languageServices.Language) + }; public static ValueTask GetExtractMethodGenerationOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) => document.GetExtractMethodGenerationOptionsAsync(globalOptions.GetExtractMethodGenerationOptions(document.Project.LanguageServices), cancellationToken); diff --git a/src/Features/LanguageServer/Protocol/Features/Options/GlobalCodeActionOptionsProvider.cs b/src/Features/LanguageServer/Protocol/Features/Options/GlobalCodeActionOptionsProvider.cs index 7668c0f593478..68356e1e08160 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/GlobalCodeActionOptionsProvider.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/GlobalCodeActionOptionsProvider.cs @@ -11,8 +11,11 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; @@ -42,6 +45,12 @@ public Provider(IGlobalOptionService globalOptions) CodeActionOptions CodeActionOptionsProvider.GetOptions(HostLanguageServices languageService) => _globalOptions.GetCodeActionOptions(languageService); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(_globalOptions.GetLineFormattingOptions(languageServices.Language)); + + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(_globalOptions.GetDocumentFormattingOptions(languageServices.Language)); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetSyntaxFormattingOptions(languageServices)); @@ -51,12 +60,18 @@ ValueTask OptionsProvider.GetOptionsAsync( ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetAddImportPlacementOptions(languageServices)); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(_globalOptions.GetOrganizeImportsOptions(languageServices.Language)); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetCodeCleanupOptions(languageServices)); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetCodeGenerationOptions(languageServices)); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(_globalOptions.GetNamingStylePreferences(languageServices.Language)); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_globalOptions.GetCleanCodeGenerationOptions(languageServices)); diff --git a/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs index 0b348595eba77..1f8f5284e2955 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/HighlightingOptionsStorage.cs @@ -9,9 +9,11 @@ namespace Microsoft.CodeAnalysis.DocumentHighlighting; internal static class HighlightingOptionsStorage { public static HighlightingOptions GetHighlightingOptions(this IGlobalOptionService globalOptions, string language) - => new( - HighlightRelatedRegexComponentsUnderCursor: globalOptions.GetOption(HighlightRelatedRegexComponentsUnderCursor, language), - HighlightRelatedJsonComponentsUnderCursor: globalOptions.GetOption(HighlightRelatedJsonComponentsUnderCursor, language)); + => new() + { + HighlightRelatedRegexComponentsUnderCursor = globalOptions.GetOption(HighlightRelatedRegexComponentsUnderCursor, language), + HighlightRelatedJsonComponentsUnderCursor = globalOptions.GetOption(HighlightRelatedJsonComponentsUnderCursor, language) + }; public static PerLanguageOption2 HighlightRelatedRegexComponentsUnderCursor = new("RegularExpressionsOptions", diff --git a/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs index fa82def580046..1bded39c1bc6b 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/IdeAnalyzerOptionsStorage.cs @@ -6,7 +6,9 @@ using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.CodeGeneration; namespace Microsoft.CodeAnalysis.Diagnostics; @@ -18,52 +20,64 @@ public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this IGlobalOptionService public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) { var language = languageServices.Language; - var supportsCleanupOptions = languageServices.GetService() != null; + var supportsLanguageSpecificOptions = languageServices.GetService() != null; - 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), - CleanupOptions: supportsCleanupOptions ? globalOptions.GetCodeCleanupOptions(languageServices) : null); + return new() + { + CrashOnAnalyzerException = globalOptions.GetOption(CrashOnAnalyzerException), + FadeOutUnusedImports = globalOptions.GetOption(FadeOutUnusedImports, language), + FadeOutUnreachableCode = globalOptions.GetOption(FadeOutUnreachableCode, language), + FadeOutComplexObjectInitialization = globalOptions.GetOption(FadeOutComplexObjectInitialization, language), + ReportInvalidPlaceholdersInStringDotFormatCalls = globalOptions.GetOption(ReportInvalidPlaceholdersInStringDotFormatCalls, language), + ReportInvalidRegexPatterns = globalOptions.GetOption(ReportInvalidRegexPatterns, language), + ReportInvalidJsonPatterns = globalOptions.GetOption(ReportInvalidJsonPatterns, language), + DetectAndOfferEditorFeaturesForProbableJsonStrings = globalOptions.GetOption(DetectAndOfferEditorFeaturesForProbableJsonStrings, language), + CleanCodeGenerationOptions = supportsLanguageSpecificOptions ? globalOptions.GetCleanCodeGenerationOptions(languageServices) : null, + CodeStyleOptions = supportsLanguageSpecificOptions ? globalOptions.GetCodeStyleOptions(languageServices) : null, + }; } public static readonly Option2 CrashOnAnalyzerException = new( - "InternalDiagnosticsOptions", "CrashOnAnalyzerException", IdeAnalyzerOptions.DefaultCrashOnAnalyzerException, + "InternalDiagnosticsOptions", "CrashOnAnalyzerException", IdeAnalyzerOptions.CommonDefault.CrashOnAnalyzerException, storageLocation: new LocalUserProfileStorageLocation(@"Roslyn\Internal\Diagnostics\CrashOnAnalyzerException")); public static readonly PerLanguageOption2 FadeOutUnusedImports = new( - "FadingOptions", "FadeOutUnusedImports", IdeAnalyzerOptions.DefaultFadeOutUnusedImports, + "FadingOptions", "FadeOutUnusedImports", IdeAnalyzerOptions.CommonDefault.FadeOutUnusedImports, storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.FadeOutUnusedImports")); public static readonly PerLanguageOption2 FadeOutUnreachableCode = new( - "FadingOptions", "FadeOutUnreachableCode", IdeAnalyzerOptions.DefaultFadeOutUnreachableCode, + "FadingOptions", "FadeOutUnreachableCode", IdeAnalyzerOptions.CommonDefault.FadeOutUnreachableCode, storageLocation: new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.FadeOutUnreachableCode")); + public static readonly PerLanguageOption2 FadeOutComplexObjectInitialization = new( + "CodeStyleOptions", "PreferObjectInitializer_FadeOutCode", IdeAnalyzerOptions.CommonDefault.FadeOutComplexObjectInitialization, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer_FadeOutCode")); + + internal static readonly PerLanguageOption2 FadeOutComplexCollectionInitialization = new( + "CodeStyleOptions", "PreferCollectionInitializer_FadeOutCode", IdeAnalyzerOptions.CommonDefault.FadeOutComplexCollectionInitialization, + storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferCollectionInitializer_FadeOutCode")); + public static PerLanguageOption2 ReportInvalidPlaceholdersInStringDotFormatCalls = new("ValidateFormatStringOption", "ReportInvalidPlaceholdersInStringDotFormatCalls", - IdeAnalyzerOptions.DefaultReportInvalidPlaceholdersInStringDotFormatCalls, + IdeAnalyzerOptions.CommonDefault.ReportInvalidPlaceholdersInStringDotFormatCalls, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.WarnOnInvalidStringDotFormatCalls")); public static PerLanguageOption2 ReportInvalidRegexPatterns = new("RegularExpressionsOptions", "ReportInvalidRegexPatterns", - IdeAnalyzerOptions.DefaultReportInvalidRegexPatterns, + IdeAnalyzerOptions.CommonDefault.ReportInvalidRegexPatterns, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ReportInvalidRegexPatterns")); public static PerLanguageOption2 ReportInvalidJsonPatterns = new("JsonFeatureOptions", "ReportInvalidJsonPatterns", - defaultValue: IdeAnalyzerOptions.DefaultReportInvalidJsonPatterns, + defaultValue: IdeAnalyzerOptions.CommonDefault.ReportInvalidJsonPatterns, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ReportInvalidJsonPatterns")); public static PerLanguageOption2 DetectAndOfferEditorFeaturesForProbableJsonStrings = new("JsonFeatureOptions", "DetectAndOfferEditorFeaturesForProbableJsonStrings", - defaultValue: IdeAnalyzerOptions.DefaultDetectAndOfferEditorFeaturesForProbableJsonStrings, + defaultValue: IdeAnalyzerOptions.CommonDefault.DetectAndOfferEditorFeaturesForProbableJsonStrings, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.DetectAndOfferEditorFeaturesForProbableJsonStrings")); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/ImplementTypeOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/ImplementTypeOptionsStorage.cs index 688a5fd575d3a..016a156d0fa38 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/ImplementTypeOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/ImplementTypeOptionsStorage.cs @@ -11,9 +11,11 @@ namespace Microsoft.CodeAnalysis.ImplementType internal static class ImplementTypeOptionsStorage { public static ImplementTypeOptions GetImplementTypeOptions(this IGlobalOptionService globalOptions, string language) - => new( - InsertionBehavior: globalOptions.GetOption(InsertionBehavior, language), - PropertyGenerationBehavior: globalOptions.GetOption(PropertyGenerationBehavior, language)); + => new() + { + InsertionBehavior = globalOptions.GetOption(InsertionBehavior, language), + PropertyGenerationBehavior = globalOptions.GetOption(PropertyGenerationBehavior, language) + }; public static ImplementTypeGenerationOptions GetImplementTypeGenerationOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) => new(globalOptions.GetImplementTypeOptions(languageServices.Language), diff --git a/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs index fcab504f4b285..9fd8f38c93dcc 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/IndentationOptionsStorage.cs @@ -14,10 +14,12 @@ internal static class IndentationOptionsStorage public static async Task GetIndentationOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) { var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(globalOptions, cancellationToken).ConfigureAwait(false); - var autoFormattingOptions = globalOptions.GetAutoFormattingOptions(document.Project.Language); - var indentStyle = globalOptions.GetOption(SmartIndent, document.Project.Language); - return new(formattingOptions, autoFormattingOptions, indentStyle); + return new IndentationOptions(formattingOptions) + { + AutoFormattingOptions = globalOptions.GetAutoFormattingOptions(document.Project.Language), + IndentStyle = globalOptions.GetOption(SmartIndent, document.Project.Language) + }; } public static PerLanguageOption2 SmartIndent => FormattingOptions2.SmartIndent; diff --git a/src/Features/LanguageServer/Protocol/Features/Options/LineFormattingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/LineFormattingOptionsStorage.cs index 7fad59a840b9f..0c03b709c2ba7 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/LineFormattingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/LineFormattingOptionsStorage.cs @@ -14,14 +14,16 @@ namespace Microsoft.CodeAnalysis.Formatting; internal static class LineFormattingOptionsStorage { - public static Task GetLineFormattingOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) - => LineFormattingOptions.FromDocumentAsync(document, globalOptions.GetLineFormattingOptions(document.Project.Language), cancellationToken); + public static ValueTask GetLineFormattingOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) + => document.GetLineFormattingOptionsAsync(globalOptions.GetLineFormattingOptions(document.Project.Language), cancellationToken); public static LineFormattingOptions GetLineFormattingOptions(this IGlobalOptionService globalOptions, string language) - => new( - UseTabs: globalOptions.GetOption(FormattingOptions2.UseTabs, language), - TabSize: globalOptions.GetOption(FormattingOptions2.TabSize, language), - IndentationSize: globalOptions.GetOption(FormattingOptions2.IndentationSize, language), - NewLine: globalOptions.GetOption(FormattingOptions2.NewLine, language)); + => new() + { + UseTabs = globalOptions.GetOption(FormattingOptions2.UseTabs, language), + TabSize = globalOptions.GetOption(FormattingOptions2.TabSize, language), + IndentationSize = globalOptions.GetOption(FormattingOptions2.IndentationSize, language), + NewLine = globalOptions.GetOption(FormattingOptions2.NewLine, language) + }; } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/NamingStylePreferencesStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/NamingStyleOptionsStorage.cs similarity index 74% rename from src/Features/LanguageServer/Protocol/Features/Options/NamingStylePreferencesStorage.cs rename to src/Features/LanguageServer/Protocol/Features/Options/NamingStyleOptionsStorage.cs index 965865012f8b5..da07069aa51eb 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/NamingStylePreferencesStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/NamingStyleOptionsStorage.cs @@ -2,7 +2,10 @@ // 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.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Simplification; @@ -12,7 +15,4 @@ internal static class NamingStyleOptionsStorage { public static NamingStylePreferences GetNamingStylePreferences(this IGlobalOptionService globalOptions, string language) => globalOptions.GetOption(NamingStyleOptions.NamingPreferences, language); - - public static NamingStylePreferencesProvider GetNamingStylePreferencesProvider(this IGlobalOptionService globalOptions) - => languageServices => globalOptions.GetNamingStylePreferences(languageServices.Language); } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/OrganizeImportsOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/OrganizeImportsOptionsStorage.cs new file mode 100644 index 0000000000000..904689ddcfbea --- /dev/null +++ b/src/Features/LanguageServer/Protocol/Features/Options/OrganizeImportsOptionsStorage.cs @@ -0,0 +1,25 @@ +// 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.Editing; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.OrganizeImports; + +internal static class OrganizeImportsOptionsStorage +{ + public static ValueTask GetOrganizeImportsOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) + => document.GetOrganizeImportsOptionsAsync(globalOptions.GetOrganizeImportsOptions(document.Project.Language), cancellationToken); + + public static OrganizeImportsOptions GetOrganizeImportsOptions(this IGlobalOptionService globalOptions, string language) + => new() + { + PlaceSystemNamespaceFirst = globalOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, language), + SeparateImportDirectiveGroups = globalOptions.GetOption(GenerationOptions.SeparateImportDirectiveGroups, language), + NewLine = globalOptions.GetOption(FormattingOptions2.NewLine, language) + }; +} diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs index 0e8073eced14e..c1546e9bded13 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/SimplifierOptionsStorage.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; @@ -21,4 +22,15 @@ public static ValueTask GetSimplifierOptionsAsync(this Docume public static SimplifierOptions GetSimplifierOptions(this IGlobalOptionService globalOptions, HostLanguageServices languageServices) => languageServices.GetRequiredService().GetOptions(globalOptions); + + public static SimplifierOptions.CommonOptions GetCommonSimplifierOptions(this IGlobalOptionService globalOptions, string language) + => new() + { + QualifyFieldAccess = globalOptions.GetOption(CodeStyleOptions2.QualifyFieldAccess, language), + QualifyPropertyAccess = globalOptions.GetOption(CodeStyleOptions2.QualifyPropertyAccess, language), + QualifyMethodAccess = globalOptions.GetOption(CodeStyleOptions2.QualifyMethodAccess, language), + QualifyEventAccess = globalOptions.GetOption(CodeStyleOptions2.QualifyEventAccess, language), + PreferPredefinedTypeKeywordInMemberAccess = globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, language), + PreferPredefinedTypeKeywordInDeclaration = globalOptions.GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, language) + }; } diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SymbolSearchOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SymbolSearchOptionsStorage.cs index fbd8903617613..63e76785a6abe 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/SymbolSearchOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/SymbolSearchOptionsStorage.cs @@ -9,9 +9,11 @@ namespace Microsoft.CodeAnalysis.SymbolSearch internal static class SymbolSearchOptionsStorage { internal static SymbolSearchOptions GetSymbolSearchOptions(this IGlobalOptionService globalOptions, string language) - => new( - SearchReferenceAssemblies: globalOptions.GetOption(SearchReferenceAssemblies, language), - SearchNuGetPackages: globalOptions.GetOption(SearchNuGetPackages, language)); + => new() + { + SearchReferenceAssemblies = globalOptions.GetOption(SearchReferenceAssemblies, language), + SearchNuGetPackages = globalOptions.GetOption(SearchNuGetPackages, language) + }; private const string FeatureName = "SymbolSearchOptions"; diff --git a/src/Features/LanguageServer/Protocol/Features/Options/SyntaxFormattingOptionsStorage.cs b/src/Features/LanguageServer/Protocol/Features/Options/SyntaxFormattingOptionsStorage.cs index 2a087964517bf..816cb2c28b511 100644 --- a/src/Features/LanguageServer/Protocol/Features/Options/SyntaxFormattingOptionsStorage.cs +++ b/src/Features/LanguageServer/Protocol/Features/Options/SyntaxFormattingOptionsStorage.cs @@ -7,6 +7,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; @@ -19,6 +21,14 @@ internal interface ISyntaxFormattingOptionsStorage : ILanguageService internal static class SyntaxFormattingOptionsStorage { + public static SyntaxFormattingOptions.CommonOptions GetCommonSyntaxFormattingOptions(this IGlobalOptionService globalOptions, string language) + => new() + { + LineFormatting = globalOptions.GetLineFormattingOptions(language), + SeparateImportDirectiveGroups = globalOptions.GetOption(GenerationOptions.SeparateImportDirectiveGroups, language), + AccessibilityModifiersRequired = globalOptions.GetOption(CodeStyleOptions2.AccessibilityModifiersRequired, language).Value + }; + public static ValueTask GetSyntaxFormattingOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) => document.GetSyntaxFormattingOptionsAsync(globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices), cancellationToken); diff --git a/src/Features/Core/Portable/SolutionCrawler/MiscSolutionCrawlerWorkspaceEventListener.cs b/src/Features/LanguageServer/Protocol/Features/SolutionCrawler/MiscSolutionCrawlerWorkspaceEventListener.cs similarity index 100% rename from src/Features/Core/Portable/SolutionCrawler/MiscSolutionCrawlerWorkspaceEventListener.cs rename to src/Features/LanguageServer/Protocol/Features/SolutionCrawler/MiscSolutionCrawlerWorkspaceEventListener.cs diff --git a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs index 0ec8822d42302..b922ed7c4b78a 100644 --- a/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs +++ b/src/Features/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs @@ -37,7 +37,7 @@ public static async ValueTask> GetFilt Document document, TextSpan selection, CodeActionRequestPriority priority, - CodeActionOptionsProvider options, + CodeActionOptionsProvider fallbackOptions, bool isBlocking, Func addOperationScope, CancellationToken cancellationToken) @@ -48,7 +48,7 @@ public static async ValueTask> GetFilt document, selection, priority, - options, + fallbackOptions, isBlocking, addOperationScope, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs index d199238e85ad6..ba51b316078fb 100644 --- a/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/Formatting/FormatDocumentOnTypeHandler.cs @@ -64,7 +64,10 @@ public FormatDocumentOnTypeHandler(IGlobalOptionService globalOptions) // We should use the options passed in by LSP instead of the document's options. var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(request.Options, document, _globalOptions, cancellationToken).ConfigureAwait(false); - var indentationOptions = new IndentationOptions(formattingOptions, _globalOptions.GetAutoFormattingOptions(document.Project.Language)); + var indentationOptions = new IndentationOptions(formattingOptions) + { + AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language) + }; var textChanges = await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); if (textChanges.IsEmpty) diff --git a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs index b1b32520cf8f1..ffd56eda7c2e1 100644 --- a/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/OnAutoInsert/OnAutoInsertHandler.cs @@ -81,7 +81,10 @@ public OnAutoInsertHandler( // Once LSP supports overtype we can move all of brace completion to LSP. if (request.Character == "\n" && context.ServerKind == WellKnownLspServerKinds.RazorLspServer) { - var indentationOptions = new IndentationOptions(formattingOptions, _globalOptions.GetAutoFormattingOptions(document.Project.Language)); + var indentationOptions = new IndentationOptions(formattingOptions) + { + AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language) + }; var braceCompletionAfterReturnResponse = await GetBraceCompletionAfterReturnResponseAsync( request, document, indentationOptions, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/LanguageServer/Protocol/LspOptions.cs b/src/Features/LanguageServer/Protocol/LspOptions.cs index c3315c0cd4aef..cff00ff3fa61a 100644 --- a/src/Features/LanguageServer/Protocol/LspOptions.cs +++ b/src/Features/LanguageServer/Protocol/LspOptions.cs @@ -11,8 +11,7 @@ namespace Microsoft.CodeAnalysis.LanguageServer { - [ExportGlobalOptionProvider, Shared] - internal sealed class LspOptions : IOptionProvider + internal sealed class LspOptions { private const string LocalRegistryPath = @"Roslyn\Internal\Lsp\"; private const string FeatureName = "LspOptions"; @@ -31,15 +30,5 @@ internal sealed class LspOptions : IOptionProvider // Flag is defined in VisualStudio\Core\Def\PackageRegistration.pkgdef. public static readonly Option2 LspSemanticTokensFeatureFlag = new(FeatureName, nameof(LspSemanticTokensFeatureFlag), defaultValue: false, new FeatureFlagStorageLocation("Roslyn.LSP.SemanticTokens")); - - public ImmutableArray Options { get; } = ImmutableArray.Create( - MaxCompletionListSize, - LspEditorFeatureFlag); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public LspOptions() - { - } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index 6d04d3ffbdf24..8f4e2ac619d48 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Editor.Test; using Microsoft.CodeAnalysis.LanguageServer.Handler; using Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Experimental; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.SolutionCrawler; @@ -100,7 +101,7 @@ public async Task TestNoDocumentDiagnosticsForOpenFilesIfDefaultAndFeatureFlagOf await OpenDocumentAsync(testLspServer, document); // Ensure we get no diagnostics when feature flag is off. - testLspServer.TestWorkspace.SetOptions(testLspServer.TestWorkspace.Options.WithChangedOption(DiagnosticOptions.LspPullDiagnosticsFeatureFlag, false)); + testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(new OptionKey(DiagnosticOptions.LspPullDiagnosticsFeatureFlag), false); var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI(), useVSDiagnostics); Assert.Empty(results.Single().Diagnostics); @@ -118,7 +119,7 @@ public async Task TestDocumentDiagnosticsForOpenFilesIfDefaultAndFeatureFlagOn(b var document = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(); await OpenDocumentAsync(testLspServer, document); - testLspServer.TestWorkspace.SetOptions(testLspServer.TestWorkspace.Options.WithChangedOption(DiagnosticOptions.LspPullDiagnosticsFeatureFlag, true)); + testLspServer.TestWorkspace.GlobalOptions.SetGlobalOption(new OptionKey(DiagnosticOptions.LspPullDiagnosticsFeatureFlag), true); var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI(), useVSDiagnostics); Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); diff --git a/src/Features/VisualBasic/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.vb index 98cfb2c72bd98..3c6e5efe9c2ce 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/GenerateEnumMember/GenerateEnumMemberCodeFixProvider.vb @@ -32,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateEnumMember End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateEnumMemberService)() Return service.GenerateEnumMemberAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateConversionCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateConversionCodeFixProvider.vb index 76f5fb193d21e..cd765a87427d0 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateConversionCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateConversionCodeFixProvider.vb @@ -32,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateMethod End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateConversionService)() Return service.GenerateConversionAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateParameterizedMemberCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateParameterizedMemberCodeFixProvider.vb index 22ca8aef89b7d..84af5d9e3c77d 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateParameterizedMemberCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/GenerateParameterizedMember/GenerateParameterizedMemberCodeFixProvider.vb @@ -51,7 +51,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateMethod End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateParameterizedMemberService)() Return service.GenerateMethodAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.vb index 3dcf7f51329f7..46a81e7a1d719 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/GenerateType/GenerateTypeCodeFixProvider.vb @@ -40,7 +40,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateType End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateTypeService)() Return service.GenerateTypeAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/ConvertAutoPropertyToFullProperty/VisualBasicConvertAutoPropertyToFullProperty.vb b/src/Features/VisualBasic/Portable/ConvertAutoPropertyToFullProperty/VisualBasicConvertAutoPropertyToFullProperty.vb index 313a6aa6a82d1..29efb65cdf84d 100644 --- a/src/Features/VisualBasic/Portable/ConvertAutoPropertyToFullProperty/VisualBasicConvertAutoPropertyToFullProperty.vb +++ b/src/Features/VisualBasic/Portable/ConvertAutoPropertyToFullProperty/VisualBasicConvertAutoPropertyToFullProperty.vb @@ -7,6 +7,7 @@ Imports System.Diagnostics.CodeAnalysis Imports System.Threading Imports Microsoft.CodeAnalysis.CodeGeneration Imports Microsoft.CodeAnalysis.CodeRefactorings +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.ConvertAutoPropertyToFullProperty Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Options @@ -30,7 +31,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertAutoPropertyToFullProperty ''' name preceded by an underscore. We will use this as the field name so we don't mess up ''' any existing references to this field. ''' - Friend Overrides Function GetFieldNameAsync(document As Document, propertySymbol As IPropertySymbol, cancellationToken As CancellationToken) As Task(Of String) + Friend Overrides Function GetFieldNameAsync(document As Document, propertySymbol As IPropertySymbol, fallbackOptions As NamingStylePreferencesProvider, cancellationToken As CancellationToken) As Task(Of String) Return Task.FromResult(Underscore + propertySymbol.Name) End Function diff --git a/src/Features/VisualBasic/Portable/ConvertForToForEach/VisualBasicConvertForToForEachCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/ConvertForToForEach/VisualBasicConvertForToForEachCodeRefactoringProvider.vb index 5e55d16a3162f..cd1196a835eed 100644 --- a/src/Features/VisualBasic/Portable/ConvertForToForEach/VisualBasicConvertForToForEachCodeRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/ConvertForToForEach/VisualBasicConvertForToForEachCodeRefactoringProvider.vb @@ -78,7 +78,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertForToForEach Protected Overrides Function ConvertForNode( currentFor As ForBlockSyntax, typeNode As TypeSyntax, - foreachIdentifier As SyntaxToken, collectionExpression As ExpressionSyntax, iterationVariableType As ITypeSymbol, options As OptionSet) As SyntaxNode + foreachIdentifier As SyntaxToken, collectionExpression As ExpressionSyntax, iterationVariableType As ITypeSymbol) As SyntaxNode Dim forStatement = currentFor.ForStatement Return SyntaxFactory.ForEachBlock( diff --git a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb index 2456c2287bdb3..16d720c1804de 100644 --- a/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/Diagnostics/Analyzers/VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb @@ -39,7 +39,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Dim semanticModel = context.SemanticModel Dim cancellationToken = context.CancellationToken - Dim simplifierOptions = context.Options.GetVisualBasicSimplifierOptions(semanticModel.SyntaxTree) + Dim simplifierOptions = context.GetVisualBasicAnalyzerOptions().GetSimplifierOptions() Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, simplifierOptions, ignoredSpans:=Nothing, cancellationToken) simplifier.Visit(context.CodeBlock) @@ -52,7 +52,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames Dim syntaxTree = semanticModel.SyntaxTree Dim configOptions = context.Options.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree) - Dim simplifierOptions = context.Options.GetVisualBasicSimplifierOptions(semanticModel.SyntaxTree) + Dim simplifierOptions = context.GetVisualBasicAnalyzerOptions().GetSimplifierOptions() Dim root = syntaxTree.GetRoot(cancellationToken) Dim simplifier As New TypeSyntaxSimplifierWalker(Me, semanticModel, simplifierOptions, ignoredSpans:=codeBlockIntervalTree, cancellationToken) diff --git a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb index bc5014c92bde9..3e1362584bc24 100644 --- a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb +++ b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.ExpressionCodeGenerator.vb @@ -7,6 +7,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.ExtractMethod Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod @@ -15,8 +16,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod Private Class ExpressionCodeGenerator Inherits VisualBasicCodeGenerator - Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult) - MyBase.New(insertionPoint, selectionResult, analyzerResult) + Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions) + MyBase.New(insertionPoint, selectionResult, analyzerResult, options) End Sub Public Shared Function IsExtractMethodOnExpression(code As SelectionResult) As Boolean diff --git a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb index 0a7d67bffd491..02c8c2c32d8e0 100644 --- a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb +++ b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.MultipleStatementsCodeGenerator.vb @@ -6,6 +6,7 @@ Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.ExtractMethod +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod @@ -14,8 +15,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod Private Class MultipleStatementsCodeGenerator Inherits VisualBasicCodeGenerator - Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult) - MyBase.New(insertionPoint, selectionResult, analyzerResult) + Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions) + MyBase.New(insertionPoint, selectionResult, analyzerResult, options) End Sub Public Shared Function IsExtractMethodOnMultipleStatements(code As SelectionResult) As Boolean diff --git a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb index 276662358b6a2..7d6a77181c7c1 100644 --- a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb +++ b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.SingleStatementCodeGenerator.vb @@ -6,6 +6,7 @@ Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.ExtractMethod +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod @@ -14,8 +15,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod Private Class SingleStatementCodeGenerator Inherits VisualBasicCodeGenerator - Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult) - MyBase.New(insertionPoint, selectionResult, analyzerResult) + Public Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions) + MyBase.New(insertionPoint, selectionResult, analyzerResult, options) End Sub Public Shared Function IsExtractMethodOnSingleStatement(code As SelectionResult) As Boolean diff --git a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb index 2f47b5dd6822a..b18200622ecbc 100644 --- a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb +++ b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.VisualBasicCodeGenerator.vb @@ -23,30 +23,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod Private ReadOnly _methodName As SyntaxToken - Public Shared Async Function GenerateResultAsync(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, cancellationToken As CancellationToken) As Task(Of GeneratedCode) - Dim generator = Create(insertionPoint, selectionResult, analyzerResult) + Public Shared Async Function GenerateResultAsync(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions, cancellationToken As CancellationToken) As Task(Of GeneratedCode) + Dim generator = Create(insertionPoint, selectionResult, analyzerResult, options) Return Await generator.GenerateAsync(cancellationToken).ConfigureAwait(False) End Function - Private Shared Function Create(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult) As VisualBasicCodeGenerator + Private Shared Function Create(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions) As VisualBasicCodeGenerator If ExpressionCodeGenerator.IsExtractMethodOnExpression(selectionResult) Then - Return New ExpressionCodeGenerator(insertionPoint, selectionResult, analyzerResult) + Return New ExpressionCodeGenerator(insertionPoint, selectionResult, analyzerResult, options) End If If SingleStatementCodeGenerator.IsExtractMethodOnSingleStatement(selectionResult) Then - Return New SingleStatementCodeGenerator(insertionPoint, selectionResult, analyzerResult) + Return New SingleStatementCodeGenerator(insertionPoint, selectionResult, analyzerResult, options) End If If MultipleStatementsCodeGenerator.IsExtractMethodOnMultipleStatements(selectionResult) Then - Return New MultipleStatementsCodeGenerator(insertionPoint, selectionResult, analyzerResult) + Return New MultipleStatementsCodeGenerator(insertionPoint, selectionResult, analyzerResult, options) End If Throw ExceptionUtilities.UnexpectedValue(selectionResult) End Function - Protected Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult) - MyBase.New(insertionPoint, selectionResult, analyzerResult, VisualBasicCodeGenerationOptions.Default, Function(language) NamingStylePreferences.Default, localFunction:=False) + Protected Sub New(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzerResult As AnalyzerResult, options As VisualBasicCodeGenerationOptions) + MyBase.New(insertionPoint, selectionResult, analyzerResult, options, localFunction:=False) Contract.ThrowIfFalse(Me.SemanticDocument Is selectionResult.SemanticDocument) Me._methodName = CreateMethodName().WithAdditionalAnnotations(MethodNameAnnotation) diff --git a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb index 7dbde2a0b8fc0..517b9feb0380f 100644 --- a/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb +++ b/src/Features/VisualBasic/Portable/ExtractMethod/VisualBasicMethodExtractor.vb @@ -12,6 +12,7 @@ Imports Microsoft.CodeAnalysis.Formatting.Rules Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.VisualBasic +Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod @@ -68,8 +69,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractMethod Return Await selection.SemanticDocument.WithSyntaxRootAsync(selection.SemanticDocument.Root.ReplaceNode(lastExpression, newStatement), cancellationToken).ConfigureAwait(False) End Function - Protected Overrides Function GenerateCodeAsync(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzeResult As AnalyzerResult, options As CodeGenerationOptions, namingPreferences As NamingStylePreferencesProvider, cancellationToken As CancellationToken) As Task(Of GeneratedCode) - Return VisualBasicCodeGenerator.GenerateResultAsync(insertionPoint, selectionResult, analyzeResult, cancellationToken) + Protected Overrides Function GenerateCodeAsync(insertionPoint As InsertionPoint, selectionResult As SelectionResult, analyzeResult As AnalyzerResult, options As CodeGenerationOptions, cancellationToken As CancellationToken) As Task(Of GeneratedCode) + Return VisualBasicCodeGenerator.GenerateResultAsync(insertionPoint, selectionResult, analyzeResult, DirectCast(options, VisualBasicCodeGenerationOptions), cancellationToken) End Function Protected Overrides Function GetCustomFormattingRules(document As Document) As ImmutableArray(Of AbstractFormattingRule) diff --git a/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb b/src/Features/VisualBasic/Portable/Formatting/VisualBasicOrganizeUsingsNewDocumentFormattingProvider.vb index 51b0f473ae6cd..672ce0df743cf 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.OrganizeImports Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Host.Mef @@ -18,8 +19,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Public Sub New() End Sub - 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) + Public Async Function FormatNewDocumentAsync(document As Document, hintDocument As Document, options As CodeCleanupOptions, cancellationToken As CancellationToken) As Task(Of Document) Implements INewDocumentFormattingProvider.FormatNewDocumentAsync + Dim service = document.GetRequiredLanguageService(Of IOrganizeImportsService) + Dim organizeOptions = Await document.GetOrganizeImportsOptionsAsync(options.GetOrganizeImportsOptions(), cancellationToken).ConfigureAwait(False) + Return Await service.OrganizeImportsAsync(document, organizeOptions, cancellationToken).ConfigureAwait(False) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb b/src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb index fe4a611523c25..0d670ad280712 100644 --- a/src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb @@ -49,7 +49,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateConstructor End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateConstructorService)() Return service.GenerateConstructorAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/GenerateConstructorFromMembers/VisualBasicGenerateConstructorFromMembersCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/GenerateConstructorFromMembers/VisualBasicGenerateConstructorFromMembersCodeRefactoringProvider.vb index 99a44994cd680..a6bff1c2e155e 100644 --- a/src/Features/VisualBasic/Portable/GenerateConstructorFromMembers/VisualBasicGenerateConstructorFromMembersCodeRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/GenerateConstructorFromMembers/VisualBasicGenerateConstructorFromMembersCodeRefactoringProvider.vb @@ -4,11 +4,13 @@ Imports System.Composition Imports System.Diagnostics.CodeAnalysis +Imports System.Threading Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.GenerateConstructorFromMembers Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.PickMembers +Imports Microsoft.CodeAnalysis.Simplification Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateConstructorFromMembers @@ -37,9 +39,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateConstructorFromMembers Return SymbolDisplay.ToDisplayString(parameter, format) End Function - Protected Overrides Function PrefersThrowExpression(options As DocumentOptionSet) As Boolean + Protected Overrides Function PrefersThrowExpressionAsync(document As Document, fallbackOptions As SimplifierOptionsProvider, cancellationToken As CancellationToken) As ValueTask(Of Boolean) ' No throw expression preference option is defined for VB because it doesn't support throw expressions. - Return False + Return ValueTaskFactory.FromResult(False) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb b/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb index df35bfcb8462b..dc029b8b77b94 100644 --- a/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb +++ b/src/Features/VisualBasic/Portable/GenerateType/VisualBasicGenerateTypeService.vb @@ -5,6 +5,7 @@ Imports System.Collections.Immutable Imports System.Composition Imports System.Threading +Imports Microsoft.CodeAnalysis.AddImport Imports Microsoft.CodeAnalysis.CodeGeneration Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Formatting @@ -623,17 +624,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateType Return TypeOf expression Is SimpleNameSyntax End Function - Friend Overrides Async Function TryAddUsingsOrImportToDocumentAsync(updatedSolution As Solution, modifiedRoot As SyntaxNode, document As Document, simpleName As SimpleNameSyntax, includeUsingsOrImports As String, cancellationToken As CancellationToken) As Task(Of Solution) + Friend Overrides Async Function TryAddUsingsOrImportToDocumentAsync( + updatedSolution As Solution, + modifiedRoot As SyntaxNode, + document As Document, + simpleName As SimpleNameSyntax, + includeUsingsOrImports As String, + fallbackOptions As AddImportPlacementOptionsProvider, + cancellationToken As CancellationToken) As Task(Of Solution) + ' Nothing to include If String.IsNullOrWhiteSpace(includeUsingsOrImports) Then Return updatedSolution End If - Dim documentOptions = Await document.GetOptionsAsync(cancellationToken).ConfigureAwait(False) - Dim placeSystemNamespaceFirst = documentOptions.GetOption(GenerationOptions.PlaceSystemNamespaceFirst) - Dim root As SyntaxNode = Nothing - If (modifiedRoot Is Nothing) Then + If modifiedRoot Is Nothing Then root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Else root = modifiedRoot @@ -670,7 +676,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateType Return updatedSolution End If - Dim addedCompilationRoot = compilationRoot.AddImportsStatement(newImport, placeSystemNamespaceFirst, Formatter.Annotation, Simplifier.Annotation) + Dim addImportOptions = Await document.GetAddImportPlacementOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(False) + Dim addedCompilationRoot = compilationRoot.AddImportsStatement(newImport, addImportOptions.PlaceSystemNamespaceFirst, Formatter.Annotation, Simplifier.Annotation) updatedSolution = updatedSolution.WithDocumentSyntaxRoot(document.Id, addedCompilationRoot, PreservationMode.PreserveIdentity) End If diff --git a/src/Features/VisualBasic/Portable/GenerateVariable/VisualBasicGenerateVariableCodeFixProvider.vb b/src/Features/VisualBasic/Portable/GenerateVariable/VisualBasicGenerateVariableCodeFixProvider.vb index 703bbf4972f5e..ae7311d89a27c 100644 --- a/src/Features/VisualBasic/Portable/GenerateVariable/VisualBasicGenerateVariableCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/GenerateVariable/VisualBasicGenerateVariableCodeFixProvider.vb @@ -35,7 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateVariable End Get End Property - Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CodeAndImportGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) + Protected Overrides Function GetCodeActionsAsync(document As Document, node As SyntaxNode, fallbackOptions As CleanCodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of CodeAction)) Dim service = document.GetLanguageService(Of IGenerateVariableService)() Return service.GenerateVariableAsync(document, node, fallbackOptions, cancellationToken) End Function diff --git a/src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb index 98d6344cad377..7082e5a344291 100644 --- a/src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb +++ b/src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb @@ -5,12 +5,15 @@ Imports System.Composition Imports System.Diagnostics.CodeAnalysis Imports System.Threading +Imports Microsoft.CodeAnalysis.CodeGeneration Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.InitializeParameter Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.Options +Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices +Imports Microsoft.CodeAnalysis.VisualBasic.Simplification Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter @@ -22,7 +25,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter ParameterSyntax, StatementSyntax, ExpressionSyntax, - BinaryExpressionSyntax) + BinaryExpressionSyntax, + VisualBasicSimplifierOptions) @@ -55,7 +59,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter Return True End Function - Protected Overrides Function PrefersThrowExpression(options As DocumentOptionSet) As Boolean + Protected Overrides Function PrefersThrowExpression(options As VisualBasicSimplifierOptions) As Boolean ' No throw expression preference option is defined for VB because it doesn't support throw expressions. Return False End Function @@ -64,7 +68,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter Return input.Replace("""", """""") End Function - Protected Overrides Function CreateParameterCheckIfStatement(options As DocumentOptionSet, condition As ExpressionSyntax, ifTrueStatement As StatementSyntax) As StatementSyntax + Protected Overrides Function CreateParameterCheckIfStatement(condition As ExpressionSyntax, ifTrueStatement As StatementSyntax, options As VisualBasicSimplifierOptions) As StatementSyntax Return SyntaxFactory.MultiLineIfBlock( ifStatement:=SyntaxFactory.IfStatement(SyntaxFactory.Token(SyntaxKind.IfKeyword), condition, SyntaxFactory.Token(SyntaxKind.ThenKeyword)), statements:=New SyntaxList(Of StatementSyntax)(ifTrueStatement), @@ -72,7 +76,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter elseBlock:=Nothing) End Function - Protected Overrides Function TryAddNullCheckToParameterDeclarationAsync(document As Document, parameterSyntax As ParameterSyntax, cancellationToken As CancellationToken) As Task(Of Document) + Protected Overrides Function TryAddNullCheckToParameterDeclarationAsync(document As Document, parameterSyntax As ParameterSyntax, options As VisualBasicSimplifierOptions, cancellationToken As CancellationToken) As Task(Of Document) Return Task.FromResult(Of Document)(Nothing) End Function End Class diff --git a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb index 28e6c13c35a24..ad304a9c680f5 100644 --- a/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb +++ b/src/Features/VisualBasic/Portable/InlineHints/VisualBasicInlineParameterNameHintsService.vb @@ -18,8 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InlineHints - Public Sub New(globalOptions As IGlobalOptionService) - MyBase.New(globalOptions) + Public Sub New() End Sub Protected Overrides Sub AddAllParameterNameHintLocations( diff --git a/src/Features/VisualBasic/Portable/ReplaceMethodWithProperty/VisualBasicReplaceMethodWithPropertyService.vb b/src/Features/VisualBasic/Portable/ReplaceMethodWithProperty/VisualBasicReplaceMethodWithPropertyService.vb index 623bfd254d72c..3c35fa6842d6a 100644 --- a/src/Features/VisualBasic/Portable/ReplaceMethodWithProperty/VisualBasicReplaceMethodWithPropertyService.vb +++ b/src/Features/VisualBasic/Portable/ReplaceMethodWithProperty/VisualBasicReplaceMethodWithPropertyService.vb @@ -11,6 +11,7 @@ Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.ReplaceMethodWithProperty Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices +Imports Microsoft.CodeAnalysis.CodeGeneration Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithProperty @@ -34,7 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP End Sub Public Sub ReplaceGetMethodWithProperty( - documentOptions As DocumentOptionSet, + options As CodeGenerationOptions, parseOptions As ParseOptions, editor As SyntaxEditor, semanticModel As SemanticModel, diff --git a/src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb b/src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb index 822aca823e272..7a137bf14f375 100644 --- a/src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb +++ b/src/Features/VisualBasic/Portable/ReplacePropertyWithMethods/VisualBasicReplacePropertyWithMethods.vb @@ -30,6 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeRefactorings.ReplaceMethodWithP propertyBackingField As IFieldSymbol, desiredGetMethodName As String, desiredSetMethodName As String, + fallbackOptions As CodeGenerationOptionsProvider, cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of SyntaxNode)) Dim propertyStatement = TryCast(propertyDeclarationNode, PropertyStatementSyntax) diff --git a/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb index e6e5b72ba40a3..08cb415cba697 100644 --- a/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/SimplifyThisOrMe/VisualBasicSimplifyThisOrMeDiagnosticAnalyzer.vb @@ -4,6 +4,7 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.LanguageServices +Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Simplification.Simplifiers Imports Microsoft.CodeAnalysis.SimplifyThisOrMe Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices @@ -18,14 +19,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyThisOrMe SyntaxKind, ExpressionSyntax, MeExpressionSyntax, - MemberAccessExpressionSyntax, - VisualBasicSimplifierOptions) + MemberAccessExpressionSyntax) Protected Overrides ReadOnly Property SyntaxKinds As ISyntaxKinds = VisualBasicSyntaxKinds.Instance - Protected Overrides Function GetSimplifierOptions(options As AnalyzerOptions, syntaxTree As SyntaxTree) As VisualBasicSimplifierOptions - Return options.GetVisualBasicSimplifierOptions(syntaxTree) - End Function + Protected Overrides ReadOnly Property Simplification As ISimplification + Get + Return VisualBasicSimplification.Instance + End Get + End Property Protected Overrides ReadOnly Property Simplifier As AbstractMemberAccessExpressionSimplifier(Of ExpressionSyntax, MemberAccessExpressionSyntax, MeExpressionSyntax) = MemberAccessExpressionSimplifier.Instance End Class diff --git a/src/Features/VisualBasic/Portable/Wrapping/VisualBasicSyntaxWrappingOptions.vb b/src/Features/VisualBasic/Portable/Wrapping/VisualBasicSyntaxWrappingOptions.vb index f5b70f3ff63d7..2b5599ca17e12 100644 --- a/src/Features/VisualBasic/Portable/Wrapping/VisualBasicSyntaxWrappingOptions.vb +++ b/src/Features/VisualBasic/Portable/Wrapping/VisualBasicSyntaxWrappingOptions.vb @@ -23,7 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Wrapping Public Shared Function Create(options As AnalyzerConfigOptions, ideOptions As CodeActionOptions) As VisualBasicSyntaxWrappingOptions Return New VisualBasicSyntaxWrappingOptions( - formattingOptions:=VisualBasicSyntaxFormattingOptions.Create(options, DirectCast(If(ideOptions.CleanupOptions?.FormattingOptions, VisualBasicSyntaxFormattingOptions.Default), VisualBasicSyntaxFormattingOptions)), + formattingOptions:=VisualBasicSyntaxFormattingOptions.Create(options, DirectCast(ideOptions.CleanupOptions.FormattingOptions, VisualBasicSyntaxFormattingOptions)), operatorPlacement:=options.GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping), wrappingColumn:=ideOptions.WrappingColumn) End Function diff --git a/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs index b3cc604a393f9..02f821d824580 100644 --- a/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs +++ b/src/Tools/ExternalAccess/OmniSharp.CSharp/Formatting/OmniSharpSyntaxFormattingOptionsFactory.cs @@ -79,14 +79,20 @@ public static OmniSharpSyntaxFormattingOptionsWrapper Create( bool newLineForMembersInAnonymousTypes, bool newLineForClausesInQuery) => new(new( - FormattingOptions: new CSharpSyntaxFormattingOptions( - new LineFormattingOptions( - UseTabs: useTabs, - TabSize: tabSize, - IndentationSize: indentationSize, - NewLine: newLine), - separateImportDirectiveGroups: separateImportDirectiveGroups, - spacing: + FormattingOptions: new CSharpSyntaxFormattingOptions() + { + Common = new SyntaxFormattingOptions.CommonOptions() + { + LineFormatting = 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) | @@ -109,8 +115,8 @@ public static OmniSharpSyntaxFormattingOptionsWrapper Create( (spaceBeforeComma ? SpacePlacement.BeforeComma : 0) | (spaceAfterDot ? SpacePlacement.AfterDot : 0) | (spaceBeforeDot ? SpacePlacement.BeforeDot : 0), - spacingAroundBinaryOperator: (BinaryOperatorSpacingOptions)spacingAroundBinaryOperator, - newLines: + SpacingAroundBinaryOperator = (BinaryOperatorSpacingOptions)spacingAroundBinaryOperator, + NewLines = (newLineForMembersInObjectInit ? NewLinePlacement.BeforeMembersInObjectInitializers : 0) | (newLineForMembersInAnonymousTypes ? NewLinePlacement.BeforeMembersInAnonymousTypes : 0) | (newLineForElse ? NewLinePlacement.BeforeElse : 0) | @@ -126,16 +132,16 @@ public static OmniSharpSyntaxFormattingOptionsWrapper Create( (newLinesForBracesInLambdaExpressionBody ? NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody : 0) | (newLinesForBracesInControlBlocks ? NewLinePlacement.BeforeOpenBraceInControlBlocks : 0) | (newLineForClausesInQuery ? NewLinePlacement.BetweenQueryExpressionClauses : 0), - labelPositioning: (LabelPositionOptions)labelPositioning, - indentation: + 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, - AddImportOptions: AddImportPlacementOptions.Default)); + 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 a7181ba1a4a51..d9ba5b33a1fdf 100644 --- a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs +++ b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeActionOptions.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.ImplementType; +using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.SymbolSearch; @@ -12,9 +13,14 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.CodeActions internal readonly record struct OmniSharpCodeActionOptions( OmniSharpImplementTypeOptions ImplementTypeOptions) { - internal CodeActionOptions GetCodeActionOptions() - => new(ImplementTypeOptions: new( - InsertionBehavior: (ImplementTypeInsertionBehavior)ImplementTypeOptions.InsertionBehavior, - PropertyGenerationBehavior: (ImplementTypePropertyGenerationBehavior)ImplementTypeOptions.PropertyGenerationBehavior)); + internal CodeActionOptions GetCodeActionOptions(HostLanguageServices languageServices) + => CodeActionOptions.GetDefault(languageServices) with + { + 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 a073e85127469..a154ef68110bf 100644 --- a/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs +++ b/src/Tools/ExternalAccess/OmniSharp/CodeActions/OmniSharpCodeFixContextFactory.cs @@ -22,7 +22,7 @@ public static CodeFixContext CreateCodeFixContext( Action> registerCodeFix, OmniSharpCodeActionOptions options, CancellationToken cancellationToken) - => new(document, span, diagnostics, registerCodeFix, new DelegatingCodeActionOptionsProvider(_ => options.GetCodeActionOptions()), isBlocking: false, cancellationToken); + => new(document, span, diagnostics, registerCodeFix, new DelegatingCodeActionOptionsProvider(options.GetCodeActionOptions), isBlocking: false, cancellationToken); public static CodeAnalysis.CodeRefactorings.CodeRefactoringContext CreateCodeRefactoringContext( Document document, @@ -30,7 +30,7 @@ public static CodeAnalysis.CodeRefactorings.CodeRefactoringContext CreateCodeRef Action registerRefactoring, OmniSharpCodeActionOptions options, CancellationToken cancellationToken) - => new(document, span, registerRefactoring, new DelegatingCodeActionOptionsProvider(_ => options.GetCodeActionOptions()), isBlocking: false, cancellationToken); + => new(document, span, registerRefactoring, new DelegatingCodeActionOptionsProvider(options.GetCodeActionOptions), isBlocking: false, cancellationToken); public static FixAllContext CreateFixAllContext( Document? document, @@ -53,7 +53,7 @@ public static FixAllContext CreateFixAllContext( codeActionEquivalenceKey, diagnosticIds, fixAllDiagnosticProvider, - new DelegatingCodeActionOptionsProvider(languageServices => optionsProvider(languageServices.Language).GetCodeActionOptions())), + new DelegatingCodeActionOptionsProvider(languageServices => optionsProvider(languageServices.Language).GetCodeActionOptions(languageServices))), new ProgressTracker(), cancellationToken); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs index 336642f1c431e..16bb5b7b49835 100644 --- a/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs +++ b/src/Tools/ExternalAccess/OmniSharp/DocumentationComments/OmniSharpDocumentationCommentOptionsWrapper.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.DocumentationComments; using Microsoft.CodeAnalysis.Formatting; @@ -21,7 +22,11 @@ public OmniSharpDocumentationCommentOptionsWrapper( int tabSize, bool useTabs, string newLine) - : this(new(autoXmlDocCommentGeneration, tabSize, useTabs, newLine)) + : this(new DocumentationCommentOptions() + { + LineFormatting = new LineFormattingOptions() { UseTabs = useTabs, TabSize = tabSize, IndentationSize = tabSize, NewLine = newLine }, + AutoXmlDocCommentGeneration = autoXmlDocCommentGeneration + }) { } @@ -30,13 +35,9 @@ public static async ValueTask FromD bool autoXmlDocCommentGeneration, CancellationToken cancellationToken) { - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(CodeActionOptions.DefaultProvider, cancellationToken).ConfigureAwait(false); - return new(new DocumentationCommentOptions( - AutoXmlDocCommentGeneration: autoXmlDocCommentGeneration, - TabSize: formattingOptions.TabSize, - UseTabs: formattingOptions.UseTabs, - NewLine: formattingOptions.NewLine)); + return new(new() { LineFormatting = formattingOptions.LineFormatting, AutoXmlDocCommentGeneration = autoXmlDocCommentGeneration }); } } } diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs index e6721fffbdcd7..7b0a46d18d6d6 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpOrganizeImportsOptionsWrapper.cs @@ -21,14 +21,17 @@ private OmniSharpOrganizeImportsOptionsWrapper(OrganizeImportsOptions underlying public OmniSharpOrganizeImportsOptionsWrapper( bool placeSystemNamespaceFirst, bool separateImportDirectiveGroups, - string newLine) : this(new OrganizeImportsOptions( - placeSystemNamespaceFirst, - separateImportDirectiveGroups, - newLine)) + string newLine) + : this(new OrganizeImportsOptions() + { + PlaceSystemNamespaceFirst = placeSystemNamespaceFirst, + SeparateImportDirectiveGroups = separateImportDirectiveGroups, + NewLine = newLine + }) { } public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) - => new(await OrganizeImportsOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false)); + => new(await document.GetOrganizeImportsOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false)); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs index e29ea1d92ca8b..c9b6dbe28ab4d 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Formatting/OmniSharpSyntaxFormattingOptionsWrapper.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Simplification; @@ -21,7 +22,7 @@ internal OmniSharpSyntaxFormattingOptionsWrapper(CodeCleanupOptions cleanupOptio public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) { - var cleanupOptions = await document.GetCodeCleanupOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await document.GetCodeCleanupOptionsAsync(CodeActionOptions.DefaultProvider, cancellationToken).ConfigureAwait(false); return new OmniSharpSyntaxFormattingOptionsWrapper(cleanupOptions); } } diff --git a/src/Tools/ExternalAccess/OmniSharp/Internal/ExtractInterface/OmniSharpExtractInterfaceOptionsService.cs b/src/Tools/ExternalAccess/OmniSharp/Internal/ExtractInterface/OmniSharpExtractInterfaceOptionsService.cs index fd1f6d040febc..a548126865277 100644 --- a/src/Tools/ExternalAccess/OmniSharp/Internal/ExtractInterface/OmniSharpExtractInterfaceOptionsService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/Internal/ExtractInterface/OmniSharpExtractInterfaceOptionsService.cs @@ -43,6 +43,7 @@ public async Task GetExtractInterfaceOptionsAsync string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var result = await _omniSharpExtractInterfaceOptionsService.GetExtractInterfaceOptionsAsync(extractableMembers, defaultInterfaceName).ConfigureAwait(false); @@ -52,7 +53,7 @@ public async Task GetExtractInterfaceOptionsAsync result.InterfaceName, result.FileName, (ExtractInterfaceOptionsResult.ExtractLocation)result.Location, - CodeActionOptions.DefaultProvider); + fallbackOptions); } } } diff --git a/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs b/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs index ef2dd3729bffc..15413195b7401 100644 --- a/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs +++ b/src/Tools/ExternalAccess/OmniSharp/MetadataAsSource/OmniSharpMetadataAsSourceService.cs @@ -5,6 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.ExternalAccess.OmniSharp.Formatting; @@ -33,7 +34,7 @@ public static async Task AddSourceToAsync(Document document, Compilati { var service = document.GetRequiredLanguageService(); - var cleanupOptions = await document.GetCodeCleanupOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var cleanupOptions = await document.GetCodeCleanupOptionsAsync(CodeActionOptions.DefaultProvider, cancellationToken).ConfigureAwait(false); var options = new CleanCodeGenerationOptions( GenerationOptions: CodeGenerationOptions.GetDefault(document.Project.LanguageServices), diff --git a/src/Tools/ExternalAccess/Razor/RazorAutoFormattingOptions.cs b/src/Tools/ExternalAccess/Razor/RazorAutoFormattingOptions.cs index 3e73f9b0251b7..aa392a29bc995 100644 --- a/src/Tools/ExternalAccess/Razor/RazorAutoFormattingOptions.cs +++ b/src/Tools/ExternalAccess/Razor/RazorAutoFormattingOptions.cs @@ -18,11 +18,13 @@ public RazorAutoFormattingOptions( bool formatOnTyping, bool formatOnSemicolon, bool formatOnCloseBrace) - : this(new AutoFormattingOptions( - FormatOnReturn: formatOnReturn, - FormatOnTyping: formatOnTyping, - FormatOnSemicolon: formatOnSemicolon, - FormatOnCloseBrace: formatOnCloseBrace)) + : this(new AutoFormattingOptions() + { + FormatOnReturn = formatOnReturn, + FormatOnTyping = formatOnTyping, + FormatOnSemicolon = formatOnSemicolon, + FormatOnCloseBrace = formatOnCloseBrace, + }) { } } diff --git a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs index bc71064d6c697..2f704a46ec10c 100644 --- a/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs +++ b/src/Tools/ExternalAccess/Razor/RazorCSharpFormattingInteractionService.cs @@ -44,13 +44,19 @@ public static async Task> GetFormattingChangesAsync( return ImmutableArray.Empty; } - var services = document.Project.Solution.Workspace.Services; + var languageServices = document.Project.LanguageServices; - var globalOptions = document.Project.Solution.Workspace.Services.GetRequiredService().GlobalOptions; + var services = document.Project.Solution.Workspace.Services; + var globalOptions = services.GetRequiredService(); + var optionsProvider = (OptionsProvider)globalOptions.CleanCodeGenerationOptionsProvider; + var fallbackOptions = await optionsProvider.GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false); + var optionService = services.GetRequiredService(); + var configOptions = documentOptions.AsAnalyzerConfigOptions(optionService, document.Project.Language); - var indentationOptions = new IndentationOptions( - SyntaxFormattingOptions.Create(documentOptions, globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices), document.Project.LanguageServices), - globalOptions.GetAutoFormattingOptions(document.Project.Language)); + var indentationOptions = new IndentationOptions(formattingService.GetFormattingOptions(configOptions, fallbackOptions)) + { + AutoFormattingOptions = globalOptions.GetAutoFormattingOptions(languageServices) + }; return await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, indentationOptions, cancellationToken).ConfigureAwait(false); } @@ -78,7 +84,11 @@ public static async Task> GetFormattingChangesAsync( } var formattingOptions = GetFormattingOptions(indentationOptions); - var roslynIndentationOptions = new IndentationOptions(formattingOptions, autoFormattingOptions.UnderlyingObject, (FormattingOptions2.IndentStyle)indentStyle); + var roslynIndentationOptions = new IndentationOptions(formattingOptions) + { + AutoFormattingOptions = autoFormattingOptions.UnderlyingObject, + IndentStyle = (FormattingOptions2.IndentStyle)indentStyle + }; return await formattingService.GetFormattingChangesOnTypedCharacterAsync(document, position, roslynIndentationOptions, cancellationToken).ConfigureAwait(false); } @@ -105,10 +115,12 @@ public static SyntaxNode Format( } private static SyntaxFormattingOptions GetFormattingOptions(RazorIndentationOptions indentationOptions) - => CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions( - UseTabs: indentationOptions.UseTabs, - TabSize: indentationOptions.TabSize, - IndentationSize: indentationOptions.IndentationSize, - NewLine: CSharpSyntaxFormattingOptions.Default.NewLine)); + => CSharpSyntaxFormattingOptions.Default.With(new LineFormattingOptions() + { + UseTabs = indentationOptions.UseTabs, + TabSize = indentationOptions.TabSize, + IndentationSize = indentationOptions.IndentationSize, + NewLine = CSharpSyntaxFormattingOptions.Default.NewLine + }); } } diff --git a/src/Tools/IdeCoreBenchmarks/FormatterBenchmarks.cs b/src/Tools/IdeCoreBenchmarks/FormatterBenchmarks.cs index 3973144156146..6f9c59417461c 100644 --- a/src/Tools/IdeCoreBenchmarks/FormatterBenchmarks.cs +++ b/src/Tools/IdeCoreBenchmarks/FormatterBenchmarks.cs @@ -55,16 +55,10 @@ public void GlobalSetup() solution = solution.WithDocumentSyntaxRoot(documentId, root); _document = solution.GetDocument(documentId); - _options = new CSharpSyntaxFormattingOptions( - LineFormattingOptions.Default, - separateImportDirectiveGroups: CSharpSyntaxFormattingOptions.Default.SeparateImportDirectiveGroups, - spacing: CSharpSyntaxFormattingOptions.Default.Spacing, - spacingAroundBinaryOperator: CSharpSyntaxFormattingOptions.Default.SpacingAroundBinaryOperator, - CSharpSyntaxFormattingOptions.Default.NewLines | NewLinePlacement.BeforeOpenBraceInTypes, - labelPositioning: CSharpSyntaxFormattingOptions.Default.LabelPositioning, - indentation: CSharpSyntaxFormattingOptions.Default.Indentation, - wrappingKeepStatementsOnSingleLine: false, - wrappingPreserveSingleLine: false); + _options = new CSharpSyntaxFormattingOptions() + { + NewLines = CSharpSyntaxFormattingOptions.Default.NewLines | NewLinePlacement.BeforeOpenBraceInTypes + }; } [Benchmark] diff --git a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs index 43766199f0f01..00bb85970b01a 100644 --- a/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs +++ b/src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -30,7 +31,7 @@ private class NodeLocator : AbstractNodeLocator protected override EnvDTE.vsCMPart DefaultPart => EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; - protected override VirtualTreePoint? GetStartPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part) + protected override VirtualTreePoint? GetStartPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { @@ -81,7 +82,7 @@ private class NodeLocator : AbstractNodeLocator } } - protected override VirtualTreePoint? GetEndPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part) + protected override VirtualTreePoint? GetEndPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { @@ -144,7 +145,7 @@ private static VirtualTreePoint GetBodyStartPoint(SourceText text, SyntaxToken o : new VirtualTreePoint(openBrace.SyntaxTree, text, openBrace.Span.End); } - private VirtualTreePoint GetBodyStartPoint(SourceText text, OptionSet options, SyntaxToken openBrace, SyntaxToken closeBrace, int memberStartColumn) + private static VirtualTreePoint GetBodyStartPoint(SourceText text, LineFormattingOptions options, SyntaxToken openBrace, SyntaxToken closeBrace, int memberStartColumn) { Debug.Assert(!openBrace.IsMissing); Debug.Assert(!closeBrace.IsMissing); @@ -184,7 +185,7 @@ private VirtualTreePoint GetBodyStartPoint(SourceText text, OptionSet options, S // If the line is all whitespace then place the caret at the first indent after the start // of the member. - var indentSize = GetTabSize(options); + var indentSize = options.TabSize; var lineText = lineAfterOpenBrace.ToString(); var lineEndColumn = lineText.GetColumnFromLineOffset(lineText.Length, indentSize); @@ -350,7 +351,7 @@ private static VirtualTreePoint GetStartPoint(SourceText text, BaseTypeDeclarati return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } - private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) + private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -383,7 +384,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseM if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } @@ -439,7 +440,7 @@ private static AccessorDeclarationSyntax FindFirstAccessorNode(BasePropertyDecla return node.AccessorList.Accessors.FirstOrDefault(); } - private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) + private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -470,7 +471,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseP if (firstAccessorNode != null) { var line = text.Lines.GetLineFromPosition(firstAccessorNode.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); if (firstAccessorNode.Body != null) { @@ -490,7 +491,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseP if (node.AccessorList != null && !node.AccessorList.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.AccessorList.OpenBraceToken, node.AccessorList.CloseBraceToken, indentation); } @@ -504,7 +505,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, BaseP return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } - private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) + private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; @@ -529,7 +530,7 @@ private VirtualTreePoint GetStartPoint(SourceText text, OptionSet options, Acces if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); - var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(GetTabSize(options)); + var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs index ced9c909852e4..26a8048f199e7 100644 --- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs @@ -156,7 +156,7 @@ private IEnumerable GetExpressionCodeStyleOptions(AnalyzerConf yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, description: ServicesVSResources.Prefer_range_operator, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, description: CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, editorConfigOptions, visualStudioOptions, updaterService, FileName); yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, description: ServicesVSResources.Prefer_tuple_swap, editorConfigOptions, visualStudioOptions, updaterService, FileName); - yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferUTF8StringLiterals, description: ServicesVSResources.Prefer_UTF8_string_literals, editorConfigOptions, visualStudioOptions, updaterService, FileName); + yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferUtf8StringLiterals, description: ServicesVSResources.Prefer_UTF8_string_literals, editorConfigOptions, visualStudioOptions, updaterService, FileName); } private IEnumerable GetPatternMatchingCodeStyleOptions(AnalyzerConfigOptions editorConfigOptions, OptionSet visualStudioOptions, OptionUpdater updaterService) diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Naming.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Naming.cs index 2a46c91f0952a..9989c9be60631 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Naming.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Naming.cs @@ -4,9 +4,8 @@ using System; using System.Xml.Linq; -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; -using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.VisualStudio.LanguageServices.CSharp.Options { diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs index cd267e9b60cf8..a5962232c74e1 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject/AutomationObject.Style.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.VisualStudio.LanguageServices.CSharp.Options { @@ -215,14 +216,14 @@ public string Style_PreferReadonly public int Style_PreferObjectInitializer_FadeOutCode { - get { return GetBooleanOption(CodeStyleOptions2.PreferObjectInitializer_FadeOutCode); } - set { SetBooleanOption(CodeStyleOptions2.PreferObjectInitializer_FadeOutCode, value); } + get { return GetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexObjectInitialization); } + set { SetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexObjectInitialization, value); } } public int Style_PreferCollectionInitializer_FadeOutCode { - get { return GetBooleanOption(CodeStyleOptions2.PreferCollectionInitializer_FadeOutCode); } - set { SetBooleanOption(CodeStyleOptions2.PreferCollectionInitializer_FadeOutCode, value); } + get { return GetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexCollectionInitialization); } + set { SetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexCollectionInitialization, value); } } public string Style_PreferSimplifiedBooleanExpressions @@ -281,8 +282,8 @@ public string Style_PreferSimplifiedInterpolation public string Style_RequireAccessibilityModifiers { - get { return GetXmlOption(CodeStyleOptions2.RequireAccessibilityModifiers); } - set { SetXmlOption(CodeStyleOptions2.RequireAccessibilityModifiers, value); } + get { return GetXmlOption(CodeStyleOptions2.AccessibilityModifiersRequired); } + set { SetXmlOption(CodeStyleOptions2.AccessibilityModifiersRequired, value); } } public string Style_RemoveUnnecessarySuppressionExclusions @@ -383,8 +384,8 @@ public string Style_PreferTupleSwap public string Style_PreferUTF8StringLiterals { - get { return GetXmlOption(CSharpCodeStyleOptions.PreferUTF8StringLiterals); } - set { SetXmlOption(CSharpCodeStyleOptions.PreferUTF8StringLiterals, value); } + get { return GetXmlOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals); } + set { SetXmlOption(CSharpCodeStyleOptions.PreferUtf8StringLiterals, value); } } public string Style_PreferredUsingDirectivePlacement diff --git a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs index 86806ef13f103..b3c3d56755880 100644 --- a/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs +++ b/src/VisualStudio/CSharp/Impl/Options/Formatting/StyleViewModel.cs @@ -2192,7 +2192,7 @@ internal StyleViewModel(OptionStore optionStore, IServiceProvider serviceProvide CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferRangeOperator, ServicesVSResources.Prefer_range_operator, s_preferRangeOperator, s_preferRangeOperator, this, optionStore, expressionPreferencesGroupTitle)); CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferTupleSwap, ServicesVSResources.Prefer_tuple_swap, s_preferTupleSwap, s_preferTupleSwap, this, optionStore, expressionPreferencesGroupTitle)); - CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferUTF8StringLiterals, ServicesVSResources.Prefer_UTF8_string_literals, s_preferUTF8StringLiterals, s_preferUTF8StringLiterals, this, optionStore, expressionPreferencesGroupTitle)); + CodeStyleItems.Add(new BooleanCodeStyleOptionViewModel(CSharpCodeStyleOptions.PreferUtf8StringLiterals, ServicesVSResources.Prefer_UTF8_string_literals, s_preferUTF8StringLiterals, s_preferUTF8StringLiterals, this, optionStore, expressionPreferencesGroupTitle)); AddExpressionBodyOptions(optionStore, expressionPreferencesGroupTitle); AddUnusedValueOptions(optionStore, expressionPreferencesGroupTitle); diff --git a/src/VisualStudio/Core/Def/EditorConfigSettings/DataProvider/CodeStyle/CommonCodeStyleSettingsProvider.cs b/src/VisualStudio/Core/Def/EditorConfigSettings/DataProvider/CodeStyle/CommonCodeStyleSettingsProvider.cs index f3022ef26f3ab..7ac5ebb7c7c52 100644 --- a/src/VisualStudio/Core/Def/EditorConfigSettings/DataProvider/CodeStyle/CommonCodeStyleSettingsProvider.cs +++ b/src/VisualStudio/Core/Def/EditorConfigSettings/DataProvider/CodeStyle/CommonCodeStyleSettingsProvider.cs @@ -113,7 +113,7 @@ private IEnumerable GetNullCheckingCodeStyleOptions(AnalyzerCo private IEnumerable GetModifierCodeStyleOptions(AnalyzerConfigOptions options, OptionSet visualStudioOptions, OptionUpdater updater) { - yield return CodeStyleSetting.Create(option: CodeStyleOptions2.RequireAccessibilityModifiers, + yield return CodeStyleSetting.Create(option: CodeStyleOptions2.AccessibilityModifiersRequired, description: ServicesVSResources.Require_accessibility_modifiers, enumValues: new[] { AccessibilityModifiersRequired.Always, AccessibilityModifiersRequired.ForNonInterfaceMembers, AccessibilityModifiersRequired.Never, AccessibilityModifiersRequired.OmitIfDefault }, valueDescriptions: new[] { ServicesVSResources.Always, ServicesVSResources.For_non_interface_members, ServicesVSResources.Never, ServicesVSResources.Omit_if_default }, diff --git a/src/VisualStudio/Core/Def/ExtractInterface/VisualStudioExtractInterfaceOptionsService.cs b/src/VisualStudio/Core/Def/ExtractInterface/VisualStudioExtractInterfaceOptionsService.cs index 3d6520619859d..48ea2f38a9fc3 100644 --- a/src/VisualStudio/Core/Def/ExtractInterface/VisualStudioExtractInterfaceOptionsService.cs +++ b/src/VisualStudio/Core/Def/ExtractInterface/VisualStudioExtractInterfaceOptionsService.cs @@ -30,15 +30,13 @@ internal class VisualStudioExtractInterfaceOptionsService : IExtractInterfaceOpt { private readonly IGlyphService _glyphService; private readonly IThreadingContext _threadingContext; - private readonly IGlobalOptionService _globalOptions; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VisualStudioExtractInterfaceOptionsService(IGlyphService glyphService, IThreadingContext threadingContext, IGlobalOptionService globalOptions) + public VisualStudioExtractInterfaceOptionsService(IGlyphService glyphService, IThreadingContext threadingContext) { _glyphService = glyphService; _threadingContext = threadingContext; - _globalOptions = globalOptions; } public async Task GetExtractInterfaceOptionsAsync( @@ -50,6 +48,7 @@ public async Task GetExtractInterfaceOptionsAsync string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName, + CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); @@ -78,7 +77,7 @@ public async Task GetExtractInterfaceOptionsAsync interfaceName: viewModel.DestinationViewModel.TypeName.Trim(), fileName: viewModel.DestinationViewModel.FileName.Trim(), location: GetLocation(viewModel.DestinationViewModel.Destination), - _globalOptions.CreateProvider()); + fallbackOptions); } else { diff --git a/src/VisualStudio/Core/Def/Implementation/ICodeModelNavigationPointService.cs b/src/VisualStudio/Core/Def/Implementation/ICodeModelNavigationPointService.cs index ffc868580884b..86de659e37956 100644 --- a/src/VisualStudio/Core/Def/Implementation/ICodeModelNavigationPointService.cs +++ b/src/VisualStudio/Core/Def/Implementation/ICodeModelNavigationPointService.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; @@ -16,11 +17,11 @@ internal interface ICodeModelNavigationPointService : ILanguageService /// /// Retrieves the start point of a given node for the specified EnvDTE.vsCMPart. /// - VirtualTreePoint? GetStartPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part = null); + VirtualTreePoint? GetStartPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part = null); /// /// Retrieves the end point of a given node for the specified EnvDTE.vsCMPart. /// - VirtualTreePoint? GetEndPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part = null); + VirtualTreePoint? GetEndPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part = null); } } diff --git a/src/VisualStudio/Core/Def/KeybindingReset/KeybindingResetOptions.cs b/src/VisualStudio/Core/Def/KeybindingReset/KeybindingResetOptions.cs index 103b11f617c16..04a7c55c8f087 100644 --- a/src/VisualStudio/Core/Def/KeybindingReset/KeybindingResetOptions.cs +++ b/src/VisualStudio/Core/Def/KeybindingReset/KeybindingResetOptions.cs @@ -11,8 +11,7 @@ namespace Microsoft.VisualStudio.LanguageServices.KeybindingReset { - [ExportGlobalOptionProvider, Shared] - internal sealed class KeybindingResetOptions : IOptionProvider + internal sealed class KeybindingResetOptions { private const string LocalRegistryPath = @"Roslyn\Internal\KeybindingsStatus\"; @@ -31,17 +30,5 @@ internal sealed class KeybindingResetOptions : IOptionProvider public static readonly Option2 EnabledFeatureFlag = new(nameof(KeybindingResetOptions), nameof(EnabledFeatureFlag), defaultValue: false, storageLocation: new FeatureFlagStorageLocation("Roslyn.KeybindingResetEnabled")); - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - ReSharperStatus, - NeedsReset, - NeverShowAgain, - EnabledFeatureFlag); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public KeybindingResetOptions() - { - } } } diff --git a/src/VisualStudio/Core/Def/Log/LoggerOptions.cs b/src/VisualStudio/Core/Def/Log/LoggerOptions.cs index 8fb46abaf7f3d..1ba239270d1d6 100644 --- a/src/VisualStudio/Core/Def/Log/LoggerOptions.cs +++ b/src/VisualStudio/Core/Def/Log/LoggerOptions.cs @@ -13,20 +13,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation { - [ExportGlobalOptionProvider, Shared] - internal sealed class LoggerOptions : IOptionProvider + internal sealed class LoggerOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public LoggerOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - EtwLoggerKey, - TraceLoggerKey, - OutputWindowLoggerKey); - private const string LocalRegistryPath = @"Roslyn\Internal\Performance\Logger\"; public static readonly Option2 EtwLoggerKey = new(nameof(LoggerOptions), nameof(EtwLoggerKey), defaultValue: true, diff --git a/src/VisualStudio/Core/Def/Options/XamlOptions.cs b/src/VisualStudio/Core/Def/Options/XamlOptions.cs index 6415d2f04e12a..801721deba258 100644 --- a/src/VisualStudio/Core/Def/Options/XamlOptions.cs +++ b/src/VisualStudio/Core/Def/Options/XamlOptions.cs @@ -18,21 +18,11 @@ namespace Microsoft.CodeAnalysis.Editor.Xaml /// Currently GlobalOptionService.CreateLazySerializableOptionsByLanguage loads all IOptionProvider types eagerly to determine whether or not they contribute to solution options. /// This is causing RPS regression. /// - [ExportGlobalOptionProvider, Shared] - internal sealed class XamlOptions : IOptionProvider + internal sealed class XamlOptions { private const string FeatureName = "XamlOptions"; public static readonly Option2 EnableLspIntelliSenseFeatureFlag = new(FeatureName, nameof(EnableLspIntelliSenseFeatureFlag), defaultValue: false, new FeatureFlagStorageLocation("Xaml.EnableLspIntelliSense")); - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - EnableLspIntelliSenseFeatureFlag); - - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public XamlOptions() - { - } } } diff --git a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs index 5f64ab6e50436..f6c9156cf9350 100644 --- a/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs +++ b/src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs @@ -247,8 +247,9 @@ public async Task InitializeUIAffinitizedServicesAsync(IAsyncServiceProvider asy // Switch to a background thread to avoid loading option providers on UI thread (telemetry is reading options). await TaskScheduler.Default; + var logDelta = _globalOptions.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution); var telemetryService = (VisualStudioWorkspaceTelemetryService)Services.GetRequiredService(); - telemetryService.InitializeTelemetrySession(telemetrySession); + telemetryService.InitializeTelemetrySession(telemetrySession, logDelta); Logger.Log(FunctionId.Run_Environment, KeyValueLogMessage.Create(m => m["Version"] = FileVersionInfo.GetVersionInfo(typeof(VisualStudioWorkspace).Assembly.Location).FileVersion)); diff --git a/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs b/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs index 3b15632634832..fddc36d8d7b89 100644 --- a/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs +++ b/src/VisualStudio/Core/Def/Snippets/AbstractSnippetExpansionClient.cs @@ -290,8 +290,8 @@ private void CleanUpEndLocation(ITrackingSpan? endTrackingSpan) var document = this.SubjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { - var documentOptions = document.GetOptionsAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); - _indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, documentOptions.GetOption(FormattingOptions.TabSize)); + var formattingOptions = document.GetLineFormattingOptionsAsync(GlobalOptions, CancellationToken.None).AsTask().WaitAndGetResult(CancellationToken.None); + _indentDepth = lineText.GetColumnFromLineOffset(lineText.Length, formattingOptions.TabSize); } else { @@ -903,7 +903,6 @@ public void MoveToSpecificMethod(IMethodSymbol method, CancellationToken cancell } // Now compute the new arguments for the new call - var options = document.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken); var semanticModel = document.GetRequiredSemanticModelAsync(cancellationToken).AsTask().WaitAndGetResult(cancellationToken); var position = SubjectBuffer.CurrentSnapshot.GetPosition(adjustedTextSpan.iStartLine, adjustedTextSpan.iStartIndex); @@ -913,7 +912,7 @@ public void MoveToSpecificMethod(IMethodSymbol method, CancellationToken cancell foreach (var provider in GetArgumentProviders(document.Project.Solution.Workspace)) { - var context = new ArgumentContext(provider, options, semanticModel, position, parameter, value, cancellationToken); + var context = new ArgumentContext(provider, semanticModel, position, parameter, value, cancellationToken); ThreadingContext.JoinableTaskFactory.Run(() => provider.ProvideArgumentAsync(context)); if (context.DefaultValue is not null) diff --git a/src/VisualStudio/Core/Def/StackTraceExplorer/StackTraceExplorerOptions.cs b/src/VisualStudio/Core/Def/StackTraceExplorer/StackTraceExplorerOptions.cs index 46dce1fdd6297..9c4a7d649b75d 100644 --- a/src/VisualStudio/Core/Def/StackTraceExplorer/StackTraceExplorerOptions.cs +++ b/src/VisualStudio/Core/Def/StackTraceExplorer/StackTraceExplorerOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.CodeAnalysis.StackTraceExplorer { - [ExportGlobalOptionProvider, Shared] - internal sealed class StackTraceExplorerOptionsMetadata : IOptionProvider + internal sealed class StackTraceExplorerOptionsMetadata { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public StackTraceExplorerOptionsMetadata() - { - } - - public ImmutableArray Options { get; } = ImmutableArray.Create( - OpenOnFocus); - private const string FeatureName = "StackTraceExplorerOptions"; /// diff --git a/src/VisualStudio/Core/Def/Telemetry/AbstractWorkspaceTelemetryService.cs b/src/VisualStudio/Core/Def/Telemetry/AbstractWorkspaceTelemetryService.cs index ec9c95da8674b..0366806465efa 100644 --- a/src/VisualStudio/Core/Def/Telemetry/AbstractWorkspaceTelemetryService.cs +++ b/src/VisualStudio/Core/Def/Telemetry/AbstractWorkspaceTelemetryService.cs @@ -19,13 +19,13 @@ internal abstract class AbstractWorkspaceTelemetryService : IWorkspaceTelemetryS { public TelemetrySession? CurrentSession { get; private set; } - protected abstract ILogger CreateLogger(TelemetrySession telemetrySession); + protected abstract ILogger CreateLogger(TelemetrySession telemetrySession, bool logDelta); - public void InitializeTelemetrySession(TelemetrySession telemetrySession) + public void InitializeTelemetrySession(TelemetrySession telemetrySession, bool logDelta) { Contract.ThrowIfFalse(CurrentSession is null); - Logger.SetLogger(CreateLogger(telemetrySession)); + Logger.SetLogger(CreateLogger(telemetrySession, logDelta)); FaultReporter.RegisterTelemetrySesssion(telemetrySession); CurrentSession = telemetrySession; diff --git a/src/VisualStudio/Core/Def/Telemetry/TelemetryLogger.cs b/src/VisualStudio/Core/Def/Telemetry/TelemetryLogger.cs index 409e285d63373..ebeef7d25da1f 100644 --- a/src/VisualStudio/Core/Def/Telemetry/TelemetryLogger.cs +++ b/src/VisualStudio/Core/Def/Telemetry/TelemetryLogger.cs @@ -22,12 +22,10 @@ private sealed class Implementation : TelemetryLogger { private readonly TelemetrySession _session; - public Implementation(TelemetrySession session, IGlobalOptionService globalOptions) + public Implementation(TelemetrySession session, bool logDelta) { _session = session; - - // Only log "delta" property for block end events if feature flag is enabled. - LogDelta = globalOptions.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution); + LogDelta = logDelta; } protected override bool LogDelta { get; } @@ -86,8 +84,8 @@ internal static string GetPropertyName(FunctionId id, string name) private static string GetTelemetryName(FunctionId id, char separator) => Enum.GetName(typeof(FunctionId), id)!.Replace('_', separator).ToLowerInvariant(); - public static TelemetryLogger Create(TelemetrySession session, IGlobalOptionService globalOptions) - => new Implementation(session, globalOptions); + public static TelemetryLogger Create(TelemetrySession session, bool logDelta) + => new Implementation(session, logDelta); public abstract bool IsEnabled(FunctionId functionId); protected abstract void PostEvent(TelemetryEvent telemetryEvent); diff --git a/src/VisualStudio/Core/Def/Telemetry/VisualStudioWorkspaceTelemetryService.cs b/src/VisualStudio/Core/Def/Telemetry/VisualStudioWorkspaceTelemetryService.cs index 493c302a97bf7..d5f447dece3a1 100644 --- a/src/VisualStudio/Core/Def/Telemetry/VisualStudioWorkspaceTelemetryService.cs +++ b/src/VisualStudio/Core/Def/Telemetry/VisualStudioWorkspaceTelemetryService.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Options; @@ -34,11 +35,11 @@ public VisualStudioWorkspaceTelemetryService( _globalOptions = globalOptions; } - protected override ILogger CreateLogger(TelemetrySession telemetrySession) + protected override ILogger CreateLogger(TelemetrySession telemetrySession, bool logDelta) => AggregateLogger.Create( CodeMarkerLogger.Instance, new EtwLogger(FunctionIdOptions.CreateFunctionIsEnabledPredicate(_globalOptions)), - TelemetryLogger.Create(telemetrySession, _globalOptions), + TelemetryLogger.Create(telemetrySession, logDelta), new FileLogger(_globalOptions), Logger.GetLogger()); @@ -55,9 +56,12 @@ protected override void TelemetrySessionInitialized() var settings = SerializeCurrentSessionSettings(); Contract.ThrowIfNull(settings); + // Only log "delta" property for block end events if feature flag is enabled. + var logDelta = _globalOptions.GetOption(DiagnosticOptions.LogTelemetryForBackgroundAnalyzerExecution); + // initialize session in the remote service _ = await client.TryInvokeAsync( - (service, cancellationToken) => service.InitializeTelemetrySessionAsync(Process.GetCurrentProcess().Id, settings, cancellationToken), + (service, cancellationToken) => service.InitializeTelemetrySessionAsync(Process.GetCurrentProcess().Id, settings, logDelta, cancellationToken), CancellationToken.None).ConfigureAwait(false); }); } diff --git a/src/VisualStudio/Core/Def/Venus/ContainedDocument.cs b/src/VisualStudio/Core/Def/Venus/ContainedDocument.cs index 44a164eaf8135..50d5a2365327a 100644 --- a/src/VisualStudio/Core/Def/Venus/ContainedDocument.cs +++ b/src/VisualStudio/Core/Def/Venus/ContainedDocument.cs @@ -766,11 +766,13 @@ private void AdjustIndentation(IProjectionBuffer subjectBuffer, IEnumerable var editorOptionsFactory = _componentModel.GetService(); var editorOptions = editorOptionsFactory.GetOptions(DataBuffer); - var formattingOptions = _globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices).With(new LineFormattingOptions( - UseTabs: !editorOptions.IsConvertTabsToSpacesEnabled(), - TabSize: editorOptions.GetTabSize(), - IndentationSize: editorOptions.GetIndentSize(), - NewLine: editorOptions.GetNewLineCharacter())); + var formattingOptions = _globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices).With(new LineFormattingOptions() + { + UseTabs = !editorOptions.IsConvertTabsToSpacesEnabled(), + TabSize = editorOptions.GetTabSize(), + IndentationSize = editorOptions.GetIndentSize(), + NewLine = editorOptions.GetNewLineCharacter() + }); using var pooledObject = SharedPools.Default>().GetPooledObject(); diff --git a/src/VisualStudio/Core/Def/Venus/ContainedLanguage.IVsContainedLanguageCodeSupport.cs b/src/VisualStudio/Core/Def/Venus/ContainedLanguage.IVsContainedLanguageCodeSupport.cs index c0efece2d6155..e48a0a99ee516 100644 --- a/src/VisualStudio/Core/Def/Venus/ContainedLanguage.IVsContainedLanguageCodeSupport.cs +++ b/src/VisualStudio/Core/Def/Venus/ContainedLanguage.IVsContainedLanguageCodeSupport.cs @@ -32,7 +32,7 @@ public int CreateUniqueEventName(string pszClassName, string pszObjectName, stri allowCancellation: false, showProgress: false, action: c => - result = ContainedLanguageCodeSupport.CreateUniqueEventName(GetThisDocument(), pszClassName, pszObjectName, pszNameOfEvent, c.UserCancellationToken)); + result = ContainedLanguageCodeSupport.CreateUniqueEventName(GetThisDocument(), GlobalOptions, pszClassName, pszObjectName, pszNameOfEvent, c.UserCancellationToken)); pbstrEventHandlerName = result; return VSConstants.S_OK; @@ -77,6 +77,7 @@ public int EnsureEventHandler( itemidInsertionPoint, useHandlesClause: false, additionalFormattingRule: targetDocument.Project.LanguageServices.GetService().GetAdditionalCodeGenerationRule(), + GlobalOptions, cancellationToken: c.UserCancellationToken)); pbstrUniqueMemberID = idBodyAndInsertionPoint.Item1; @@ -156,7 +157,7 @@ public int GetMemberNavigationPoint(string pszClassName, string pszUniqueMemberI showProgress: false, action: c => { - if (ContainedLanguageCodeSupport.TryGetMemberNavigationPoint(GetThisDocument(), pszClassName, pszUniqueMemberID, out textSpan, out var targetDocument, c.UserCancellationToken)) + if (ContainedLanguageCodeSupport.TryGetMemberNavigationPoint(GetThisDocument(), GlobalOptions, pszClassName, pszUniqueMemberID, out textSpan, out var targetDocument, c.UserCancellationToken)) { succeeded = true; itemId = this.ContainedDocument.FindItemIdOfDocument(targetDocument); diff --git a/src/VisualStudio/Core/Def/Venus/ContainedLanguage.cs b/src/VisualStudio/Core/Def/Venus/ContainedLanguage.cs index 6112a098500c8..14c84adbb7623 100644 --- a/src/VisualStudio/Core/Def/Venus/ContainedLanguage.cs +++ b/src/VisualStudio/Core/Def/Venus/ContainedLanguage.cs @@ -150,6 +150,8 @@ internal ContainedLanguage( this.DataBuffer.Changed += OnDataBufferChanged; } + public IGlobalOptionService GlobalOptions => _diagnosticAnalyzerService.GlobalOptions; + private void OnDisconnect() { this.DataBuffer.Changed -= OnDataBufferChanged; diff --git a/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs b/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs index 8b0f88712f675..101a0ff884ed7 100644 --- a/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs +++ b/src/VisualStudio/Core/Def/Venus/ContainedLanguageCodeSupport.cs @@ -55,7 +55,7 @@ public static bool TryGetBaseClassName(Document document, string className, Canc } public static string CreateUniqueEventName( - Document document, string className, string objectName, string nameOfEvent, CancellationToken cancellationToken) + Document document, IGlobalOptionService globalOptions, string className, string objectName, string nameOfEvent, CancellationToken cancellationToken) { var type = document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken).GetTypeByMetadataName(className); var name = objectName + "_" + nameOfEvent; @@ -65,7 +65,7 @@ public static string CreateUniqueEventName( var tree = document.GetSyntaxTreeSynchronously(cancellationToken); var typeNode = type.DeclaringSyntaxReferences.Where(r => r.SyntaxTree == tree).Select(r => r.GetSyntax(cancellationToken)).First(); var codeModel = document.GetRequiredLanguageService(); - var options = document.GetOptionsAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken); + var options = document.GetLineFormattingOptionsAsync(globalOptions, cancellationToken).AsTask().WaitAndGetResult_Venus(cancellationToken); var point = codeModel.GetStartPoint(typeNode, options, EnvDTE.vsCMPart.vsCMPartBody); var reservedNames = semanticModel.LookupSymbols(point.Value.Position, type).Select(m => m.Name); @@ -152,6 +152,7 @@ public static Tuple EnsureEventHandler( uint itemidInsertionPoint, bool useHandlesClause, AbstractFormattingRule additionalFormattingRule, + IGlobalOptionService globalOptions, CancellationToken cancellationToken) #pragma warning restore IDE0060 // Remove unused parameter { @@ -209,7 +210,7 @@ public static Tuple EnsureEventHandler( var position = type.Locations.First(loc => loc.SourceTree == targetSyntaxTree).SourceSpan.Start; var destinationType = syntaxFacts.GetContainingTypeDeclaration(targetSyntaxTree.GetRoot(cancellationToken), position); - var documentOptions = targetDocument.GetOptionsAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken); + var documentOptions = targetDocument.GetLineFormattingOptionsAsync(globalOptions, cancellationToken).AsTask().WaitAndGetResult_Venus(cancellationToken); var insertionPoint = codeModel.GetEndPoint(destinationType, documentOptions, EnvDTE.vsCMPart.vsCMPartBody); if (insertionPoint == null) @@ -217,9 +218,9 @@ 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 fallbackOptions = targetDocument.Project.Solution.Workspace.Services.GetRequiredService().CleanCodeGenerationOptionsProvider; - var options = targetDocument.GetCleanCodeGenerationOptionsAsync(globalOptions, cancellationToken).AsTask().WaitAndGetResult_Venus(cancellationToken); + var options = targetDocument.GetCleanCodeGenerationOptionsAsync(fallbackOptions, cancellationToken).AsTask().WaitAndGetResult_Venus(cancellationToken); var info = options.GenerationOptions.GetInfo(new CodeGenerationContext(autoInsertionLocation: false), targetDocument.Project); var newType = codeGenerationService.AddMethod(destinationType, newMethod, info, cancellationToken); @@ -253,6 +254,7 @@ public static Tuple EnsureEventHandler( public static bool TryGetMemberNavigationPoint( Document thisDocument, + IGlobalOptionService globalOptions, string className, string uniqueMemberID, out VsTextSpan textSpan, @@ -275,7 +277,7 @@ public static bool TryGetMemberNavigationPoint( if (memberNode != null) { var memberNodeDocument = thisDocument.Project.Solution.GetDocument(memberNode.SyntaxTree); - var options = memberNodeDocument.GetOptionsAsync(cancellationToken).WaitAndGetResult_Venus(cancellationToken); + var options = memberNodeDocument.GetLineFormattingOptionsAsync(globalOptions, cancellationToken).AsTask().WaitAndGetResult_Venus(cancellationToken); var navigationPoint = codeModel.GetStartPoint(memberNode, options, EnvDTE.vsCMPart.vsCMPartNavigate); if (navigationPoint != null) { diff --git a/src/VisualStudio/Core/Def/Workspace/VisualStudioNavigationOptions.cs b/src/VisualStudio/Core/Def/Workspace/VisualStudioNavigationOptions.cs index 06fc6d936684c..33c9f7ab138f6 100644 --- a/src/VisualStudio/Core/Def/Workspace/VisualStudioNavigationOptions.cs +++ b/src/VisualStudio/Core/Def/Workspace/VisualStudioNavigationOptions.cs @@ -11,18 +11,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation { - [ExportGlobalOptionProvider, Shared] - internal sealed class VisualStudioNavigationOptions : IOptionProvider + internal sealed class VisualStudioNavigationOptions { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public VisualStudioNavigationOptions() - { - } - - ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( - NavigateToObjectBrowser); - public static readonly PerLanguageOption2 NavigateToObjectBrowser = new(nameof(VisualStudioNavigationOptions), nameof(NavigateToObjectBrowser), defaultValue: false, storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NavigateToObjectBrowser")); } diff --git a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs index 824e4be8f3f36..e2d962013f9ee 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelObject_CodeGen.cs @@ -18,27 +18,22 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel /// public partial class AbstractCodeModelObject { - private CodeGenerationContextInfo GetCodeGenerationContextInfo( + private static CodeGenerationContextInfo GetCodeGenerationContextInfo( SyntaxNode containerNode, - OptionSet? options = null, + CodeGenerationOptions options, EnvDTE.vsCMAccess access = EnvDTE.vsCMAccess.vsCMAccessDefault, bool generateMethodBodies = true) { var generateDefaultAccessibility = (access & EnvDTE.vsCMAccess.vsCMAccessDefault) == 0; - var globalOptions = State.ProjectCodeModelFactory.GlobalOptions; - var languageServices = Workspace.Services.GetLanguageServices(containerNode.SyntaxTree.Options.Language); - var fallbackOptions = globalOptions.GetCodeGenerationOptions(languageServices); - var codeGenOptions = CodeGenerationOptions.Create(options ?? Workspace.Options, fallbackOptions, languageServices); - - return codeGenOptions.GetInfo( + return options.GetInfo( new CodeGenerationContext( generateDefaultAccessibility: generateDefaultAccessibility, generateMethodBodies: generateMethodBodies), containerNode.SyntaxTree.Options); } - protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, string typeName, EnvDTE.vsCMAccess access) + private protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, string typeName, EnvDTE.vsCMAccess access, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -49,13 +44,13 @@ protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, stri typeName: typeName, parameters: default); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, access: access); - var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, codeGenOptions, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options, access: access); + var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None); Contract.ThrowIfNull(method); return method; } - protected SyntaxNode CreateDestructorDeclaration(SyntaxNode containerNode, string typeName) + private protected SyntaxNode CreateDestructorDeclaration(SyntaxNode containerNode, string typeName, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -63,13 +58,13 @@ protected SyntaxNode CreateDestructorDeclaration(SyntaxNode containerNode, strin attributes: default, typeName: typeName); - var options = GetCodeGenerationContextInfo(containerNode); - var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, options, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options); + var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None); Contract.ThrowIfNull(method); return method; } - protected SyntaxNode CreateDelegateTypeDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, INamedTypeSymbol returnType) + private protected SyntaxNode CreateDelegateTypeDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, INamedTypeSymbol returnType, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -81,12 +76,12 @@ protected SyntaxNode CreateDelegateTypeDeclaration(SyntaxNode containerNode, str refKind: RefKind.None, name: name); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, access: access); + var info = GetCodeGenerationContextInfo(containerNode, options, access: access); - return CodeGenerationService.CreateNamedTypeDeclaration(newTypeSymbol, destination, codeGenOptions, CancellationToken.None); + return CodeGenerationService.CreateNamedTypeDeclaration(newTypeSymbol, destination, info, CancellationToken.None); } - protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, bool createPropertyStyleEvent) + private protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, CodeGenerationOptions options, bool createPropertyStyleEvent) { var destination = CodeModelService.GetDestination(containerNode); @@ -128,11 +123,11 @@ protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string nam addMethod: addMethod, removeMethod: removeMethod); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, access: access); - return CodeGenerationService.CreateEventDeclaration(newEventSymbol, destination, codeGenOptions, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options, access: access); + return CodeGenerationService.CreateEventDeclaration(newEventSymbol, destination, info, CancellationToken.None); } - protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type) + private protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -143,11 +138,11 @@ protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string nam type: type, name: name); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, access: access); - return CodeGenerationService.CreateFieldDeclaration(newFieldSymbol, destination, codeGenOptions, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options, access: access); + return CodeGenerationService.CreateFieldDeclaration(newFieldSymbol, destination, info, CancellationToken.None); } - protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol returnType) + private protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol returnType, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -164,24 +159,25 @@ protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string na // Generating method with body is allowed when targeting an interface, // so we have to explicitly disable it here. - var codeGenerationOptions = GetCodeGenerationContextInfo( + var info = GetCodeGenerationContextInfo( containerNode, + options, access: access, generateMethodBodies: destination != CodeGenerationDestination.InterfaceType); - var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, codeGenerationOptions, CancellationToken.None); + var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None); Contract.ThrowIfNull(method); return method; } - protected SyntaxNode CreatePropertyDeclaration( + private protected SyntaxNode CreatePropertyDeclaration( SyntaxNode containerNode, string name, bool generateGetter, bool generateSetter, EnvDTE.vsCMAccess access, ITypeSymbol type, - OptionSet options) + CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); @@ -228,24 +224,25 @@ protected SyntaxNode CreatePropertyDeclaration( getMethod: getMethod, setMethod: setMethod); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, options, access); - return CodeGenerationService.CreatePropertyDeclaration(newPropertySymbol, destination, codeGenOptions, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options, access); + return CodeGenerationService.CreatePropertyDeclaration(newPropertySymbol, destination, info, CancellationToken.None); } - protected SyntaxNode CreateNamespaceDeclaration(SyntaxNode containerNode, string name) + private protected SyntaxNode CreateNamespaceDeclaration(SyntaxNode containerNode, string name, CodeGenerationOptions options) { var destination = CodeModelService.GetDestination(containerNode); var newNamespaceSymbol = CodeGenerationSymbolFactory.CreateNamespaceSymbol(name); - var options = GetCodeGenerationContextInfo(containerNode); - return CodeGenerationService.CreateNamespaceDeclaration(newNamespaceSymbol, destination, options, CancellationToken.None); + var info = GetCodeGenerationContextInfo(containerNode, options); + return CodeGenerationService.CreateNamespaceDeclaration(newNamespaceSymbol, destination, info, CancellationToken.None); } - protected SyntaxNode CreateTypeDeclaration( + private protected SyntaxNode CreateTypeDeclaration( SyntaxNode containerNode, TypeKind typeKind, string name, EnvDTE.vsCMAccess access, + CodeGenerationOptions options, INamedTypeSymbol? baseType = null, ImmutableArray implementedInterfaces = default) { @@ -263,7 +260,7 @@ protected SyntaxNode CreateTypeDeclaration( specialType: SpecialType.None, members: default); - var codeGenOptions = GetCodeGenerationContextInfo(containerNode, access: access); + var codeGenOptions = GetCodeGenerationContextInfo(containerNode, options, access: access); return CodeGenerationService.CreateNamedTypeDeclaration(newTypeSymbol, destination, codeGenOptions, CancellationToken.None); } } diff --git a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.AbstractNodeLocator.cs b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.AbstractNodeLocator.cs index 06d37653e503d..34fcbef892bff 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.AbstractNodeLocator.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.AbstractNodeLocator.cs @@ -22,19 +22,16 @@ protected abstract class AbstractNodeLocator protected abstract EnvDTE.vsCMPart DefaultPart { get; } - protected abstract VirtualTreePoint? GetStartPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part); - protected abstract VirtualTreePoint? GetEndPoint(SourceText text, OptionSet options, SyntaxNode node, EnvDTE.vsCMPart part); + protected abstract VirtualTreePoint? GetStartPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part); + protected abstract VirtualTreePoint? GetEndPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part); - protected int GetTabSize(OptionSet options) - => options.GetOption(FormattingOptions.TabSize, LanguageName); - - public VirtualTreePoint? GetStartPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part) + public VirtualTreePoint? GetStartPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part) { var text = node.SyntaxTree.GetText(); return GetStartPoint(text, options, node, part ?? DefaultPart); } - public VirtualTreePoint? GetEndPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part) + public VirtualTreePoint? GetEndPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part) { var text = node.SyntaxTree.GetText(); return GetEndPoint(text, options, node, part ?? DefaultPart); diff --git a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs index e790153fd1457..c1b2e9c47ff8c 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/AbstractCodeModelService.cs @@ -523,10 +523,10 @@ public void Rename(ISymbol symbol, string newName, Workspace workspace, ProjectC public abstract string GetExternalSymbolName(ISymbol symbol); public abstract string GetExternalSymbolFullName(ISymbol symbol); - public VirtualTreePoint? GetStartPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part) + public VirtualTreePoint? GetStartPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part) => _nodeLocator.GetStartPoint(node, options, part); - public VirtualTreePoint? GetEndPoint(SyntaxNode node, OptionSet options, EnvDTE.vsCMPart? part) + public VirtualTreePoint? GetEndPoint(SyntaxNode node, LineFormattingOptions options, EnvDTE.vsCMPart? part) => _nodeLocator.GetEndPoint(node, options, part); public abstract EnvDTE.vsCMAccess GetAccess(ISymbol symbol); diff --git a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs index b3f398fd6d509..051f22e145435 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel.cs @@ -10,6 +10,7 @@ using System.Runtime.InteropServices; using System.Threading; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Internal.Log; @@ -452,6 +453,13 @@ internal SemanticModel GetSemanticModel() .GetRequiredSemanticModelAsync(CancellationToken.None).AsTask(); }); + internal CodeGenerationOptions GetDocumentOptions() + => State.ThreadingContext.JoinableTaskFactory.Run(() => + { + return GetDocument() + .GetCodeGenerationOptionsAsync(GlobalOptions, CancellationToken.None).AsTask(); + }); + internal Compilation GetCompilation() => State.ThreadingContext.JoinableTaskFactory.Run(() => { diff --git a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel_CodeGen.cs b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel_CodeGen.cs index f53aa5a72fdce..3a1213d0d2013 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel_CodeGen.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/FileCodeModel_CodeGen.cs @@ -194,6 +194,7 @@ internal EnvDTE.CodeClass AddClass(SyntaxNode containerNode, string name, object { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var baseArray = GetValidArray(bases, allowMultipleElements: false); Debug.Assert(baseArray.Length is 0 or 1); @@ -212,6 +213,7 @@ internal EnvDTE.CodeClass AddClass(SyntaxNode containerNode, string name, object TypeKind.Class, CodeModelService.GetUnescapedName(name), access, + options, baseType: baseTypeSymbol, implementedInterfaces: implementedInterfaceSymbols.ToImmutableArray()); @@ -226,10 +228,11 @@ internal EnvDTE.CodeDelegate AddDelegate(SyntaxNode containerNode, string name, { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var returnType = (INamedTypeSymbol)CodeModelService.GetTypeSymbol(type, semanticModel, containerNodePosition); - var newType = CreateDelegateTypeDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, returnType); + var newType = CreateDelegateTypeDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, returnType, options); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); newType = InsertMember(containerNode, newType, insertionIndex); @@ -241,7 +244,9 @@ internal EnvDTE.CodeDelegate AddDelegate(SyntaxNode containerNode, string name, internal EnvDTE.CodeEnum AddEnum(SyntaxNode containerNode, string name, object position, object bases, EnvDTE.vsCMAccess access) #pragma warning restore IDE0060 // Remove unused parameter { - var newType = CreateTypeDeclaration(containerNode, TypeKind.Enum, name, access); + var options = GetDocumentOptions(); + + var newType = CreateTypeDeclaration(containerNode, TypeKind.Enum, name, access, options); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); newType = InsertMember(containerNode, newType, insertionIndex); @@ -257,6 +262,7 @@ public EnvDTE.CodeVariable AddEnumMember(SyntaxNode containerNode, string name, } var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var type = (ITypeSymbol?)semanticModel.GetDeclaredSymbol(containerNode); if (type == null) @@ -264,7 +270,7 @@ public EnvDTE.CodeVariable AddEnumMember(SyntaxNode containerNode, string name, throw Exceptions.ThrowEInvalidArg(); } - var newField = CreateFieldDeclaration(containerNode, CodeModelService.GetUnescapedName(name), EnvDTE.vsCMAccess.vsCMAccessPublic, type); + var newField = CreateFieldDeclaration(containerNode, CodeModelService.GetUnescapedName(name), EnvDTE.vsCMAccess.vsCMAccessPublic, type, options); if (value != null) { newField = CodeModelService.AddInitExpression(newField, (string)value); @@ -281,10 +287,11 @@ public EnvDTE80.CodeEvent AddEvent(SyntaxNode containerNode, string name, string { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var eventType = (INamedTypeSymbol)CodeModelService.GetTypeSymbol(fullDelegateName, semanticModel, containerNodePosition); - var newEvent = CreateEventDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, eventType, createPropertyStyleEvent); + var newEvent = CreateEventDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, eventType, options, createPropertyStyleEvent); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); newEvent = InsertMember(containerNode, newEvent, insertionIndex); @@ -294,6 +301,7 @@ public EnvDTE80.CodeEvent AddEvent(SyntaxNode containerNode, string name, string internal EnvDTE.CodeFunction AddFunction(SyntaxNode containerNode, string name, EnvDTE.vsCMFunction kind, object type, object position, EnvDTE.vsCMAccess access) { + var options = GetDocumentOptions(); kind = CodeModelService.ValidateFunctionKind(containerNode, kind, name); SyntaxNode newMember; @@ -307,15 +315,15 @@ internal EnvDTE.CodeFunction AddFunction(SyntaxNode containerNode, string name, ? CodeModelService.GetTypeSymbol(type, semanticModel, containerNodePosition) : semanticModel.Compilation.GetSpecialType(SpecialType.System_Void); - newMember = CreateMethodDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, returnType); + newMember = CreateMethodDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, returnType, options); } else if (kind == EnvDTE.vsCMFunction.vsCMFunctionConstructor) { - newMember = CreateConstructorDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access); + newMember = CreateConstructorDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, options); } else { - newMember = CreateDestructorDeclaration(containerNode, CodeModelService.GetUnescapedName(name)); + newMember = CreateDestructorDeclaration(containerNode, CodeModelService.GetUnescapedName(name), options); } var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); @@ -339,6 +347,7 @@ internal EnvDTE.CodeInterface AddInterface(SyntaxNode containerNode, string name { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var implementedInterfaceArray = GetValidArray(bases, allowMultipleElements: true); @@ -350,6 +359,7 @@ internal EnvDTE.CodeInterface AddInterface(SyntaxNode containerNode, string name TypeKind.Interface, CodeModelService.GetUnescapedName(name), access, + options, implementedInterfaces: implementedInterfaceSymbols.ToImmutableArray()); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); @@ -361,7 +371,8 @@ internal EnvDTE.CodeInterface AddInterface(SyntaxNode containerNode, string name internal EnvDTE.CodeNamespace AddNamespace(SyntaxNode containerNode, string name, object position) { - var newNamespace = CreateNamespaceDeclaration(containerNode, name); + var options = GetDocumentOptions(); + var newNamespace = CreateNamespaceDeclaration(containerNode, name, options); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); newNamespace = InsertMember(containerNode, newNamespace, insertionIndex); @@ -382,8 +393,8 @@ internal EnvDTE.CodeProperty AddProperty(SyntaxNode containerNode, string getter var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); - var options = State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetOptionsAsync(CancellationToken.None)); var propertyType = CodeModelService.GetTypeSymbol(type, semanticModel, containerNodePosition); var newProperty = CreatePropertyDeclaration( containerNode, @@ -406,6 +417,7 @@ internal EnvDTE.CodeStruct AddStruct(SyntaxNode containerNode, string name, obje { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var implementedInterfaceArray = GetValidArray(bases, allowMultipleElements: true); @@ -417,6 +429,7 @@ internal EnvDTE.CodeStruct AddStruct(SyntaxNode containerNode, string name, obje TypeKind.Struct, CodeModelService.GetUnescapedName(name), access, + options, implementedInterfaces: implementedInterfaceSymbols.ToImmutableArray()); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); @@ -430,9 +443,10 @@ public EnvDTE.CodeVariable AddVariable(SyntaxNode containerNode, string name, ob { var containerNodePosition = containerNode.SpanStart; var semanticModel = GetSemanticModel(); + var options = GetDocumentOptions(); var fieldType = CodeModelService.GetTypeSymbol(type, semanticModel, containerNodePosition); - var newField = CreateFieldDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, fieldType); + var newField = CreateFieldDeclaration(containerNode, CodeModelService.GetUnescapedName(name), access, fieldType, options); var insertionIndex = CodeModelService.PositionVariantToMemberInsertionIndex(position, containerNode, fileCodeModel: this); newField = InsertMember(containerNode, newField, insertionIndex); diff --git a/src/VisualStudio/Core/Impl/CodeModel/InternalElements/AbstractCodeElement.cs b/src/VisualStudio/Core/Impl/CodeModel/InternalElements/AbstractCodeElement.cs index dafb8e6f82999..8ee898fcbaf2c 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/InternalElements/AbstractCodeElement.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/InternalElements/AbstractCodeElement.cs @@ -9,6 +9,7 @@ using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.LanguageServices.Implementation.Interop; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; @@ -36,9 +37,7 @@ internal AbstractCodeElement( } internal FileCodeModel FileCodeModel - { - get { return _fileCodeModel.Object; } - } + => _fileCodeModel.Object; protected SyntaxTree GetSyntaxTree() => FileCodeModel.GetSyntaxTree(); @@ -52,6 +51,9 @@ protected SemanticModel GetSemanticModel() protected ProjectId GetProjectId() => FileCodeModel.GetProjectId(); + internal IGlobalOptionService GlobalOptions + => FileCodeModel.GlobalOptions; + internal bool IsValidNode() { if (!TryLookupNode(out var node)) @@ -140,11 +142,14 @@ public virtual EnvDTE.CodeElements Collection get { return GetCollection(); } } + private LineFormattingOptions GetLineFormattingOptions() + => State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetLineFormattingOptionsAsync(GlobalOptions, CancellationToken.None).AsTask()); + public EnvDTE.TextPoint StartPoint { get { - var options = State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetOptionsAsync(CancellationToken.None)); + var options = GetLineFormattingOptions(); var point = CodeModelService.GetStartPoint(LookupNode(), options); if (point == null) { @@ -159,7 +164,7 @@ public EnvDTE.TextPoint EndPoint { get { - var options = State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetOptionsAsync(CancellationToken.None)); + var options = GetLineFormattingOptions(); var point = CodeModelService.GetEndPoint(LookupNode(), options); if (point == null) { @@ -172,7 +177,7 @@ public EnvDTE.TextPoint EndPoint public virtual EnvDTE.TextPoint GetStartPoint(EnvDTE.vsCMPart part) { - var options = State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetOptionsAsync(CancellationToken.None)); + var options = GetLineFormattingOptions(); var point = CodeModelService.GetStartPoint(LookupNode(), options, part); if (point == null) { @@ -184,7 +189,7 @@ public virtual EnvDTE.TextPoint GetStartPoint(EnvDTE.vsCMPart part) public virtual EnvDTE.TextPoint GetEndPoint(EnvDTE.vsCMPart part) { - var options = State.ThreadingContext.JoinableTaskFactory.Run(() => GetDocument().GetOptionsAsync(CancellationToken.None)); + var options = GetLineFormattingOptions(); var point = CodeModelService.GetEndPoint(LookupNode(), options, part); if (point == null) { diff --git a/src/VisualStudio/Core/Impl/Options/AbstractOptionPreviewViewModel.cs b/src/VisualStudio/Core/Impl/Options/AbstractOptionPreviewViewModel.cs index a9d53716730c3..ae8250028a21a 100644 --- a/src/VisualStudio/Core/Impl/Options/AbstractOptionPreviewViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/AbstractOptionPreviewViewModel.cs @@ -139,7 +139,10 @@ public void UpdatePreview(string text) var document = project.AddDocument("document", SourceText.From(text, Encoding.UTF8)); var fallbackFormattingOptions = _globalOptions.GetSyntaxFormattingOptions(document.Project.LanguageServices); - var formattingOptions = SyntaxFormattingOptions.Create(OptionStore.GetOptions(), fallbackFormattingOptions, document.Project.LanguageServices); + var optionService = workspace.Services.GetRequiredService(); + var configOptions = OptionStore.GetOptions().AsAnalyzerConfigOptions(optionService, document.Project.Language); + var formattingService = document.GetRequiredLanguageService(); + var formattingOptions = formattingService.GetFormattingOptions(configOptions, fallbackFormattingOptions); var formatted = Formatter.FormatAsync(document, formattingOptions, CancellationToken.None).WaitAndGetResult(CancellationToken.None); var textBuffer = _textBufferFactoryService.CreateTextBuffer(formatted.GetTextSynchronously(CancellationToken.None).ToString(), _contentType); diff --git a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs index e8a3d8fd74995..f022a616398f7 100644 --- a/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/VisualStudioDiagnosticAnalyzerExecutorTests.cs @@ -12,7 +12,9 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle; using Microsoft.CodeAnalysis.CSharp.Formatting; @@ -20,6 +22,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Remote.Testing; @@ -27,6 +30,7 @@ using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.VisualBasic.CodeStyle; using Microsoft.CodeAnalysis.VisualBasic.UseNullPropagation; using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Roslyn.Test.Utilities; @@ -58,12 +62,17 @@ void Method() Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id); Assert.Equal(DiagnosticSeverity.Hidden, diagnostics[0].Severity); - var ideOptions = new IdeAnalyzerOptions( - CleanupOptions: new CodeCleanupOptions( - FormattingOptions: CSharpSyntaxFormattingOptions.Default, - SimplifierOptions: new CSharpSimplifierOptions( - varWhenTypeIsApparent: new CodeStyleOption2(false, NotificationOption2.Suggestion)), - AddImportOptions: AddImportPlacementOptions.Default)); + var ideOptions = new IdeAnalyzerOptions() + { + CleanCodeGenerationOptions = new CleanCodeGenerationOptions( + CSharpCodeGenerationOptions.Default, + new CodeCleanupOptions( + FormattingOptions: CSharpSyntaxFormattingOptions.Default, + SimplifierOptions: new CSharpSimplifierOptions() + { + VarWhenTypeIsApparent = new CodeStyleOption2(false, NotificationOption2.Suggestion) + })) + }; analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, ideOptions); @@ -84,20 +93,31 @@ End Sub using (var workspace = CreateWorkspace(LanguageNames.VisualBasic, code)) { - // set option - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(CodeStyleOptions2.PreferNullPropagation, LanguageNames.VisualBasic, new CodeStyleOption2(false, NotificationOption2.Silent)))); - var ideAnalyzerOptions = IdeAnalyzerOptions.GetDefault(workspace.Services.GetLanguageServices(LanguageNames.VisualBasic)); + ideAnalyzerOptions = ideAnalyzerOptions with + { + CodeStyleOptions = new VisualBasicIdeCodeStyleOptions( + Common: new IdeCodeStyleOptions.CommonOptions() + { + PreferNullPropagation = new CodeStyleOption2(false, NotificationOption2.Silent) + }) + }; + var analyzerType = typeof(VisualBasicUseNullPropagationDiagnosticAnalyzer); var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, ideAnalyzerOptions); Assert.True(analyzerResult.IsEmpty); - // set option - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options - .WithChangedOption(CodeStyleOptions2.PreferNullPropagation, LanguageNames.VisualBasic, new CodeStyleOption2(true, NotificationOption2.Error)))); + ideAnalyzerOptions = ideAnalyzerOptions with + { + CodeStyleOptions = new VisualBasicIdeCodeStyleOptions( + Common: new IdeCodeStyleOptions.CommonOptions() + { + PreferNullPropagation = new CodeStyleOption2(true, NotificationOption2.Error) + }) + }; + analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType, ideAnalyzerOptions); var diagnostics = analyzerResult.GetDocumentDiagnostics(analyzerResult.DocumentIds.First(), AnalysisKind.Semantic); diff --git a/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb b/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb index 23e7de87258a3..a8e0c4824ad78 100644 --- a/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb +++ b/src/VisualStudio/Core/Test/Snippets/CSharpSnippetExpansionClientTests.vb @@ -394,10 +394,10 @@ using G= H.I; workspace.GetService(Of IGlobalOptionService)) Dim document = workspace.CurrentSolution.Projects.Single().Documents.Single() - Dim addImportOptions = New AddImportPlacementOptions( - PlaceSystemNamespaceFirst:=placeSystemNamespaceFirst, - PlaceImportsInsideNamespaces:=False, - AllowInHiddenRegions:=False) + Dim addImportOptions = New AddImportPlacementOptions() With + { + .PlaceSystemNamespaceFirst = placeSystemNamespaceFirst + } Dim formattingOptions = CSharpSyntaxFormattingOptions.Default diff --git a/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb b/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb index 252e427a8422e..2a0f64fece3b6 100644 --- a/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb +++ b/src/VisualStudio/Core/Test/Snippets/VisualBasicSnippetExpansionClientTests.vb @@ -413,10 +413,10 @@ End Class Dim document = workspace.CurrentSolution.Projects.Single().Documents.Single() - Dim addImportOptions = New AddImportPlacementOptions( - PlaceSystemNamespaceFirst:=placeSystemNamespaceFirst, - PlaceImportsInsideNamespaces:=False, - AllowInHiddenRegions:=False) + Dim addImportOptions = New AddImportPlacementOptions() With + { + .PlaceSystemNamespaceFirst = placeSystemNamespaceFirst + } Dim formattingOptions = VisualBasicSyntaxFormattingOptions.Default diff --git a/src/VisualStudio/Core/Test/Venus/CSharpContainedLanguageSupportTests.vb b/src/VisualStudio/Core/Test/Venus/CSharpContainedLanguageSupportTests.vb index 71a9482094bae..73e69e1e147af 100644 --- a/src/VisualStudio/Core/Test/Venus/CSharpContainedLanguageSupportTests.vb +++ b/src/VisualStudio/Core/Test/Venus/CSharpContainedLanguageSupportTests.vb @@ -163,6 +163,7 @@ public partial class _Default : System.Web.UI.Page Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -192,6 +193,7 @@ public class _Default : System.Web.UI.Page Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -218,6 +220,7 @@ public class _Default : System.Web.UI.Page Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -246,6 +249,7 @@ public partial class _Default Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -277,6 +281,7 @@ public class MyBaseClass Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -543,6 +548,7 @@ public class _Default itemidInsertionPoint:=0, useHandlesClause:=False, additionalFormattingRule:=BlankLineInGeneratedMethodFormattingRule.Instance, + workspace.GlobalOptions, cancellationToken:=Nothing) ' Since a valid handler exists, item2 and item3 of the tuple returned must be nothing @@ -592,6 +598,7 @@ protected void Button1_Click(object sender, EventArgs e) itemidInsertionPoint:=0, useHandlesClause:=False, additionalFormattingRule:=BlankLineInGeneratedMethodFormattingRule.Instance, + workspace.GlobalOptions, cancellationToken:=Nothing) Assert.Equal("Button1_Click(object,System.EventArgs)", eventHandlerIdTextPosition.Item1) @@ -642,6 +649,7 @@ public class _Default Dim actualSpan As TextSpan = Nothing If Not ContainedLanguageCodeSupport.TryGetMemberNavigationPoint( thisDocument:=document, + workspace.GlobalOptions, className:="_Default", uniqueMemberID:="Button1_Click(object,System.EventArgs)", textSpan:=actualSpan, diff --git a/src/VisualStudio/Core/Test/Venus/VisualBasicContainedLanguageSupportTests.vb b/src/VisualStudio/Core/Test/Venus/VisualBasicContainedLanguageSupportTests.vb index 81b309c25bd08..5036eee90cefb 100644 --- a/src/VisualStudio/Core/Test/Venus/VisualBasicContainedLanguageSupportTests.vb +++ b/src/VisualStudio/Core/Test/Venus/VisualBasicContainedLanguageSupportTests.vb @@ -201,6 +201,7 @@ End Class Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -229,6 +230,7 @@ End Class Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -255,6 +257,7 @@ End Class.Value Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -282,6 +285,7 @@ End Class.Value Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -311,6 +315,7 @@ End Class.Value Dim document = GetDocument(workspace) Dim eventName = ContainedLanguageCodeSupport.CreateUniqueEventName( document:=document, + workspace.GlobalOptions, className:="_Default", objectName:="Button1", nameOfEvent:="Click", @@ -556,6 +561,7 @@ End Class.Value itemidInsertionPoint:=0, useHandlesClause:=True, additionalFormattingRule:=LineAdjustmentFormattingRule.Instance, + workspace.GlobalOptions, cancellationToken:=Nothing) ' Since a valid handler exists, item2 and item3 of the tuple returned must be nothing @@ -600,6 +606,7 @@ End Sub.NormalizedValue itemidInsertionPoint:=0, useHandlesClause:=True, additionalFormattingRule:=LineAdjustmentFormattingRule.Instance, + workspace.GlobalOptions, cancellationToken:=Nothing) Assert.Equal("Button1_Click(Object,System.EventArgs)", eventHandlerIdTextPosition.Item1) @@ -644,6 +651,7 @@ End Sub" itemidInsertionPoint:=0, useHandlesClause:=True, additionalFormattingRule:=LineAdjustmentFormattingRule.Instance, + workspace.GlobalOptions, cancellationToken:=Nothing) Assert.Equal("Page_Load(Object,System.EventArgs)", eventHandlerIdTextPosition.Item1) @@ -690,6 +698,7 @@ End Class.Value Dim actualSpan As TextSpan = Nothing If Not ContainedLanguageCodeSupport.TryGetMemberNavigationPoint( thisDocument:=document, + workspace.GlobalOptions, className:="_Default", uniqueMemberID:="Button1_Click(Object,System.EventArgs)", textSpan:=actualSpan, diff --git a/src/VisualStudio/VisualBasic/Impl/CodeModel/VisualBasicCodeModelService.NodeLocator.vb b/src/VisualStudio/VisualBasic/Impl/CodeModel/VisualBasicCodeModelService.NodeLocator.vb index 3215ea28c5867..4e255ca47373b 100644 --- a/src/VisualStudio/VisualBasic/Impl/CodeModel/VisualBasicCodeModelService.NodeLocator.vb +++ b/src/VisualStudio/VisualBasic/Impl/CodeModel/VisualBasicCodeModelService.NodeLocator.vb @@ -5,6 +5,7 @@ Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities +Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic @@ -34,7 +35,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel End Get End Property - Protected Overrides Function GetStartPoint(text As SourceText, options As OptionSet, node As SyntaxNode, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Protected Overrides Function GetStartPoint(text As SourceText, options As LineFormattingOptions, node As SyntaxNode, part As EnvDTE.vsCMPart) As VirtualTreePoint? Select Case node.Kind Case SyntaxKind.ClassBlock, SyntaxKind.InterfaceBlock, @@ -124,7 +125,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel End Select End Function - Protected Overrides Function GetEndPoint(text As SourceText, options As OptionSet, node As SyntaxNode, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Protected Overrides Function GetEndPoint(text As SourceText, options As LineFormattingOptions, node As SyntaxNode, part As EnvDTE.vsCMPart) As VirtualTreePoint? Select Case node.Kind Case SyntaxKind.ClassBlock, SyntaxKind.InterfaceBlock, @@ -296,7 +297,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel End If End Function - Private Function GetTypeBlockStartPoint(text As SourceText, options As OptionSet, typeBlock As TypeBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Private Shared Function GetTypeBlockStartPoint(text As SourceText, options As LineFormattingOptions, typeBlock As TypeBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? Dim startPosition As Integer Select Case part @@ -346,7 +347,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel End If If part = EnvDTE.vsCMPart.vsCMPartNavigate Then - Return NavigationPointHelpers.GetNavigationPoint(text, GetTabSize(options), typeBlock.BlockStatement, statementLine.LineNumber + 1) + Return NavigationPointHelpers.GetNavigationPoint(text, options.TabSize, typeBlock.BlockStatement, statementLine.LineNumber + 1) End If Case Else @@ -382,7 +383,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel Return New VirtualTreePoint(typeBlock.SyntaxTree, text, startPosition) End Function - Private Function GetEnumBlockStartPoint(text As SourceText, options As OptionSet, enumBlock As EnumBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Private Shared Function GetEnumBlockStartPoint(text As SourceText, options As LineFormattingOptions, enumBlock As EnumBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? Dim startPosition As Integer Select Case part @@ -417,7 +418,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel End If If part = EnvDTE.vsCMPart.vsCMPartNavigate Then - Return NavigationPointHelpers.GetNavigationPoint(text, GetTabSize(options), enumBlock.EnumStatement, statementLine.LineNumber + 1) + Return NavigationPointHelpers.GetNavigationPoint(text, options.TabSize, enumBlock.EnumStatement, statementLine.LineNumber + 1) End If Case Else @@ -453,7 +454,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel Return New VirtualTreePoint(enumBlock.SyntaxTree, text, startPosition) End Function - Private Function GetMethodBlockStartPoint(text As SourceText, options As OptionSet, methodBlock As MethodBlockBaseSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Private Shared Function GetMethodBlockStartPoint(text As SourceText, options As LineFormattingOptions, methodBlock As MethodBlockBaseSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? Dim startPosition As Integer Select Case part @@ -498,7 +499,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel EnvDTE.vsCMPart.vsCMPartWhole startPosition = NavigationPointHelpers.GetHeaderStartPosition(methodBlock) Case EnvDTE.vsCMPart.vsCMPartNavigate - Return NavigationPointHelpers.GetNavigationPoint(text, GetTabSize(options), methodBlock) + Return NavigationPointHelpers.GetNavigationPoint(text, options.TabSize, methodBlock) Case EnvDTE.vsCMPart.vsCMPartBody, EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter @@ -781,7 +782,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel Return New VirtualTreePoint(propertyStatement.SyntaxTree, text, startPosition) End Function - Private Function GetEventBlockStartPoint(text As SourceText, options As OptionSet, eventBlock As EventBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Private Shared Function GetEventBlockStartPoint(text As SourceText, options As LineFormattingOptions, eventBlock As EventBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? Dim startPosition As Integer Select Case part @@ -806,7 +807,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel Case EnvDTE.vsCMPart.vsCMPartNavigate - Return NavigationPointHelpers.GetNavigationPoint(text, GetTabSize(options), eventBlock) + Return NavigationPointHelpers.GetNavigationPoint(text, options.TabSize, eventBlock) Case EnvDTE.vsCMPart.vsCMPartBody, EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter @@ -978,7 +979,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel .FirstOrNull(Function(t) t.Kind = SyntaxKind.ColonTrivia) End Function - Private Function GetNamespaceBlockStartPoint(text As SourceText, options As OptionSet, namespaceBlock As NamespaceBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? + Private Shared Function GetNamespaceBlockStartPoint(text As SourceText, options As LineFormattingOptions, namespaceBlock As NamespaceBlockSyntax, part As EnvDTE.vsCMPart) As VirtualTreePoint? Dim startPosition As Integer Select Case part @@ -1007,7 +1008,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel lineNumber = text.Lines.IndexOf(colonTrivia.Value.SpanStart) End If - Return NavigationPointHelpers.GetNavigationPoint(text, GetTabSize(options), namespaceBlock.NamespaceStatement, lineNumber) + Return NavigationPointHelpers.GetNavigationPoint(text, options.TabSize, namespaceBlock.NamespaceStatement, lineNumber) Case EnvDTE.vsCMPart.vsCMPartBody, EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AutomationObject/AutomationObject.Style.vb b/src/VisualStudio/VisualBasic/Impl/Options/AutomationObject/AutomationObject.Style.vb index da0fa544c6627..c42213583895b 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AutomationObject/AutomationObject.Style.vb +++ b/src/VisualStudio/VisualBasic/Impl/Options/AutomationObject/AutomationObject.Style.vb @@ -3,6 +3,7 @@ ' See the LICENSE file in the project root for more information. Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.VisualBasic.CodeStyle Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options @@ -81,19 +82,19 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options Public Property Style_PreferObjectInitializer_FadeOutCode As Boolean Get - Return GetBooleanOption(CodeStyleOptions2.PreferObjectInitializer_FadeOutCode) + Return GetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexObjectInitialization) End Get Set(value As Boolean) - SetBooleanOption(CodeStyleOptions2.PreferObjectInitializer_FadeOutCode, value) + SetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexObjectInitialization, value) End Set End Property Public Property Style_PreferCollectionInitializer_FadeOutCode As Boolean Get - Return GetBooleanOption(CodeStyleOptions2.PreferCollectionInitializer_FadeOutCode) + Return GetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexCollectionInitialization) End Get Set(value As Boolean) - SetBooleanOption(CodeStyleOptions2.PreferCollectionInitializer_FadeOutCode, value) + SetBooleanOption(IdeAnalyzerOptionsStorage.FadeOutComplexCollectionInitialization, value) End Set End Property @@ -207,10 +208,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options Public Property Style_RequireAccessibilityModifiers As String Get - Return GetXmlOption(CodeStyleOptions2.RequireAccessibilityModifiers) + Return GetXmlOption(CodeStyleOptions2.AccessibilityModifiersRequired) End Get Set(value As String) - SetXmlOption(CodeStyleOptions2.RequireAccessibilityModifiers, value) + SetXmlOption(CodeStyleOptions2.AccessibilityModifiersRequired, value) End Set End Property diff --git a/src/VisualStudio/VisualBasic/Impl/Venus/VisualBasicContainedLanguage.vb b/src/VisualStudio/VisualBasic/Impl/Venus/VisualBasicContainedLanguage.vb index df8b1ec1c1ce0..925b3a99f4418 100644 --- a/src/VisualStudio/VisualBasic/Impl/Venus/VisualBasicContainedLanguage.vb +++ b/src/VisualStudio/VisualBasic/Impl/Venus/VisualBasicContainedLanguage.vb @@ -87,6 +87,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Venus itemidInsertionPoint, useHandlesClause:=True, additionalFormattingRule:=LineAdjustmentFormattingRule.Instance, + GlobalOptions, cancellationToken:=Nothing) pbstrUniqueMemberID = idBodyAndInsertionPoint.Item1 diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationOptions.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationOptions.cs deleted file mode 100644 index 7e8758b68ab3f..0000000000000 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationOptions.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Runtime.Serialization; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.CSharp.CodeStyle; -using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Editing; -using Microsoft.CodeAnalysis.Options; -using Roslyn.Utilities; - -namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration; - -[DataContract] -internal sealed class CSharpCodeGenerationOptions : CodeGenerationOptions -{ - private static readonly CodeStyleOption2 s_neverWithSilentEnforcement = - new(ExpressionBodyPreference.Never, NotificationOption2.Silent); - - private static readonly CodeStyleOption2 s_whenPossibleWithSilentEnforcement = - new(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent); - - private static readonly CodeStyleOption2 s_blockedScopedWithSilentEnforcement = - new(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Silent); - - private static readonly CodeStyleOption2 s_trueWithSuggestionEnforcement = - new(value: true, notification: NotificationOption2.Suggestion); - - [DataMember(Order = BaseMemberCount + 0)] public readonly CodeStyleOption2 PreferExpressionBodiedMethods; - [DataMember(Order = BaseMemberCount + 1)] public readonly CodeStyleOption2 PreferExpressionBodiedAccessors; - [DataMember(Order = BaseMemberCount + 2)] public readonly CodeStyleOption2 PreferExpressionBodiedProperties; - [DataMember(Order = BaseMemberCount + 3)] public readonly CodeStyleOption2 PreferExpressionBodiedIndexers; - [DataMember(Order = BaseMemberCount + 4)] public readonly CodeStyleOption2 PreferExpressionBodiedConstructors; - [DataMember(Order = BaseMemberCount + 5)] public readonly CodeStyleOption2 PreferExpressionBodiedOperators; - [DataMember(Order = BaseMemberCount + 6)] public readonly CodeStyleOption2 PreferExpressionBodiedLocalFunctions; - [DataMember(Order = BaseMemberCount + 7)] public readonly CodeStyleOption2 PreferExpressionBodiedLambdas; - [DataMember(Order = BaseMemberCount + 8)] public readonly CodeStyleOption2 PreferStaticLocalFunction; - [DataMember(Order = BaseMemberCount + 9)] public readonly CodeStyleOption2 NamespaceDeclarations; - - public CSharpCodeGenerationOptions( - CodeStyleOption2? preferExpressionBodiedMethods = null, - CodeStyleOption2? preferExpressionBodiedAccessors = null, - CodeStyleOption2? preferExpressionBodiedProperties = null, - CodeStyleOption2? preferExpressionBodiedIndexers = null, - CodeStyleOption2? preferExpressionBodiedConstructors = null, - CodeStyleOption2? preferExpressionBodiedOperators = null, - CodeStyleOption2? preferExpressionBodiedLocalFunctions = null, - CodeStyleOption2? preferExpressionBodiedLambdas = null, - CodeStyleOption2? preferStaticLocalFunction = null, - CodeStyleOption2? namespaceDeclarations = null) - { - PreferExpressionBodiedMethods = preferExpressionBodiedMethods ?? s_neverWithSilentEnforcement; - PreferExpressionBodiedAccessors = preferExpressionBodiedAccessors ?? s_whenPossibleWithSilentEnforcement; - PreferExpressionBodiedProperties = preferExpressionBodiedProperties ?? s_whenPossibleWithSilentEnforcement; - PreferExpressionBodiedIndexers = preferExpressionBodiedIndexers ?? s_whenPossibleWithSilentEnforcement; - PreferExpressionBodiedConstructors = preferExpressionBodiedConstructors ?? s_neverWithSilentEnforcement; - PreferExpressionBodiedOperators = preferExpressionBodiedOperators ?? s_neverWithSilentEnforcement; - PreferExpressionBodiedLocalFunctions = preferExpressionBodiedLocalFunctions ?? s_neverWithSilentEnforcement; - PreferExpressionBodiedLambdas = preferExpressionBodiedLambdas ?? s_whenPossibleWithSilentEnforcement; - PreferStaticLocalFunction = preferStaticLocalFunction ?? s_trueWithSuggestionEnforcement; - NamespaceDeclarations = namespaceDeclarations ?? s_blockedScopedWithSilentEnforcement; - } - - public static readonly CSharpCodeGenerationOptions Default = new(); - - public static CSharpCodeGenerationOptions Create(AnalyzerConfigOptions options, CSharpCodeGenerationOptions? fallbackOptions) - { - fallbackOptions ??= Default; - - return new( - preferExpressionBodiedMethods: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, fallbackOptions.PreferExpressionBodiedMethods), - preferExpressionBodiedAccessors: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, fallbackOptions.PreferExpressionBodiedAccessors), - preferExpressionBodiedProperties: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, fallbackOptions.PreferExpressionBodiedProperties), - preferExpressionBodiedIndexers: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, fallbackOptions.PreferExpressionBodiedIndexers), - preferExpressionBodiedConstructors: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, fallbackOptions.PreferExpressionBodiedConstructors), - preferExpressionBodiedOperators: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, fallbackOptions.PreferExpressionBodiedOperators), - preferExpressionBodiedLocalFunctions: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, fallbackOptions.PreferExpressionBodiedLocalFunctions), - preferExpressionBodiedLambdas: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas, fallbackOptions.PreferExpressionBodiedLambdas), - preferStaticLocalFunction: options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, fallbackOptions.PreferStaticLocalFunction), - namespaceDeclarations: options.GetEditorConfigOption(CSharpCodeStyleOptions.NamespaceDeclarations, fallbackOptions.NamespaceDeclarations)); - } - - public override CodeGenerationContextInfo GetInfo(CodeGenerationContext context, ParseOptions parseOptions) - => new CSharpCodeGenerationContextInfo(context, this, ((CSharpParseOptions)parseOptions).LanguageVersion); -} diff --git a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs index de91562e04f04..4685f85bbe48b 100644 --- a/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs +++ b/src/Workspaces/CSharp/Portable/CodeGeneration/CSharpCodeGenerationService.cs @@ -33,8 +33,8 @@ public CSharpCodeGenerationService(HostLanguageServices languageServices) public override CodeGenerationOptions DefaultOptions => CSharpCodeGenerationOptions.Default; - public override CodeGenerationOptions GetCodeGenerationOptions(AnalyzerConfigOptions info, CodeGenerationOptions? fallbackOptions) - => CSharpCodeGenerationOptions.Create(info, (CSharpCodeGenerationOptions?)fallbackOptions); + public override CodeGenerationOptions GetCodeGenerationOptions(AnalyzerConfigOptions options, CodeGenerationOptions? fallbackOptions) + => options.GetCSharpCodeGenerationOptions((CSharpCodeGenerationOptions?)fallbackOptions); public override CodeGenerationDestination GetDestination(SyntaxNode node) => CSharpCodeGenerationHelpers.GetDestination(node); diff --git a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptionsProvider.cs b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptionsProvider.cs index 44b158c2af7fc..522e0462fcedf 100644 --- a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptionsProvider.cs +++ b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleOptionsProvider.cs @@ -12,11 +12,11 @@ namespace Microsoft.CodeAnalysis.CSharp.CodeStyle { [ExportSolutionOptionProvider(LanguageNames.CSharp), Shared] - internal sealed class CSharpCodeStyleOptionsProvider : IOptionProvider + internal sealed class CSharpSolutionCodeStyleOptionsProvider : IOptionProvider { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpCodeStyleOptionsProvider() + public CSharpSolutionCodeStyleOptionsProvider() { } diff --git a/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleService.cs b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleService.cs new file mode 100644 index 0000000000000..53e97e51cf884 --- /dev/null +++ b/src/Workspaces/CSharp/Portable/CodeStyle/CSharpCodeStyleService.cs @@ -0,0 +1,23 @@ +// 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.Host.Mef; + +namespace Microsoft.CodeAnalysis.CSharp.CodeStyle; + +[ExportLanguageService(typeof(ICodeStyleService), LanguageNames.CSharp), Shared] +internal sealed class CSharpCodeStyleService : ICodeStyleService +{ + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CSharpCodeStyleService() + { + } + + public IdeCodeStyleOptions DefaultOptions + => CSharpIdeCodeStyleOptions.Default; +} diff --git a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs index 6ee54271b0f42..4792d141b4c2f 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.cs @@ -48,7 +48,7 @@ public override SimplifierOptions DefaultOptions => CSharpSimplifierOptions.Default; public override SimplifierOptions GetSimplifierOptions(AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions) - => CSharpSimplifierOptions.Create(options, (CSharpSimplifierOptions?)fallbackOptions); + => options.GetCSharpSimplifierOptions((CSharpSimplifierOptions?)fallbackOptions); public override SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation? annotationForReplacedAliasIdentifier, Func? expandInsideNode, bool expandParameter, CancellationToken cancellationToken) { diff --git a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs index ad6f7fd99e0d4..c9eda64b0a230 100644 --- a/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs +++ b/src/Workspaces/CSharpTest/CodeGeneration/AddImportsTests.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -75,10 +76,11 @@ private static async Task TestAsync( { var doc = await GetDocument(initialText, useSymbolAnnotations); - var addImportOptions = new AddImportPlacementOptions( - PlaceSystemNamespaceFirst: placeSystemNamespaceFirst, - PlaceImportsInsideNamespaces: placeImportsInsideNamespaces, - AllowInHiddenRegions: false); + var addImportOptions = new AddImportPlacementOptions() + { + PlaceSystemNamespaceFirst = placeSystemNamespaceFirst, + UsingDirectivePlacement = new CodeStyleOption2(placeImportsInsideNamespaces ? AddImportPlacement.InsideNamespace : AddImportPlacement.OutsideNamespace, NotificationOption2.None), + }; var formattingOptions = CSharpSyntaxFormattingOptions.Default; diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs index da61d0ffd3e3e..d46a293a5d52a 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs @@ -1752,7 +1752,10 @@ public void NewLineOptions_LineFeedOnly() // replace all EOL trivia with elastic markers to force the formatter to add EOL back tree = tree.ReplaceTrivia(tree.DescendantTrivia().Where(tr => tr.IsKind(SyntaxKind.EndOfLineTrivia)), (o, r) => SyntaxFactory.ElasticMarker); - var options = new CSharpSyntaxFormattingOptions(new LineFormattingOptions(NewLine: "\n")); + var options = new CSharpSyntaxFormattingOptions() + { + Common = new SyntaxFormattingOptions.CommonOptions { LineFormatting = new LineFormattingOptions { NewLine = "\n" } } + }; var formatted = Formatter.Format(tree, workspace.Services, options, CancellationToken.None); @@ -1797,7 +1800,14 @@ class F using var workspace = new AdhocWorkspace(); - var options = new CSharpSyntaxFormattingOptions(new LineFormattingOptions(UseTabs: true)); + var options = new CSharpSyntaxFormattingOptions() + { + Common = new SyntaxFormattingOptions.CommonOptions + { + LineFormatting = new LineFormattingOptions { UseTabs = true } + } + }; + var formatted = Formatter.Format(tree, workspace.Services, options, CancellationToken.None); var actual = formatted.ToFullString(); diff --git a/src/Workspaces/CSharpTest/OrganizeImports/OrganizeUsingsTests.cs b/src/Workspaces/CSharpTest/OrganizeImports/OrganizeUsingsTests.cs index 102471bfc5043..28a4e731b17e7 100644 --- a/src/Workspaces/CSharpTest/OrganizeImports/OrganizeUsingsTests.cs +++ b/src/Workspaces/CSharpTest/OrganizeImports/OrganizeUsingsTests.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -28,15 +29,16 @@ protected static async Task CheckAsync( var project = workspace.CurrentSolution.AddProject("Project", "Project.dll", LanguageNames.CSharp); var document = project.AddDocument("Document", initial.ReplaceLineEndings(endOfLine ?? Environment.NewLine)); - var newOptions = workspace.Options.WithChangedOption(new OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst); - newOptions = newOptions.WithChangedOption(new OptionKey(GenerationOptions.SeparateImportDirectiveGroups, document.Project.Language), separateImportGroups); + var options = new OrganizeImportsOptions() + { + PlaceSystemNamespaceFirst = placeSystemNamespaceFirst, + SeparateImportDirectiveGroups = separateImportGroups, + NewLine = endOfLine ?? OrganizeImportsOptions.Default.NewLine + }; - if (endOfLine is not null) - newOptions = newOptions.WithChangedOption(new OptionKey(FormattingOptions2.NewLine, document.Project.Language), endOfLine); - - document = document.WithSolutionOptions(newOptions); - - var newRoot = await (await Formatter.OrganizeImportsAsync(document, CancellationToken.None)).GetRequiredSyntaxRootAsync(default); + var organizeImportsService = document.GetRequiredLanguageService(); + var newDocument = await organizeImportsService.OrganizeImportsAsync(document, options, CancellationToken.None); + var newRoot = await newDocument.GetRequiredSyntaxRootAsync(default); Assert.Equal(final.ReplaceLineEndings(endOfLine ?? Environment.NewLine), newRoot.ToFullString()); } diff --git a/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs b/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs index dcfe7b090e60b..49678798e9d70 100644 --- a/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs +++ b/src/Workspaces/Core/Portable/CodeActions/CodeAction.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; @@ -314,8 +315,11 @@ protected virtual async Task PostProcessChangesAsync(Document document { if (document.SupportsSyntaxTree) { - // TODO: fallback options https://github.com/dotnet/roslyn/issues/60777 - var options = await document.GetCodeCleanupOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + // TODO: avoid ILegacyGlobalOptionsWorkspaceService https://github.com/dotnet/roslyn/issues/60777 + var globalOptions = document.Project.Solution.Workspace.Services.GetService(); + var fallbackOptions = globalOptions?.CleanCodeGenerationOptionsProvider ?? CodeActionOptions.DefaultProvider; + + var options = await document.GetCodeCleanupOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); return await CleanupDocumentAsync(document, options, cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs index cf43d86a635c8..e6f2486fabe30 100644 --- a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs +++ b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleaner.cs @@ -49,38 +49,36 @@ public static ImmutableArray GetDefaultProviders(Document /// Cleans up the whole document. /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used. /// - public static async Task CleanupAsync(Document document, ImmutableArray providers = default, CancellationToken cancellationToken = default) + public static async Task CleanupAsync(Document document, CodeCleanupOptions options, ImmutableArray providers = default, CancellationToken cancellationToken = default) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); - return await CleanupAsync(document, new TextSpan(0, text.Length), providers, cancellationToken: cancellationToken).ConfigureAwait(false); + return await CleanupAsync(document, new TextSpan(0, text.Length), options, providers, cancellationToken: cancellationToken).ConfigureAwait(false); } /// /// Cleans up the document marked with the provided annotation. /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used. /// - public static async Task CleanupAsync(Document document, SyntaxAnnotation annotation, ImmutableArray providers = default, CancellationToken cancellationToken = default) + public static async Task CleanupAsync(Document document, SyntaxAnnotation annotation, CodeCleanupOptions options, ImmutableArray providers = default, CancellationToken cancellationToken = default) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - return await CleanupAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(n => n.Span).ToImmutableArray(), providers, cancellationToken: cancellationToken).ConfigureAwait(false); + return await CleanupAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(n => n.Span).ToImmutableArray(), options, providers, cancellationToken: cancellationToken).ConfigureAwait(false); } /// /// Clean up the provided span in the document. /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used. /// - public static Task CleanupAsync(Document document, TextSpan span, ImmutableArray providers = default, CancellationToken cancellationToken = default) - => CleanupAsync(document, ImmutableArray.Create(span), providers, cancellationToken); + public static Task CleanupAsync(Document document, TextSpan span, CodeCleanupOptions options, ImmutableArray providers = default, CancellationToken cancellationToken = default) + => CleanupAsync(document, ImmutableArray.Create(span), options, providers, cancellationToken); /// /// Clean up the provided spans in the document. /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used. /// - public static async Task CleanupAsync(Document document, ImmutableArray spans, ImmutableArray providers = default, CancellationToken cancellationToken = default) + public static async Task CleanupAsync(Document document, ImmutableArray spans, CodeCleanupOptions options, ImmutableArray providers = default, CancellationToken cancellationToken = default) { var cleanupService = document.GetRequiredLanguageService(); - var options = await document.GetCodeCleanupOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); - return await cleanupService.CleanupAsync(document, spans, options, providers, cancellationToken).ConfigureAwait(false); } @@ -88,20 +86,18 @@ public static async Task CleanupAsync(Document document, ImmutableArra /// Clean up the provided span in the node. /// This will only cleanup stuff that doesn't require semantic information. /// - public static Task CleanupAsync(SyntaxNode root, TextSpan span, OptionSet options, HostWorkspaceServices services, ImmutableArray providers = default, CancellationToken cancellationToken = default) + public static Task CleanupAsync(SyntaxNode root, TextSpan span, SyntaxFormattingOptions options, HostWorkspaceServices services, ImmutableArray providers = default, CancellationToken cancellationToken = default) => CleanupAsync(root, ImmutableArray.Create(span), options, services, providers, cancellationToken); /// /// Clean up the provided spans in the node. /// This will only cleanup stuff that doesn't require semantic information. /// - public static Task CleanupAsync(SyntaxNode root, ImmutableArray spans, OptionSet options, HostWorkspaceServices services, ImmutableArray providers = default, CancellationToken cancellationToken = default) + public static Task CleanupAsync(SyntaxNode root, ImmutableArray spans, SyntaxFormattingOptions options, HostWorkspaceServices services, ImmutableArray providers = default, CancellationToken cancellationToken = default) { var languageServices = services.GetLanguageServices(root.Language); - var formattingOptions = SyntaxFormattingOptions.Create(options, fallbackOptions: null, languageServices); - var cleanupService = languageServices.GetRequiredService(); - return cleanupService.CleanupAsync(root, spans, formattingOptions, services, providers, cancellationToken); + return cleanupService.CleanupAsync(root, spans, options, services, providers, cancellationToken); } } } diff --git a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs b/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs deleted file mode 100644 index 3fd28e16702e4..0000000000000 --- a/src/Workspaces/Core/Portable/CodeCleanup/CodeCleanupOptions.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading; -using System.Threading.Tasks; -using System.Runtime.Serialization; -using Microsoft.CodeAnalysis.Formatting; -using Microsoft.CodeAnalysis.Simplification; -using Microsoft.CodeAnalysis.AddImport; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.CodeActions; -using Roslyn.Utilities; - -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 CodeCleanupOptions GetDefault(HostLanguageServices languageServices) - => new( - FormattingOptions: SyntaxFormattingOptions.GetDefault(languageServices), - SimplifierOptions: SimplifierOptions.GetDefault(languageServices), - AddImportOptions: AddImportPlacementOptions.Default); -} - -internal interface CodeCleanupOptionsProvider : - OptionsProvider, - SyntaxFormattingOptionsProvider, - SimplifierOptionsProvider, - AddImportPlacementOptionsProvider -{ -} - -internal abstract class AbstractCodeCleanupOptionsProvider : CodeCleanupOptionsProvider -{ - public abstract ValueTask GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken); - - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).FormattingOptions; - - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).SimplifierOptions; - - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).AddImportOptions; -} - -internal static class CodeCleanupOptionsProviders -{ - public static async ValueTask GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptions? fallbackOptions, CancellationToken cancellationToken) - { - var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions?.FormattingOptions, cancellationToken).ConfigureAwait(false); - var simplifierOptions = await document.GetSimplifierOptionsAsync(fallbackOptions?.SimplifierOptions, cancellationToken).ConfigureAwait(false); - var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions?.AddImportOptions, cancellationToken).ConfigureAwait(false); - return new CodeCleanupOptions(formattingOptions, simplifierOptions, addImportOptions); - } - - public static async ValueTask GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - => await document.GetCodeCleanupOptionsAsync(await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); -} - diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOptions.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationContextInfo.cs similarity index 100% rename from src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationOptions.cs rename to src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationContextInfo.cs diff --git a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptionsProvider.cs b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptionsProvider.cs index 48fdb34347c20..c79398a052b5d 100644 --- a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptionsProvider.cs +++ b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleOptionsProvider.cs @@ -12,11 +12,11 @@ namespace Microsoft.CodeAnalysis.CodeStyle { [ExportSolutionOptionProvider, Shared] - internal sealed class CodeStyleOptionsProvider : IOptionProvider + internal sealed class SolutionCodeStyleOptionsProvider : IOptionProvider { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CodeStyleOptionsProvider() + public SolutionCodeStyleOptionsProvider() { } diff --git a/src/Workspaces/Core/Portable/CodeStyle/ICodeStyleService.cs b/src/Workspaces/Core/Portable/CodeStyle/ICodeStyleService.cs new file mode 100644 index 0000000000000..2cddece71f715 --- /dev/null +++ b/src/Workspaces/Core/Portable/CodeStyle/ICodeStyleService.cs @@ -0,0 +1,15 @@ +// 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.Text; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.CodeAnalysis.CodeStyle; + +internal interface ICodeStyleService : ILanguageService +{ + IdeCodeStyleOptions DefaultOptions { get; } +} diff --git a/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs b/src/Workspaces/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs similarity index 71% rename from src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs rename to src/Workspaces/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs index 82ec24b4ae9fb..efde4b7778f43 100644 --- a/src/Features/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs +++ b/src/Workspaces/Core/Portable/Diagnostics/WorkspaceAnalyzerOptions.cs @@ -32,24 +32,6 @@ public WorkspaceAnalyzerOptions(AnalyzerOptions options, Solution solution, IdeA public HostWorkspaceServices Services => _solution.Workspace.Services; - [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/23582", OftenCompletesSynchronously = true)] - public async ValueTask GetDocumentOptionSetAsync(SyntaxTree syntaxTree, CancellationToken cancellationToken) - { - var documentId = _solution.GetDocumentId(syntaxTree); - if (documentId == null) - { - return _solution.Options; - } - - var document = _solution.GetDocument(documentId); - if (document == null) - { - return _solution.Options; - } - - return await document.GetOptionsAsync(_solution.Options, cancellationToken).ConfigureAwait(false); - } - public override bool Equals(object obj) { if (ReferenceEquals(this, obj)) diff --git a/src/Workspaces/Core/Portable/Editing/ImportAdder.cs b/src/Workspaces/Core/Portable/Editing/ImportAdder.cs index dd73ebef87e0d..3659aeec125c1 100644 --- a/src/Workspaces/Core/Portable/Editing/ImportAdder.cs +++ b/src/Workspaces/Core/Portable/Editing/ImportAdder.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; @@ -61,7 +62,7 @@ private static async Task AddImportsFromSyntaxesAsync(Document documen } // Since no public options affect the behavior we can ignore options parameter and pass no fallback options: - var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var addImportOptions = await document.GetAddImportPlacementOptionsAsync(CodeActionOptions.DefaultProvider, cancellationToken).ConfigureAwait(false); return await service.AddImportsAsync(document, spans, ImportAdderService.Strategy.AddImportsFromSyntaxes, addImportOptions, cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Core/Portable/ExternalAccess/Pythia/Api/PythiaOptions.cs b/src/Workspaces/Core/Portable/ExternalAccess/Pythia/Api/PythiaOptions.cs deleted file mode 100644 index 4f6ca531104fc..0000000000000 --- a/src/Workspaces/Core/Portable/ExternalAccess/Pythia/Api/PythiaOptions.cs +++ /dev/null @@ -1,45 +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. - -#nullable disable - -using System; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Options.Providers; - -namespace Microsoft.CodeAnalysis.ExternalAccess.Pythia.Api -{ - [Obsolete("Use PythiaGlobalOptions instead")] - internal static class PythiaOptions - { - public const string LocalRegistryPath = @"Roslyn\Internal\OnOff\Features\"; - - public static readonly Option ShowDebugInfo = new( - "InternalFeatureOnOffOptions", nameof(ShowDebugInfo), defaultValue: false, - storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(ShowDebugInfo))); - - public static readonly Option RemoveRecommendationLimit = new( - "InternalFeatureOnOffOptions", nameof(RemoveRecommendationLimit), defaultValue: false, - storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(RemoveRecommendationLimit))); - } - - [Obsolete("Use PythiaGlobalOptions instead")] - [ExportSolutionOptionProvider, Shared] - internal class PythiaOptionsProvider : IOptionProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public PythiaOptionsProvider() - { - } - - public ImmutableArray Options { get; } - = ImmutableArray.Create( - PythiaOptions.ShowDebugInfo, - PythiaOptions.RemoveRecommendationLimit); - } -} diff --git a/src/Workspaces/Core/Portable/ExtractMethod/ExtractMethodOptions.cs b/src/Workspaces/Core/Portable/ExtractMethod/ExtractMethodOptions.cs index 3b1ae5ef35a3e..e04da82a962b7 100644 --- a/src/Workspaces/Core/Portable/ExtractMethod/ExtractMethodOptions.cs +++ b/src/Workspaces/Core/Portable/ExtractMethod/ExtractMethodOptions.cs @@ -8,18 +8,18 @@ using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeGeneration; -using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.ExtractMethod; [DataContract] -internal readonly record struct ExtractMethodOptions( - [property: DataMember(Order = 0)] bool DontPutOutOrRefOnStruct = true) +internal readonly record struct ExtractMethodOptions { + [DataMember] public bool DontPutOutOrRefOnStruct { get; init; } = true; + public ExtractMethodOptions() - : this(DontPutOutOrRefOnStruct: true) { } @@ -28,19 +28,18 @@ public ExtractMethodOptions() /// /// All options needed to perform method extraction. -/// Combines global with document specific code generation options. +/// Combines global with document specific code generation options. /// +[DataContract] internal readonly record struct ExtractMethodGenerationOptions( - ExtractMethodOptions ExtractOptions, - CodeGenerationOptions CodeGenerationOptions, - AddImportPlacementOptions AddImportOptions, - NamingStylePreferencesProvider NamingPreferences) + [property: DataMember] CodeGenerationOptions CodeGenerationOptions) { + [DataMember] public ExtractMethodOptions ExtractOptions { get; init; } = ExtractMethodOptions.Default; + [DataMember] public AddImportPlacementOptions AddImportOptions { get; init; } = AddImportPlacementOptions.Default; + [DataMember] public LineFormattingOptions LineFormattingOptions { get; init; } = LineFormattingOptions.Default; + public static ExtractMethodGenerationOptions GetDefault(HostLanguageServices languageServices) - => new(ExtractMethodOptions.Default, - CodeGenerationOptions.GetDefault(languageServices), - AddImportPlacementOptions.Default, - new NamingStylePreferencesProvider(_ => NamingStylePreferences.Default)); + => new(CodeGenerationOptions.GetDefault(languageServices)); } internal static class ExtractMethodGenerationOptionsProviders @@ -52,16 +51,14 @@ public static async ValueTask GetExtractMethodGe var extractOptions = fallbackOptions.Value.ExtractOptions; var codeGenerationOptions = await document.GetCodeGenerationOptionsAsync(fallbackOptions.Value.CodeGenerationOptions, cancellationToken).ConfigureAwait(false); var addImportOptions = await document.GetAddImportPlacementOptionsAsync(fallbackOptions.Value.AddImportOptions, cancellationToken).ConfigureAwait(false); + var lineFormattingOptions = await document.GetLineFormattingOptionsAsync(fallbackOptions.Value.LineFormattingOptions, cancellationToken).ConfigureAwait(false); - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var namingPreferences = documentOptions.GetOption(NamingStyleOptions.NamingPreferences, document.Project.Language); - var namingPreferencesProvider = new NamingStylePreferencesProvider(language => namingPreferences); - - return new ExtractMethodGenerationOptions( - extractOptions, - codeGenerationOptions, - addImportOptions, - namingPreferencesProvider); + return new ExtractMethodGenerationOptions(codeGenerationOptions) + { + ExtractOptions = extractOptions, + AddImportOptions = addImportOptions, + LineFormattingOptions = lineFormattingOptions, + }; } public static ValueTask GetExtractMethodGenerationOptionsAsync(this Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) diff --git a/src/Workspaces/Core/Portable/Formatting/Formatter.cs b/src/Workspaces/Core/Portable/Formatting/Formatter.cs index 8d8bbdfd214df..79105b2e76570 100644 --- a/src/Workspaces/Core/Portable/Formatting/Formatter.cs +++ b/src/Workspaces/Core/Portable/Formatting/Formatter.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting.Rules; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; @@ -97,7 +98,7 @@ public static async Task FormatAsync(Document document, IEnumerable FormatAsync(Document document, SyntaxAnnota var services = document.Project.Solution.Workspace.Services; // must have syntax formatting options since we require the document to have a syntax tree: - var (formattingOptions, _) = await GetOptionsAsync(document, optionSet, cancellationToken).ConfigureAwait(false); + var (formattingOptions, _) = await GetFormattingOptionsAsync(document, optionSet, cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(formattingOptions); return document.WithSyntaxRoot(Format(root, annotation, services, formattingOptions, rules, cancellationToken)); @@ -259,7 +260,7 @@ internal static SyntaxNode Format(SyntaxNode node, IEnumerable? spans, } spans ??= SpecializedCollections.SingletonEnumerable(node.FullSpan); - var formattingOptions = GetOptions(workspace, options, node.Language); + var formattingOptions = GetFormattingOptions(workspace, options, node.Language); return languageFormatter.GetFormattingResult(node, spans, formattingOptions, rules, cancellationToken); } @@ -327,7 +328,7 @@ internal static IList GetFormattedTextChanges(SyntaxNode node, IEnum return formatter.GetFormattingResult(node, spans, options, rules, cancellationToken).GetTextChanges(cancellationToken); } - internal static SyntaxFormattingOptions GetOptions(Workspace workspace, OptionSet? optionSet, string language) + internal static SyntaxFormattingOptions GetFormattingOptions(Workspace workspace, OptionSet? optionSet, string language) { var syntaxFormattingService = workspace.Services.GetRequiredLanguageService(language); var optionService = workspace.Services.GetRequiredService(); @@ -335,7 +336,8 @@ internal static SyntaxFormattingOptions GetOptions(Workspace workspace, OptionSe return syntaxFormattingService.GetFormattingOptions(configOptionSet, fallbackOptions: null); } - internal static async ValueTask<(SyntaxFormattingOptions? Syntax, LineFormattingOptions Line)> GetOptionsAsync(Document document, OptionSet? optionSet, CancellationToken cancellationToken) +#pragma warning disable RS0030 // Do not used banned APIs (backwards compatibility) + internal static async ValueTask<(SyntaxFormattingOptions? Syntax, LineFormattingOptions Line)> GetFormattingOptionsAsync(Document document, OptionSet? optionSet, CancellationToken cancellationToken) { var optionService = document.Project.Solution.Workspace.Services.GetRequiredService(); var configOptionSet = (optionSet ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)).AsAnalyzerConfigOptions(optionService, document.Project.Language); @@ -352,11 +354,12 @@ internal static SyntaxFormattingOptions GetOptions(Workspace workspace, OptionSe else { syntaxFormattingOptions = null; - lineFormattingOptions = LineFormattingOptions.Create(configOptionSet, fallbackOptions: null); + lineFormattingOptions = configOptionSet.GetLineFormattingOptions(fallbackOptions: null); } return (syntaxFormattingOptions, lineFormattingOptions); } +#pragma warning restore /// /// Organizes the imports in the document. @@ -372,8 +375,17 @@ public static async Task OrganizeImportsAsync(Document document, Cance return document; } - var options = await OrganizeImportsOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); + var options = await GetOrganizeImportsOptionsAsync(document, cancellationToken).ConfigureAwait(false); return await organizeImportsService.OrganizeImportsAsync(document, options, cancellationToken).ConfigureAwait(false); } + +#pragma warning disable RS0030 // Do not used banned APIs (backwards compatibility) + internal static async ValueTask GetOrganizeImportsOptionsAsync(Document document, CancellationToken cancellationToken) + { + var optionService = document.Project.Solution.Workspace.Services.GetRequiredService(); + var configOptionSet = (await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)).AsAnalyzerConfigOptions(optionService, document.Project.Language); + return configOptionSet.GetOrganizeImportsOptions(fallbackOptions: null); + } +#pragma warning restore } } diff --git a/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs b/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs index ca727f9ffdeec..fac219fc6ac18 100644 --- a/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs +++ b/src/Workspaces/Core/Portable/ImplementType/ImplementTypeOptions.cs @@ -7,24 +7,26 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; -namespace Microsoft.CodeAnalysis.ImplementType +namespace Microsoft.CodeAnalysis.ImplementType; + +[DataContract] +internal readonly record struct ImplementTypeOptions { - [DataContract] - internal readonly record struct ImplementTypeOptions( - [property: DataMember(Order = 0)] ImplementTypeInsertionBehavior InsertionBehavior = ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind, - [property: DataMember(Order = 1)] ImplementTypePropertyGenerationBehavior PropertyGenerationBehavior = ImplementTypePropertyGenerationBehavior.PreferThrowingProperties) - { - public ImplementTypeOptions() - : this(InsertionBehavior: ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind) - { - } + [DataMember] public ImplementTypeInsertionBehavior InsertionBehavior { get; init; } = ImplementTypeInsertionBehavior.WithOtherMembersOfTheSameKind; + [DataMember] public ImplementTypePropertyGenerationBehavior PropertyGenerationBehavior { get; init; } = ImplementTypePropertyGenerationBehavior.PreferThrowingProperties; - public static readonly ImplementTypeOptions Default = new(); + public ImplementTypeOptions() + { } - internal readonly record struct ImplementTypeGenerationOptions( - ImplementTypeOptions ImplementTypeOptions, - CodeAndImportGenerationOptionsProvider FallbackOptions); + public static readonly ImplementTypeOptions Default = new(); } + +internal readonly record struct ImplementTypeGenerationOptions( + ImplementTypeOptions ImplementTypeOptions, + CleanCodeGenerationOptionsProvider FallbackOptions); diff --git a/src/Workspaces/Core/Portable/Options/DocumentOptionSet.cs b/src/Workspaces/Core/Portable/Options/DocumentOptionSet.cs index 4c3de113c72fa..287b1c835a5e9 100644 --- a/src/Workspaces/Core/Portable/Options/DocumentOptionSet.cs +++ b/src/Workspaces/Core/Portable/Options/DocumentOptionSet.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. +#pragma warning disable RS0030 // Do not used banned APIs (backwards compatibility) + using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Workspaces/Core/Portable/Options/EditorConfig/EditorConfigFileGenerator.cs b/src/Workspaces/Core/Portable/Options/EditorConfig/EditorConfigFileGenerator.cs index 8719dea2db5d4..0e16f34402f62 100644 --- a/src/Workspaces/Core/Portable/Options/EditorConfig/EditorConfigFileGenerator.cs +++ b/src/Workspaces/Core/Portable/Options/EditorConfig/EditorConfigFileGenerator.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.Options diff --git a/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs b/src/Workspaces/Core/Portable/Options/IGlobalOptionService.cs index f72e59031232d..dfda41db85ad2 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.CodeCleanup; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Options diff --git a/src/Workspaces/Core/Portable/Options/ILegacyGlobalOptionsWorkspaceService.cs b/src/Workspaces/Core/Portable/Options/ILegacyGlobalOptionsWorkspaceService.cs index 09e25ff7610f1..f9ca403cfe28a 100644 --- a/src/Workspaces/Core/Portable/Options/ILegacyGlobalOptionsWorkspaceService.cs +++ b/src/Workspaces/Core/Portable/Options/ILegacyGlobalOptionsWorkspaceService.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.CodeGeneration; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Options @@ -12,9 +14,22 @@ namespace Microsoft.CodeAnalysis.Options /// internal interface ILegacyGlobalOptionsWorkspaceService : IWorkspaceService { - public IGlobalOptionService GlobalOptions { get; } - public bool RazorUseTabs { get; } public int RazorTabSize { get; } + + public bool GenerateOverrides { get; set; } + public bool InlineHintsOptionsDisplayAllOverride { get; set; } + + public bool GetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(string language); + public void SetGenerateEqualsAndGetHashCodeFromMembersGenerateOperators(string language, bool value); + + public bool GetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(string language); + public void SetGenerateEqualsAndGetHashCodeFromMembersImplementIEquatable(string language, bool value); + + public bool GetGenerateConstructorFromMembersOptionsAddNullChecks(string language); + public void SetGenerateConstructorFromMembersOptionsAddNullChecks(string language, bool value); + + public AutoFormattingOptions GetAutoFormattingOptions(HostLanguageServices languageServices); + public CleanCodeGenerationOptionsProvider CleanCodeGenerationOptionsProvider { get; } } } diff --git a/src/Workspaces/Core/Portable/Options/Providers/ExportOptionProviderAttribute.cs b/src/Workspaces/Core/Portable/Options/Providers/ExportOptionProviderAttribute.cs index b27133100b4bc..454999bb0e848 100644 --- a/src/Workspaces/Core/Portable/Options/Providers/ExportOptionProviderAttribute.cs +++ b/src/Workspaces/Core/Portable/Options/Providers/ExportOptionProviderAttribute.cs @@ -30,22 +30,6 @@ public ExportOptionProviderAttribute(string language, bool isGlobal) } } - /// - /// Global client-only options. - /// - internal sealed class ExportGlobalOptionProviderAttribute : ExportOptionProviderAttribute - { - public ExportGlobalOptionProviderAttribute() - : this(language: string.Empty) - { - } - - public ExportGlobalOptionProviderAttribute(string language) - : base(language, isGlobal: true) - { - } - } - /// /// Options that are part of the solution snapshot. /// Some of these options may be configurable per document via editorconfig. diff --git a/src/Workspaces/Core/Portable/OrganizeImports/OrganizeImportsOptions.cs b/src/Workspaces/Core/Portable/OrganizeImports/OrganizeImportsOptions.cs index 5bd63acd7575f..87c0a8f63482e 100644 --- a/src/Workspaces/Core/Portable/OrganizeImports/OrganizeImportsOptions.cs +++ b/src/Workspaces/Core/Portable/OrganizeImports/OrganizeImportsOptions.cs @@ -2,26 +2,54 @@ // 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.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; -namespace Microsoft.CodeAnalysis.OrganizeImports +namespace Microsoft.CodeAnalysis.OrganizeImports; + +[DataContract] +internal readonly record struct OrganizeImportsOptions { - internal readonly record struct OrganizeImportsOptions( - bool PlaceSystemNamespaceFirst, - bool SeparateImportDirectiveGroups, - string NewLine) + [property: DataMember(Order = 0)] public bool PlaceSystemNamespaceFirst { get; init; } = AddImportPlacementOptions.Default.PlaceSystemNamespaceFirst; + [property: DataMember(Order = 1)] public bool SeparateImportDirectiveGroups { get; init; } = SyntaxFormattingOptions.CommonOptions.Default.SeparateImportDirectiveGroups; + [property: DataMember(Order = 2)] public string NewLine { get; init; } = LineFormattingOptions.Default.NewLine; + + public OrganizeImportsOptions() { - public static async ValueTask FromDocumentAsync(Document document, CancellationToken cancellationToken) + } + + public static readonly OrganizeImportsOptions Default = new(); +} + +internal interface OrganizeImportsOptionsProvider : OptionsProvider +{ +} + +internal static class OrganizeImportsOptionsProviders +{ + public static OrganizeImportsOptions GetOrganizeImportsOptions(this AnalyzerConfigOptions options, OrganizeImportsOptions? fallbackOptions) + { + fallbackOptions ??= OrganizeImportsOptions.Default; + + return new() { - var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + PlaceSystemNamespaceFirst = options.GetEditorConfigOption(GenerationOptions.PlaceSystemNamespaceFirst, fallbackOptions.Value.PlaceSystemNamespaceFirst), + SeparateImportDirectiveGroups = options.GetEditorConfigOption(GenerationOptions.SeparateImportDirectiveGroups, fallbackOptions.Value.SeparateImportDirectiveGroups), + NewLine = options.GetEditorConfigOption(FormattingOptions2.NewLine, fallbackOptions.Value.NewLine) + }; + } - return new( - PlaceSystemNamespaceFirst: options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst), - SeparateImportDirectiveGroups: options.GetOption(GenerationOptions.SeparateImportDirectiveGroups), - NewLine: options.GetOption(FormattingOptions2.NewLine)); - } + public static async ValueTask GetOrganizeImportsOptionsAsync(this Document document, OrganizeImportsOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetOrganizeImportsOptions(fallbackOptions); } + + public static async ValueTask GetOrganizeImportsOptionsAsync(this Document document, OrganizeImportsOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await GetOrganizeImportsOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptionProvider.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptionProvider.cs index 53b2205fe5064..447b5355c20ff 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptionProvider.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptionProvider.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Immutable; using System.Composition; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options.Providers; @@ -21,6 +22,6 @@ public SimplificationOptionsProvider() } public ImmutableArray Options { get; } = ImmutableArray.Create( - NamingStyleOptions.NamingPreferences); + NamingStyleOptions.NamingPreferences); } } diff --git a/src/Workspaces/Core/Portable/Simplification/Simplifier.cs b/src/Workspaces/Core/Portable/Simplification/Simplifier.cs index b96372cb5a9d1..21030d131fa7a 100644 --- a/src/Workspaces/Core/Portable/Simplification/Simplifier.cs +++ b/src/Workspaces/Core/Portable/Simplification/Simplifier.cs @@ -238,11 +238,15 @@ internal static async Task ReduceAsync( reducers, cancellationToken).ConfigureAwait(false); } +#pragma warning disable RS0030 // Do not used banned APIs (backwards compatibility) 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 document.GetSimplifierOptionsAsync(fallbackOptions: null, cancellationToken).ConfigureAwait(false); + var services = document.Project.Solution.Workspace.Services; + var optionService = services.GetRequiredService(); + var configOptionSet = (optionSet ?? await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false)).AsAnalyzerConfigOptions(optionService, document.Project.Language); + var simplificationService = services.GetRequiredLanguageService(document.Project.Language); + return simplificationService.GetSimplifierOptions(configOptionSet, fallbackOptions: null); } +#pragma warning restore } } diff --git a/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs b/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs index 5ba383a870aea..2ea25038f4b27 100644 --- a/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs +++ b/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs @@ -4,18 +4,18 @@ using System.Runtime.Serialization; -namespace Microsoft.CodeAnalysis.SymbolSearch +namespace Microsoft.CodeAnalysis.SymbolSearch; + +[DataContract] +internal readonly record struct SymbolSearchOptions { - [DataContract] - internal readonly record struct SymbolSearchOptions( - [property: DataMember(Order = 0)] bool SearchReferenceAssemblies = true, - [property: DataMember(Order = 1)] bool SearchNuGetPackages = true) - { - public SymbolSearchOptions() - : this(SearchReferenceAssemblies: true) - { - } + [DataMember] public bool SearchReferenceAssemblies { get; init; } = true; + [DataMember] public bool SearchNuGetPackages { get; init; } = true; - public static readonly SymbolSearchOptions Default = new(); + // required to make sure new SymbolSearchOptions() runs property initializers + public SymbolSearchOptions() + { } + + public static readonly SymbolSearchOptions Default = new(); } diff --git a/src/Workspaces/Core/Portable/Telemetry/IRemoteProcessTelemetryService.cs b/src/Workspaces/Core/Portable/Telemetry/IRemoteProcessTelemetryService.cs index 6164f66094c3f..92c1a79d14df2 100644 --- a/src/Workspaces/Core/Portable/Telemetry/IRemoteProcessTelemetryService.cs +++ b/src/Workspaces/Core/Portable/Telemetry/IRemoteProcessTelemetryService.cs @@ -20,7 +20,7 @@ internal interface IRemoteProcessTelemetryService /// /// Initializes telemetry session. /// - ValueTask InitializeTelemetrySessionAsync(int hostProcessId, string serializedSession, CancellationToken cancellationToken); + ValueTask InitializeTelemetrySessionAsync(int hostProcessId, string serializedSession, bool logDelta, CancellationToken cancellationToken); /// /// Sets for the process. diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs index a74f2087c6dd1..c2b1c0639e951 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Document.cs @@ -466,6 +466,7 @@ internal virtual Document WithFrozenPartialSemantics(CancellationToken cancellat private string GetDebuggerDisplay() => this.Name; +#pragma warning disable RS0030 // Do not used banned APIs (backwards compat) private AsyncLazy? _cachedOptions; /// @@ -475,43 +476,34 @@ private string GetDebuggerDisplay() /// /// This method is async because this may require reading other files. In files that are already open, this is expected to be cheap and complete synchronously. /// - public Task GetOptionsAsync(CancellationToken cancellationToken = default) - => GetOptionsAsync(Project.Solution.Options, cancellationToken); - [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/23582", AllowCaptures = false)] - internal Task GetOptionsAsync(OptionSet solutionOptions, CancellationToken cancellationToken) + public Task GetOptionsAsync(CancellationToken cancellationToken = default) { - // TODO: we have this workaround since Solution.Options is not actually snapshot but just return Workspace.Options which violate snapshot model. - // this doesn't validate whether same optionset is given to invalidate the cache or not. this is not new since existing implementation - // also didn't check whether Workspace.Option is same as before or not. all weird-ness come from the root cause of Solution.Options violating - // snapshot model. once that is fixed, we can remove this workaround - https://github.com/dotnet/roslyn/issues/19284 if (_cachedOptions == null) { - InitializeCachedOptions(solutionOptions); + InitializeCachedOptions(Project.Solution.Options); } Contract.ThrowIfNull(_cachedOptions); return _cachedOptions.GetValueAsync(cancellationToken); } - internal async ValueTask GetAnalyzerConfigOptionsAsync(CancellationToken cancellationToken) - { - var optionService = Project.Solution.Workspace.Services.GetRequiredService(); - var documentOptions = await GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return documentOptions.AsAnalyzerConfigOptions(optionService, Project.Language); - } - private void InitializeCachedOptions(OptionSet solutionOptions) { - var newAsyncLazy = new AsyncLazy(async c => + var newAsyncLazy = new AsyncLazy(async cancellationToken => { - var provider = (ProjectState.ProjectAnalyzerConfigOptionsProvider)Project.State.AnalyzerOptions.AnalyzerConfigOptionsProvider; - var options = await provider.GetOptionsAsync(DocumentState, c).ConfigureAwait(false); - + var options = await GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); return new DocumentOptionSet(options, solutionOptions, Project.Language); }, cacheResult: true); Interlocked.CompareExchange(ref _cachedOptions, newAsyncLazy, comparand: null); } +#pragma warning restore + + internal async ValueTask GetAnalyzerConfigOptionsAsync(CancellationToken cancellationToken) + { + var provider = (ProjectState.ProjectAnalyzerConfigOptionsProvider)Project.State.AnalyzerOptions.AnalyzerConfigOptionsProvider; + return await provider.GetOptionsAsync(DocumentState, cancellationToken).ConfigureAwait(false); + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState.cs index 7e892afb42c48..f5ce96cef176b 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState.cs @@ -314,23 +314,19 @@ public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) var cache = GetCache(); if (documentId != null && _projectState.DocumentStates.TryGetState(documentId, out var documentState)) { - var result = GetOptions(cache, documentState); - if (result != null) - { - return result; - } + return GetOptions(cache, documentState); } return GetOptionsForSourcePath(cache, tree.FilePath); } - internal async ValueTask GetOptionsAsync(DocumentState documentState, CancellationToken cancellationToken) + internal async ValueTask GetOptionsAsync(DocumentState documentState, CancellationToken cancellationToken) { var cache = await _projectState._lazyAnalyzerConfigOptions.GetValueAsync(cancellationToken).ConfigureAwait(false); return GetOptions(cache, documentState); } - private StructuredAnalyzerConfigOptions? GetOptions(in AnalyzerConfigOptionsCache cache, DocumentState documentState) + private StructuredAnalyzerConfigOptions GetOptions(in AnalyzerConfigOptionsCache cache, DocumentState documentState) { if (documentState.IsRazorDocument()) { @@ -340,7 +336,7 @@ public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) var filePath = GetEffectiveFilePath(documentState); if (filePath == null) { - return null; + return StructuredAnalyzerConfigOptions.Empty; } var options = GetOptionsForSourcePath(cache, filePath); diff --git a/src/Workspaces/CoreTest/CodeCleanup/AddMissingTokensTests.cs b/src/Workspaces/CoreTest/CodeCleanup/AddMissingTokensTests.cs index f420d18e10751..d5264297e7169 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/AddMissingTokensTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/AddMissingTokensTests.cs @@ -2844,7 +2844,7 @@ private static async Task VerifyAsync(string codeWithMarker, string expectedResu var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic); var codeCleanups = CodeCleaner.GetDefaultProviders(document).WhereAsArray(p => p.Name is PredefinedCodeCleanupProviderNames.AddMissingTokens or PredefinedCodeCleanupProviderNames.Format or PredefinedCodeCleanupProviderNames.Simplification); - var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups); + var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups); Assert.Equal(expectedResult, (await cleanDocument.GetSyntaxRootAsync()).ToFullString()); } diff --git a/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs b/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs index 0465307892c44..585aa37775194 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/CodeCleanupTests.cs @@ -41,7 +41,7 @@ public void DefaultCSharpCodeCleanups() public async Task CodeCleanersCSharp_NoSpans() { var document = CreateDocument("class C { }", LanguageNames.CSharp); - var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Empty); + var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Empty, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -50,7 +50,7 @@ public async Task CodeCleanersCSharp_NoSpans() public async Task CodeCleanersCSharp_Document() { var document = CreateDocument("class C { }", LanguageNames.CSharp); - var cleanDocument = await CodeCleaner.CleanupAsync(document); + var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -59,7 +59,8 @@ public async Task CodeCleanersCSharp_Document() public async Task CodeCleanersCSharp_Span() { var document = CreateDocument("class C { }", LanguageNames.CSharp); - var cleanDocument = await CodeCleaner.CleanupAsync(document, (await document.GetSyntaxRootAsync()).FullSpan); + var root = await document.GetSyntaxRootAsync(); + var cleanDocument = await CodeCleaner.CleanupAsync(document, root.FullSpan, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -68,8 +69,8 @@ public async Task CodeCleanersCSharp_Span() public async Task CodeCleanersCSharp_Spans() { var document = CreateDocument("class C { }", LanguageNames.CSharp); - var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Create( - (await document.GetSyntaxRootAsync()).FullSpan)); + var root = await document.GetSyntaxRootAsync(); + var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Create(root.FullSpan), CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -92,7 +93,7 @@ public async Task CodeCleanersVisualBasic_NoSpans() { var document = CreateDocument(@"Class C End Class", LanguageNames.VisualBasic); - var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Empty); + var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Empty, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -102,7 +103,7 @@ public async Task CodeCleanersVisualBasic_Document() { var document = CreateDocument(@"Class C End Class", LanguageNames.VisualBasic); - var cleanDocument = await CodeCleaner.CleanupAsync(document); + var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -112,7 +113,8 @@ public async Task CodeCleanersVisualBasic_Span() { var document = CreateDocument(@"Class C End Class", LanguageNames.VisualBasic); - var cleanDocument = await CodeCleaner.CleanupAsync(document, (await document.GetSyntaxRootAsync()).FullSpan); + var root = await document.GetSyntaxRootAsync(); + var cleanDocument = await CodeCleaner.CleanupAsync(document, root.FullSpan, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -122,8 +124,8 @@ public async Task CodeCleanersVisualBasic_Spans() { var document = CreateDocument(@"Class C End Class", LanguageNames.VisualBasic); - var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Create( - (await document.GetSyntaxRootAsync()).FullSpan)); + var root = await document.GetSyntaxRootAsync(); + var cleanDocument = await CodeCleaner.CleanupAsync(document, ImmutableArray.Create(root.FullSpan), CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -135,7 +137,7 @@ public async Task CodeCleanersCSharp_Annotation() var annotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot((await document.GetSyntaxRootAsync()).WithAdditionalAnnotations(annotation)); - var cleanDocument = await CodeCleaner.CleanupAsync(document, annotation); + var cleanDocument = await CodeCleaner.CleanupAsync(document, annotation, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -148,7 +150,7 @@ public async Task CodeCleanersVisualBasic_Annotation() var annotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot((await document.GetSyntaxRootAsync()).WithAdditionalAnnotations(annotation)); - var cleanDocument = await CodeCleaner.CleanupAsync(document, annotation); + var cleanDocument = await CodeCleaner.CleanupAsync(document, annotation, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -321,7 +323,7 @@ End Class Assert.NotNull(newSemanticModel); Assert.True(newSemanticModel.IsSpeculativeSemanticModel); - var cleanDocument = await CodeCleaner.CleanupAsync(document); + var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices)); Assert.Equal(document, cleanDocument); } @@ -406,7 +408,7 @@ private static void VerifyRange(string code, ImmutableArray p.Name is PredefinedCodeCleanupProviderNames.FixIncorrectTokens or PredefinedCodeCleanupProviderNames.Format); - var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups); + var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups); Assert.Equal(expectedResult, (await cleanDocument.GetSyntaxRootAsync()).ToFullString()); } diff --git a/src/Workspaces/CoreTest/CodeCleanup/NormalizeModifiersOrOperatorsTests.cs b/src/Workspaces/CoreTest/CodeCleanup/NormalizeModifiersOrOperatorsTests.cs index c0c80f418b0a2..119acbc99fc51 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/NormalizeModifiersOrOperatorsTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/NormalizeModifiersOrOperatorsTests.cs @@ -1079,7 +1079,7 @@ private static async Task VerifyAsync(string codeWithMarker, string expectedResu var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic); var codeCleanups = CodeCleaner.GetDefaultProviders(document).WhereAsArray(p => p.Name is PredefinedCodeCleanupProviderNames.NormalizeModifiersOrOperators or PredefinedCodeCleanupProviderNames.Format); - var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups); + var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups); Assert.Equal(expectedResult, (await cleanDocument.GetSyntaxRootAsync()).ToFullString()); } diff --git a/src/Workspaces/CoreTest/CodeCleanup/ReduceTokenTests.cs b/src/Workspaces/CoreTest/CodeCleanup/ReduceTokenTests.cs index c72bbc172f670..915e1c7926728 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/ReduceTokenTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/ReduceTokenTests.cs @@ -2058,7 +2058,7 @@ private static async Task VerifyAsync(string codeWithMarker, string expectedResu var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic); var codeCleanups = CodeCleaner.GetDefaultProviders(document).WhereAsArray(p => p.Name is PredefinedCodeCleanupProviderNames.ReduceTokens or PredefinedCodeCleanupProviderNames.CaseCorrection or PredefinedCodeCleanupProviderNames.Format); - var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups); + var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups); AssertEx.EqualOrDiff(expectedResult, (await cleanDocument.GetSyntaxRootAsync()).ToFullString()); } diff --git a/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs b/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs index a1b5f39c1c13e..5f177bcce158c 100644 --- a/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs +++ b/src/Workspaces/CoreTest/CodeCleanup/RemoveUnnecessaryLineContinuationTests.cs @@ -1475,7 +1475,7 @@ private static async Task VerifyAsync(string codeWithMarker, string expectedResu var document = CreateDocument(codeWithoutMarker, LanguageNames.VisualBasic, langVersion); var codeCleanups = CodeCleaner.GetDefaultProviders(document).WhereAsArray(p => p.Name is PredefinedCodeCleanupProviderNames.RemoveUnnecessaryLineContinuation or PredefinedCodeCleanupProviderNames.Format); - var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], codeCleanups); + var cleanDocument = await CodeCleaner.CleanupAsync(document, textSpans[0], CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups); var actualResult = (await cleanDocument.GetSyntaxRootAsync()).ToFullString(); Assert.Equal(expectedResult, actualResult); diff --git a/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs b/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs index 851afd8ccbe48..89daaefe5a073 100644 --- a/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs +++ b/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs @@ -64,7 +64,7 @@ public void TestParseEditorConfigCodeStyleOption(string args, bool isEnabled, Re [InlineData("omit_if_default : error", (int)AccessibilityModifiersRequired.OmitIfDefault, ReportDiagnostic.Error)] public void TestParseEditorConfigAccessibilityModifiers(string args, int value, ReportDiagnostic severity) { - var storageLocation = CodeStyleOptions2.RequireAccessibilityModifiers.StorageLocations + var storageLocation = CodeStyleOptions2.AccessibilityModifiersRequired.StorageLocations .OfType>>() .Single(); var allRawConventions = StructuredAnalyzerConfigOptions.Create(DictionaryAnalyzerConfigOptions.EmptyDictionary.Add(storageLocation.KeyName, args)); diff --git a/src/Workspaces/CoreTest/Formatter/FormatterTests.cs b/src/Workspaces/CoreTest/Formatter/FormatterTests.cs index f636e48dd2b09..d1c1acd3360cc 100644 --- a/src/Workspaces/CoreTest/Formatter/FormatterTests.cs +++ b/src/Workspaces/CoreTest/Formatter/FormatterTests.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -79,8 +80,10 @@ public async Task FormatAsync_ForeignLanguageWithFormattingSupport_Options(bool document = document.Project.Solution.WithOptions(solutionOptions).GetRequiredDocument(document.Id); +#pragma warning disable RS0030 // Do not used banned APIs var documentOptions = await document.GetOptionsAsync(); Assert.Equal(7, documentOptions.GetOption(FormattingOptions.IndentationSize)); +#pragma warning restore var options = passExplicitOptions ? new OptionValueSet(ImmutableDictionary.Empty. Add(new OptionKey(FormattingOptions.UseTabs, NoCompilationConstants.LanguageName), true). @@ -90,7 +93,7 @@ public async Task FormatAsync_ForeignLanguageWithFormattingSupport_Options(bool #pragma warning disable RS0030 // Do not used banned APIs var formattedDocument = await Formatter.FormatAsync(document, spans: null, options, CancellationToken.None); -#pragma warning restore RS0030 // Do not used banned APIs +#pragma warning restore var formattedText = await formattedDocument.GetTextAsync(); @@ -119,8 +122,8 @@ public async Task PublicOptions() // Validate that options are read from specified OptionSet: - ValidateCSharpOptions((CSharpSyntaxFormattingOptions)(await Formatter.GetOptionsAsync(csDocument, updatedOptions, CancellationToken.None)).Syntax!); - ValidateVisualBasicOptions((VisualBasicSyntaxFormattingOptions)(await Formatter.GetOptionsAsync(vbDocument, updatedOptions, CancellationToken.None)).Syntax!); + ValidateCSharpOptions((CSharpSyntaxFormattingOptions)(await Formatter.GetFormattingOptionsAsync(csDocument, updatedOptions, CancellationToken.None)).Syntax!); + ValidateVisualBasicOptions((VisualBasicSyntaxFormattingOptions)(await Formatter.GetFormattingOptionsAsync(vbDocument, updatedOptions, CancellationToken.None)).Syntax!); // Validate that options are read from solution snapshot as a fallback (we have no editorconfig file, so all options should fall back): @@ -128,8 +131,10 @@ public async Task PublicOptions() var csDocumentWithUpdatedOptions = solutionWithUpdatedOptions.GetRequiredDocument(csDocument.Id); var vbDocumentWithUpdatedOptions = solutionWithUpdatedOptions.GetRequiredDocument(vbDocument.Id); - ValidateCSharpOptions((CSharpSyntaxFormattingOptions)(await Formatter.GetOptionsAsync(csDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)).Syntax!); - ValidateVisualBasicOptions((VisualBasicSyntaxFormattingOptions)(await Formatter.GetOptionsAsync(vbDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)).Syntax!); + ValidateCSharpOptions((CSharpSyntaxFormattingOptions)(await Formatter.GetFormattingOptionsAsync(csDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)).Syntax!); + ValidateVisualBasicOptions((VisualBasicSyntaxFormattingOptions)(await Formatter.GetFormattingOptionsAsync(vbDocumentWithUpdatedOptions, optionSet: null, CancellationToken.None)).Syntax!); + ValidateOrganizeImportsOptions(await Formatter.GetOrganizeImportsOptionsAsync(csDocumentWithUpdatedOptions, CancellationToken.None)); + ValidateOrganizeImportsOptions(await Formatter.GetOrganizeImportsOptionsAsync(vbDocumentWithUpdatedOptions, CancellationToken.None)); static OptionSet GetOptionSetWithChangedPublicOptions(OptionSet options) { @@ -274,5 +279,10 @@ static void ValidateVisualBasicOptions(VisualBasicSyntaxFormattingOptions simpli { ValidateCommonOptions(simplifierOptions); } + + static void ValidateOrganizeImportsOptions(OrganizeImportsOptions options) + { + Assert.Equal("\r", options.NewLine); + } } } diff --git a/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs b/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs index c10b80796b7a2..4e77fb1c355e9 100644 --- a/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs +++ b/src/Workspaces/CoreTest/Remote/ServiceDescriptorTests.cs @@ -16,9 +16,24 @@ using System.Threading.Tasks; using MessagePack; using MessagePack.Formatters; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeGeneration; +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.DocumentationComments; +using Microsoft.CodeAnalysis.DocumentHighlighting; +using Microsoft.CodeAnalysis.ExtractMethod; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host.Mef; +using Microsoft.CodeAnalysis.Indentation; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.VisualBasic.CodeStyle; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; @@ -128,16 +143,69 @@ void AddTypeRecursive(Type type, MemberInfo declaringMember) } [Fact] - public void OptionsAreMessagePackSerializable() + public void OptionsAreMessagePackSerializable_LanguageAgnostic() { var messagePackOptions = MessagePackSerializerOptions.Standard.WithResolver(MessagePackFormatters.DefaultResolver); + var options = new object[] + { + ExtractMethodOptions.Default, + AddImportPlacementOptions.Default, + LineFormattingOptions.Default, + DocumentFormattingOptions.Default, + HighlightingOptions.Default, + DocumentationCommentOptions.Default + }; + + foreach (var original in options) + { + using var stream = new MemoryStream(); + MessagePackSerializer.Serialize(stream, original, messagePackOptions); + stream.Position = 0; + + var deserialized = MessagePackSerializer.Deserialize(original.GetType(), stream, messagePackOptions); + Assert.Equal(original, deserialized); + } + } + + [Theory] + [InlineData(LanguageNames.CSharp)] + [InlineData(LanguageNames.VisualBasic)] + public void OptionsAreMessagePackSerializable(string language) + { + var messagePackOptions = MessagePackSerializerOptions.Standard.WithResolver(MessagePackFormatters.DefaultResolver); + + using var workspace = new AdhocWorkspace(); + var languageServices = workspace.Services.GetLanguageServices(language); + + var options = new object[] + { + SimplifierOptions.GetDefault(languageServices), + SyntaxFormattingOptions.GetDefault(languageServices), + CodeCleanupOptions.GetDefault(languageServices), + CodeGenerationOptions.GetDefault(languageServices), + IdeCodeStyleOptions.GetDefault(languageServices), + CodeActionOptions.GetDefault(languageServices), + IndentationOptions.GetDefault(languageServices), + ExtractMethodGenerationOptions.GetDefault(languageServices), + + // some non-default values: + new VisualBasicIdeCodeStyleOptions( + new IdeCodeStyleOptions.CommonOptions() + { + AllowStatementImmediatelyAfterBlock = new CodeStyleOption2(false, NotificationOption2.Error) + }, + PreferredModifierOrder: new CodeStyleOption2("Public Private", NotificationOption2.Error)) - foreach (var original in new[] { NamingStylePreferences.Default }) + }; + + foreach (var original in options) { using var stream = new MemoryStream(); MessagePackSerializer.Serialize(stream, original, messagePackOptions); stream.Position = 0; - Assert.Equal(original, MessagePackSerializer.Deserialize(original.GetType(), stream, messagePackOptions)); + + var deserialized = MessagePackSerializer.Deserialize(original.GetType(), stream, messagePackOptions); + Assert.Equal(original, deserialized); } } diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs index 8b24b531764e7..7811cfbf34279 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs @@ -3422,8 +3422,10 @@ public async Task EditorConfigOptions(string projectPath, string configPath, str var document = solution.GetRequiredDocument(documentId); +#pragma warning disable RS0030 // Do not used banned APIs var documentOptions = await document.GetOptionsAsync(CancellationToken.None); Assert.Equal(appliedToDocument, documentOptions.GetOption(FormattingOptions2.UseTabs)); +#pragma warning restore var syntaxTree = await document.GetSyntaxTreeAsync(); var documentOptionsViaSyntaxTree = document.Project.State.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); diff --git a/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs b/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs index 64b18ea3b65c6..8ce5e584f6360 100644 --- a/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs +++ b/src/Workspaces/Remote/Core/Serialization/MessagePackFormatters.cs @@ -9,6 +9,7 @@ using MessagePack.Formatters; using MessagePack.Resolvers; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; @@ -29,7 +30,8 @@ internal sealed class MessagePackFormatters // TODO: add a resolver that provides these https://github.com/dotnet/roslyn/issues/60724 new ForceTypelessFormatter(), new ForceTypelessFormatter(), - new ForceTypelessFormatter()); + new ForceTypelessFormatter(), + new ForceTypelessFormatter()); private static readonly ImmutableArray s_resolvers = ImmutableArray.Create( StandardResolverAllowPrivate.Instance); diff --git a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs index dcf051cdcf609..f38c986807b08 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ClientOptionProviders.cs @@ -49,7 +49,7 @@ internal sealed class ClientCleanCodeGenerationOptionsProvider : AbstractCleanCo public ClientCleanCodeGenerationOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) => _cache = new RemoteOptionsProviderCache(callback, callbackId); - public override ValueTask GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + public override ValueTask GetCleanCodeGenerationOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => _cache.GetOptionsAsync(languageServices, cancellationToken); } @@ -60,7 +60,7 @@ internal sealed class ClientCodeCleanupOptionsProvider : AbstractCodeCleanupOpti public ClientCodeCleanupOptionsProvider(Func> callback, RemoteServiceCallbackId callbackId) => _cache = new RemoteOptionsProviderCache(callback, callbackId); - public override ValueTask GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + public override ValueTask GetCodeCleanupOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => _cache.GetOptionsAsync(languageServices, cancellationToken); } diff --git a/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteProcessTelemetryService.cs b/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteProcessTelemetryService.cs index a7d75647fa344..18fb60ba9dfa5 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteProcessTelemetryService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteProcessTelemetryService.cs @@ -45,7 +45,7 @@ public RemoteProcessTelemetryService(ServiceConstructionArguments arguments) /// /// Remote API. Initializes ServiceHub process global state. /// - public ValueTask InitializeTelemetrySessionAsync(int hostProcessId, string serializedSession, CancellationToken cancellationToken) + public ValueTask InitializeTelemetrySessionAsync(int hostProcessId, string serializedSession, bool logDelta, CancellationToken cancellationToken) { return RunServiceAsync(cancellationToken => { @@ -58,7 +58,7 @@ public ValueTask InitializeTelemetrySessionAsync(int hostProcessId, string seria // adds property to each event reported from this session telemetrySession.SetSharedProperty("VS.Core.Version", Environment.GetEnvironmentVariable("VisualStudioVersion")); - telemetryService.InitializeTelemetrySession(telemetrySession); + telemetryService.InitializeTelemetrySession(telemetrySession, logDelta); telemetryService.RegisterUnexpectedExceptionLogger(TraceLogger); FaultReporter.InitializeFatalErrorHandlers(); diff --git a/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteWorkspaceTelemetryService.cs b/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteWorkspaceTelemetryService.cs index bccce75da349f..142e5cf35cfa9 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteWorkspaceTelemetryService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/ProcessTelemetry/RemoteWorkspaceTelemetryService.cs @@ -15,18 +15,15 @@ namespace Microsoft.VisualStudio.LanguageServices.Telemetry [ExportWorkspaceService(typeof(IWorkspaceTelemetryService)), Shared] internal sealed class RemoteWorkspaceTelemetryService : AbstractWorkspaceTelemetryService { - private readonly IGlobalOptionService _globalOptions; - [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public RemoteWorkspaceTelemetryService(IGlobalOptionService globalOptions) + public RemoteWorkspaceTelemetryService() { - _globalOptions = globalOptions; } - protected override ILogger CreateLogger(TelemetrySession telemetrySession) + protected override ILogger CreateLogger(TelemetrySession telemetrySession, bool logDelta) => AggregateLogger.Create( - TelemetryLogger.Create(telemetrySession, _globalOptions), + TelemetryLogger.Create(telemetrySession, logDelta), Logger.GetLogger()); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems index 198a7aff13bcc..5b4435907b1a9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CSharpCompilerExtensions.projitems @@ -9,8 +9,10 @@ Microsoft.CodeAnalysis.CSharp.Shared + + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs new file mode 100644 index 0000000000000..fec7b194448a8 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeGeneration/CSharpCodeGenerationOptions.cs @@ -0,0 +1,107 @@ +// 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.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration; + +[DataContract] +internal sealed class CSharpCodeGenerationOptions : CodeGenerationOptions, IEquatable +{ + private static readonly CodeStyleOption2 s_neverWithSilentEnforcement = + new(ExpressionBodyPreference.Never, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_whenPossibleWithSilentEnforcement = + new(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_blockedScopedWithSilentEnforcement = + new(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_trueWithSuggestionEnforcement = + new(value: true, notification: NotificationOption2.Suggestion); + + public static readonly CSharpCodeGenerationOptions Default = new(); + + [DataMember] public CodeStyleOption2 PreferExpressionBodiedMethods { get; init; } = s_neverWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedAccessors { get; init; } = s_whenPossibleWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedProperties { get; init; } = s_whenPossibleWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedIndexers { get; init; } = s_whenPossibleWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedConstructors { get; init; } = s_neverWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedOperators { get; init; } = s_neverWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedLocalFunctions { get; init; } = s_neverWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedLambdas { get; init; } = s_whenPossibleWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferStaticLocalFunction { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 NamespaceDeclarations { get; init; } = s_blockedScopedWithSilentEnforcement; + + public override bool Equals(object? obj) + => Equals(obj as CSharpCodeGenerationOptions); + + public bool Equals(CSharpCodeGenerationOptions? other) + => other is not null && + Common.Equals(other.Common) && + PreferExpressionBodiedMethods.Equals(other.PreferExpressionBodiedMethods) && + PreferExpressionBodiedAccessors.Equals(other.PreferExpressionBodiedAccessors) && + PreferExpressionBodiedProperties.Equals(other.PreferExpressionBodiedProperties) && + PreferExpressionBodiedIndexers.Equals(other.PreferExpressionBodiedIndexers) && + PreferExpressionBodiedConstructors.Equals(other.PreferExpressionBodiedConstructors) && + PreferExpressionBodiedOperators.Equals(other.PreferExpressionBodiedOperators) && + PreferExpressionBodiedLocalFunctions.Equals(other.PreferExpressionBodiedLocalFunctions) && + PreferExpressionBodiedLambdas.Equals(other.PreferExpressionBodiedLambdas) && + PreferStaticLocalFunction.Equals(other.PreferStaticLocalFunction) && + NamespaceDeclarations.Equals(other.NamespaceDeclarations); + + public override int GetHashCode() + => Hash.Combine(Common, + Hash.Combine(PreferExpressionBodiedMethods, + Hash.Combine(PreferExpressionBodiedAccessors, + Hash.Combine(PreferExpressionBodiedProperties, + Hash.Combine(PreferExpressionBodiedIndexers, + Hash.Combine(PreferExpressionBodiedConstructors, + Hash.Combine(PreferExpressionBodiedOperators, + Hash.Combine(PreferExpressionBodiedLocalFunctions, + Hash.Combine(PreferExpressionBodiedLambdas, + Hash.Combine(PreferStaticLocalFunction, + Hash.Combine(NamespaceDeclarations, 0))))))))))); + +#if !CODE_STYLE + public override CodeGenerationContextInfo GetInfo(CodeGenerationContext context, ParseOptions parseOptions) + => new CSharpCodeGenerationContextInfo(context, this, ((CSharpParseOptions)parseOptions).LanguageVersion); +#endif +} + +internal static class CSharpCodeGenerationOptionsProviders +{ + public static CSharpCodeGenerationOptions GetCSharpCodeGenerationOptions(this AnalyzerConfigOptions options, CSharpCodeGenerationOptions? fallbackOptions) + { + fallbackOptions ??= CSharpCodeGenerationOptions.Default; + + return new() + { + Common = options.GetCommonCodeGenerationOptions(fallbackOptions.Common), + PreferExpressionBodiedMethods = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, fallbackOptions.PreferExpressionBodiedMethods), + PreferExpressionBodiedAccessors = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, fallbackOptions.PreferExpressionBodiedAccessors), + PreferExpressionBodiedProperties = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, fallbackOptions.PreferExpressionBodiedProperties), + PreferExpressionBodiedIndexers = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, fallbackOptions.PreferExpressionBodiedIndexers), + PreferExpressionBodiedConstructors = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, fallbackOptions.PreferExpressionBodiedConstructors), + PreferExpressionBodiedOperators = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, fallbackOptions.PreferExpressionBodiedOperators), + PreferExpressionBodiedLocalFunctions = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLocalFunctions, fallbackOptions.PreferExpressionBodiedLocalFunctions), + PreferExpressionBodiedLambdas = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas, fallbackOptions.PreferExpressionBodiedLambdas), + PreferStaticLocalFunction = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferStaticLocalFunction, fallbackOptions.PreferStaticLocalFunction), + NamespaceDeclarations = options.GetEditorConfigOption(CSharpCodeStyleOptions.NamespaceDeclarations, fallbackOptions.NamespaceDeclarations) + }; + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs index 2f1857297bc10..4fd1c2a8a9eaa 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs @@ -7,6 +7,8 @@ using System.Linq; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Simplification; using Microsoft.CodeAnalysis.Options; @@ -67,81 +69,81 @@ private static Option2> CreateOption( public static readonly Option2> PreferConditionalDelegateCall = CreateOption( CSharpCodeStyleOptionGroups.NullCheckingPreferences, nameof(PreferConditionalDelegateCall), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferConditionalDelegateCall, "csharp_style_conditional_delegate_call", "TextEditor.CSharp.Specific.PreferConditionalDelegateCall"); public static readonly Option2> PreferSwitchExpression = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferSwitchExpression), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferSwitchExpression, "csharp_style_prefer_switch_expression", - $"TextEditor.CSharp.Specific.{nameof(PreferSwitchExpression)}"); + "TextEditor.CSharp.Specific.PreferSwitchExpression"); public static readonly Option2> PreferPatternMatching = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatching), - defaultValue: s_trueWithSilentEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferPatternMatching, "csharp_style_prefer_pattern_matching", - $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatching)}"); + "TextEditor.CSharp.Specific.PreferPatternMatching"); public static readonly Option2> PreferPatternMatchingOverAsWithNullCheck = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatchingOverAsWithNullCheck), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferPatternMatchingOverAsWithNullCheck, "csharp_style_pattern_matching_over_as_with_null_check", - $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverAsWithNullCheck)}"); + "TextEditor.CSharp.Specific.PreferPatternMatchingOverAsWithNullCheck"); public static readonly Option2> PreferPatternMatchingOverIsWithCastCheck = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatchingOverIsWithCastCheck), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferPatternMatchingOverIsWithCastCheck, "csharp_style_pattern_matching_over_is_with_cast_check", - $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverIsWithCastCheck)}"); + "TextEditor.CSharp.Specific.PreferPatternMatchingOverIsWithCastCheck"); public static readonly Option2> PreferNotPattern = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferNotPattern), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferNotPattern, "csharp_style_prefer_not_pattern", - $"TextEditor.CSharp.Specific.{nameof(PreferNotPattern)}"); + "TextEditor.CSharp.Specific.PreferNotPattern"); public static readonly Option2> PreferExtendedPropertyPattern = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferExtendedPropertyPattern), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferExtendedPropertyPattern, "csharp_style_prefer_extended_property_pattern", - $"TextEditor.CSharp.Specific.{nameof(PreferExtendedPropertyPattern)}"); + "TextEditor.CSharp.Specific.PreferExtendedPropertyPattern"); public static readonly Option2> PreferThrowExpression = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferThrowExpression), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpSimplifierOptions.Default.PreferThrowExpression, "csharp_style_throw_expression", "TextEditor.CSharp.Specific.PreferThrowExpression"); public static readonly Option2> PreferInlinedVariableDeclaration = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInlinedVariableDeclaration), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferInlinedVariableDeclaration, "csharp_style_inlined_variable_declaration", "TextEditor.CSharp.Specific.PreferInlinedVariableDeclaration"); public static readonly Option2> PreferDeconstructedVariableDeclaration = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferDeconstructedVariableDeclaration), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferDeconstructedVariableDeclaration, "csharp_style_deconstructed_variable_declaration", - $"TextEditor.CSharp.Specific.{nameof(PreferDeconstructedVariableDeclaration)}"); + "TextEditor.CSharp.Specific.PreferDeconstructedVariableDeclaration"); public static readonly Option2> PreferIndexOperator = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferIndexOperator), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferIndexOperator, "csharp_style_prefer_index_operator", "TextEditor.CSharp.Specific.PreferIndexOperator"); public static readonly Option2> PreferRangeOperator = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferRangeOperator), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferRangeOperator, "csharp_style_prefer_range_operator", "TextEditor.CSharp.Specific.PreferRangeOperator"); - public static readonly Option2> PreferUTF8StringLiterals = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferUTF8StringLiterals), - defaultValue: s_trueWithSuggestionEnforcement, + public static readonly Option2> PreferUtf8StringLiterals = CreateOption( + CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, "PreferUTF8StringLiterals", + CSharpIdeCodeStyleOptions.Default.PreferUtf8StringLiterals, "csharp_style_prefer_utf8_string_literals", - $"TextEditor.CSharp.Specific.{nameof(PreferUTF8StringLiterals)}"); + $"TextEditor.CSharp.Specific.PreferUTF8StringLiterals"); public static readonly CodeStyleOption2 NeverWithSilentEnforcement = new(ExpressionBodyPreference.Never, NotificationOption2.Silent); @@ -217,46 +219,35 @@ private static Option2> CreatePreferBra "csharp_prefer_simple_default_expression", "TextEditor.CSharp.Specific.PreferSimpleDefaultExpression"); - private static readonly ImmutableArray s_preferredModifierOrderDefault = ImmutableArray.Create( - SyntaxKind.PublicKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, - SyntaxKind.StaticKeyword, - SyntaxKind.ExternKeyword, - SyntaxKind.NewKeyword, - SyntaxKind.VirtualKeyword, SyntaxKind.AbstractKeyword, SyntaxKind.SealedKeyword, SyntaxKind.OverrideKeyword, - SyntaxKind.ReadOnlyKeyword, - SyntaxKind.UnsafeKeyword, - SyntaxKind.VolatileKeyword, - SyntaxKind.AsyncKeyword); - public static readonly Option2> PreferredModifierOrder = CreateOption( CSharpCodeStyleOptionGroups.Modifier, nameof(PreferredModifierOrder), - defaultValue: new CodeStyleOption2(string.Join(",", s_preferredModifierOrderDefault.Select(SyntaxFacts.GetText)), NotificationOption2.Silent), + CSharpIdeCodeStyleOptions.Default.PreferredModifierOrder, "csharp_preferred_modifier_order", - $"TextEditor.CSharp.Specific.{nameof(PreferredModifierOrder)}"); + "TextEditor.CSharp.Specific.PreferredModifierOrder"); public static readonly Option2> PreferStaticLocalFunction = CreateOption( CSharpCodeStyleOptionGroups.Modifier, nameof(PreferStaticLocalFunction), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferStaticLocalFunction, "csharp_prefer_static_local_function", - $"TextEditor.CSharp.Specific.{nameof(PreferStaticLocalFunction)}"); + "TextEditor.CSharp.Specific.PreferStaticLocalFunction"); public static readonly Option2> PreferSimpleUsingStatement = CreateOption( CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferSimpleUsingStatement), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferSimpleUsingStatement, "csharp_prefer_simple_using_statement", - $"TextEditor.CSharp.Specific.{nameof(PreferSimpleUsingStatement)}"); + "TextEditor.CSharp.Specific.PreferSimpleUsingStatement"); public static readonly Option2> PreferLocalOverAnonymousFunction = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferLocalOverAnonymousFunction), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferLocalOverAnonymousFunction, "csharp_style_prefer_local_over_anonymous_function", - $"TextEditor.CSharp.Specific.{nameof(PreferLocalOverAnonymousFunction)}"); + "TextEditor.CSharp.Specific.PreferLocalOverAnonymousFunction"); public static readonly Option2> PreferTupleSwap = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferTupleSwap), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferTupleSwap, "csharp_style_prefer_tuple_swap", - $"TextEditor.CSharp.Specific.{nameof(PreferTupleSwap)}"); + "TextEditor.CSharp.Specific.PreferTupleSwap"); public static readonly CodeStyleOption2 PreferOutsidePlacementWithSilentEnforcement = new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent); @@ -272,61 +263,61 @@ private static Option2> CreateUsingDirectiv new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{optionName}")); public static readonly Option2> PreferredUsingDirectivePlacement = CreateUsingDirectivePlacementOption( - nameof(PreferredUsingDirectivePlacement), defaultValue: PreferOutsidePlacementWithSilentEnforcement, "csharp_using_directive_placement"); + "PreferredUsingDirectivePlacement", AddImportPlacementOptions.Default.UsingDirectivePlacement, "csharp_using_directive_placement"); internal static readonly Option2> UnusedValueExpressionStatement = CodeStyleHelpers.CreateUnusedExpressionAssignmentOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, feature: nameof(CSharpCodeStyleOptions), - name: nameof(UnusedValueExpressionStatement), + name: "UnusedValueExpressionStatement", editorConfigName: "csharp_style_unused_value_expression_statement_preference", - defaultValue: new CodeStyleOption2(UnusedValuePreference.DiscardVariable, NotificationOption2.Silent), + CSharpIdeCodeStyleOptions.Default.UnusedValueExpressionStatement, s_allOptionsBuilder); internal static readonly Option2> UnusedValueAssignment = CodeStyleHelpers.CreateUnusedExpressionAssignmentOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, feature: nameof(CSharpCodeStyleOptions), - name: nameof(UnusedValueAssignment), + name: "UnusedValueAssignment", editorConfigName: "csharp_style_unused_value_assignment_preference", - defaultValue: new CodeStyleOption2(UnusedValuePreference.DiscardVariable, NotificationOption2.Suggestion), + CSharpIdeCodeStyleOptions.Default.UnusedValueAssignment, s_allOptionsBuilder); public static readonly Option2> ImplicitObjectCreationWhenTypeIsApparent = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(ImplicitObjectCreationWhenTypeIsApparent), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.ImplicitObjectCreationWhenTypeIsApparent, "csharp_style_implicit_object_creation_when_type_is_apparent", "TextEditor.CSharp.Specific.ImplicitObjectCreationWhenTypeIsApparent"); internal static readonly Option2> PreferNullCheckOverTypeCheck = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferNullCheckOverTypeCheck), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferNullCheckOverTypeCheck, "csharp_style_prefer_null_check_over_type_check", - $"TextEditor.CSharp.Specific.{nameof(PreferNullCheckOverTypeCheck)}"); + "TextEditor.CSharp.Specific.PreferNullCheckOverTypeCheck"); internal static readonly Option2> PreferParameterNullChecking = CreateOption( CSharpCodeStyleOptionGroups.NullCheckingPreferences, nameof(PreferParameterNullChecking), - defaultValue: s_trueWithSuggestionEnforcement, + CSharpSimplifierOptions.Default.PreferParameterNullChecking, "csharp_style_prefer_parameter_null_checking", - $"TextEditor.CSharp.Specific.{nameof(PreferParameterNullChecking)}"); + "TextEditor.CSharp.Specific.PreferParameterNullChecking"); public static Option2> AllowEmbeddedStatementsOnSameLine { get; } = CreateOption( CSharpCodeStyleOptionGroups.NewLinePreferences, nameof(AllowEmbeddedStatementsOnSameLine), - defaultValue: CodeStyleOptions2.TrueWithSilentEnforcement, + CSharpSimplifierOptions.Default.AllowEmbeddedStatementsOnSameLine, EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_allow_embedded_statements_on_same_line_experimental", CodeStyleOptions2.TrueWithSilentEnforcement), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(AllowEmbeddedStatementsOnSameLine)}")); + new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.AllowEmbeddedStatementsOnSameLine")); public static Option2> AllowBlankLinesBetweenConsecutiveBraces { get; } = CreateOption( CSharpCodeStyleOptionGroups.NewLinePreferences, nameof(AllowBlankLinesBetweenConsecutiveBraces), - defaultValue: CodeStyleOptions2.TrueWithSilentEnforcement, + CSharpIdeCodeStyleOptions.Default.AllowBlankLinesBetweenConsecutiveBraces, EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_allow_blank_lines_between_consecutive_braces_experimental", CodeStyleOptions2.TrueWithSilentEnforcement), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(AllowBlankLinesBetweenConsecutiveBraces)}")); + new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.AllowBlankLinesBetweenConsecutiveBraces")); public static Option2> AllowBlankLineAfterColonInConstructorInitializer { get; } = CreateOption( CSharpCodeStyleOptionGroups.NewLinePreferences, nameof(AllowBlankLineAfterColonInConstructorInitializer), - defaultValue: CodeStyleOptions2.TrueWithSilentEnforcement, + CSharpIdeCodeStyleOptions.Default.AllowBlankLineAfterColonInConstructorInitializer, EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental", CodeStyleOptions2.TrueWithSilentEnforcement), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(AllowBlankLineAfterColonInConstructorInitializer)}")); + new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.AllowBlankLineAfterColonInConstructorInitializer")); private static Option2> CreateNamespaceDeclarationOption(string optionName, CodeStyleOption2 defaultValue, string editorconfigKeyName) => CreateOption( @@ -339,21 +330,21 @@ private static Option2> CreateN new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{optionName}")); public static readonly Option2> NamespaceDeclarations = CreateNamespaceDeclarationOption( - nameof(NamespaceDeclarations), - new(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Silent), + "NamespaceDeclarations", + CSharpSyntaxFormattingOptions.Default.NamespaceDeclarations, "csharp_style_namespace_declarations"); public static readonly Option2> PreferMethodGroupConversion = CreateOption( CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferMethodGroupConversion), - defaultValue: s_trueWithSilentEnforcement, + CSharpIdeCodeStyleOptions.Default.PreferMethodGroupConversion, "csharp_style_prefer_method_group_conversion", "TextEditor.CSharp.Specific.PreferMethodGroupConversion"); public static readonly Option2> PreferTopLevelStatements = CreateOption( CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferTopLevelStatements), - defaultValue: s_trueWithSilentEnforcement, + CSharpSyntaxFormattingOptions.Default.PreferTopLevelStatements, "csharp_style_prefer_top_level_statements", - $"TextEditor.CSharp.Specific.{nameof(PreferTopLevelStatements)}"); + "TextEditor.CSharp.Specific.PreferTopLevelStatements"); #if false diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpIdeCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpIdeCodeStyleOptions.cs new file mode 100644 index 0000000000000..fa9248ac0eea3 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpIdeCodeStyleOptions.cs @@ -0,0 +1,135 @@ +// 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.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.Serialization; +using Microsoft.CodeAnalysis.AddImport; +using Microsoft.CodeAnalysis.CodeStyle; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.CodeStyle; + +[DataContract] +internal sealed class CSharpIdeCodeStyleOptions : IdeCodeStyleOptions, IEquatable +{ + private static readonly ImmutableArray s_preferredModifierOrderDefault = ImmutableArray.Create( + SyntaxKind.PublicKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, + SyntaxKind.StaticKeyword, + SyntaxKind.ExternKeyword, + SyntaxKind.NewKeyword, + SyntaxKind.VirtualKeyword, SyntaxKind.AbstractKeyword, SyntaxKind.SealedKeyword, SyntaxKind.OverrideKeyword, + SyntaxKind.ReadOnlyKeyword, + SyntaxKind.UnsafeKeyword, + SyntaxKind.VolatileKeyword, + SyntaxKind.AsyncKeyword); + + private static readonly CodeStyleOption2 s_discardVariableWithSilentEnforcement = + new(UnusedValuePreference.DiscardVariable, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_discardVariableWithSuggestionEnforcement = + new(UnusedValuePreference.DiscardVariable, NotificationOption2.Suggestion); + + private static readonly CodeStyleOption2 s_defaultModifierOrder = + new(string.Join(",", s_preferredModifierOrderDefault.Select(SyntaxFacts.GetText)), NotificationOption2.Silent); + + public static readonly CodeStyleOption2 s_outsideNamespacePlacementWithSilentEnforcement = + new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_whenPossibleWithSilentEnforcement = + new(ExpressionBodyPreference.WhenPossible, NotificationOption2.Silent); + + public static readonly CSharpIdeCodeStyleOptions Default = new(); + + [DataMember] public CodeStyleOption2 ImplicitObjectCreationWhenTypeIsApparent { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferNullCheckOverTypeCheck { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 AllowBlankLinesBetweenConsecutiveBraces { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 AllowBlankLineAfterColonInConstructorInitializer { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferConditionalDelegateCall { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferSwitchExpression { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferPatternMatching { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferPatternMatchingOverAsWithNullCheck { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferPatternMatchingOverIsWithCastCheck { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferNotPattern { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferExtendedPropertyPattern { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferInlinedVariableDeclaration { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferDeconstructedVariableDeclaration { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferIndexOperator { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferRangeOperator { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferUtf8StringLiterals { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferredModifierOrder { get; init; } = s_defaultModifierOrder; + [DataMember] public CodeStyleOption2 PreferSimpleUsingStatement { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferLocalOverAnonymousFunction { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferTupleSwap { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 UnusedValueExpressionStatement { get; init; } = s_discardVariableWithSilentEnforcement; + [DataMember] public CodeStyleOption2 UnusedValueAssignment { get; init; } = s_discardVariableWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferMethodGroupConversion { get; init; } = s_trueWithSilentEnforcement; + + // the following are also used in code generation features, consider sharing: + [DataMember] public CodeStyleOption2 PreferStaticLocalFunction { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferExpressionBodiedLambdas { get; init; } = s_whenPossibleWithSilentEnforcement; + + public override bool Equals(object? obj) + => Equals(obj as CSharpIdeCodeStyleOptions); + + public bool Equals([AllowNull] CSharpIdeCodeStyleOptions other) + => other is not null && + Common.Equals(Common) && + ImplicitObjectCreationWhenTypeIsApparent.Equals(ImplicitObjectCreationWhenTypeIsApparent) && + PreferNullCheckOverTypeCheck.Equals(PreferNullCheckOverTypeCheck) && + AllowBlankLinesBetweenConsecutiveBraces.Equals(AllowBlankLinesBetweenConsecutiveBraces) && + AllowBlankLineAfterColonInConstructorInitializer.Equals(AllowBlankLineAfterColonInConstructorInitializer) && + PreferConditionalDelegateCall.Equals(PreferConditionalDelegateCall) && + PreferSwitchExpression.Equals(PreferSwitchExpression) && + PreferPatternMatching.Equals(PreferPatternMatching) && + PreferPatternMatchingOverAsWithNullCheck.Equals(PreferPatternMatchingOverAsWithNullCheck) && + PreferPatternMatchingOverIsWithCastCheck.Equals(PreferPatternMatchingOverIsWithCastCheck) && + PreferNotPattern.Equals(PreferNotPattern) && + PreferExtendedPropertyPattern.Equals(PreferExtendedPropertyPattern) && + PreferInlinedVariableDeclaration.Equals(PreferInlinedVariableDeclaration) && + PreferDeconstructedVariableDeclaration.Equals(PreferDeconstructedVariableDeclaration) && + PreferIndexOperator.Equals(PreferIndexOperator) && + PreferRangeOperator.Equals(PreferRangeOperator) && + PreferUtf8StringLiterals.Equals(PreferUtf8StringLiterals) && + PreferredModifierOrder.Equals(PreferredModifierOrder) && + PreferSimpleUsingStatement.Equals(PreferSimpleUsingStatement) && + PreferLocalOverAnonymousFunction.Equals(PreferLocalOverAnonymousFunction) && + PreferTupleSwap.Equals(PreferTupleSwap) && + UnusedValueExpressionStatement.Equals(UnusedValueExpressionStatement) && + UnusedValueAssignment.Equals(UnusedValueAssignment) && + PreferMethodGroupConversion.Equals(PreferMethodGroupConversion) && + PreferStaticLocalFunction.Equals(PreferStaticLocalFunction) && + PreferExpressionBodiedLambdas.Equals(PreferExpressionBodiedLambdas); + + public override int GetHashCode() + => Hash.Combine(Common, + Hash.Combine(ImplicitObjectCreationWhenTypeIsApparent, + Hash.Combine(PreferNullCheckOverTypeCheck, + Hash.Combine(AllowBlankLinesBetweenConsecutiveBraces, + Hash.Combine(AllowBlankLineAfterColonInConstructorInitializer, + Hash.Combine(PreferConditionalDelegateCall, + Hash.Combine(PreferSwitchExpression, + Hash.Combine(PreferPatternMatching, + Hash.Combine(PreferPatternMatchingOverAsWithNullCheck, + Hash.Combine(PreferPatternMatchingOverIsWithCastCheck, + Hash.Combine(PreferNotPattern, + Hash.Combine(PreferExtendedPropertyPattern, + Hash.Combine(PreferInlinedVariableDeclaration, + Hash.Combine(PreferDeconstructedVariableDeclaration, + Hash.Combine(PreferIndexOperator, + Hash.Combine(PreferRangeOperator, + Hash.Combine(PreferUtf8StringLiterals, + Hash.Combine(PreferredModifierOrder, + Hash.Combine(PreferSimpleUsingStatement, + Hash.Combine(PreferLocalOverAnonymousFunction, + Hash.Combine(PreferTupleSwap, + Hash.Combine(UnusedValueExpressionStatement, + Hash.Combine(UnusedValueAssignment, + Hash.Combine(PreferMethodGroupConversion, + Hash.Combine(PreferStaticLocalFunction, + Hash.Combine(PreferExpressionBodiedLambdas, 0)))))))))))))))))))))))))); +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs index 531a5dd3d0aa3..a5148d642f996 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormatting.cs @@ -39,7 +39,7 @@ public override SyntaxFormattingOptions DefaultOptions => CSharpSyntaxFormattingOptions.Default; public override SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options, SyntaxFormattingOptions? fallbackOptions) - => CSharpSyntaxFormattingOptions.Create(options, (CSharpSyntaxFormattingOptions?)fallbackOptions); + => options.GetCSharpSyntaxFormattingOptions((CSharpSyntaxFormattingOptions?)fallbackOptions); protected override IFormattingResult CreateAggregatedFormattingResult(SyntaxNode node, IList results, SimpleIntervalTree? formattingSpans = null) => new AggregatedFormattingResult(node, results, formattingSpans); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormattingOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormattingOptions.cs index 9caf795280e77..60e148f66f5d7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormattingOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/CSharpSyntaxFormattingOptions.cs @@ -3,10 +3,14 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Runtime.Serialization; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Formatting { @@ -69,50 +73,13 @@ internal enum IndentationPlacement } [DataContract] - internal sealed class CSharpSyntaxFormattingOptions : SyntaxFormattingOptions + internal sealed class CSharpSyntaxFormattingOptions : SyntaxFormattingOptions, IEquatable { - [DataMember(Order = BaseMemberCount + 0)] - public readonly SpacePlacement Spacing; - - [DataMember(Order = BaseMemberCount + 1)] - public readonly BinaryOperatorSpacingOptions SpacingAroundBinaryOperator; - - [DataMember(Order = BaseMemberCount + 2)] - public readonly NewLinePlacement NewLines; - - [DataMember(Order = BaseMemberCount + 3)] - public readonly LabelPositionOptions LabelPositioning; - - [DataMember(Order = BaseMemberCount + 4)] - public readonly IndentationPlacement Indentation; - - [DataMember(Order = BaseMemberCount + 5)] - public readonly bool WrappingKeepStatementsOnSingleLine; - - [DataMember(Order = BaseMemberCount + 6)] - public readonly bool WrappingPreserveSingleLine; - - public CSharpSyntaxFormattingOptions( - LineFormattingOptions? lineFormatting = null, - bool separateImportDirectiveGroups = false, - SpacePlacement spacing = SpacingDefault, - BinaryOperatorSpacingOptions spacingAroundBinaryOperator = BinaryOperatorSpacingOptions.Single, - NewLinePlacement newLines = NewLinesDefault, - LabelPositionOptions labelPositioning = LabelPositionOptions.OneLess, - IndentationPlacement indentation = IndentationDefault, - bool wrappingKeepStatementsOnSingleLine = true, - bool wrappingPreserveSingleLine = true) - : base(lineFormatting, - separateImportDirectiveGroups) - { - Spacing = spacing; - SpacingAroundBinaryOperator = spacingAroundBinaryOperator; - NewLines = newLines; - LabelPositioning = labelPositioning; - Indentation = indentation; - WrappingKeepStatementsOnSingleLine = wrappingKeepStatementsOnSingleLine; - WrappingPreserveSingleLine = wrappingPreserveSingleLine; - } + private static readonly CodeStyleOption2 s_defaultNamespaceDeclarations = + new(NamespaceDeclarationPreference.BlockScoped, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_trueWithSilentEnforcement = + new(value: true, notification: NotificationOption2.Silent); public const SpacePlacement SpacingDefault = SpacePlacement.AfterControlFlowStatementKeyword | @@ -146,14 +113,68 @@ public CSharpSyntaxFormattingOptions( public static readonly CSharpSyntaxFormattingOptions Default = new(); - public static CSharpSyntaxFormattingOptions Create(AnalyzerConfigOptions options, CSharpSyntaxFormattingOptions? fallbackOptions) + [DataMember] public SpacePlacement Spacing { get; init; } = SpacingDefault; + [DataMember] public BinaryOperatorSpacingOptions SpacingAroundBinaryOperator { get; init; } = BinaryOperatorSpacingOptions.Single; + [DataMember] public NewLinePlacement NewLines { get; init; } = NewLinesDefault; + [DataMember] public LabelPositionOptions LabelPositioning { get; init; } = LabelPositionOptions.OneLess; + [DataMember] public IndentationPlacement Indentation { get; init; } = IndentationDefault; + [DataMember] public bool WrappingKeepStatementsOnSingleLine { get; init; } = true; + [DataMember] public bool WrappingPreserveSingleLine { get; init; } = true; + [DataMember] public CodeStyleOption2 NamespaceDeclarations { get; init; } = s_defaultNamespaceDeclarations; + [DataMember] public CodeStyleOption2 PreferTopLevelStatements { get; init; } = s_trueWithSilentEnforcement; + + public override SyntaxFormattingOptions With(LineFormattingOptions lineFormatting) + => new CSharpSyntaxFormattingOptions() + { + Common = Common with { LineFormatting = lineFormatting }, + Spacing = Spacing, + SpacingAroundBinaryOperator = SpacingAroundBinaryOperator, + NewLines = NewLines, + LabelPositioning = LabelPositioning, + Indentation = Indentation, + WrappingKeepStatementsOnSingleLine = WrappingKeepStatementsOnSingleLine, + WrappingPreserveSingleLine = WrappingPreserveSingleLine, + NamespaceDeclarations = NamespaceDeclarations, + PreferTopLevelStatements = PreferTopLevelStatements + }; + + public override bool Equals(object? obj) + => Equals(obj as CSharpSyntaxFormattingOptions); + + public bool Equals(CSharpSyntaxFormattingOptions? other) + => other is not null && + Common.Equals(other.Common) && + SpacingAroundBinaryOperator == other.SpacingAroundBinaryOperator && + NewLines == other.NewLines && + LabelPositioning == other.LabelPositioning && + Indentation == other.Indentation && + WrappingKeepStatementsOnSingleLine == other.WrappingKeepStatementsOnSingleLine && + WrappingPreserveSingleLine == other.WrappingPreserveSingleLine && + NamespaceDeclarations.Equals(other.NamespaceDeclarations) && + PreferTopLevelStatements.Equals(other.PreferTopLevelStatements); + + public override int GetHashCode() + => Hash.Combine(Common, + Hash.Combine((int)SpacingAroundBinaryOperator, + Hash.Combine((int)NewLines, + Hash.Combine((int)LabelPositioning, + Hash.Combine((int)Indentation, + Hash.Combine(WrappingKeepStatementsOnSingleLine, + Hash.Combine(WrappingPreserveSingleLine, + Hash.Combine(NamespaceDeclarations, + Hash.Combine(PreferTopLevelStatements, 0))))))))); + } + + internal static class CSharpSyntaxFormattingOptionsProviders + { + public static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions(this AnalyzerConfigOptions options, CSharpSyntaxFormattingOptions? fallbackOptions) { - fallbackOptions ??= Default; + fallbackOptions ??= CSharpSyntaxFormattingOptions.Default; - return new( - LineFormattingOptions.Create(options, fallbackOptions.LineFormatting), - separateImportDirectiveGroups: options.GetEditorConfigOption(GenerationOptions.SeparateImportDirectiveGroups, fallbackOptions.SeparateImportDirectiveGroups), - spacing: + return new() + { + Common = options.GetCommonSyntaxFormattingOptions(fallbackOptions.Common), + Spacing = (options.GetEditorConfigOption(CSharpFormattingOptions2.SpacesIgnoreAroundVariableDeclaration, fallbackOptions.Spacing.HasFlag(SpacePlacement.IgnoreAroundVariableDeclaration)) ? SpacePlacement.IgnoreAroundVariableDeclaration : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.SpacingAfterMethodDeclarationName, fallbackOptions.Spacing.HasFlag(SpacePlacement.AfterMethodDeclarationName)) ? SpacePlacement.AfterMethodDeclarationName : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.SpaceBetweenEmptyMethodDeclarationParentheses, fallbackOptions.Spacing.HasFlag(SpacePlacement.BetweenEmptyMethodDeclarationParentheses)) ? SpacePlacement.BetweenEmptyMethodDeclarationParentheses : 0) | @@ -177,8 +198,8 @@ public static CSharpSyntaxFormattingOptions Create(AnalyzerConfigOptions options (options.GetEditorConfigOption(CSharpFormattingOptions2.SpaceBeforeComma, fallbackOptions.Spacing.HasFlag(SpacePlacement.BeforeComma)) ? SpacePlacement.BeforeComma : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.SpaceAfterDot, fallbackOptions.Spacing.HasFlag(SpacePlacement.AfterDot)) ? SpacePlacement.AfterDot : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.SpaceBeforeDot, fallbackOptions.Spacing.HasFlag(SpacePlacement.BeforeDot)) ? SpacePlacement.BeforeDot : 0), - spacingAroundBinaryOperator: options.GetEditorConfigOption(CSharpFormattingOptions2.SpacingAroundBinaryOperator, fallbackOptions.SpacingAroundBinaryOperator), - newLines: + SpacingAroundBinaryOperator = options.GetEditorConfigOption(CSharpFormattingOptions2.SpacingAroundBinaryOperator, fallbackOptions.SpacingAroundBinaryOperator), + NewLines = (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLineForMembersInObjectInit, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BeforeMembersInObjectInitializers)) ? NewLinePlacement.BeforeMembersInObjectInitializers : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLineForMembersInAnonymousTypes, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BeforeMembersInAnonymousTypes)) ? NewLinePlacement.BeforeMembersInAnonymousTypes : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLineForElse, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BeforeElse)) ? NewLinePlacement.BeforeElse : 0) | @@ -194,27 +215,18 @@ public static CSharpSyntaxFormattingOptions Create(AnalyzerConfigOptions options (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLinesForBracesInLambdaExpressionBody, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody)) ? NewLinePlacement.BeforeOpenBraceInLambdaExpressionBody : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLinesForBracesInControlBlocks, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BeforeOpenBraceInControlBlocks)) ? NewLinePlacement.BeforeOpenBraceInControlBlocks : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.NewLineForClausesInQuery, fallbackOptions.NewLines.HasFlag(NewLinePlacement.BetweenQueryExpressionClauses)) ? NewLinePlacement.BetweenQueryExpressionClauses : 0), - labelPositioning: options.GetEditorConfigOption(CSharpFormattingOptions2.LabelPositioning, fallbackOptions.LabelPositioning), - indentation: + LabelPositioning = options.GetEditorConfigOption(CSharpFormattingOptions2.LabelPositioning, fallbackOptions.LabelPositioning), + Indentation = (options.GetEditorConfigOption(CSharpFormattingOptions2.IndentBraces, fallbackOptions.Indentation.HasFlag(IndentationPlacement.Braces)) ? IndentationPlacement.Braces : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.IndentBlock, fallbackOptions.Indentation.HasFlag(IndentationPlacement.BlockContents)) ? IndentationPlacement.BlockContents : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.IndentSwitchCaseSection, fallbackOptions.Indentation.HasFlag(IndentationPlacement.SwitchCaseContents)) ? IndentationPlacement.SwitchCaseContents : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.IndentSwitchCaseSectionWhenBlock, fallbackOptions.Indentation.HasFlag(IndentationPlacement.SwitchCaseContentsWhenBlock)) ? IndentationPlacement.SwitchCaseContentsWhenBlock : 0) | (options.GetEditorConfigOption(CSharpFormattingOptions2.IndentSwitchSection, fallbackOptions.Indentation.HasFlag(IndentationPlacement.SwitchSection)) ? IndentationPlacement.SwitchSection : 0), - wrappingKeepStatementsOnSingleLine: options.GetEditorConfigOption(CSharpFormattingOptions2.WrappingKeepStatementsOnSingleLine, fallbackOptions.WrappingKeepStatementsOnSingleLine), - wrappingPreserveSingleLine: options.GetEditorConfigOption(CSharpFormattingOptions2.WrappingPreserveSingleLine, fallbackOptions.WrappingPreserveSingleLine)); + WrappingKeepStatementsOnSingleLine = options.GetEditorConfigOption(CSharpFormattingOptions2.WrappingKeepStatementsOnSingleLine, fallbackOptions.WrappingKeepStatementsOnSingleLine), + WrappingPreserveSingleLine = options.GetEditorConfigOption(CSharpFormattingOptions2.WrappingPreserveSingleLine, fallbackOptions.WrappingPreserveSingleLine), + NamespaceDeclarations = options.GetEditorConfigOption(CSharpCodeStyleOptions.NamespaceDeclarations, fallbackOptions.NamespaceDeclarations), + PreferTopLevelStatements = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferTopLevelStatements, fallbackOptions.PreferTopLevelStatements) + }; } - - public override SyntaxFormattingOptions With(LineFormattingOptions lineFormatting) - => new CSharpSyntaxFormattingOptions( - lineFormatting, - SeparateImportDirectiveGroups, - Spacing, - SpacingAroundBinaryOperator, - NewLines, - LabelPositioning, - Indentation, - WrappingKeepStatementsOnSingleLine, - WrappingPreserveSingleLine); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplification.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplification.cs index dfca2ae3ec556..992685b730a86 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplification.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplification.cs @@ -15,5 +15,5 @@ public override SimplifierOptions DefaultOptions => CSharpSimplifierOptions.Default; public override SimplifierOptions GetSimplifierOptions(AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions) - => CSharpSimplifierOptions.Create(options, (CSharpSimplifierOptions?)fallbackOptions); + => options.GetCSharpSimplifierOptions((CSharpSimplifierOptions?)fallbackOptions); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs index 2254bba7a70c1..8649e6574795e 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs @@ -3,79 +3,84 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Simplification; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Simplification { [DataContract] - internal sealed class CSharpSimplifierOptions : SimplifierOptions + internal sealed class CSharpSimplifierOptions : SimplifierOptions, IEquatable { - private static readonly CodeStyleOption2 s_defaultPreferBraces = new(PreferBracesPreference.Always, NotificationOption2.Silent); + private static readonly CodeStyleOption2 s_defaultPreferBraces = + new(PreferBracesPreference.Always, NotificationOption2.Silent); - [DataMember(Order = BaseMemberCount + 0)] - public readonly CodeStyleOption2 VarForBuiltInTypes; + private static readonly CodeStyleOption2 s_trueWithSuggestionEnforcement = + new(value: true, notification: NotificationOption2.Suggestion); - [DataMember(Order = BaseMemberCount + 1)] - public readonly CodeStyleOption2 VarWhenTypeIsApparent; + private static readonly CodeStyleOption2 s_trueWithSilentEnforcement = + new(value: true, notification: NotificationOption2.Silent); - [DataMember(Order = BaseMemberCount + 2)] - public readonly CodeStyleOption2 VarElsewhere; + public static readonly CSharpSimplifierOptions Default = new(); - [DataMember(Order = BaseMemberCount + 3)] - public readonly CodeStyleOption2 PreferSimpleDefaultExpression; + [DataMember] public CodeStyleOption2 VarForBuiltInTypes { get; init; } = CodeStyleOption2.Default; + [DataMember] public CodeStyleOption2 VarWhenTypeIsApparent { get; init; } = CodeStyleOption2.Default; + [DataMember] public CodeStyleOption2 VarElsewhere { get; init; } = CodeStyleOption2.Default; + [DataMember] public CodeStyleOption2 PreferSimpleDefaultExpression { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferParameterNullChecking { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferBraces { get; init; } = s_defaultPreferBraces; + [DataMember] public CodeStyleOption2 PreferThrowExpression { get; init; } = s_trueWithSuggestionEnforcement; - [DataMember(Order = BaseMemberCount + 4)] - public readonly CodeStyleOption2 PreferBraces; + public override bool Equals(object? obj) + => Equals(obj as CSharpSimplifierOptions); - 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, - qualifyPropertyAccess: qualifyPropertyAccess, - qualifyMethodAccess: qualifyMethodAccess, - qualifyEventAccess: qualifyEventAccess, - preferPredefinedTypeKeywordInMemberAccess, - preferPredefinedTypeKeywordInDeclaration) - { - VarForBuiltInTypes = varForBuiltInTypes ?? CodeStyleOption2.Default; - VarWhenTypeIsApparent = varWhenTypeIsApparent ?? CodeStyleOption2.Default; - VarElsewhere = varElsewhere ?? CodeStyleOption2.Default; - PreferSimpleDefaultExpression = preferSimpleDefaultExpression ?? CodeStyleOptions2.TrueWithSuggestionEnforcement; - PreferBraces = preferBraces ?? s_defaultPreferBraces; - } + public bool Equals([AllowNull] CSharpSimplifierOptions other) + => other is not null && + Common.Equals(other.Common) && + VarForBuiltInTypes.Equals(other.VarForBuiltInTypes) && + VarWhenTypeIsApparent.Equals(other.VarWhenTypeIsApparent) && + VarElsewhere.Equals(other.VarElsewhere) && + PreferSimpleDefaultExpression.Equals(other.PreferSimpleDefaultExpression) && + PreferParameterNullChecking.Equals(other.PreferParameterNullChecking) && + AllowEmbeddedStatementsOnSameLine.Equals(other.AllowEmbeddedStatementsOnSameLine) && + PreferBraces.Equals(other.PreferBraces) && + PreferThrowExpression.Equals(other.PreferThrowExpression); - public static readonly CSharpSimplifierOptions Default = new(); + public override int GetHashCode() + => Hash.Combine(VarForBuiltInTypes, + Hash.Combine(VarWhenTypeIsApparent, + Hash.Combine(VarElsewhere, + Hash.Combine(PreferSimpleDefaultExpression, + Hash.Combine(PreferParameterNullChecking, + Hash.Combine(AllowEmbeddedStatementsOnSameLine, + Hash.Combine(PreferBraces, + Hash.Combine(PreferThrowExpression, 0)))))))); + } - internal static CSharpSimplifierOptions Create(AnalyzerConfigOptions options, CSharpSimplifierOptions? fallbackOptions) + internal static class CSharpSimplifierOptionsProviders + { + public static CSharpSimplifierOptions GetCSharpSimplifierOptions(this AnalyzerConfigOptions options, CSharpSimplifierOptions? fallbackOptions) { - fallbackOptions ??= Default; + fallbackOptions ??= CSharpSimplifierOptions.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)); + return new() + { + Common = options.GetCommonSimplifierOptions(fallbackOptions.Common), + 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), + PreferParameterNullChecking = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferParameterNullChecking, fallbackOptions.PreferParameterNullChecking), + AllowEmbeddedStatementsOnSameLine = options.GetEditorConfigOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine, fallbackOptions.AllowEmbeddedStatementsOnSameLine), + PreferBraces = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferBraces, fallbackOptions.PreferBraces), + PreferThrowExpression = options.GetEditorConfigOption(CSharpCodeStyleOptions.PreferThrowExpression, fallbackOptions.PreferThrowExpression) + }; } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/AddImport/AddImportPlacementOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/AddImport/AddImportPlacementOptions.cs new file mode 100644 index 0000000000000..3896d252d315d --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/AddImport/AddImportPlacementOptions.cs @@ -0,0 +1,66 @@ +// 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.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.AddImport; + +[DataContract] +internal sealed record class AddImportPlacementOptions +{ + public static readonly CodeStyleOption2 s_outsideNamespacePlacementWithSilentEnforcement = + new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent); + + [DataMember] + public bool PlaceSystemNamespaceFirst { get; init; } = true; + + /// + /// Where to place C# usings relative to namespace declaration, ignored by VB. + /// + [DataMember] + public CodeStyleOption2 UsingDirectivePlacement { get; init; } = s_outsideNamespacePlacementWithSilentEnforcement; + + [DataMember] + public bool AllowInHiddenRegions { get; init; } = false; + + public bool PlaceImportsInsideNamespaces => UsingDirectivePlacement.Value == AddImportPlacement.InsideNamespace; + + public static readonly AddImportPlacementOptions Default = new(); +} + +internal interface AddImportPlacementOptionsProvider +#if !CODE_STYLE + : OptionsProvider +#endif +{ +} + +internal static partial class AddImportPlacementOptionsProviders +{ +#if !CODE_STYLE + public static AddImportPlacementOptions GetAddImportPlacementOptions(this AnalyzerConfigOptions options, bool allowInHiddenRegions, AddImportPlacementOptions? fallbackOptions, HostLanguageServices languageServices) + => languageServices.GetRequiredService().GetAddImportOptions(options, allowInHiddenRegions, fallbackOptions); + + public static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, AddImportPlacementOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetAddImportPlacementOptions(document.AllowImportsInHiddenRegions(), fallbackOptions, document.Project.LanguageServices); + } + + // Normally we don't allow generation into a hidden region in the file. However, if we have a + // modern span mapper at our disposal, we do allow it as that host span mapper can handle mapping + // our edit to their domain appropriate. + public static bool AllowImportsInHiddenRegions(this Document document) + => document.Services.GetService()?.SupportsMappingImportDirectives == true; + + public static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, AddImportPlacementOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await GetAddImportPlacementOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs new file mode 100644 index 0000000000000..47f113c877e27 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeCleanup/CodeCleanupOptions.cs @@ -0,0 +1,109 @@ +// 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; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.CodeActions; +using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Diagnostics; + +#if !CODE_STYLE +using Microsoft.CodeAnalysis.OrganizeImports; +#endif + +namespace Microsoft.CodeAnalysis.CodeCleanup; + +[DataContract] +internal sealed record class CodeCleanupOptions( + [property: DataMember] SyntaxFormattingOptions FormattingOptions, + [property: DataMember] SimplifierOptions SimplifierOptions) +{ + [DataMember] public AddImportPlacementOptions AddImportOptions { get; init; } = AddImportPlacementOptions.Default; + [DataMember] public DocumentFormattingOptions DocumentFormattingOptions { get; init; } = DocumentFormattingOptions.Default; + +#if !CODE_STYLE + public static CodeCleanupOptions GetDefault(HostLanguageServices languageServices) + => new( + FormattingOptions: SyntaxFormattingOptions.GetDefault(languageServices), + SimplifierOptions: SimplifierOptions.GetDefault(languageServices)); + + public OrganizeImportsOptions GetOrganizeImportsOptions() + => new() + { + SeparateImportDirectiveGroups = FormattingOptions.SeparateImportDirectiveGroups, + PlaceSystemNamespaceFirst = AddImportOptions.PlaceSystemNamespaceFirst, + NewLine = FormattingOptions.LineFormatting.NewLine, + }; +#endif +} + +internal interface CodeCleanupOptionsProvider : +#if !CODE_STYLE + OptionsProvider, +#endif + SyntaxFormattingOptionsProvider, + SimplifierOptionsProvider, + AddImportPlacementOptionsProvider, + DocumentFormattingOptionsProvider +{ +} + +#if !CODE_STYLE +internal abstract class AbstractCodeCleanupOptionsProvider : CodeCleanupOptionsProvider +{ + public abstract ValueTask GetCodeCleanupOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken); + + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => GetCodeCleanupOptionsAsync(languageServices, cancellationToken); + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCodeCleanupOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).FormattingOptions.LineFormatting; + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCodeCleanupOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).DocumentFormattingOptions; + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCodeCleanupOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).FormattingOptions; + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCodeCleanupOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).SimplifierOptions; + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCodeCleanupOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).AddImportOptions; +} +#endif + +internal static class CodeCleanupOptionsProviders +{ +#if !CODE_STYLE + public static CodeCleanupOptions GetCodeCleanupOptions(this AnalyzerConfigOptions options, bool allowImportsInHiddenRegions, CodeCleanupOptions? fallbackOptions, HostLanguageServices languageServices) + { + var formattingOptions = options.GetSyntaxFormattingOptions(fallbackOptions?.FormattingOptions, languageServices); + var simplifierOptions = options.GetSimplifierOptions(fallbackOptions?.SimplifierOptions, languageServices); + var addImportOptions = options.GetAddImportPlacementOptions(allowImportsInHiddenRegions, fallbackOptions?.AddImportOptions, languageServices); + var documentFormattingOptions = options.GetDocumentFormattingOptions(fallbackOptions?.DocumentFormattingOptions); + + return new CodeCleanupOptions(formattingOptions, simplifierOptions) + { + AddImportOptions = addImportOptions, + DocumentFormattingOptions = documentFormattingOptions + }; + } + + public static async ValueTask GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetCodeCleanupOptions(document.AllowImportsInHiddenRegions(), fallbackOptions, document.Project.LanguageServices); + } + + public static async ValueTask GetCodeCleanupOptionsAsync(this Document document, CodeCleanupOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await document.GetCodeCleanupOptionsAsync(await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); +#endif +} + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CleanCodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs similarity index 67% rename from src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CleanCodeGenerationOptions.cs rename to src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs index 6b28595f08489..7175237746647 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CleanCodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CleanCodeGenerationOptions.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeCleanup; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Simplification; @@ -33,36 +34,35 @@ public CodeAndImportGenerationOptions CodeAndImportGenerationOptions #endif } -#if !CODE_STYLE internal interface CleanCodeGenerationOptionsProvider : +#if !CODE_STYLE OptionsProvider, +#endif CodeGenerationOptionsProvider, CodeCleanupOptionsProvider, CodeAndImportGenerationOptionsProvider { } -internal abstract class AbstractCleanCodeGenerationOptionsProvider : CleanCodeGenerationOptionsProvider +#if !CODE_STYLE +internal abstract class AbstractCleanCodeGenerationOptionsProvider : AbstractCodeCleanupOptionsProvider, CleanCodeGenerationOptionsProvider { - public abstract ValueTask GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken); + public abstract ValueTask GetCleanCodeGenerationOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken); - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CleanupOptions; + public sealed override async ValueTask GetCodeCleanupOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCleanCodeGenerationOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CleanupOptions; - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CleanupOptions.FormattingOptions; - - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CleanupOptions.SimplifierOptions; - - async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CleanupOptions.AddImportOptions; + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => GetCleanCodeGenerationOptionsAsync(languageServices, cancellationToken); async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CodeAndImportGenerationOptions; + => (await GetCleanCodeGenerationOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).CodeAndImportGenerationOptions; async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => (await GetOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).GenerationOptions; + => (await GetCleanCodeGenerationOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).GenerationOptions; + + async ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => (await GetCleanCodeGenerationOptionsAsync(languageServices, cancellationToken).ConfigureAwait(false)).GenerationOptions.NamingStyle; } internal static class CleanCodeGenerationOptionsProviders diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CodeGenerationOptions.cs similarity index 62% rename from src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationOptions.cs rename to src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CodeGenerationOptions.cs index 39497a54c9c52..1a4e9d1f13918 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeGeneration/CodeGenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeGeneration/CodeGenerationOptions.cs @@ -2,7 +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. -#if !CODE_STYLE using System; using System.Runtime.Serialization; using System.Threading; @@ -14,7 +13,9 @@ using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.AddImport; using Roslyn.Utilities; -#endif +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.CodeAnalysis.CodeGeneration; @@ -23,23 +24,23 @@ namespace Microsoft.CodeAnalysis.CodeGeneration; /// internal abstract class CodeGenerationOptions { - protected const int BaseMemberCount = 0; - - public CodeGenerationOptions() + [DataContract] + internal sealed record class CommonOptions { + public static readonly CommonOptions Default = new(); + + [DataMember] public NamingStylePreferences NamingStyle { get; init; } = NamingStylePreferences.Default; } + [DataMember] + public CommonOptions Common { get; init; } = CommonOptions.Default; + + public NamingStylePreferences NamingStyle => Common.NamingStyle; + #if !CODE_STYLE public static CodeGenerationOptions GetDefault(HostLanguageServices languageServices) => languageServices.GetRequiredService().DefaultOptions; - public static CodeGenerationOptions Create(OptionSet options, CodeGenerationOptions? fallbackOptions, HostLanguageServices languageServices) - { - var formattingService = languageServices.GetRequiredService(); - var configOptions = options.AsAnalyzerConfigOptions(languageServices.WorkspaceServices.GetRequiredService(), languageServices.Language); - return formattingService.GetCodeGenerationOptions(configOptions, fallbackOptions); - } - public abstract CodeGenerationContextInfo GetInfo(CodeGenerationContext context, ParseOptions parseOptions); public CodeGenerationContextInfo GetInfo(CodeGenerationContext context, Project project) @@ -50,12 +51,12 @@ public CodeGenerationContextInfo GetInfo(CodeGenerationContext context, Project #endif } -#if !CODE_STYLE [DataContract] internal readonly record struct CodeAndImportGenerationOptions( [property: DataMember(Order = 0)] CodeGenerationOptions GenerationOptions, [property: DataMember(Order = 1)] AddImportPlacementOptions AddImportOptions) { +#if !CODE_STYLE internal static CodeAndImportGenerationOptions GetDefault(HostLanguageServices languageServices) => new(CodeGenerationOptions.GetDefault(languageServices), AddImportPlacementOptions.Default); @@ -75,17 +76,27 @@ ValueTask OptionsProvider OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_options.GenerationOptions); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(_options.GenerationOptions.NamingStyle); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) => ValueTaskFactory.FromResult(_options.AddImportOptions); } +#endif } -internal interface CodeGenerationOptionsProvider : OptionsProvider +internal interface CodeGenerationOptionsProvider : +#if !CODE_STYLE + OptionsProvider, +#endif + NamingStylePreferencesProvider { } internal interface CodeAndImportGenerationOptionsProvider : +#if !CODE_STYLE OptionsProvider, +#endif CodeGenerationOptionsProvider, AddImportPlacementOptionsProvider { @@ -93,15 +104,27 @@ internal interface CodeAndImportGenerationOptionsProvider : internal static class CodeGenerationOptionsProviders { - public static async ValueTask GetCodeGenerationOptionsAsync(this Document document, CodeGenerationOptions? fallbackOptions, CancellationToken cancellationToken) + public static CodeGenerationOptions.CommonOptions GetCommonCodeGenerationOptions(this AnalyzerConfigOptions options, CodeGenerationOptions.CommonOptions? fallbackOptions) { - Contract.ThrowIfNull(document.Project.ParseOptions); + fallbackOptions ??= CodeGenerationOptions.CommonOptions.Default; - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return CodeGenerationOptions.Create(documentOptions, fallbackOptions, document.Project.LanguageServices); + return new() + { + NamingStyle = options.GetEditorConfigOption(NamingStyleOptions.NamingPreferences, fallbackOptions.NamingStyle) + }; + } + +#if !CODE_STYLE + public static CodeGenerationOptions GetCodeGenerationOptions(this AnalyzerConfigOptions options, CodeGenerationOptions? fallbackOptions, HostLanguageServices languageServices) + => languageServices.GetRequiredService().GetCodeGenerationOptions(options, fallbackOptions); + + public static async ValueTask GetCodeGenerationOptionsAsync(this Document document, CodeGenerationOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetCodeGenerationOptions(fallbackOptions, document.Project.LanguageServices); } public static async ValueTask GetCodeGenerationOptionsAsync(this Document document, CodeGenerationOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - => await GetCodeGenerationOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); -} + => await GetCodeGenerationOptionsAsync(document, await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); #endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs index 8fb1ade940ada..d6fe06e3eec89 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs @@ -4,11 +4,12 @@ using System.Collections.Immutable; using System.Diagnostics; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Simplification; using Roslyn.Utilities; using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers; -using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.CodeStyle { @@ -138,30 +139,19 @@ private static PerLanguageOption2> CreateQualifyAccessOpt internal static readonly PerLanguageOption2> PreferObjectInitializer = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferObjectInitializer), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferObjectInitializer, "dotnet_style_object_initializer", "TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer"); internal static readonly PerLanguageOption2> PreferCollectionInitializer = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCollectionInitializer), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferCollectionInitializer, "dotnet_style_collection_initializer", "TextEditor.%LANGUAGE%.Specific.PreferCollectionInitializer"); - // TODO: Should both the below "_FadeOutCode" options be added to AllOptions? - internal static readonly PerLanguageOption2 PreferObjectInitializer_FadeOutCode = new( - "CodeStyleOptions", nameof(PreferObjectInitializer_FadeOutCode), - defaultValue: false, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer_FadeOutCode")); - - internal static readonly PerLanguageOption2 PreferCollectionInitializer_FadeOutCode = new( - "CodeStyleOptions", nameof(PreferCollectionInitializer_FadeOutCode), - defaultValue: false, - storageLocation: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferCollectionInitializer_FadeOutCode")); - internal static readonly PerLanguageOption2> PreferSimplifiedBooleanExpressions = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSimplifiedBooleanExpressions), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferSimplifiedBooleanExpressions, "dotnet_style_prefer_simplified_boolean_expressions", "TextEditor.%LANGUAGE%.Specific.PreferSimplifiedBooleanExpressions"); @@ -169,7 +159,7 @@ private static PerLanguageOption2> CreateQualifyAccessOpt CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(OperatorPlacementWhenWrapping), - defaultValue: OperatorPlacementWhenWrappingPreference.BeginningOfLine, + IdeCodeStyleOptions.CommonOptions.Default.OperatorPlacementWhenWrapping, new EditorConfigStorageLocation( "dotnet_style_operator_placement_when_wrapping", OperatorPlacementUtilities.Parse, @@ -177,124 +167,118 @@ private static PerLanguageOption2> CreateQualifyAccessOpt internal static readonly PerLanguageOption2> PreferCoalesceExpression = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCoalesceExpression), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferCoalesceExpression, "dotnet_style_coalesce_expression", "TextEditor.%LANGUAGE%.Specific.PreferCoalesceExpression"); internal static readonly PerLanguageOption2> PreferNullPropagation = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferNullPropagation), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferNullPropagation, "dotnet_style_null_propagation", "TextEditor.%LANGUAGE%.Specific.PreferNullPropagation"); internal static readonly PerLanguageOption2> PreferExplicitTupleNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferExplicitTupleNames), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferExplicitTupleNames, "dotnet_style_explicit_tuple_names", "TextEditor.%LANGUAGE%.Specific.PreferExplicitTupleNames"); internal static readonly PerLanguageOption2> PreferAutoProperties = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferAutoProperties), - defaultValue: TrueWithSilentEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferAutoProperties, "dotnet_style_prefer_auto_properties", "TextEditor.%LANGUAGE%.Specific.PreferAutoProperties"); internal static readonly PerLanguageOption2> PreferInferredTupleNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInferredTupleNames), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferInferredTupleNames, "dotnet_style_prefer_inferred_tuple_names", $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredTupleNames)}"); internal static readonly PerLanguageOption2> PreferInferredAnonymousTypeMemberNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInferredAnonymousTypeMemberNames), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferInferredAnonymousTypeMemberNames, "dotnet_style_prefer_inferred_anonymous_type_member_names", - $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredAnonymousTypeMemberNames)}"); + $"TextEditor.%LANGUAGE%.Specific.PreferInferredAnonymousTypeMemberNames"); internal static readonly PerLanguageOption2> PreferIsNullCheckOverReferenceEqualityMethod = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferIsNullCheckOverReferenceEqualityMethod), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferIsNullCheckOverReferenceEqualityMethod, "dotnet_style_prefer_is_null_check_over_reference_equality_method", - $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferIsNullCheckOverReferenceEqualityMethod)}"); + $"TextEditor.%LANGUAGE%.Specific.PreferIsNullCheckOverReferenceEqualityMethod"); internal static readonly PerLanguageOption2> PreferConditionalExpressionOverAssignment = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferConditionalExpressionOverAssignment), - defaultValue: TrueWithSilentEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferConditionalExpressionOverAssignment, "dotnet_style_prefer_conditional_expression_over_assignment", "TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverAssignment"); internal static readonly PerLanguageOption2> PreferConditionalExpressionOverReturn = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferConditionalExpressionOverReturn), - defaultValue: TrueWithSilentEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferConditionalExpressionOverReturn, "dotnet_style_prefer_conditional_expression_over_return", "TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverReturn"); internal static readonly PerLanguageOption2> PreferCompoundAssignment = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCompoundAssignment), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferCompoundAssignment, "dotnet_style_prefer_compound_assignment", "TextEditor.%LANGUAGE%.Specific.PreferCompoundAssignment"); internal static readonly PerLanguageOption2> PreferSimplifiedInterpolation = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSimplifiedInterpolation), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferSimplifiedInterpolation, "dotnet_style_prefer_simplified_interpolation", - $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferSimplifiedInterpolation)}"); - - private static readonly CodeStyleOption2 s_preferAllMethodsUnusedParametersPreference = - new(UnusedParametersPreference.AllMethods, NotificationOption2.Suggestion); + $"TextEditor.%LANGUAGE%.Specific.PreferSimplifiedInterpolation"); // TODO: https://github.com/dotnet/roslyn/issues/31225 tracks adding CodeQualityOption and CodeQualityOptions // and moving this option to CodeQualityOptions. internal static readonly PerLanguageOption2> UnusedParameters = CreateOption( CodeStyleOptionGroups.Parameter, nameof(UnusedParameters), - defaultValue: s_preferAllMethodsUnusedParametersPreference, + IdeCodeStyleOptions.CommonOptions.Default.UnusedParameters, new EditorConfigStorageLocation>( "dotnet_code_quality_unused_parameters", - s => ParseUnusedParametersPreference(s, s_preferAllMethodsUnusedParametersPreference), - o => GetUnusedParametersPreferenceEditorConfigString(o, s_preferAllMethodsUnusedParametersPreference)), - new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(UnusedParameters)}Preference")); + s => ParseUnusedParametersPreference(s, IdeCodeStyleOptions.CommonOptions.Default.UnusedParameters), + o => GetUnusedParametersPreferenceEditorConfigString(o, IdeCodeStyleOptions.CommonOptions.Default.UnusedParameters)), + new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.UnusedParametersPreference")); - private static readonly CodeStyleOption2 s_requireAccessibilityModifiersDefault = - new(AccessibilityModifiersRequired.ForNonInterfaceMembers, NotificationOption2.Silent); - - internal static readonly PerLanguageOption2> RequireAccessibilityModifiers = + internal static readonly PerLanguageOption2> AccessibilityModifiersRequired = CreateOption( - CodeStyleOptionGroups.Modifier, nameof(RequireAccessibilityModifiers), - defaultValue: s_requireAccessibilityModifiersDefault, + CodeStyleOptionGroups.Modifier, "RequireAccessibilityModifiers", + IdeCodeStyleOptions.CommonOptions.Default.AccessibilityModifiersRequired, new EditorConfigStorageLocation>( "dotnet_style_require_accessibility_modifiers", - s => ParseAccessibilityModifiersRequired(s, s_requireAccessibilityModifiersDefault), - v => GetAccessibilityModifiersRequiredEditorConfigString(v, s_requireAccessibilityModifiersDefault)), + s => ParseAccessibilityModifiersRequired(s, IdeCodeStyleOptions.CommonOptions.Default.AccessibilityModifiersRequired), + v => GetAccessibilityModifiersRequiredEditorConfigString(v, IdeCodeStyleOptions.CommonOptions.Default.AccessibilityModifiersRequired)), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RequireAccessibilityModifiers")); internal static readonly PerLanguageOption2> PreferReadonly = CreateOption( CodeStyleOptionGroups.Field, nameof(PreferReadonly), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferReadonly, "dotnet_style_readonly_field", "TextEditor.%LANGUAGE%.Specific.PreferReadonly"); internal static readonly Option2 FileHeaderTemplate = CreateCommonOption( CodeStyleOptionGroups.Usings, nameof(FileHeaderTemplate), - defaultValue: "", + DocumentFormattingOptions.Default.FileHeaderTemplate, EditorConfigStorageLocation.ForStringOption("file_header_template", emptyStringRepresentation: "unset")); internal static readonly Option2 RemoveUnnecessarySuppressionExclusions = CreateCommonOption( CodeStyleOptionGroups.Suppressions, nameof(RemoveUnnecessarySuppressionExclusions), - defaultValue: "", + IdeCodeStyleOptions.CommonOptions.Default.RemoveUnnecessarySuppressionExclusions, EditorConfigStorageLocation.ForStringOption("dotnet_remove_unnecessary_suppression_exclusions", emptyStringRepresentation: "none"), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RemoveUnnecessarySuppressionExclusions")); private static readonly BidirectionalMap s_accessibilityModifiersRequiredMap = new(new[] { - KeyValuePairUtil.Create("never", AccessibilityModifiersRequired.Never), - KeyValuePairUtil.Create("always", AccessibilityModifiersRequired.Always), - KeyValuePairUtil.Create("for_non_interface_members", AccessibilityModifiersRequired.ForNonInterfaceMembers), - KeyValuePairUtil.Create("omit_if_default", AccessibilityModifiersRequired.OmitIfDefault), + KeyValuePairUtil.Create("never", CodeStyle.AccessibilityModifiersRequired.Never), + KeyValuePairUtil.Create("always", CodeStyle.AccessibilityModifiersRequired.Always), + KeyValuePairUtil.Create("for_non_interface_members", CodeStyle.AccessibilityModifiersRequired.ForNonInterfaceMembers), + KeyValuePairUtil.Create("omit_if_default", CodeStyle.AccessibilityModifiersRequired.OmitIfDefault), }); private static CodeStyleOption2 ParseAccessibilityModifiersRequired(string optionString, CodeStyleOption2 defaultValue) @@ -306,7 +290,7 @@ private static CodeStyleOption2 ParseAccessibili return new CodeStyleOption2(s_accessibilityModifiersRequiredMap.GetValueOrDefault(value), notificationOpt); } - return s_requireAccessibilityModifiersDefault; + return defaultValue; } private static string GetAccessibilityModifiersRequiredEditorConfigString(CodeStyleOption2 option, CodeStyleOption2 defaultValue) @@ -315,12 +299,6 @@ private static string GetAccessibilityModifiersRequiredEditorConfigString(CodeSt return $"{s_accessibilityModifiersRequiredMap.GetKeyOrDefault(option.Value)}{GetEditorConfigStringNotificationPart(option, defaultValue)}"; } - private static readonly CodeStyleOption2 s_alwaysForClarityPreference = - new(ParenthesesPreference.AlwaysForClarity, NotificationOption2.Silent); - - private static readonly CodeStyleOption2 s_neverIfUnnecessaryPreference = - new(ParenthesesPreference.NeverIfUnnecessary, NotificationOption2.Silent); - private static PerLanguageOption2> CreateParenthesesOption( string fieldName, CodeStyleOption2 defaultValue, string styleName) @@ -337,25 +315,25 @@ private static PerLanguageOption2> Creat internal static readonly PerLanguageOption2> ArithmeticBinaryParentheses = CreateParenthesesOption( nameof(ArithmeticBinaryParentheses), - s_alwaysForClarityPreference, + IdeCodeStyleOptions.CommonOptions.Default.ArithmeticBinaryParentheses, "dotnet_style_parentheses_in_arithmetic_binary_operators"); internal static readonly PerLanguageOption2> OtherBinaryParentheses = CreateParenthesesOption( nameof(OtherBinaryParentheses), - s_alwaysForClarityPreference, + IdeCodeStyleOptions.CommonOptions.Default.OtherBinaryParentheses, "dotnet_style_parentheses_in_other_binary_operators"); internal static readonly PerLanguageOption2> RelationalBinaryParentheses = CreateParenthesesOption( nameof(RelationalBinaryParentheses), - s_alwaysForClarityPreference, + IdeCodeStyleOptions.CommonOptions.Default.RelationalBinaryParentheses, "dotnet_style_parentheses_in_relational_binary_operators"); internal static readonly PerLanguageOption2> OtherParentheses = CreateParenthesesOption( nameof(OtherParentheses), - s_neverIfUnnecessaryPreference, + IdeCodeStyleOptions.CommonOptions.Default.OtherParentheses, "dotnet_style_parentheses_in_other_operators"); private static readonly BidirectionalMap s_parenthesesPreferenceMap = @@ -372,10 +350,7 @@ private static PerLanguageOption2> Creat KeyValuePairUtil.Create("all", UnusedParametersPreference.AllMethods), }); - #region dotnet_style_prefer_foreach_explicit_cast_in_Source - - private static readonly CodeStyleOption2 s_forEachExplicitCastInSourceNonLegacyPreference = - new(ForEachExplicitCastInSourcePreference.WhenStronglyTyped, NotificationOption2.Suggestion); + #region dotnet_style_prefer_foreach_explicit_cast_in_source private static readonly BidirectionalMap s_forEachExplicitCastInSourcePreferencePreferenceMap = new(new[] @@ -388,11 +363,11 @@ private static PerLanguageOption2> Creat CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(ForEachExplicitCastInSource), - s_forEachExplicitCastInSourceNonLegacyPreference, + IdeCodeStyleOptions.CommonOptions.Default.ForEachExplicitCastInSource, new EditorConfigStorageLocation>( "dotnet_style_prefer_foreach_explicit_cast_in_source", - s => ParseForEachExplicitCastInSourcePreference(s, s_forEachExplicitCastInSourceNonLegacyPreference), - v => GetForEachExplicitCastInSourceEditorConfigString(v, s_forEachExplicitCastInSourceNonLegacyPreference))); + s => ParseForEachExplicitCastInSourcePreference(s, IdeCodeStyleOptions.CommonOptions.Default.ForEachExplicitCastInSource), + v => GetForEachExplicitCastInSourceEditorConfigString(v, IdeCodeStyleOptions.CommonOptions.Default.ForEachExplicitCastInSource))); private static CodeStyleOption2 ParseForEachExplicitCastInSourcePreference( string optionString, CodeStyleOption2 defaultValue) @@ -423,24 +398,24 @@ private static string GetForEachExplicitCastInSourceEditorConfigString( internal static readonly PerLanguageOption2> PreferSystemHashCode = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSystemHashCode), - defaultValue: TrueWithSuggestionEnforcement, + IdeAnalyzerOptions.DefaultPreferSystemHashCode, new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferSystemHashCode")); public static readonly PerLanguageOption2> PreferNamespaceAndFolderMatchStructure = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferNamespaceAndFolderMatchStructure), - defaultValue: TrueWithSuggestionEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.PreferNamespaceAndFolderMatchStructure, editorconfigKeyName: "dotnet_style_namespace_match_folder", - roamingProfileStorageKeyName: $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferNamespaceAndFolderMatchStructure)}"); + roamingProfileStorageKeyName: "TextEditor.%LANGUAGE%.Specific.PreferNamespaceAndFolderMatchStructure"); internal static readonly PerLanguageOption2> AllowMultipleBlankLines = CreateOption( CodeStyleOptionGroups.NewLinePreferences, nameof(AllowMultipleBlankLines), - defaultValue: TrueWithSilentEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.AllowMultipleBlankLines, "dotnet_style_allow_multiple_blank_lines_experimental", "TextEditor.%LANGUAGE%.Specific.AllowMultipleBlankLines"); internal static readonly PerLanguageOption2> AllowStatementImmediatelyAfterBlock = CreateOption( CodeStyleOptionGroups.NewLinePreferences, nameof(AllowStatementImmediatelyAfterBlock), - defaultValue: TrueWithSilentEnforcement, + IdeCodeStyleOptions.CommonOptions.Default.AllowStatementImmediatelyAfterBlock, "dotnet_style_allow_statement_immediately_after_block_experimental", "TextEditor.%LANGUAGE%.Specific.AllowStatementImmediatelyAfterBlock"); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/IdeCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/IdeCodeStyleOptions.cs new file mode 100644 index 0000000000000..ab172a4643092 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/IdeCodeStyleOptions.cs @@ -0,0 +1,77 @@ +// 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.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.CodeStyle; + +internal abstract class IdeCodeStyleOptions +{ + protected static readonly CodeStyleOption2 s_trueWithSuggestionEnforcement = + new(value: true, notification: NotificationOption2.Suggestion); + + protected static readonly CodeStyleOption2 s_trueWithSilentEnforcement = + new(value: true, notification: NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_preferAllMethodsUnusedParametersPreference = + new(UnusedParametersPreference.AllMethods, NotificationOption2.Suggestion); + + private static readonly CodeStyleOption2 s_accessibilityModifiersRequiredDefault = + new(SyntaxFormattingOptions.CommonOptions.Default.AccessibilityModifiersRequired, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_alwaysForClarityPreference = + new(ParenthesesPreference.AlwaysForClarity, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_neverIfUnnecessaryPreference = + new(ParenthesesPreference.NeverIfUnnecessary, NotificationOption2.Silent); + + private static readonly CodeStyleOption2 s_forEachExplicitCastInSourceNonLegacyPreference = + new(ForEachExplicitCastInSourcePreference.WhenStronglyTyped, NotificationOption2.Suggestion); + + [DataContract] + internal sealed record class CommonOptions + { + public static readonly CommonOptions Default = new(); + + [DataMember] public CodeStyleOption2 PreferObjectInitializer { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferCollectionInitializer { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferSimplifiedBooleanExpressions { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public OperatorPlacementWhenWrappingPreference OperatorPlacementWhenWrapping { get; init; } = OperatorPlacementWhenWrappingPreference.BeginningOfLine; + [DataMember] public CodeStyleOption2 PreferCoalesceExpression { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferNullPropagation { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferExplicitTupleNames { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferAutoProperties { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferInferredTupleNames { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferInferredAnonymousTypeMemberNames { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferIsNullCheckOverReferenceEqualityMethod { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferConditionalExpressionOverAssignment { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferConditionalExpressionOverReturn { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 PreferCompoundAssignment { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 PreferSimplifiedInterpolation { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 UnusedParameters { get; init; } = s_preferAllMethodsUnusedParametersPreference; + [DataMember] public CodeStyleOption2 AccessibilityModifiersRequired { get; init; } = s_accessibilityModifiersRequiredDefault; + [DataMember] public CodeStyleOption2 PreferReadonly { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 ArithmeticBinaryParentheses { get; init; } = s_alwaysForClarityPreference; + [DataMember] public CodeStyleOption2 OtherBinaryParentheses { get; init; } = s_alwaysForClarityPreference; + [DataMember] public CodeStyleOption2 RelationalBinaryParentheses { get; init; } = s_alwaysForClarityPreference; + [DataMember] public CodeStyleOption2 OtherParentheses { get; init; } = s_neverIfUnnecessaryPreference; + [DataMember] public CodeStyleOption2 ForEachExplicitCastInSource { get; init; } = s_forEachExplicitCastInSourceNonLegacyPreference; + [DataMember] public CodeStyleOption2 PreferNamespaceAndFolderMatchStructure { get; init; } = s_trueWithSuggestionEnforcement; + [DataMember] public CodeStyleOption2 AllowMultipleBlankLines { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public CodeStyleOption2 AllowStatementImmediatelyAfterBlock { get; init; } = s_trueWithSilentEnforcement; + [DataMember] public string RemoveUnnecessarySuppressionExclusions { get; init; } = ""; + } + + [DataMember] + public CommonOptions Common { get; init; } = CommonOptions.Default; + +#if !CODE_STYLE + public static IdeCodeStyleOptions GetDefault(HostLanguageServices languageServices) + => languageServices.GetRequiredService().DefaultOptions; +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems index c17730357f3ff..701c383ea9290 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems @@ -178,7 +178,11 @@ InternalUtilities\UnicodeCharacterUtilities.cs + + + + @@ -187,6 +191,7 @@ + @@ -194,6 +199,8 @@ + + @@ -233,7 +240,10 @@ + + + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/AnalyzerOptionsProvider.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/AnalyzerOptionsProvider.cs new file mode 100644 index 0000000000000..f482e46cfe149 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/AnalyzerOptionsProvider.cs @@ -0,0 +1,158 @@ +// 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.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.Diagnostics; + +/// +/// Provides C# and VB analyzers a convenient access to common editorconfig options with fallback to IDE default values. +/// +internal readonly struct AnalyzerOptionsProvider +{ + /// + /// Document editorconfig options. + /// + private readonly AnalyzerConfigOptions _options; + + /// + /// Fallback options - the default options in Code Style layer. + /// + private readonly IdeAnalyzerOptions _fallbackOptions; + + public AnalyzerOptionsProvider(AnalyzerConfigOptions options, IdeAnalyzerOptions fallbackOptions) + { + _options = options; + _fallbackOptions = fallbackOptions; + } + + public AnalyzerOptionsProvider(AnalyzerConfigOptions options, AnalyzerOptions fallbackOptions) + : this(options, fallbackOptions.GetIdeOptions()) + { + } + + // SimplifierOptions + + public CodeStyleOption2 QualifyFieldAccess => GetOption(CodeStyleOptions2.QualifyFieldAccess, FallbackSimplifierOptions.QualifyFieldAccess); + public CodeStyleOption2 QualifyPropertyAccess => GetOption(CodeStyleOptions2.QualifyPropertyAccess, FallbackSimplifierOptions.QualifyPropertyAccess); + public CodeStyleOption2 QualifyMethodAccess => GetOption(CodeStyleOptions2.QualifyMethodAccess, FallbackSimplifierOptions.QualifyMethodAccess); + public CodeStyleOption2 QualifyEventAccess => GetOption(CodeStyleOptions2.QualifyEventAccess, FallbackSimplifierOptions.QualifyEventAccess); + public CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, FallbackSimplifierOptions.PreferPredefinedTypeKeywordInMemberAccess); + public CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration => GetOption(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInDeclaration, FallbackSimplifierOptions.PreferPredefinedTypeKeywordInDeclaration); + + public SimplifierOptions GetSimplifierOptions(ISimplification simplification) + => simplification.GetSimplifierOptions(_options, _fallbackOptions.CleanupOptions?.SimplifierOptions); + + // SyntaxFormattingOptions + + public SyntaxFormattingOptions GetSyntaxFormattingOptions(ISyntaxFormatting formatting) + => formatting.GetFormattingOptions(_options, _fallbackOptions.CleanupOptions?.FormattingOptions); + + // CodeGenerationOptions + + public NamingStylePreferences NamingPreferences => GetOption(NamingStyleOptions.NamingPreferences, _fallbackOptions.GenerationOptions?.NamingStyle ?? NamingStylePreferences.Default); + + // CodeStyleOptions + + public CodeStyleOption2 PreferObjectInitializer => GetOption(CodeStyleOptions2.PreferObjectInitializer, FallbackCodeStyleOptions.PreferObjectInitializer); + public CodeStyleOption2 PreferCollectionInitializer => GetOption(CodeStyleOptions2.PreferCollectionInitializer, FallbackCodeStyleOptions.PreferCollectionInitializer); + public CodeStyleOption2 PreferSimplifiedBooleanExpressions => GetOption(CodeStyleOptions2.PreferSimplifiedBooleanExpressions, FallbackCodeStyleOptions.PreferSimplifiedBooleanExpressions); + public OperatorPlacementWhenWrappingPreference OperatorPlacementWhenWrapping => GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping, FallbackCodeStyleOptions.OperatorPlacementWhenWrapping); + public CodeStyleOption2 PreferCoalesceExpression => GetOption(CodeStyleOptions2.PreferCoalesceExpression, FallbackCodeStyleOptions.PreferCoalesceExpression); + public CodeStyleOption2 PreferNullPropagation => GetOption(CodeStyleOptions2.PreferNullPropagation, FallbackCodeStyleOptions.PreferNullPropagation); + public CodeStyleOption2 PreferExplicitTupleNames => GetOption(CodeStyleOptions2.PreferExplicitTupleNames, FallbackCodeStyleOptions.PreferExplicitTupleNames); + public CodeStyleOption2 PreferAutoProperties => GetOption(CodeStyleOptions2.PreferAutoProperties, FallbackCodeStyleOptions.PreferAutoProperties); + public CodeStyleOption2 PreferInferredTupleNames => GetOption(CodeStyleOptions2.PreferInferredTupleNames, FallbackCodeStyleOptions.PreferInferredTupleNames); + public CodeStyleOption2 PreferInferredAnonymousTypeMemberNames => GetOption(CodeStyleOptions2.PreferInferredAnonymousTypeMemberNames, FallbackCodeStyleOptions.PreferInferredAnonymousTypeMemberNames); + public CodeStyleOption2 PreferIsNullCheckOverReferenceEqualityMethod => GetOption(CodeStyleOptions2.PreferIsNullCheckOverReferenceEqualityMethod, FallbackCodeStyleOptions.PreferIsNullCheckOverReferenceEqualityMethod); + public CodeStyleOption2 PreferConditionalExpressionOverAssignment => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverAssignment, FallbackCodeStyleOptions.PreferConditionalExpressionOverAssignment); + public CodeStyleOption2 PreferConditionalExpressionOverReturn => GetOption(CodeStyleOptions2.PreferConditionalExpressionOverReturn, FallbackCodeStyleOptions.PreferConditionalExpressionOverReturn); + public CodeStyleOption2 PreferCompoundAssignment => GetOption(CodeStyleOptions2.PreferCompoundAssignment, FallbackCodeStyleOptions.PreferCompoundAssignment); + public CodeStyleOption2 PreferSimplifiedInterpolation => GetOption(CodeStyleOptions2.PreferSimplifiedInterpolation, FallbackCodeStyleOptions.PreferSimplifiedInterpolation); + public CodeStyleOption2 UnusedParameters => GetOption(CodeStyleOptions2.UnusedParameters, FallbackCodeStyleOptions.UnusedParameters); + public CodeStyleOption2 RequireAccessibilityModifiers => GetOption(CodeStyleOptions2.AccessibilityModifiersRequired, FallbackCodeStyleOptions.AccessibilityModifiersRequired); + public CodeStyleOption2 PreferReadonly => GetOption(CodeStyleOptions2.PreferReadonly, FallbackCodeStyleOptions.PreferReadonly); + public CodeStyleOption2 ArithmeticBinaryParentheses => GetOption(CodeStyleOptions2.ArithmeticBinaryParentheses, FallbackCodeStyleOptions.ArithmeticBinaryParentheses); + public CodeStyleOption2 OtherBinaryParentheses => GetOption(CodeStyleOptions2.OtherBinaryParentheses, FallbackCodeStyleOptions.OtherBinaryParentheses); + public CodeStyleOption2 RelationalBinaryParentheses => GetOption(CodeStyleOptions2.RelationalBinaryParentheses, FallbackCodeStyleOptions.RelationalBinaryParentheses); + public CodeStyleOption2 OtherParentheses => GetOption(CodeStyleOptions2.OtherParentheses, FallbackCodeStyleOptions.OtherParentheses); + public CodeStyleOption2 ForEachExplicitCastInSource => GetOption(CodeStyleOptions2.ForEachExplicitCastInSource, FallbackCodeStyleOptions.ForEachExplicitCastInSource); + public CodeStyleOption2 PreferNamespaceAndFolderMatchStructure => GetOption(CodeStyleOptions2.PreferNamespaceAndFolderMatchStructure, FallbackCodeStyleOptions.PreferNamespaceAndFolderMatchStructure); + public CodeStyleOption2 AllowMultipleBlankLines => GetOption(CodeStyleOptions2.AllowMultipleBlankLines, FallbackCodeStyleOptions.AllowMultipleBlankLines); + public CodeStyleOption2 AllowStatementImmediatelyAfterBlock => GetOption(CodeStyleOptions2.AllowStatementImmediatelyAfterBlock, FallbackCodeStyleOptions.AllowStatementImmediatelyAfterBlock); + public string RemoveUnnecessarySuppressionExclusions => GetOption(CodeStyleOptions2.RemoveUnnecessarySuppressionExclusions, FallbackCodeStyleOptions.RemoveUnnecessarySuppressionExclusions); + + public string FileHeaderTemplate => GetOption(CodeStyleOptions2.FileHeaderTemplate, defaultValue: string.Empty); // no fallback IDE option + + private TValue GetOption(Option2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private TValue GetOption(PerLanguageOption2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private IdeCodeStyleOptions.CommonOptions FallbackCodeStyleOptions + => _fallbackOptions.CodeStyleOptions?.Common ?? IdeCodeStyleOptions.CommonOptions.Default; + + private SimplifierOptions.CommonOptions FallbackSimplifierOptions + => _fallbackOptions.CleanupOptions?.SimplifierOptions.Common ?? SimplifierOptions.CommonOptions.Default; + + internal AnalyzerConfigOptions GetAnalyzerConfigOptions() + => _options; + + internal IdeAnalyzerOptions GetFallbackOptions() + => _fallbackOptions; +} + +internal static partial class AnalyzerOptionsProviders +{ + public static IdeAnalyzerOptions GetIdeOptions(this AnalyzerOptions options) +#if CODE_STYLE + => IdeAnalyzerOptions.CodeStyleDefault; +#else + => (options is WorkspaceAnalyzerOptions workspaceOptions) ? workspaceOptions.IdeOptions : IdeAnalyzerOptions.CodeStyleDefault; +#endif + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree) + => new(analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), analyzerOptions); + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this SemanticModelAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.SemanticModel.SyntaxTree), context.Options); + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this SyntaxNodeAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Node.SyntaxTree), context.Options); + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this SyntaxTreeAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Tree), context.Options); + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this OperationAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Operation.Syntax.SyntaxTree), context.Options); + + public static AnalyzerOptionsProvider GetAnalyzerOptions(this CodeBlockAnalysisContext context) + => new(context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.CodeBlock.SyntaxTree), context.Options); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SemanticModelAnalysisContext context) + => context.Options.GetIdeOptions(); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SyntaxNodeAnalysisContext context) + => context.Options.GetIdeOptions(); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this SyntaxTreeAnalysisContext context) + => context.Options.GetIdeOptions(); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this OperationAnalysisContext context) + => context.Options.GetIdeOptions(); + + public static IdeAnalyzerOptions GetIdeAnalyzerOptions(this CodeBlockAnalysisContext context) + => context.Options.GetIdeOptions(); +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/IdeAnalyzerOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/IdeAnalyzerOptions.cs new file mode 100644 index 0000000000000..78e371746d9e7 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/IdeAnalyzerOptions.cs @@ -0,0 +1,58 @@ +// 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.CodeCleanup; +using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.CodeAnalysis.Diagnostics; + +/// +/// IDE specific options available to analyzers in a specific project (language). +/// +[DataContract] +internal sealed record class IdeAnalyzerOptions +{ + public static readonly CodeStyleOption2 DefaultPreferSystemHashCode = new(value: true, notification: NotificationOption2.Suggestion); + + public static readonly IdeAnalyzerOptions CodeStyleDefault = new() + { + CrashOnAnalyzerException = false, + FadeOutUnusedImports = false, + FadeOutUnreachableCode = false + }; + + public static readonly IdeAnalyzerOptions CommonDefault = new(); + + [DataMember(Order = 0)] public bool CrashOnAnalyzerException { get; init; } = false; + [DataMember(Order = 1)] public bool FadeOutUnusedImports { get; init; } = true; + [DataMember(Order = 2)] public bool FadeOutUnreachableCode { get; init; } = true; + [DataMember(Order = 3)] public bool FadeOutComplexObjectInitialization { get; init; } = false; + [DataMember(Order = 4)] public bool FadeOutComplexCollectionInitialization { get; init; } = false; + [DataMember(Order = 5)] public bool ReportInvalidPlaceholdersInStringDotFormatCalls { get; init; } = true; + [DataMember(Order = 6)] public bool ReportInvalidRegexPatterns { get; init; } = true; + [DataMember(Order = 7)] public bool ReportInvalidJsonPatterns { get; init; } = true; + [DataMember(Order = 8)] public bool DetectAndOfferEditorFeaturesForProbableJsonStrings { get; init; } = true; + [DataMember(Order = 9)] public CodeStyleOption2 PreferSystemHashCode { get; init; } = DefaultPreferSystemHashCode; + + /// + /// Default values for , or null if not available (the project language does not support these options). + /// + [DataMember(Order = 10)] public CleanCodeGenerationOptions? CleanCodeGenerationOptions { get; init; } = null; + + /// + /// Default values for , or null if not available (the project language does not support these options). + /// + [DataMember(Order = 11)] public IdeCodeStyleOptions? CodeStyleOptions { get; init; } = null; + + public CodeCleanupOptions? CleanupOptions => CleanCodeGenerationOptions?.CleanupOptions; + public CodeGenerationOptions? GenerationOptions => CleanCodeGenerationOptions?.GenerationOptions; + +#if !CODE_STYLE + public static IdeAnalyzerOptions GetDefault(HostLanguageServices languageServices) + => new() { CleanCodeGenerationOptions = CodeGeneration.CleanCodeGenerationOptions.GetDefault(languageServices) }; +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/StructuredAnalyzerConfigOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/StructuredAnalyzerConfigOptions.cs index 041573f48731d..5a2ff851a55a6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/StructuredAnalyzerConfigOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Diagnostics/StructuredAnalyzerConfigOptions.cs @@ -40,6 +40,23 @@ public override NamingStylePreferences GetNamingStylePreferences() => _lazyNamingStylePreferences.Value; } + private sealed class EmptyImplementation : StructuredAnalyzerConfigOptions + { + public override NamingStylePreferences GetNamingStylePreferences() + => NamingStylePreferences.Empty; + + public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value) + { + value = null; + return false; + } + + public override IEnumerable Keys + => SpecializedCollections.EmptyEnumerable(); + } + + public static readonly StructuredAnalyzerConfigOptions Empty = new EmptyImplementation(); + public abstract NamingStylePreferences GetNamingStylePreferences(); public static StructuredAnalyzerConfigOptions Create(ImmutableDictionary options) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Editing/GenerationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Editing/GenerationOptions.cs index 8b45e837e7400..a06292979c330 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Editing/GenerationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Editing/GenerationOptions.cs @@ -3,21 +3,24 @@ // See the LICENSE file in the project root for more information. using System.Collections.Immutable; +using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.Editing { internal class GenerationOptions { - public static readonly PerLanguageOption2 PlaceSystemNamespaceFirst = new(nameof(GenerationOptions), - CodeStyleOptionGroups.Usings, - nameof(PlaceSystemNamespaceFirst), defaultValue: true, + public static readonly PerLanguageOption2 PlaceSystemNamespaceFirst = new( + "GenerationOptions", CodeStyleOptionGroups.Usings, "PlaceSystemNamespaceFirst", + AddImportPlacementOptions.Default.PlaceSystemNamespaceFirst, EditorConfigStorageLocation.ForBoolOption("dotnet_sort_system_directives_first"), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PlaceSystemNamespaceFirst")); public static readonly PerLanguageOption2 SeparateImportDirectiveGroups = new( - nameof(GenerationOptions), CodeStyleOptionGroups.Usings, nameof(SeparateImportDirectiveGroups), defaultValue: false, + "GenerationOptions", CodeStyleOptionGroups.Usings, "SeparateImportDirectiveGroups", + SyntaxFormattingOptions.CommonOptions.Default.SeparateImportDirectiveGroups, EditorConfigStorageLocation.ForBoolOption("dotnet_separate_import_directive_groups"), new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(SeparateImportDirectiveGroups)}")); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs index 9006335cb9933..251b80da7489c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/AnalyzerConfigOptionsExtensions.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Options; using Roslyn.Utilities; @@ -63,6 +64,9 @@ public static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyz public static T GetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, T defaultValue) => TryGetEditorConfigOption(analyzerConfigOptions, option, new Optional(defaultValue), out var value) ? value! : throw ExceptionUtilities.Unreachable; + public static T GetEditorConfigOptionValue(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, T defaultValue) + => TryGetEditorConfigOption(analyzerConfigOptions, option, new Optional?>(new CodeStyleOption2(defaultValue, NotificationOption2.None)), out var style) ? style!.Value : throw ExceptionUtilities.Unreachable; + private static bool TryGetEditorConfigOption(this AnalyzerConfigOptions analyzerConfigOptions, TOption option, Optional defaultValue, out T? value) { var hasEditorConfigStorage = false; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AutoFormattingOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AutoFormattingOptions.cs index 468ba10561469..34dcd332e1fb0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AutoFormattingOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/AutoFormattingOptions.cs @@ -10,14 +10,14 @@ namespace Microsoft.CodeAnalysis.Formatting; /// Automatic (on-type) formatting options. /// [DataContract] -internal readonly record struct AutoFormattingOptions( - [property: DataMember(Order = 0)] bool FormatOnReturn = true, - [property: DataMember(Order = 1)] bool FormatOnTyping = true, - [property: DataMember(Order = 2)] bool FormatOnSemicolon = true, - [property: DataMember(Order = 3)] bool FormatOnCloseBrace = true) +internal readonly record struct AutoFormattingOptions { + [DataMember(Order = 0)] public bool FormatOnReturn { get; init; } = true; + [DataMember(Order = 1)] public bool FormatOnTyping { get; init; } = true; + [DataMember(Order = 2)] public bool FormatOnSemicolon { get; init; } = true; + [DataMember(Order = 3)] public bool FormatOnCloseBrace { get; init; } = true; + public AutoFormattingOptions() - : this(FormatOnReturn: true) { } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/DocumentFormattingOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/DocumentFormattingOptions.cs new file mode 100644 index 0000000000000..fdacea2dac27e --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/DocumentFormattingOptions.cs @@ -0,0 +1,54 @@ +// 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.CodeCleanup; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.Formatting; + +[DataContract] +internal sealed record class DocumentFormattingOptions +{ + public static readonly DocumentFormattingOptions Default = new(); + + [DataMember] public string FileHeaderTemplate { get; init; } = ""; + [DataMember] public bool InsertFinalNewLine { get; init; } = false; +} + +internal interface DocumentFormattingOptionsProvider +#if !CODE_STYLE + : OptionsProvider +#endif +{ +} + +internal static class DocumentFormattingOptionsProviders +{ + public static DocumentFormattingOptions GetDocumentFormattingOptions(this AnalyzerConfigOptions options, DocumentFormattingOptions? fallbackOptions) + { + fallbackOptions ??= DocumentFormattingOptions.Default; + + return new() + { + FileHeaderTemplate = options.GetEditorConfigOption(CodeStyleOptions2.FileHeaderTemplate, fallbackOptions.FileHeaderTemplate), + InsertFinalNewLine = options.GetEditorConfigOption(FormattingOptions2.InsertFinalNewLine, fallbackOptions.InsertFinalNewLine) + }; + } + +#if !CODE_STYLE + public static async ValueTask GetDocumentFormattingOptionsAsync(this Document document, DocumentFormattingOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetDocumentFormattingOptions(fallbackOptions); + } + + public static async ValueTask GetDocumentFormattingOptionsAsync(this Document document, DocumentFormattingOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await document.GetDocumentFormattingOptionsAsync(await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/FormattingOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/FormattingOptions2.cs index 46209b412e7de..ea388ce1453e3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/FormattingOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/FormattingOptions2.cs @@ -74,7 +74,7 @@ public Provider() })); internal static Option2 InsertFinalNewLine = - new(FeatureName, FormattingOptionGroups.NewLine, nameof(InsertFinalNewLine), defaultValue: false, + new(FeatureName, FormattingOptionGroups.NewLine, nameof(InsertFinalNewLine), DocumentFormattingOptions.Default.InsertFinalNewLine, storageLocation: EditorConfigStorageLocation.ForBoolOption("insert_final_newline")); public static PerLanguageOption2 SmartIndent { get; } = diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs index e2520ad3fda2a..6301d47059ce8 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/ISyntaxFormatting.cs @@ -2,123 +2,20 @@ // 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.Collections.Immutable; -using System.Runtime.Serialization; using System.Threading; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Formatting.Rules; using Microsoft.CodeAnalysis.Text; -using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeCleanup; -using Roslyn.Utilities; -#if !CODE_STYLE -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; -#endif +namespace Microsoft.CodeAnalysis.Formatting; -namespace Microsoft.CodeAnalysis.Formatting +internal interface ISyntaxFormatting { - internal interface ISyntaxFormatting - { - SyntaxFormattingOptions DefaultOptions { get; } - SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options, SyntaxFormattingOptions? fallbackOptions); + SyntaxFormattingOptions DefaultOptions { get; } + SyntaxFormattingOptions GetFormattingOptions(AnalyzerConfigOptions options, SyntaxFormattingOptions? fallbackOptions); - ImmutableArray GetDefaultFormattingRules(); - IFormattingResult GetFormattingResult(SyntaxNode node, IEnumerable? spans, SyntaxFormattingOptions options, IEnumerable? rules, CancellationToken cancellationToken); - } - - [DataContract] - internal sealed record class LineFormattingOptions( - [property: DataMember(Order = 0)] bool UseTabs = false, - [property: DataMember(Order = 1)] int TabSize = 4, - [property: DataMember(Order = 2)] int IndentationSize = 4, - string? NewLine = null) - { - [property: DataMember(Order = 3)] - public string NewLine { get; init; } = NewLine ?? Environment.NewLine; - - public static readonly LineFormattingOptions Default = new(); - - public static LineFormattingOptions Create(AnalyzerConfigOptions options, LineFormattingOptions? fallbackOptions) - { - fallbackOptions ??= Default; - - return new( - UseTabs: options.GetEditorConfigOption(FormattingOptions2.UseTabs, fallbackOptions.UseTabs), - TabSize: options.GetEditorConfigOption(FormattingOptions2.TabSize, fallbackOptions.TabSize), - IndentationSize: options.GetEditorConfigOption(FormattingOptions2.IndentationSize, fallbackOptions.IndentationSize), - NewLine: options.GetEditorConfigOption(FormattingOptions2.NewLine, fallbackOptions.NewLine)); - } - -#if !CODE_STYLE - public static async Task FromDocumentAsync(Document document, LineFormattingOptions? fallbackOptions, CancellationToken cancellationToken) - { - var documentOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); - return Create(documentOptions, fallbackOptions); - } -#endif - } - - internal abstract class SyntaxFormattingOptions - { - [DataMember(Order = 0)] - public readonly LineFormattingOptions LineFormatting; - - [DataMember(Order = 1)] - public readonly bool SeparateImportDirectiveGroups; - - protected const int BaseMemberCount = 2; - - protected SyntaxFormattingOptions( - LineFormattingOptions? lineFormatting, - bool separateImportDirectiveGroups) - { - LineFormatting = lineFormatting ?? LineFormattingOptions.Default; - SeparateImportDirectiveGroups = separateImportDirectiveGroups; - } - - public abstract SyntaxFormattingOptions With(LineFormattingOptions lineFormatting); - - public bool UseTabs => LineFormatting.UseTabs; - public int TabSize => LineFormatting.TabSize; - public int IndentationSize => LineFormatting.IndentationSize; - public string NewLine => LineFormatting.NewLine; - -#if !CODE_STYLE - public static SyntaxFormattingOptions GetDefault(HostLanguageServices languageServices) - => languageServices.GetRequiredService().DefaultOptions; - - public static SyntaxFormattingOptions Create(OptionSet options, SyntaxFormattingOptions? fallbackOptions, HostLanguageServices languageServices) - { - var formattingService = languageServices.GetRequiredService(); - var configOptions = options.AsAnalyzerConfigOptions(languageServices.WorkspaceServices.GetRequiredService(), languageServices.Language); - return formattingService.GetFormattingOptions(configOptions, fallbackOptions); - } -#endif - } - - internal interface SyntaxFormattingOptionsProvider -#if !CODE_STYLE - : OptionsProvider -#endif - { - } - -#if !CODE_STYLE - internal static class SyntaxFormattingOptionsProviders - { - public static async ValueTask GetSyntaxFormattingOptionsAsync(this Document document, SyntaxFormattingOptions? fallbackOptions, CancellationToken cancellationToken) - { - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return SyntaxFormattingOptions.Create(documentOptions, fallbackOptions, document.Project.LanguageServices); - } - - public static async ValueTask GetSyntaxFormattingOptionsAsync(this Document document, SyntaxFormattingOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - => await GetSyntaxFormattingOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); - } -#endif + ImmutableArray GetDefaultFormattingRules(); + IFormattingResult GetFormattingResult(SyntaxNode node, IEnumerable? spans, SyntaxFormattingOptions options, IEnumerable? rules, CancellationToken cancellationToken); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/LineFormattingOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/LineFormattingOptions.cs new file mode 100644 index 0000000000000..dbcb673e4bf86 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/LineFormattingOptions.cs @@ -0,0 +1,57 @@ +// 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 System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.CodeAnalysis.Formatting; + +[DataContract] +internal sealed record class LineFormattingOptions +{ + public static readonly LineFormattingOptions Default = new(); + + [DataMember] public bool UseTabs { get; init; } = false; + [DataMember] public int TabSize { get; init; } = 4; + [DataMember] public int IndentationSize { get; init; } = 4; + [DataMember] public string NewLine { get; init; } = Environment.NewLine; +} + +internal interface LineFormattingOptionsProvider +#if !CODE_STYLE + : OptionsProvider +#endif +{ +} + +internal static partial class LineFormattingOptionsProviders +{ + public static LineFormattingOptions GetLineFormattingOptions(this AnalyzerConfigOptions options, LineFormattingOptions? fallbackOptions) + { + fallbackOptions ??= LineFormattingOptions.Default; + + return new() + { + UseTabs = options.GetEditorConfigOption(FormattingOptions2.UseTabs, fallbackOptions.UseTabs), + TabSize = options.GetEditorConfigOption(FormattingOptions2.TabSize, fallbackOptions.TabSize), + IndentationSize = options.GetEditorConfigOption(FormattingOptions2.IndentationSize, fallbackOptions.IndentationSize), + NewLine = options.GetEditorConfigOption(FormattingOptions2.NewLine, fallbackOptions.NewLine), + }; + } + +#if !CODE_STYLE + public static async ValueTask GetLineFormattingOptionsAsync(this Document document, LineFormattingOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetLineFormattingOptions(fallbackOptions); + } + + public static async ValueTask GetLineFormattingOptionsAsync(this Document document, LineFormattingOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await GetLineFormattingOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); +#endif +} + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/SyntaxFormattingOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/SyntaxFormattingOptions.cs new file mode 100644 index 0000000000000..55f9f8843438e --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/SyntaxFormattingOptions.cs @@ -0,0 +1,82 @@ +// 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.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Formatting; + +internal abstract class SyntaxFormattingOptions +{ + [DataContract] + internal sealed record class CommonOptions + { + public static readonly CommonOptions Default = new(); + + [DataMember] public LineFormattingOptions LineFormatting { get; init; } = LineFormattingOptions.Default; + [DataMember] public bool SeparateImportDirectiveGroups { get; init; } = false; + [DataMember] public AccessibilityModifiersRequired AccessibilityModifiersRequired { get; init; } = AccessibilityModifiersRequired.ForNonInterfaceMembers; + } + + [DataMember] + public CommonOptions Common { get; init; } = CommonOptions.Default; + + public abstract SyntaxFormattingOptions With(LineFormattingOptions lineFormatting); + + public bool UseTabs => Common.LineFormatting.UseTabs; + public int TabSize => Common.LineFormatting.TabSize; + public int IndentationSize => Common.LineFormatting.IndentationSize; + public LineFormattingOptions LineFormatting => Common.LineFormatting; + public string NewLine => Common.LineFormatting.NewLine; + public bool SeparateImportDirectiveGroups => Common.SeparateImportDirectiveGroups; + public AccessibilityModifiersRequired AccessibilityModifiersRequired => Common.AccessibilityModifiersRequired; + +#if !CODE_STYLE + public static SyntaxFormattingOptions GetDefault(HostLanguageServices languageServices) + => languageServices.GetRequiredService().DefaultOptions; +#endif +} + +internal interface SyntaxFormattingOptionsProvider : +#if !CODE_STYLE + OptionsProvider, +#endif + LineFormattingOptionsProvider +{ +} + +internal static partial class SyntaxFormattingOptionsProviders +{ + public static SyntaxFormattingOptions.CommonOptions GetCommonSyntaxFormattingOptions(this AnalyzerConfigOptions options, SyntaxFormattingOptions.CommonOptions? fallbackOptions) + { + fallbackOptions ??= SyntaxFormattingOptions.CommonOptions.Default; + + return new() + { + LineFormatting = options.GetLineFormattingOptions(fallbackOptions.LineFormatting), + SeparateImportDirectiveGroups = options.GetEditorConfigOption(GenerationOptions.SeparateImportDirectiveGroups, fallbackOptions.SeparateImportDirectiveGroups), + AccessibilityModifiersRequired = options.GetEditorConfigOptionValue(CodeStyleOptions2.AccessibilityModifiersRequired, fallbackOptions.AccessibilityModifiersRequired), + }; + } + +#if !CODE_STYLE + public static SyntaxFormattingOptions GetSyntaxFormattingOptions(this AnalyzerConfigOptions options, SyntaxFormattingOptions? fallbackOptions, HostLanguageServices languageServices) + => languageServices.GetRequiredService().GetFormattingOptions(options, fallbackOptions); + + public static async ValueTask GetSyntaxFormattingOptionsAsync(this Document document, SyntaxFormattingOptions? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetSyntaxFormattingOptions(fallbackOptions, document.Project.LanguageServices); + } + + public static async ValueTask GetSyntaxFormattingOptionsAsync(this Document document, SyntaxFormattingOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + => await GetSyntaxFormattingOptionsAsync(document, await ((OptionsProvider)fallbackOptionsProvider).GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); +#endif +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/IndentationOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/IndentationOptions.cs index aaa8807344e6d..a5f961998e56d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/IndentationOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Indentation/IndentationOptions.cs @@ -4,15 +4,22 @@ using System.Runtime.Serialization; using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; namespace Microsoft.CodeAnalysis.Indentation { [DataContract] internal readonly record struct IndentationOptions( - [property: DataMember(Order = 0)] SyntaxFormattingOptions FormattingOptions, - [property: DataMember(Order = 1)] AutoFormattingOptions AutoFormattingOptions, - [property: DataMember(Order = 2)] FormattingOptions2.IndentStyle IndentStyle = IndentationOptions.DefaultIndentStyle) + [property: DataMember(Order = 0)] SyntaxFormattingOptions FormattingOptions) { + [DataMember(Order = 1)] public AutoFormattingOptions AutoFormattingOptions { get; init; } = AutoFormattingOptions.Default; + [DataMember(Order = 2)] public FormattingOptions2.IndentStyle IndentStyle { get; init; } = DefaultIndentStyle; + public const FormattingOptions2.IndentStyle DefaultIndentStyle = FormattingOptions2.IndentStyle.Smart; + +#if !CODE_STYLE + public static IndentationOptions GetDefault(HostLanguageServices languageServices) + => new(SyntaxFormattingOptions.GetDefault(languageServices)); +#endif } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyleOptions.cs index b8dadb3fdb1ba..710c036f9a35f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/NamingStyles/NamingStyleOptions.cs @@ -2,11 +2,13 @@ // 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.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Options; -namespace Microsoft.CodeAnalysis.Simplification +namespace Microsoft.CodeAnalysis.CodeStyle { internal static class NamingStyleOptions { @@ -27,7 +29,32 @@ public static OptionKey2 GetNamingPreferencesOptionKey(string language) => new(NamingPreferences, language); } + internal interface NamingStylePreferencesProvider #if !CODE_STYLE - internal delegate NamingStylePreferences NamingStylePreferencesProvider(HostLanguageServices languageServices); + : OptionsProvider +#endif + { + } + +#if !CODE_STYLE + internal static class NamingStylePreferencesProviders + { + public static async ValueTask GetNamingStylePreferencesAsync(this Document document, NamingStylePreferences? fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetEditorConfigOption(NamingStyleOptions.NamingPreferences, fallbackOptions ?? NamingStylePreferences.Default); + } + + public static async ValueTask GetNamingStylePreferencesAsync(this Document document, NamingStylePreferencesProvider fallbackOptionsProvider, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + if (configOptions.TryGetEditorConfigOption(NamingStyleOptions.NamingPreferences, out var value)) + { + return value; + } + + return await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false); + } + } #endif } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs index 21c68b732d4b4..b76883c35bd18 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Simplification/SimplifierOptions.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Diagnostics; #if !CODE_STYLE using System.Threading; @@ -23,42 +24,28 @@ internal abstract class SimplifierOptions public static readonly CodeStyleOption2 DefaultQualifyAccess = CodeStyleOption2.Default; public static readonly CodeStyleOption2 DefaultPreferPredefinedTypeKeyword = new(value: true, notification: NotificationOption2.Silent); - [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) + [DataContract] + internal sealed record class CommonOptions { - QualifyFieldAccess = qualifyFieldAccess ?? DefaultQualifyAccess; - QualifyPropertyAccess = qualifyPropertyAccess ?? DefaultQualifyAccess; - QualifyMethodAccess = qualifyMethodAccess ?? DefaultQualifyAccess; - QualifyEventAccess = qualifyEventAccess ?? DefaultQualifyAccess; - PreferPredefinedTypeKeywordInMemberAccess = preferPredefinedTypeKeywordInMemberAccess ?? DefaultPreferPredefinedTypeKeyword; - PreferPredefinedTypeKeywordInDeclaration = preferPredefinedTypeKeywordInDeclaration ?? DefaultPreferPredefinedTypeKeyword; + public static readonly CommonOptions Default = new(); + + [DataMember] public CodeStyleOption2 QualifyFieldAccess { get; init; } = DefaultQualifyAccess; + [DataMember] public CodeStyleOption2 QualifyPropertyAccess { get; init; } = DefaultQualifyAccess; + [DataMember] public CodeStyleOption2 QualifyMethodAccess { get; init; } = DefaultQualifyAccess; + [DataMember] public CodeStyleOption2 QualifyEventAccess { get; init; } = DefaultQualifyAccess; + [DataMember] public CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess { get; init; } = DefaultPreferPredefinedTypeKeyword; + [DataMember] public CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration { get; init; } = DefaultPreferPredefinedTypeKeyword; } + public CommonOptions Common { get; init; } = CommonOptions.Default; + + public CodeStyleOption2 QualifyFieldAccess => Common.QualifyFieldAccess; + public CodeStyleOption2 QualifyPropertyAccess => Common.QualifyPropertyAccess; + public CodeStyleOption2 QualifyMethodAccess => Common.QualifyMethodAccess; + public CodeStyleOption2 QualifyEventAccess => Common.QualifyEventAccess; + public CodeStyleOption2 PreferPredefinedTypeKeywordInMemberAccess => Common.PreferPredefinedTypeKeywordInMemberAccess; + public CodeStyleOption2 PreferPredefinedTypeKeywordInDeclaration => Common.PreferPredefinedTypeKeywordInDeclaration; + public bool TryGetQualifyMemberAccessOption(SymbolKind symbolKind, [NotNullWhen(true)] out CodeStyleOption2? option) { option = symbolKind switch @@ -76,13 +63,6 @@ public bool TryGetQualifyMemberAccessOption(SymbolKind symbolKind, [NotNullWhen( #if !CODE_STYLE public static SimplifierOptions GetDefault(HostLanguageServices languageServices) => languageServices.GetRequiredService().DefaultOptions; - - 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); - } #endif } @@ -93,17 +73,34 @@ internal interface SimplifierOptionsProvider { } -#if !CODE_STYLE - internal static class SimplifierOptionsProviders + internal static partial class SimplifierOptionsProviders { + internal static SimplifierOptions.CommonOptions GetCommonSimplifierOptions(this AnalyzerConfigOptions options, SimplifierOptions.CommonOptions? fallbackOptions) + { + fallbackOptions ??= SimplifierOptions.CommonOptions.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), + }; + } + +#if !CODE_STYLE + public static SimplifierOptions GetSimplifierOptions(this AnalyzerConfigOptions options, SimplifierOptions? fallbackOptions, HostLanguageServices languageServices) + => languageServices.GetRequiredService().GetSimplifierOptions(options, fallbackOptions); + public static async ValueTask GetSimplifierOptionsAsync(this Document document, SimplifierOptions? fallbackOptions, CancellationToken cancellationToken) { - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - return SimplifierOptions.Create(documentOptions, document.Project.Solution.Workspace.Services, fallbackOptions, document.Project.Language); + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return configOptions.GetSimplifierOptions(fallbackOptions, document.Project.LanguageServices); } public static async ValueTask GetSimplifierOptionsAsync(this Document document, SimplifierOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) => await document.GetSimplifierOptionsAsync(await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); - } #endif + } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptions.vb new file mode 100644 index 0000000000000..97259147945ae --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeGeneration/VisualBasicCodeGenerationOptions.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 System.Runtime.CompilerServices +Imports System.Runtime.Serialization +Imports System.Threading +Imports Microsoft.CodeAnalysis.CodeGeneration +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Diagnostics +Imports Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +Imports Microsoft.CodeAnalysis.Editing +Imports Microsoft.CodeAnalysis.Options + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration + + Friend NotInheritable Class VisualBasicCodeGenerationOptions + Inherits CodeGenerationOptions + Implements IEquatable(Of VisualBasicCodeGenerationOptions) + + Public Shared ReadOnly [Default] As New VisualBasicCodeGenerationOptions() + + Public Overrides Function Equals(obj As Object) As Boolean + Return Equals(TryCast(obj, VisualBasicCodeGenerationOptions)) + End Function + + Public Overloads Function Equals(other As VisualBasicCodeGenerationOptions) As Boolean Implements IEquatable(Of VisualBasicCodeGenerationOptions).Equals + Return other IsNot Nothing AndAlso + Common.Equals(other.Common) + End Function + + Public Overrides Function GetHashCode() As Integer + Return Common.GetHashCode() + End Function + +#If Not CODE_STYLE Then + Public Overrides Function GetInfo(context As CodeGenerationContext, parseOptions As ParseOptions) As CodeGenerationContextInfo + Return New VisualBasicCodeGenerationContextInfo(context, Me) + End Function +#End If + End Class + + Friend Module VisualBasicCodeGenerationOptionsProviders + + Public Function GetVisualBasicCodeGenerationOptions(options As AnalyzerConfigOptions, fallbackOptions As VisualBasicCodeGenerationOptions) As VisualBasicCodeGenerationOptions + Return New VisualBasicCodeGenerationOptions() With + { + .Common = options.GetCommonCodeGenerationOptions(fallbackOptions.Common) + } + End Function + End Module +End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb index 4b53161c989df..c576db5cc30d2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb @@ -35,31 +35,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle Public Shared ReadOnly Property AllOptions As ImmutableArray(Of IOption2) - Public Shared ReadOnly PreferredModifierOrderDefault As ImmutableArray(Of SyntaxKind) = - ImmutableArray.Create( - SyntaxKind.PartialKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, - SyntaxKind.PublicKeyword, SyntaxKind.FriendKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.OverridableKeyword, - SyntaxKind.MustOverrideKeyword, SyntaxKind.OverloadsKeyword, SyntaxKind.OverridesKeyword, SyntaxKind.MustInheritKeyword, - SyntaxKind.NotInheritableKeyword, SyntaxKind.StaticKeyword, SyntaxKind.SharedKeyword, SyntaxKind.ShadowsKeyword, - SyntaxKind.ReadOnlyKeyword, SyntaxKind.WriteOnlyKeyword, SyntaxKind.DimKeyword, SyntaxKind.ConstKeyword, - SyntaxKind.WithEventsKeyword, SyntaxKind.WideningKeyword, SyntaxKind.NarrowingKeyword, SyntaxKind.CustomKeyword, - SyntaxKind.AsyncKeyword, SyntaxKind.IteratorKeyword) - Public Shared ReadOnly PreferredModifierOrder As Option2(Of CodeStyleOption2(Of String)) = CreateOption( VisualBasicCodeStyleOptionGroups.Modifier, NameOf(PreferredModifierOrder), - defaultValue:=New CodeStyleOption2(Of String)(String.Join(",", PreferredModifierOrderDefault.Select(AddressOf SyntaxFacts.GetText)), NotificationOption2.Silent), + VisualBasicIdeCodeStyleOptions.Default.PreferredModifierOrder, "visual_basic_preferred_modifier_order", $"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferredModifierOrder)}") Public Shared ReadOnly PreferIsNotExpression As Option2(Of CodeStyleOption2(Of Boolean)) = CreateOption( VisualBasicCodeStyleOptionGroups.ExpressionLevelPreferences, NameOf(PreferIsNotExpression), - defaultValue:=New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Suggestion), + VisualBasicIdeCodeStyleOptions.Default.PreferIsNotExpression, "visual_basic_style_prefer_isnot_expression", $"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferIsNotExpression)}") Public Shared ReadOnly PreferSimplifiedObjectCreation As Option2(Of CodeStyleOption2(Of Boolean)) = CreateOption( VisualBasicCodeStyleOptionGroups.ExpressionLevelPreferences, NameOf(PreferSimplifiedObjectCreation), - defaultValue:=New CodeStyleOption2(Of Boolean)(True, NotificationOption2.Suggestion), + VisualBasicIdeCodeStyleOptions.Default.PreferSimplifiedObjectCreation, "visual_basic_style_prefer_simplified_object_creation", $"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferSimplifiedObjectCreation)}") @@ -69,7 +59,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle feature:=NameOf(VisualBasicCodeStyleOptions), name:=NameOf(UnusedValueExpressionStatement), editorConfigName:="visual_basic_style_unused_value_expression_statement_preference", - defaultValue:=New CodeStyleOption2(Of UnusedValuePreference)(UnusedValuePreference.UnusedLocalVariable, NotificationOption2.Silent), + defaultValue:=VisualBasicIdeCodeStyleOptions.Default.UnusedValueExpressionStatement, optionsBuilder:=s_allOptionsBuilder) Public Shared ReadOnly UnusedValueAssignment As [Option2](Of CodeStyleOption2(Of UnusedValuePreference)) = @@ -78,7 +68,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle feature:=NameOf(VisualBasicCodeStyleOptions), name:=NameOf(UnusedValueAssignment), editorConfigName:="visual_basic_style_unused_value_assignment_preference", - defaultValue:=New CodeStyleOption2(Of UnusedValuePreference)(UnusedValuePreference.UnusedLocalVariable, NotificationOption2.Suggestion), + defaultValue:=VisualBasicIdeCodeStyleOptions.Default.UnusedValueAssignment, optionsBuilder:=s_allOptionsBuilder) End Class diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicIdeCodeStyleOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicIdeCodeStyleOptions.vb new file mode 100644 index 0000000000000..660ccf4449b83 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicIdeCodeStyleOptions.vb @@ -0,0 +1,84 @@ +' 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.Collections.Immutable +Imports System.Linq +Imports System.Runtime.Serialization +Imports Microsoft.CodeAnalysis.CodeStyle + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle + + Friend NotInheritable Class VisualBasicIdeCodeStyleOptions + Inherits IdeCodeStyleOptions + Implements IEquatable(Of VisualBasicIdeCodeStyleOptions) + + Private Shared ReadOnly s_unusedLocalVariableWithSilentEnforcement As New CodeStyleOption2(Of UnusedValuePreference)( + UnusedValuePreference.UnusedLocalVariable, NotificationOption2.Silent) + + Private Shared ReadOnly s_unusedLocalVariableWithSuggestionEnforcement As New CodeStyleOption2(Of UnusedValuePreference)( + UnusedValuePreference.UnusedLocalVariable, NotificationOption2.Suggestion) + + Public Shared ReadOnly DefaultPreferredModifierOrder As ImmutableArray(Of SyntaxKind) = + ImmutableArray.Create( + SyntaxKind.PartialKeyword, SyntaxKind.DefaultKeyword, SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, + SyntaxKind.PublicKeyword, SyntaxKind.FriendKeyword, SyntaxKind.NotOverridableKeyword, SyntaxKind.OverridableKeyword, + SyntaxKind.MustOverrideKeyword, SyntaxKind.OverloadsKeyword, SyntaxKind.OverridesKeyword, SyntaxKind.MustInheritKeyword, + SyntaxKind.NotInheritableKeyword, SyntaxKind.StaticKeyword, SyntaxKind.SharedKeyword, SyntaxKind.ShadowsKeyword, + SyntaxKind.ReadOnlyKeyword, SyntaxKind.WriteOnlyKeyword, SyntaxKind.DimKeyword, SyntaxKind.ConstKeyword, + SyntaxKind.WithEventsKeyword, SyntaxKind.WideningKeyword, SyntaxKind.NarrowingKeyword, SyntaxKind.CustomKeyword, + SyntaxKind.AsyncKeyword, SyntaxKind.IteratorKeyword) + + Private Shared ReadOnly s_defaultModifierOrder As New CodeStyleOption2(Of String)( + String.Join(",", DefaultPreferredModifierOrder.Select(AddressOf SyntaxFacts.GetText)), NotificationOption2.Silent) + + Public Shared ReadOnly [Default] As New VisualBasicIdeCodeStyleOptions(CommonOptions.Default) + + Public ReadOnly PreferredModifierOrder As CodeStyleOption2(Of String) + Public ReadOnly PreferIsNotExpression As CodeStyleOption2(Of Boolean) + Public ReadOnly PreferSimplifiedObjectCreation As CodeStyleOption2(Of Boolean) + Public ReadOnly UnusedValueExpressionStatement As CodeStyleOption2(Of UnusedValuePreference) + Public ReadOnly UnusedValueAssignment As CodeStyleOption2(Of UnusedValuePreference) + +#Disable Warning IDE1006 ' Parameter names must match field names for serialization + Public Sub New( + Common As CommonOptions, + Optional PreferredModifierOrder As CodeStyleOption2(Of String) = Nothing, + Optional PreferIsNotExpression As CodeStyleOption2(Of Boolean) = Nothing, + Optional PreferSimplifiedObjectCreation As CodeStyleOption2(Of Boolean) = Nothing, + Optional UnusedValueExpressionStatement As CodeStyleOption2(Of UnusedValuePreference) = Nothing, + Optional UnusedValueAssignment As CodeStyleOption2(Of UnusedValuePreference) = Nothing) +#Enable Warning + + Me.Common = Common + Me.PreferredModifierOrder = If(PreferredModifierOrder, s_defaultModifierOrder) + Me.PreferIsNotExpression = If(PreferIsNotExpression, s_trueWithSuggestionEnforcement) + Me.PreferSimplifiedObjectCreation = If(PreferSimplifiedObjectCreation, s_trueWithSuggestionEnforcement) + Me.UnusedValueExpressionStatement = If(UnusedValueExpressionStatement, s_unusedLocalVariableWithSilentEnforcement) + Me.UnusedValueAssignment = If(UnusedValueAssignment, s_unusedLocalVariableWithSuggestionEnforcement) + End Sub + + Public Overrides Function Equals(obj As Object) As Boolean + Return Equals(TryCast(obj, VisualBasicIdeCodeStyleOptions)) + End Function + + Public Overloads Function Equals(other As VisualBasicIdeCodeStyleOptions) As Boolean Implements IEquatable(Of VisualBasicIdeCodeStyleOptions).Equals + Return other IsNot Nothing AndAlso + Common.Equals(other.Common) AndAlso + PreferredModifierOrder.Equals(other.PreferredModifierOrder) AndAlso + PreferIsNotExpression.Equals(other.PreferIsNotExpression) AndAlso + PreferSimplifiedObjectCreation.Equals(other.PreferSimplifiedObjectCreation) AndAlso + UnusedValueExpressionStatement.Equals(other.UnusedValueExpressionStatement) AndAlso + UnusedValueAssignment.Equals(other.UnusedValueAssignment) + End Function + + Public Overrides Function GetHashCode() As Integer + Return Hash.Combine(Common, + Hash.Combine(PreferredModifierOrder, + Hash.Combine(PreferIsNotExpression, + Hash.Combine(PreferSimplifiedObjectCreation, + Hash.Combine(UnusedValueExpressionStatement, + Hash.Combine(UnusedValueAssignment, 0)))))) + End Function + End Class +End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplification.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplification.vb index b01f649bcddbb..a315f6336624f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplification.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplification.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification End Property Public Overrides Function GetSimplifierOptions(options As AnalyzerConfigOptions, fallbackOptions As SimplifierOptions) As SimplifierOptions - Return VisualBasicSimplifierOptions.Create(options, DirectCast(fallbackOptions, VisualBasicSimplifierOptions)) + Return options.GetVisualBasicSimplifierOptions(DirectCast(fallbackOptions, VisualBasicSimplifierOptions)) End Function End Class End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb index 006105df2bbb3..8eca73f4b86c5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Simplification/VisualBasicSimplifierOptions.vb @@ -6,41 +6,38 @@ Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.CodeStyle Imports System.Runtime.Serialization +Imports System.Runtime.CompilerServices Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification Friend NotInheritable Class VisualBasicSimplifierOptions Inherits SimplifierOptions - - Public Sub New( - Optional qualifyFieldAccess As CodeStyleOption2(Of Boolean) = Nothing, - Optional qualifyPropertyAccess As CodeStyleOption2(Of Boolean) = Nothing, - Optional qualifyMethodAccess As CodeStyleOption2(Of Boolean) = Nothing, - Optional qualifyEventAccess As CodeStyleOption2(Of Boolean) = Nothing, - Optional preferPredefinedTypeKeywordInMemberAccess As CodeStyleOption2(Of Boolean) = Nothing, - Optional preferPredefinedTypeKeywordInDeclaration As CodeStyleOption2(Of Boolean) = Nothing) - - MyBase.New( - qualifyFieldAccess, - qualifyPropertyAccess, - qualifyMethodAccess, - qualifyEventAccess, - preferPredefinedTypeKeywordInMemberAccess, - preferPredefinedTypeKeywordInDeclaration) - End Sub + Implements IEquatable(Of VisualBasicSimplifierOptions) Public Shared ReadOnly [Default] As New VisualBasicSimplifierOptions() - Friend Overloads Shared Function Create(options As AnalyzerConfigOptions, fallbackOptions As VisualBasicSimplifierOptions) As VisualBasicSimplifierOptions - fallbackOptions = If(fallbackOptions, VisualBasicSimplifierOptions.Default) + Public Overrides Function Equals(obj As Object) As Boolean + Return Equals(TryCast(obj, VisualBasicSimplifierOptions)) + End Function - 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)) + Public Overloads Function Equals(other As VisualBasicSimplifierOptions) As Boolean Implements IEquatable(Of VisualBasicSimplifierOptions).Equals + Return other IsNot Nothing AndAlso + Common.Equals(other.Common) + End Function + + Public Overrides Function GetHashCode() As Integer + Return Common.GetHashCode() End Function End Class + + Friend Module VisualBasicSimplifierOptionsProviders + + Friend Function GetVisualBasicSimplifierOptions(options As AnalyzerConfigOptions, fallbackOptions As VisualBasicSimplifierOptions) As VisualBasicSimplifierOptions + fallbackOptions = If(fallbackOptions, VisualBasicSimplifierOptions.Default) + Return New VisualBasicSimplifierOptions() With + { + .Common = options.GetCommonSimplifierOptions(fallbackOptions.Common) + } + End Function + End Module End Namespace diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems index 9092a0d6e9283..e1769402a9de0 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/VisualBasicCompilerExtensions.projitems @@ -9,7 +9,9 @@ Microsoft.CodeAnalysis.VisualBasic.Shared + + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CSharpWorkspaceExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CSharpWorkspaceExtensions.projitems index 1a74b3cb1ba81..9ad66776faa0c 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CSharpWorkspaceExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CSharpWorkspaceExtensions.projitems @@ -9,6 +9,7 @@ Microsoft.CodeAnalysis.CSharp.Shared + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeActions/CSharpCodeFixOptionsProvider.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeActions/CSharpCodeFixOptionsProvider.cs new file mode 100644 index 0000000000000..49bf8aa6196a6 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/CodeActions/CSharpCodeFixOptionsProvider.cs @@ -0,0 +1,129 @@ +// 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.AddImport; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.CodeStyle; +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.CSharp.Simplification; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; + +// to avoid excessive #ifdefs +#pragma warning disable CA1822 // Mark members as static +#pragma warning disable IDE0052 // Remove unread private members + +namespace Microsoft.CodeAnalysis.CodeActions; + +internal readonly struct CSharpCodeFixOptionsProvider +{ + /// + /// Document editorconfig options. + /// + private readonly AnalyzerConfigOptions _options; + + /// + /// C# language services. + /// + private readonly HostLanguageServices _languageServices; + + /// + /// Fallback options provider - default options provider in Code Style layer. + /// + private readonly CodeActionOptionsProvider _fallbackOptions; + + public CSharpCodeFixOptionsProvider(AnalyzerConfigOptions options, CodeActionOptionsProvider fallbackOptions, HostLanguageServices languageServices) + { + _options = options; + _fallbackOptions = fallbackOptions; + _languageServices = languageServices; + } + + // LineFormattingOptions + + public string NewLine => GetOption(FormattingOptions2.NewLine, FallbackLineFormattingOptions.NewLine); + + // SimplifierOptions + + public CodeStyleOption2 VarForBuiltInTypes => GetOption(CSharpCodeStyleOptions.VarForBuiltInTypes, FallbackSimplifierOptions.VarForBuiltInTypes); + public CodeStyleOption2 VarElsewhere => GetOption(CSharpCodeStyleOptions.VarElsewhere, FallbackSimplifierOptions.VarElsewhere); + + public SimplifierOptions GetSimplifierOptions() + => _options.GetCSharpSimplifierOptions(FallbackSimplifierOptions); + + // FormattingOptions + + public CodeStyleOption2 NamespaceDeclarations => GetOption(CSharpCodeStyleOptions.NamespaceDeclarations, FallbackSyntaxFormattingOptions.NamespaceDeclarations); + public CodeStyleOption2 PreferTopLevelStatements => GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements, FallbackSyntaxFormattingOptions.PreferTopLevelStatements); + + internal SyntaxFormattingOptions GetFormattingOptions() + => _options.GetCSharpSyntaxFormattingOptions(FallbackSyntaxFormattingOptions); + + // AddImportPlacementOptions + + public CodeStyleOption2 UsingDirectivePlacement => GetOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, FallbackAddImportPlacementOptions.UsingDirectivePlacement); + + // CodeStyleOptions + + public CodeStyleOption2 PreferredModifierOrder => GetOption(CSharpCodeStyleOptions.PreferredModifierOrder, FallbackCodeStyleOptions.PreferredModifierOrder); + public CodeStyleOption2 AccessibilityModifiersRequired => GetOption(CodeStyleOptions2.AccessibilityModifiersRequired, FallbackCodeStyleOptions.Common.AccessibilityModifiersRequired); + + private TValue GetOption(Option2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private TValue GetOption(PerLanguageOption2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private CSharpIdeCodeStyleOptions FallbackCodeStyleOptions +#if CODE_STYLE + => CSharpIdeCodeStyleOptions.Default; +#else + => (CSharpIdeCodeStyleOptions)_fallbackOptions.GetOptions(_languageServices).CodeStyleOptions; +#endif + + private CSharpSimplifierOptions FallbackSimplifierOptions +#if CODE_STYLE + => CSharpSimplifierOptions.Default; +#else + => (CSharpSimplifierOptions)_fallbackOptions.GetOptions(_languageServices).CleanupOptions.SimplifierOptions; +#endif + + private CSharpSyntaxFormattingOptions FallbackSyntaxFormattingOptions +#if CODE_STYLE + => CSharpSyntaxFormattingOptions.Default; +#else + => (CSharpSyntaxFormattingOptions)_fallbackOptions.GetOptions(_languageServices).CleanupOptions.FormattingOptions; +#endif + + private LineFormattingOptions FallbackLineFormattingOptions +#if CODE_STYLE + => LineFormattingOptions.Default; +#else + => _fallbackOptions.GetOptions(_languageServices).CleanupOptions.FormattingOptions.LineFormatting; +#endif + + private AddImportPlacementOptions FallbackAddImportPlacementOptions +#if CODE_STYLE + => AddImportPlacementOptions.Default; +#else + => _fallbackOptions.GetOptions(_languageServices).CleanupOptions.AddImportOptions; +#endif +} + +internal static class CSharpCodeFixOptionsProviders +{ + public static async ValueTask GetCSharpCodeFixOptionsProviderAsync(this Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return new CSharpCodeFixOptionsProvider(configOptions, fallbackOptions, document.Project.GetExtendedLanguageServices()); + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpAddImportsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpAddImportsService.cs index 9da783cd3668b..2b6c36017e27b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpAddImportsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpAddImportsService.cs @@ -17,12 +17,6 @@ using Microsoft.CodeAnalysis.Host.Mef; using Roslyn.Utilities; -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#else -using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet; -#endif - namespace Microsoft.CodeAnalysis.CSharp.AddImport { [ExportLanguageService(typeof(IAddImportsService), LanguageNames.CSharp), Shared] @@ -35,11 +29,8 @@ public CSharpAddImportsService() { } - public override bool PlaceImportsInsideNamespaces(AnalyzerConfigOptions configOptions, bool fallbackValue) - { - var placementStyle = configOptions.GetEditorConfigOption?>(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, defaultValue: null); - return (placementStyle != null) ? (placementStyle.Value == AddImportPlacement.InsideNamespace) : fallbackValue; - } + public override CodeStyleOption2 GetUsingDirectivePlacementCodeStyleOption(AnalyzerConfigOptions configOptions, CodeStyleOption2 fallbackValue) + => configOptions.GetEditorConfigOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, fallbackValue); // C# doesn't have global imports. protected override ImmutableArray GetGlobalImports(Compilation compilation, SyntaxGenerator generator) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/AddImport/AddImportPlacementOptionsProviders.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/AddImport/AddImportPlacementOptionsProviders.cs new file mode 100644 index 0000000000000..5c34f9769790d --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/AddImport/AddImportPlacementOptionsProviders.cs @@ -0,0 +1,22 @@ +// 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.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.AddImport; + +internal static partial class AddImportPlacementOptionsProviders +{ + internal static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, IAddImportsService addImportsService, AddImportPlacementOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + { +#if CODE_STYLE + var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + return addImportsService.GetAddImportOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), allowInHiddenRegions: false, fallbackOptions: null); +#else + return await document.GetAddImportPlacementOptionsAsync(fallbackOptionsProvider, cancellationToken).ConfigureAwait(false); +#endif + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeActions/CodeFixOptionsProvider.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeActions/CodeFixOptionsProvider.cs new file mode 100644 index 0000000000000..e4f711085f26b --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeActions/CodeFixOptionsProvider.cs @@ -0,0 +1,93 @@ +// 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.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.Extensions; + +// to avoid excessive #ifdefs +#pragma warning disable CA1822 // Mark members as static +#pragma warning disable IDE0052 // Remove unread private members + +namespace Microsoft.CodeAnalysis.CodeActions; + +internal readonly struct CodeFixOptionsProvider +{ + /// + /// Document editorconfig options. + /// + private readonly AnalyzerConfigOptions _options; + + /// + /// C# language services. + /// + private readonly HostLanguageServices _languageServices; + + /// + /// Fallback options provider - default options provider in Code Style layer. + /// + private readonly CodeActionOptionsProvider _fallbackOptions; + + public CodeFixOptionsProvider(AnalyzerConfigOptions options, CodeActionOptionsProvider fallbackOptions, HostLanguageServices languageServices) + { + _options = options; + _fallbackOptions = fallbackOptions; + _languageServices = languageServices; + } + + // LineFormattingOptions + + public string NewLine => GetOption(FormattingOptions2.NewLine, FallbackLineFormattingOptions.NewLine); + + public LineFormattingOptions GetLineFormattingOptions() + => _options.GetLineFormattingOptions(FallbackLineFormattingOptions); + + // SyntaxFormattingOptions + + public SyntaxFormattingOptions GetFormattingOptions(ISyntaxFormatting formatting) + => formatting.GetFormattingOptions(_options, FallbackSyntaxFormattingOptions); + + public AccessibilityModifiersRequired AccessibilityModifiersRequired => _options.GetEditorConfigOptionValue(CodeStyleOptions2.AccessibilityModifiersRequired, FallbackCommonSyntaxFormattingOptions.AccessibilityModifiersRequired); + + private TValue GetOption(PerLanguageOption2 option, TValue defaultValue) + => _options.GetEditorConfigOption(option, defaultValue); + + private LineFormattingOptions FallbackLineFormattingOptions +#if CODE_STYLE + => LineFormattingOptions.Default; +#else + => _fallbackOptions.GetOptions(_languageServices).CleanupOptions.FormattingOptions.LineFormatting; +#endif + + private SyntaxFormattingOptions? FallbackSyntaxFormattingOptions +#if CODE_STYLE + => null; +#else + => _fallbackOptions.GetOptions(_languageServices).CleanupOptions.FormattingOptions; +#endif + + private SyntaxFormattingOptions.CommonOptions FallbackCommonSyntaxFormattingOptions +#if CODE_STYLE + => SyntaxFormattingOptions.CommonOptions.Default; +#else + => _fallbackOptions.GetOptions(_languageServices).CleanupOptions.FormattingOptions.Common; +#endif +} + +internal static class CodeFixOptionsProviders +{ + public static async ValueTask GetCodeFixOptionsAsync(this Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) + { + var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false); + return new CodeFixOptionsProvider(configOptions, fallbackOptions, document.Project.GetExtendedLanguageServices()); + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs index 16efce7825c15..0128c581ee9f6 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/CodeActionOptions.cs @@ -11,11 +11,13 @@ using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeFixesAndRefactorings; using Microsoft.CodeAnalysis.CodeGeneration; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.ExtractMethod; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.ImplementType; +using Microsoft.CodeAnalysis.OrganizeImports; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.SymbolSearch; @@ -27,19 +29,9 @@ namespace Microsoft.CodeAnalysis.CodeActions /// Options available to code fixes that are supplied by the IDE (i.e. not stored in editorconfig). /// [DataContract] - internal record class CodeActionOptions + internal sealed record class CodeActionOptions { - public static readonly CodeActionOptions Default = new(); - public static readonly CodeActionOptionsProvider DefaultProvider = Default.CreateProvider(); - -#if !CODE_STYLE - [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 CodeCleanupOptions? CleanupOptions { get; init; } - [DataMember(Order = 4)] public CodeGenerationOptions? CodeGenerationOptions { get; init; } - [DataMember(Order = 5)] public bool HideAdvancedMembers { get; init; } - [DataMember(Order = 7)] public int WrappingColumn { get; init; } + public static readonly CodeActionOptionsProvider DefaultProvider = new DelegatingCodeActionOptionsProvider(GetDefault); /// /// Default value of 120 was picked based on the amount of code in a github.com diff at 1080p. @@ -53,30 +45,38 @@ internal record class CodeActionOptions /// public const int DefaultWrappingColumn = 120; + public const int DefaultConditionalExpressionWrappingLength = 120; + +#if !CODE_STYLE + [DataMember(Order = 0)] public CodeCleanupOptions CleanupOptions { get; init; } + [DataMember(Order = 1)] public CodeGenerationOptions CodeGenerationOptions { get; init; } + [DataMember(Order = 2)] public IdeCodeStyleOptions CodeStyleOptions { get; init; } + [DataMember(Order = 3)] public SymbolSearchOptions SearchOptions { get; init; } = SymbolSearchOptions.Default; + [DataMember(Order = 4)] public ImplementTypeOptions ImplementTypeOptions { get; init; } = ImplementTypeOptions.Default; + [DataMember(Order = 5)] public ExtractMethodOptions ExtractMethodOptions { get; init; } = ExtractMethodOptions.Default; + [DataMember(Order = 6)] public bool HideAdvancedMembers { get; init; } = false; + [DataMember(Order = 7)] public int WrappingColumn { get; init; } = DefaultWrappingColumn; + [DataMember(Order = 8)] public int ConditionalExpressionWrappingLength { get; init; } = DefaultConditionalExpressionWrappingLength; + public CodeActionOptions( - SymbolSearchOptions? SearchOptions = null, - ImplementTypeOptions? ImplementTypeOptions = null, - ExtractMethodOptions? ExtractMethodOptions = null, - CodeCleanupOptions? CleanupOptions = null, - CodeGenerationOptions? CodeGenerationOptions = null, - bool HideAdvancedMembers = false, - int WrappingColumn = DefaultWrappingColumn) + CodeCleanupOptions cleanupOptions, + CodeGenerationOptions codeGenerationOptions, + IdeCodeStyleOptions codeStyleOptions) { - this.SearchOptions = SearchOptions ?? SymbolSearchOptions.Default; - this.ImplementTypeOptions = ImplementTypeOptions ?? ImplementType.ImplementTypeOptions.Default; - this.ExtractMethodOptions = ExtractMethodOptions ?? ExtractMethod.ExtractMethodOptions.Default; - this.CleanupOptions = CleanupOptions; - this.CodeGenerationOptions = CodeGenerationOptions; - this.HideAdvancedMembers = HideAdvancedMembers; - this.WrappingColumn = WrappingColumn; + CleanupOptions = cleanupOptions; + CodeGenerationOptions = codeGenerationOptions; + CodeStyleOptions = codeStyleOptions; } - public CodeActionOptions() - : this(SearchOptions: null) - { - } + public static CodeActionOptions GetDefault(HostLanguageServices languageServices) + => new( + CodeCleanupOptions.GetDefault(languageServices), + CodeGenerationOptions.GetDefault(languageServices), + IdeCodeStyleOptions.GetDefault(languageServices)); +#else + public static CodeActionOptions GetDefault(HostLanguageServices languageServices) + => new(); #endif - public CodeActionOptionsProvider CreateProvider() => new DelegatingCodeActionOptionsProvider(_ => this); } @@ -87,6 +87,7 @@ internal interface CodeActionOptionsProvider : CodeGenerationOptionsProvider, CleanCodeGenerationOptionsProvider, CodeAndImportGenerationOptionsProvider, + OrganizeImportsOptionsProvider, #endif SyntaxFormattingOptionsProvider, SimplifierOptionsProvider, @@ -100,35 +101,43 @@ internal abstract class AbstractCodeActionOptionsProvider : CodeActionOptionsPro public abstract CodeActionOptions GetOptions(HostLanguageServices languageService); #if !CODE_STYLE + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.FormattingOptions.LineFormatting); + + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.DocumentFormattingOptions); + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions?.FormattingOptions ?? SyntaxFormattingOptions.GetDefault(languageServices)); + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.FormattingOptions); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions?.SimplifierOptions ?? SimplifierOptions.GetDefault(languageServices)); + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.SimplifierOptions); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions?.AddImportOptions ?? AddImportPlacementOptions.Default); + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.AddImportOptions); + + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions.GetOrganizeImportsOptions()); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions ?? CodeCleanupOptions.GetDefault(languageServices)); + => ValueTaskFactory.FromResult(GetOptions(languageServices).CleanupOptions); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) - => ValueTaskFactory.FromResult(GetOptions(languageServices).CodeGenerationOptions ?? CodeGenerationOptions.GetDefault(languageServices)); + => ValueTaskFactory.FromResult(GetOptions(languageServices).CodeGenerationOptions); + + ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) + => ValueTaskFactory.FromResult(GetOptions(languageServices).CodeGenerationOptions.NamingStyle); ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) { var codeActionOptions = GetOptions(languageServices); - return ValueTaskFactory.FromResult(new CleanCodeGenerationOptions( - codeActionOptions.CodeGenerationOptions ?? CodeGenerationOptions.GetDefault(languageServices), - codeActionOptions.CleanupOptions ?? CodeCleanupOptions.GetDefault(languageServices))); + return ValueTaskFactory.FromResult(new CleanCodeGenerationOptions(codeActionOptions.CodeGenerationOptions, codeActionOptions.CleanupOptions)); } ValueTask OptionsProvider.GetOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken) { var codeActionOptions = GetOptions(languageServices); - return ValueTaskFactory.FromResult(new CodeAndImportGenerationOptions( - codeActionOptions.CodeGenerationOptions ?? CodeGenerationOptions.GetDefault(languageServices), - codeActionOptions.CleanupOptions?.AddImportOptions ?? AddImportPlacementOptions.Default)); + return ValueTaskFactory.FromResult(new CodeAndImportGenerationOptions(codeActionOptions.CodeGenerationOptions, codeActionOptions.CleanupOptions.AddImportOptions)); } #endif } @@ -161,39 +170,6 @@ internal static CodeActionOptionsProvider GetOptionsProvider(this IFixAllContext => context.State.CodeActionOptionsProvider; #endif - internal static async ValueTask GetSyntaxFormattingOptionsAsync(this Document document, ISyntaxFormatting syntaxFormatting, SyntaxFormattingOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - { -#if CODE_STYLE - var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - return syntaxFormatting.GetFormattingOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), fallbackOptions: null); -#else - var fallbackFormattingOptions = await fallbackOptionsProvider.GetOptionsAsync(document.Project.GetExtendedLanguageServices(), cancellationToken).ConfigureAwait(false); - return await document.GetSyntaxFormattingOptionsAsync(fallbackFormattingOptions, cancellationToken).ConfigureAwait(false); -#endif - } - - internal static async ValueTask GetSimplifierOptionsAsync(this Document document, ISimplification simplification, SimplifierOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - { -#if CODE_STYLE - var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - return simplification.GetSimplifierOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), fallbackOptions: null); -#else - var fallbackFormattingOptions = await fallbackOptionsProvider.GetOptionsAsync(document.Project.GetExtendedLanguageServices(), cancellationToken).ConfigureAwait(false); - return await document.GetSimplifierOptionsAsync(fallbackFormattingOptions, cancellationToken).ConfigureAwait(false); -#endif - } - - internal static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, IAddImportsService addImportsService, CodeActionOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - { -#if CODE_STYLE - var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var configOptions = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); - return AddImportPlacementOptions.Create(configOptions, addImportsService, allowInHiddenRegions: false, fallbackOptions: AddImportPlacementOptions.Default); -#else - return await document.GetAddImportPlacementOptionsAsync(fallbackOptionsProvider, cancellationToken).ConfigureAwait(false); -#endif - } - #if !CODE_STYLE public static ImplementTypeGenerationOptions GetImplementTypeGenerationOptions(this CodeActionOptionsProvider provider, HostLanguageServices languageServices) => new(provider.GetOptions(languageServices).ImplementTypeOptions, provider); @@ -201,11 +177,12 @@ public static ImplementTypeGenerationOptions GetImplementTypeGenerationOptions(t public static ExtractMethodGenerationOptions GetExtractMethodGenerationOptions(this CodeActionOptionsProvider provider, HostLanguageServices languageServices) { var codeActionOptions = provider.GetOptions(languageServices); - return new( - codeActionOptions.ExtractMethodOptions, - codeActionOptions.CodeGenerationOptions ?? CodeGenerationOptions.GetDefault(languageServices), - codeActionOptions.CleanupOptions?.AddImportOptions ?? AddImportPlacementOptions.Default, - new NamingStylePreferencesProvider(languageServices => NamingStylePreferences.Default)); // TODO: https://github.com/dotnet/roslyn/issues/60849 + return new(codeActionOptions.CodeGenerationOptions) + { + ExtractOptions = codeActionOptions.ExtractMethodOptions, + AddImportOptions = codeActionOptions.CleanupOptions.AddImportOptions, + LineFormattingOptions = codeActionOptions.CleanupOptions.FormattingOptions.LineFormatting + }; } #endif } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs index 9300644015cfc..0baf131821f8a 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/CodeFixes/SyntaxEditorBasedCodeFixProvider.cs @@ -87,6 +87,12 @@ internal static async Task FixAllWithEditorAsync( return document.WithSyntaxRoot(newRoot); } + /// + /// Fixes all in the specified . + /// The fixes are applied to the 's syntax tree via . + /// The implementation may query options of any document in the 's solution + /// with providing default values for options not specified explicitly in the corresponding editorconfig. + /// protected abstract Task FixAllAsync( Document document, ImmutableArray diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Diagnostics/AnalyzerOptionsProviders.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Diagnostics/AnalyzerOptionsProviders.cs new file mode 100644 index 0000000000000..e271583f87f08 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Diagnostics/AnalyzerOptionsProviders.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; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.Diagnostics; + +internal static partial class AnalyzerOptionsProviders +{ + public static async ValueTask GetAnalyzerOptionsProviderAsync(this Document document, CancellationToken cancellationToken) + { + var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var analyzerOptions = document.Project.AnalyzerOptions; + var configOptions = analyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); + + return new AnalyzerOptionsProvider(configOptions, analyzerOptions); + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs index baa5040bc0af0..bf325c73f6ae1 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/DocumentExtensions.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.GeneratedCodeRecognition; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.SemanticModelReuse; @@ -203,5 +204,13 @@ public static IEnumerable GetLinkedDocuments(this Document document) yield return solution.GetRequiredDocument(linkedDocumentId); } } + +#if CODE_STYLE + public static async ValueTask GetAnalyzerConfigOptionsAsync(this Document document, CancellationToken cancellationToken) + { + var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + return document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree); + } +#endif } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/AbstractAddImportsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/AbstractAddImportsService.cs index 4d62724bf7e51..da6c2d2cb72c9 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/AbstractAddImportsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/AbstractAddImportsService.cs @@ -7,16 +7,11 @@ using System.Collections.Immutable; using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Shared.Extensions; -#if CODE_STYLE -using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; -#else -using OptionSet = Microsoft.CodeAnalysis.Options.OptionSet; -#endif - namespace Microsoft.CodeAnalysis.AddImport { internal abstract class AbstractAddImportsService @@ -36,7 +31,19 @@ protected AbstractAddImportsService() protected abstract SyntaxList GetExterns(SyntaxNode node); protected abstract bool IsStaticUsing(TUsingOrAliasSyntax usingOrAlias); - public abstract bool PlaceImportsInsideNamespaces(AnalyzerConfigOptions configOptions, bool fallbackValue); + public AddImportPlacementOptions GetAddImportOptions(AnalyzerConfigOptions configOptions, bool allowInHiddenRegions, AddImportPlacementOptions? fallbackOptions) + { + fallbackOptions ??= AddImportPlacementOptions.Default; + + return new() + { + PlaceSystemNamespaceFirst = configOptions.GetEditorConfigOption(GenerationOptions.PlaceSystemNamespaceFirst, fallbackOptions.PlaceSystemNamespaceFirst), + UsingDirectivePlacement = GetUsingDirectivePlacementCodeStyleOption(configOptions, fallbackOptions.UsingDirectivePlacement), + AllowInHiddenRegions = allowInHiddenRegions + }; + } + + public abstract CodeStyleOption2 GetUsingDirectivePlacementCodeStyleOption(AnalyzerConfigOptions configOptions, CodeStyleOption2 fallbackValue); private bool IsSimpleUsing(TUsingOrAliasSyntax usingOrAlias) => !IsAlias(usingOrAlias) && !IsStaticUsing(usingOrAlias); private bool IsAlias(TUsingOrAliasSyntax usingOrAlias) => GetAlias(usingOrAlias) != null; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs index cf4298047260d..9b9acf9ca9edd 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/AddImports/IAddImportsService.cs @@ -16,64 +16,9 @@ namespace Microsoft.CodeAnalysis.AddImport { - [DataContract] - internal record struct AddImportPlacementOptions( - [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(); - - internal static AddImportPlacementOptions Create(AnalyzerConfigOptions configOptions, IAddImportsService addImportsService, bool allowInHiddenRegions, AddImportPlacementOptions? fallbackOptions) - { - fallbackOptions ??= Default; - - return new( - PlaceSystemNamespaceFirst: configOptions.GetEditorConfigOption(GenerationOptions.PlaceSystemNamespaceFirst, fallbackOptions.Value.PlaceSystemNamespaceFirst), - PlaceImportsInsideNamespaces: addImportsService.PlaceImportsInsideNamespaces(configOptions, fallbackOptions.Value.PlaceImportsInsideNamespaces), - AllowInHiddenRegions: allowInHiddenRegions); - } - } - - internal interface AddImportPlacementOptionsProvider -#if !CODE_STYLE - : OptionsProvider -#endif - { - } - -#if !CODE_STYLE - internal static class AddImportPlacementOptionsProviders - { - public static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, AddImportPlacementOptions? fallbackOptions, CancellationToken cancellationToken) - { - var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var services = document.Project.Solution.Workspace.Services; - var configOptions = documentOptions.AsAnalyzerConfigOptions(services.GetRequiredService(), document.Project.Language); - var addImportsService = document.GetRequiredLanguageService(); - - // Normally we don't allow generation into a hidden region in the file. However, if we have a - // modern span mapper at our disposal, we do allow it as that host span mapper can handle mapping - // our edit to their domain appropriate. - var spanMapper = document.Services.GetService(); - var allowInHiddenRegions = spanMapper != null && spanMapper.SupportsMappingImportDirectives; - - return AddImportPlacementOptions.Create(configOptions, addImportsService, allowInHiddenRegions, fallbackOptions); - } - - public static async ValueTask GetAddImportPlacementOptionsAsync(this Document document, AddImportPlacementOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) - => await GetAddImportPlacementOptionsAsync(document, await fallbackOptionsProvider.GetOptionsAsync(document.Project.LanguageServices, cancellationToken).ConfigureAwait(false), cancellationToken).ConfigureAwait(false); - } -#endif - internal interface IAddImportsService : ILanguageService { - bool PlaceImportsInsideNamespaces(AnalyzerConfigOptions configOptions, bool fallbackValue); + AddImportPlacementOptions GetAddImportOptions(AnalyzerConfigOptions configOptions, bool allowInHiddenRegions, AddImportPlacementOptions? fallbackOptions); /// /// Returns true if the tree already has an existing import syntactically equivalent to diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplifierOptionsProviders.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplifierOptionsProviders.cs new file mode 100644 index 0000000000000..b379467fd3da2 --- /dev/null +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Simplification/SimplifierOptionsProviders.cs @@ -0,0 +1,25 @@ +// 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.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.Simplification; + +internal static partial class SimplifierOptionsProviders +{ + internal static async ValueTask GetSimplifierOptionsAsync(this Document document, ISimplification simplification, SimplifierOptionsProvider fallbackOptionsProvider, CancellationToken cancellationToken) + { +#if CODE_STYLE + var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + return simplification.GetSimplifierOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree), fallbackOptions: null); +#else + return await document.GetSimplifierOptionsAsync(fallbackOptionsProvider, cancellationToken).ConfigureAwait(false); +#endif + } +} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems index 34b6882099b55..e126f5c79a839 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/WorkspaceExtensions.projitems @@ -10,10 +10,11 @@ + + - - + @@ -65,6 +66,7 @@ + diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicAddImportsService.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicAddImportsService.vb index bfe9370721f1f..0a1abe6113fb5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicAddImportsService.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicAddImportsService.vb @@ -6,6 +6,7 @@ Imports System.Collections.Immutable Imports System.Composition Imports System.Threading Imports Microsoft.CodeAnalysis.AddImport +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Host.Mef @@ -13,12 +14,6 @@ Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities -#If CODE_STYLE Then -Imports OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions -#Else -Imports OptionSet = Microsoft.CodeAnalysis.Options.OptionSet -#End If - Namespace Microsoft.CodeAnalysis.VisualBasic.AddImports Friend Class VisualBasicAddImportsService @@ -64,10 +59,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImports FirstOrDefault()?.Alias End Function - Public Overrides Function PlaceImportsInsideNamespaces(configOptions As AnalyzerConfigOptions, fallbackValue As Boolean) As Boolean + Public Overrides Function GetUsingDirectivePlacementCodeStyleOption(configOptions As AnalyzerConfigOptions, fallbackValue As CodeStyleOption2(Of AddImportPlacement)) As CodeStyleOption2(Of AddImportPlacement) ' Visual Basic doesn't support imports inside namespaces - Return False + Return fallbackValue End Function + Protected Overrides Function IsStaticUsing(usingOrAlias As ImportsStatementSyntax) As Boolean ' Visual Basic doesn't support static imports Return False diff --git a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb index f75b77fcdfc13..d166f5debcd06 100644 --- a/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb +++ b/src/Workspaces/VisualBasic/Portable/CodeCleanup/Providers/NormalizeModifiersOrOperatorsCodeCleanupProvider.vb @@ -52,7 +52,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers ' this order will be used when the rewriter re-order modifiers ' PERF: Using UShort instead of SyntaxKind as the element type so that the compiler can use array literal initialization Private Shared ReadOnly s_modifierKindsInOrder As SyntaxKind() = - VisualBasicCodeStyleOptions.PreferredModifierOrderDefault.ToArray() + VisualBasicIdeCodeStyleOptions.DefaultPreferredModifierOrder.ToArray() Private Shared ReadOnly s_removeDimKeywordSet As HashSet(Of SyntaxKind) = New HashSet(Of SyntaxKind)(SyntaxFacts.EqualityComparer) From { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.PublicKeyword, SyntaxKind.FriendKeyword, @@ -504,7 +504,7 @@ Namespace Microsoft.CodeAnalysis.CodeCleanup.Providers Return newPreviousToken End If - throw ExceptionUtilities.UnexpectedValue(o) + Throw ExceptionUtilities.UnexpectedValue(o) End Function) End Function diff --git a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationOptions.vb b/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationOptions.vb deleted file mode 100644 index 8dbf15c47e5a1..0000000000000 --- a/src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicCodeGenerationOptions.vb +++ /dev/null @@ -1,26 +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 System.Runtime.Serialization -Imports System.Threading -Imports Microsoft.CodeAnalysis.CodeGeneration -Imports Microsoft.CodeAnalysis.Editing -Imports Microsoft.CodeAnalysis.Options - -Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration - - Friend NotInheritable Class VisualBasicCodeGenerationOptions - Inherits CodeGenerationOptions - - Public Sub New() - MyBase.New() - End Sub - - Public Shared ReadOnly [Default] As New VisualBasicCodeGenerationOptions() - - Public Overrides Function GetInfo(context As CodeGenerationContext, parseOptions As ParseOptions) As CodeGenerationContextInfo - Return New VisualBasicCodeGenerationContextInfo(context, Me) - End Function - End Class -End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/CodeStyle/VisualBasicCodeStyleService.vb b/src/Workspaces/VisualBasic/Portable/CodeStyle/VisualBasicCodeStyleService.vb new file mode 100644 index 0000000000000..27edfd0bd80d3 --- /dev/null +++ b/src/Workspaces/VisualBasic/Portable/CodeStyle/VisualBasicCodeStyleService.vb @@ -0,0 +1,26 @@ +' 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 +Imports System.Composition +Imports Microsoft.CodeAnalysis.CodeStyle +Imports Microsoft.CodeAnalysis.Host.Mef + +Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle + + Friend NotInheritable Class CSharpCodeStyleService + Implements ICodeStyleService + + + + Public Sub New() + End Sub + + Public ReadOnly Property DefaultOptions As IdeCodeStyleOptions Implements ICodeStyleService.DefaultOptions + Get + Return VisualBasicIdeCodeStyleOptions.Default + End Get + End Property + End Class +End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingOptions.vb b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingOptions.vb index e58db1080e911..4d02c0881513c 100644 --- a/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingOptions.vb +++ b/src/Workspaces/VisualBasic/Portable/Formatting/VisualBasicSyntaxFormattingOptions.vb @@ -3,6 +3,7 @@ ' See the LICENSE file in the project root for more information. Imports System.Runtime.Serialization +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Formatting @@ -11,30 +12,42 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting Friend NotInheritable Class VisualBasicSyntaxFormattingOptions Inherits SyntaxFormattingOptions + Implements IEquatable(Of VisualBasicSyntaxFormattingOptions) - Public Sub New(Optional lineFormatting As LineFormattingOptions = Nothing, - Optional separateImportDirectiveGroups As Boolean = False) - - MyBase.New(lineFormatting, - separateImportDirectiveGroups) - End Sub - - Public Shared ReadOnly [Default] As New VisualBasicSyntaxFormattingOptions( - lineFormatting:=LineFormattingOptions.Default, - separateImportDirectiveGroups:=GenerationOptions.SeparateImportDirectiveGroups.DefaultValue) + Public Shared ReadOnly [Default] As New VisualBasicSyntaxFormattingOptions() Public Shared Shadows Function Create(options As AnalyzerConfigOptions, fallbackOptions As VisualBasicSyntaxFormattingOptions) As VisualBasicSyntaxFormattingOptions fallbackOptions = If(fallbackOptions, [Default]) - Return New VisualBasicSyntaxFormattingOptions( - lineFormatting:=LineFormattingOptions.Create(options, fallbackOptions.LineFormatting), - separateImportDirectiveGroups:=options.GetEditorConfigOption(GenerationOptions.SeparateImportDirectiveGroups, fallbackOptions.SeparateImportDirectiveGroups)) + Return New VisualBasicSyntaxFormattingOptions() With + { + .Common = options.GetCommonSyntaxFormattingOptions(fallbackOptions.Common) + } End Function Public Overrides Function [With](lineFormatting As LineFormattingOptions) As SyntaxFormattingOptions - Return New VisualBasicSyntaxFormattingOptions( - lineFormatting:=lineFormatting, - separateImportDirectiveGroups:=SeparateImportDirectiveGroups) + Return New VisualBasicSyntaxFormattingOptions() With + { + .Common = New CommonOptions() With + { + .LineFormatting = lineFormatting, + .SeparateImportDirectiveGroups = SeparateImportDirectiveGroups, + .AccessibilityModifiersRequired = AccessibilityModifiersRequired + } + } + End Function + + Public Overrides Function Equals(obj As Object) As Boolean + Return Equals(TryCast(obj, VisualBasicSyntaxFormattingOptions)) + End Function + + Public Overloads Function Equals(other As VisualBasicSyntaxFormattingOptions) As Boolean Implements IEquatable(Of VisualBasicSyntaxFormattingOptions).Equals + Return other IsNot Nothing AndAlso + Common.Equals(other.Common) + End Function + + Public Overrides Function GetHashCode() As Integer + Return Common.GetHashCode() End Function End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj b/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj index 74e8a9851cabc..bf9b842f6423e 100644 --- a/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj +++ b/src/Workspaces/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Workspaces.vbproj @@ -48,6 +48,7 @@ + diff --git a/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb b/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb index f46b72f4f0845..3d380875d19ef 100644 --- a/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Simplification/VisualBasicSimplificationService.vb @@ -44,7 +44,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Simplification End Property Public Overrides Function GetSimplifierOptions(options As AnalyzerConfigOptions, fallbackOptions As SimplifierOptions) As SimplifierOptions - Return VisualBasicSimplifierOptions.Create(options, DirectCast(fallbackOptions, VisualBasicSimplifierOptions)) + Return options.GetVisualBasicSimplifierOptions(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 diff --git a/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb b/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb index b14c8a58a0041..c09bca0514443 100644 --- a/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb +++ b/src/Workspaces/VisualBasicTest/CodeGeneration/AddImportsTests.vb @@ -4,6 +4,7 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.AddImport +Imports Microsoft.CodeAnalysis.CodeStyle Imports Microsoft.CodeAnalysis.Editing Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Simplification @@ -83,10 +84,10 @@ End NameSpace" Dim doc = Await GetDocument(initialText, useSymbolAnnotations, globalImports) - Dim addImportOptions = New AddImportPlacementOptions( - PlaceSystemNamespaceFirst:=placeSystemNamespaceFirst, - PlaceImportsInsideNamespaces:=False, - AllowInHiddenRegions:=False) + Dim addImportOptions = New AddImportPlacementOptions() With + { + .PlaceSystemNamespaceFirst = placeSystemNamespaceFirst + } Dim formattingOptions = VisualBasicSyntaxFormattingOptions.Default Dim simplifierOptions = VisualBasicSimplifierOptions.Default diff --git a/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb b/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb index a46782cc3da43..433fc4c242e3d 100644 --- a/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb +++ b/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb @@ -4733,10 +4733,16 @@ End Class ' replace all EOL trivia with elastic markers to force the formatter to add EOL back tree = tree.ReplaceTrivia(tree.DescendantTrivia().Where(Function(tr) tr.IsKind(SyntaxKind.EndOfLineTrivia)), Function(o, r) SyntaxFactory.ElasticMarker) - Dim options = SyntaxFormattingOptions.Create( - workspace.Options.WithChangedOption(FormattingOptions.NewLine, LanguageNames.VisualBasic, vbLf), - fallbackOptions:=Nothing, - workspace.Services.GetLanguageServices(tree.Language)) + Dim options = New VisualBasicSyntaxFormattingOptions() With + { + .Common = New SyntaxFormattingOptions.CommonOptions() With + { + .LineFormatting = New LineFormattingOptions() With + { + .NewLine = vbLf + } + } + } Dim formatted = Formatter.Format(tree, workspace.Services, options, CancellationToken.None) Dim actual = formatted.ToFullString() diff --git a/src/Workspaces/VisualBasicTest/OrganizeImports/OrganizeImportsTests.vb b/src/Workspaces/VisualBasicTest/OrganizeImports/OrganizeImportsTests.vb index 7c95c91de8acc..be7f54db55752 100644 --- a/src/Workspaces/VisualBasicTest/OrganizeImports/OrganizeImportsTests.vb +++ b/src/Workspaces/VisualBasicTest/OrganizeImports/OrganizeImportsTests.vb @@ -12,6 +12,7 @@ Imports Microsoft.CodeAnalysis.Options Imports Roslyn.Test.Utilities Imports Xunit Imports Microsoft.CodeAnalysis.[Shared].Extensions +Imports Microsoft.CodeAnalysis.OrganizeImports Namespace Microsoft.CodeAnalysis.VisualBasic.Workspaces.UnitTests.OrganizeImports <[UseExportProvider]> @@ -24,16 +25,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Workspaces.UnitTests.OrganizeImport Dim project = workspace.CurrentSolution.AddProject("Project", "Project.dll", LanguageNames.VisualBasic) Dim document = project.AddDocument("Document", SourceText.From(initial.Value.ReplaceLineEndings(If(endOfLine, Environment.NewLine)))) - Dim options = workspace.Options.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst) - options = options.WithChangedOption(New OptionKey(GenerationOptions.SeparateImportDirectiveGroups, document.Project.Language), separateImportGroups) + Dim service = document.GetRequiredLanguageService(Of IOrganizeImportsService) + Dim options = New OrganizeImportsOptions() With + { + .PlaceSystemNamespaceFirst = placeSystemNamespaceFirst, + .SeparateImportDirectiveGroups = separateImportGroups, + .NewLine = If(endOfLine, OrganizeImportsOptions.Default.NewLine) + } - If endOfLine IsNot Nothing Then - options = options.WithChangedOption(New OptionKey(FormattingOptions2.NewLine, document.Project.Language), endOfLine) - End If - - document = document.WithSolutionOptions(options) - - Dim newRoot = Await (Await Formatter.OrganizeImportsAsync(document, CancellationToken.None)).GetSyntaxRootAsync() + Dim newDocument = Await service.OrganizeImportsAsync(document, options, CancellationToken.None) + Dim newRoot = Await newDocument.GetSyntaxRootAsync() Assert.Equal(final.Value.ReplaceLineEndings(If(endOfLine, Environment.NewLine)), newRoot.ToFullString()) End Using End Function @@ -45,14 +46,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Workspaces.UnitTests.OrganizeImport Dim project = workspace.CurrentSolution.AddProject("Project", "Project.dll", LanguageNames.VisualBasic) Dim document = project.AddDocument("Document", SourceText.From(initial.Value.NormalizeLineEndings())) - Dim options = workspace.Options.WithChangedOption(New OptionKey(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language), placeSystemNamespaceFirst) - document = document.WithSolutionOptions(options) + Dim formattingOptions = New VisualBasicSyntaxFormattingOptions() With + { + .Common = New SyntaxFormattingOptions.CommonOptions() With {.SeparateImportDirectiveGroups = separateImportGroups} + } - Dim formattingOptions = New VisualBasicSyntaxFormattingOptions( - LineFormattingOptions.Default, - separateImportDirectiveGroups:=separateImportGroups) + Dim organizeOptions = New OrganizeImportsOptions() With + { + .PlaceSystemNamespaceFirst = placeSystemNamespaceFirst, + .SeparateImportDirectiveGroups = separateImportGroups + } - Dim organizedDocument = Await Formatter.OrganizeImportsAsync(document, CancellationToken.None) + Dim service = document.GetRequiredLanguageService(Of IOrganizeImportsService) + Dim organizedDocument = Await service.OrganizeImportsAsync(document, organizeOptions, CancellationToken.None) Dim formattedDocument = Await Formatter.FormatAsync(organizedDocument, formattingOptions, CancellationToken.None) Dim newRoot = Await formattedDocument.GetSyntaxRootAsync()