From babde044ee8372f738a0e777b6c9ef642ca0cf5d Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Tue, 13 Oct 2020 17:06:25 -0700 Subject: [PATCH] Make the ':severity' suffix in editorconfig code style value optional Contributes towards #44201 - All code style option editorconfig entries can now be specified as `option_name = option_value` without `:severity` suffix - `Configure code style option` code fix will no longer add add `:severity` suffix for new entries. For fix that changes existing entries which have `:severity` suffix, it will retain the existing severity suffix. Note that `Configure severity` code fix was already switched to use `dotnet_diagnostic.RuleID.severity` entries for code style diagnostics in https://github.com/dotnet/roslyn/pull/47052. Once we have the editorconfig UX to change code style option value and severity, we can safely deprecate the `:severity` suffix in option value syntax. All our UI gestures will use the `option_name = option_value` syntax for code style value changes and `dotnet_diagnostic.RuleID.severity = severity` syntax for severity changes and users do not need to deal with these manually editing or understanind these different syntaxes or mapping rule IDs to option names and vice versa for code styles. --- ...ooleanCodeStyleOptionConfigurationTests.cs | 88 ++++- .../EnumCodeStyleOptionConfigurationTests.cs | 62 ++- ...ltipleCodeStyleOptionConfigurationTests.cs | 102 ++++- .../IDEDiagnosticIDConfigurationTests.cs | 357 +++++++++--------- ...ooleanCodeStyleOptionConfigurationTests.vb | 73 +++- .../Configuration/ConfigurationUpdater.cs | 148 ++++---- ...ConfigureCodeStyleOptionCodeFixProvider.cs | 1 - .../CSharpEditorConfigCodeStyleParserTests.cs | 24 +- .../EditorConfigCodeStyleParserTests.cs | 4 +- .../CodeStyle/CSharpCodeStyleOptions.cs | 264 ++++++------- .../CSharpCodeStyleOptions_Parsing.cs | 81 ++-- .../Core/CodeStyle/CodeStyleHelpers.cs | 75 ++-- .../Core/CodeStyle/CodeStyleOptions2.cs | 189 ++++------ ...OperatorPlacementWhenWrappingPreference.cs | 3 +- .../Core/Extensions/StringExtensions.cs | 26 ++ .../EditorConfigStorageLocation.cs | 28 +- .../CodeStyle/VisualBasicCodeStyleOptions.vb | 16 +- 17 files changed, 878 insertions(+), 663 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.cs index 656c2bd72004d..948d63158e06c 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.cs @@ -98,7 +98,7 @@ public Customer() [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true "; @@ -247,7 +247,7 @@ public Customer() [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true "; @@ -359,6 +359,7 @@ public Customer() [*.cs] dotnet_style_object_initializerr = false:suggestion +dotnet_style_object_initializerr = false "; @@ -392,9 +393,10 @@ public Customer() [*.cs] dotnet_style_object_initializerr = false:suggestion +dotnet_style_object_initializerr = false # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true "; @@ -471,7 +473,7 @@ public Customer() [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false "; @@ -551,6 +553,78 @@ public Customer() await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] + public async Task ConfigureEditorconfig_RuleExists_False_NoSeveritySuffix() + { + var input = @" + + + +class Program1 +{ + static void Main() + { + // dotnet_style_object_initializer = true + var obj = new Customer() { _age = 21 }; + + // dotnet_style_object_initializer = false + Customer obj2 = [|new Customer()|]; + obj2._age = 21; + } + + internal class Customer + { + public int _age; + + public Customer() + { + + } + } +} + + [*.cs] +dotnet_style_object_initializer = true + + +"; + + var expected = @" + + + +class Program1 +{ + static void Main() + { + // dotnet_style_object_initializer = true + var obj = new Customer() { _age = 21 }; + + // dotnet_style_object_initializer = false + Customer obj2 = new Customer(); + obj2._age = 21; + } + + internal class Customer + { + public int _age; + + public Customer() + { + + } + } +} + + [*.cs] +dotnet_style_object_initializer = false + + +"; + + await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); + } + [ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] public async Task ConfigureEditorconfig_RuleExists_DotnetDiagnosticEntry() { @@ -618,7 +692,7 @@ public Customer() dotnet_diagnostic.IDE0017.severity = warning # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:warning +dotnet_style_object_initializer = false "; @@ -769,7 +843,7 @@ public Customer() [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false "; @@ -916,7 +990,7 @@ public Customer() dotnet_style_object_initializerr = false:suggestion # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false "; diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/EnumCodeStyleOptionConfigurationTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/EnumCodeStyleOptionConfigurationTests.cs index 75d432841f250..9849dd0b0310d 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/EnumCodeStyleOptionConfigurationTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/EnumCodeStyleOptionConfigurationTests.cs @@ -87,7 +87,7 @@ static void Main() [*.cs] # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = unused_local_variable:suggestion +csharp_style_unused_value_assignment_preference = unused_local_variable "; @@ -186,7 +186,7 @@ static void Main() dotnet_diagnostic.IDE0059.severity = warning ; Comment2 # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = unused_local_variable:warning +csharp_style_unused_value_assignment_preference = unused_local_variable "; @@ -289,7 +289,7 @@ static void Main() [*.cs] # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = unused_local_variable:suggestion +csharp_style_unused_value_assignment_preference = unused_local_variable "; @@ -388,7 +388,7 @@ static void Main() csharp_style_unused_value_assignment_preferencer = discard_variable:suggestion # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = unused_local_variable:suggestion +csharp_style_unused_value_assignment_preference = unused_local_variable "; @@ -441,7 +441,7 @@ static void Main() [*.cs] # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable "; @@ -497,6 +497,54 @@ static void Main() await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] + public async Task ConfigureEditorconfig_RuleExists_DiscardVariable_WithoutSeveritySuffix() + { + var input = @" + + + +class Program1 +{ + static void Main() + { + // csharp_style_unused_value_assignment_preference = { discard_variable, unused_local_variable } + [|var obj = new Program1();|] + obj = null; + var obj2 = obj; + } +} + + [*.cs] +csharp_style_unused_value_assignment_preference = unused_local_variable + + +"; + + var expected = @" + + + +class Program1 +{ + static void Main() + { + // csharp_style_unused_value_assignment_preference = { discard_variable, unused_local_variable } + var obj = new Program1(); + obj = null; + var obj2 = obj; + } +} + + [*.cs] +csharp_style_unused_value_assignment_preference = discard_variable + + +"; + + await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); + } + [ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] public async Task ConfigureEditorconfig_InvalidHeader_DiscardVariable() { @@ -542,7 +590,7 @@ static void Main() [*.cs] # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable "; @@ -641,7 +689,7 @@ static void Main() csharp_style_unused_value_assignment_preference_error = discard_variable:suggestion # IDE0059: Unnecessary assignment of a value -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable "; diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/MultipleCodeStyleOptionConfigurationTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/MultipleCodeStyleOptionConfigurationTests.cs index f2cadd5524a2f..3eacb198960cf 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/MultipleCodeStyleOptionConfigurationTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/Configuration/ConfigureCodeStyle/MultipleCodeStyleOptionConfigurationTests.cs @@ -88,7 +88,7 @@ static void Main() [*.cs] # IDE0008: Use explicit type -csharp_style_var_elsewhere = true:silent +csharp_style_var_elsewhere = true "; @@ -142,6 +142,52 @@ static void Main() await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] + public async Task ConfigureEditorconfig_RuleExists_True_WithoutSeveritySuffix() + { + var input = @" + + + +class Program1 +{ + static void Main() + { + // { csharp_style_var_when_type_is_apparent, csharp_style_var_for_built_in_types, csharp_style_var_elsewhere } + [|var obj = new Program1();|] + } +} + + [*.cs] # Comment1 +csharp_style_var_elsewhere = false ; Comment2 +csharp_style_var_for_built_in_types = true ; Comment3 + + +"; + + var expected = @" + + + +class Program1 +{ + static void Main() + { + // { csharp_style_var_when_type_is_apparent, csharp_style_var_for_built_in_types, csharp_style_var_elsewhere } + var obj = new Program1(); + } +} + + [*.cs] # Comment1 +csharp_style_var_elsewhere = true ; Comment2 +csharp_style_var_for_built_in_types = true ; Comment3 + + +"; + + await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); + } + [ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] public async Task ConfigureEditorconfig_InvalidHeader_True() { @@ -183,7 +229,7 @@ static void Main() [*.cs] # IDE0008: Use explicit type -csharp_style_var_elsewhere = true:silent +csharp_style_var_elsewhere = true "; @@ -274,7 +320,7 @@ static void Main() csharp_style_var_when_type_is_apparent_error = false:suggestion # IDE0008: Use explicit type -csharp_style_var_elsewhere = true:silent +csharp_style_var_elsewhere = true "; @@ -325,7 +371,7 @@ static void Main() [*.cs] # IDE0008: Use explicit type -csharp_style_var_for_built_in_types = false:silent +csharp_style_var_for_built_in_types = false "; @@ -377,6 +423,50 @@ static void Main() await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] + public async Task ConfigureEditorconfig_RuleExists_False_WithoutSeveritySuffix() + { + var input = @" + + + +class Program1 +{ + static void Main() + { + // { csharp_style_var_when_type_is_apparent, csharp_style_var_for_built_in_types, csharp_style_var_elsewhere } + [|var obj = new Program1();|] + } +} + + [*.cs] +csharp_style_var_for_built_in_types = true + + +"; + + var expected = @" + + + +class Program1 +{ + static void Main() + { + // { csharp_style_var_when_type_is_apparent, csharp_style_var_for_built_in_types, csharp_style_var_elsewhere } + var obj = new Program1(); + } +} + + [*.cs] +csharp_style_var_for_built_in_types = false + + +"; + + await TestInRegularAndScriptAsync(input, expected, CodeActionIndex); + } + [ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsConfiguration)] public async Task ConfigureEditorconfig_InvalidHeader_False() { @@ -418,7 +508,7 @@ static void Main() [*.cs] # IDE0008: Use explicit type -csharp_style_var_for_built_in_types = false:silent +csharp_style_var_for_built_in_types = false "; @@ -509,7 +599,7 @@ static void Main() csharp_style_var_for_built_in_types_error = false:silent # IDE0008: Use explicit type -csharp_style_var_for_built_in_types = false:silent +csharp_style_var_for_built_in_types = false "; diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs index f576bf5786ceb..f33ad82df5312 100644 --- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs @@ -24,10 +24,6 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics.ConfigureSeverityL [UseExportProvider] public class IDEDiagnosticIDConfigurationTests { - // Regular expression for .editorconfig code style option entry. - // For example: "dotnet_style_object_initializer = true:suggestion # Optional comment" - private static readonly Regex s_optionBasedEntryPattern = new Regex(@"([\w ]+)=([\w ]+):[ ]*([\w]+)([ ]*[;#].*)?"); - private static ImmutableArray<(string diagnosticId, ImmutableHashSet codeStyleOptions)> GetIDEDiagnosticIdsAndOptions( string languageName) { @@ -97,20 +93,7 @@ private static void VerifyConfigureSeverityCore(string expected, string language var baseline = new StringBuilder(); foreach (var (diagnosticId, options) in diagnosticIdAndOptions) { - var optionOpt = options.Count == 1 ? options.Single() : null; - var editorConfigLocation = optionOpt?.StorageLocations.OfType().FirstOrDefault(); - var editorConfigString = $"dotnet_diagnostic.{diagnosticId}.severity = %value%"; - if (editorConfigLocation != null) - { - var optionKey = new OptionKey(optionOpt, optionOpt.IsPerLanguage ? languageName : null); - var value = optionSet.GetOption(optionKey); - var codeStyleEditorConfigString = editorConfigLocation.GetEditorConfigString(value, optionSet); - if (s_optionBasedEntryPattern.IsMatch(codeStyleEditorConfigString)) - { - editorConfigString = codeStyleEditorConfigString; - } - } // Verify we have an entry for diagnosticId var diagnosticIdString = $"# {diagnosticId}"; @@ -196,64 +179,64 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0010.severity = %value% # IDE0011 -csharp_prefer_braces = true:silent +dotnet_diagnostic.IDE0011.severity = %value% # IDE0016 -csharp_style_throw_expression = true:suggestion +dotnet_diagnostic.IDE0016.severity = %value% # IDE0017 -dotnet_style_object_initializer = true:suggestion +dotnet_diagnostic.IDE0017.severity = %value% # IDE0018 -csharp_style_inlined_variable_declaration = true:suggestion +dotnet_diagnostic.IDE0018.severity = %value% # IDE0019 -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +dotnet_diagnostic.IDE0019.severity = %value% # IDE0020 -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +dotnet_diagnostic.IDE0020.severity = %value% # IDE0021 -csharp_style_expression_bodied_constructors = false:silent +dotnet_diagnostic.IDE0021.severity = %value% # IDE0022 -csharp_style_expression_bodied_methods = false:silent +dotnet_diagnostic.IDE0022.severity = %value% # IDE0023 -csharp_style_expression_bodied_operators = false:silent +dotnet_diagnostic.IDE0023.severity = %value% # IDE0024 -csharp_style_expression_bodied_operators = false:silent +dotnet_diagnostic.IDE0024.severity = %value% # IDE0025 -csharp_style_expression_bodied_properties = true:silent +dotnet_diagnostic.IDE0025.severity = %value% # IDE0026 -csharp_style_expression_bodied_indexers = true:silent +dotnet_diagnostic.IDE0026.severity = %value% # IDE0027 -csharp_style_expression_bodied_accessors = true:silent +dotnet_diagnostic.IDE0027.severity = %value% # IDE0028 -dotnet_style_collection_initializer = true:suggestion +dotnet_diagnostic.IDE0028.severity = %value% # IDE0029 -dotnet_style_coalesce_expression = true:suggestion +dotnet_diagnostic.IDE0029.severity = %value% # IDE0030 -dotnet_style_coalesce_expression = true:suggestion +dotnet_diagnostic.IDE0030.severity = %value% # IDE0031 -dotnet_style_null_propagation = true:suggestion +dotnet_diagnostic.IDE0031.severity = %value% # IDE0032 -dotnet_style_prefer_auto_properties = true:silent +dotnet_diagnostic.IDE0032.severity = %value% # IDE0033 -dotnet_style_explicit_tuple_names = true:suggestion +dotnet_diagnostic.IDE0033.severity = %value% # IDE0034 -csharp_prefer_simple_default_expression = true:suggestion +dotnet_diagnostic.IDE0034.severity = %value% # IDE0035 dotnet_diagnostic.IDE0035.severity = %value% @@ -268,28 +251,28 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0038.severity = %value% # IDE0039 -csharp_style_pattern_local_over_anonymous_function = true:suggestion +dotnet_diagnostic.IDE0039.severity = %value% # IDE0040 -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_diagnostic.IDE0040.severity = %value% # IDE0041 -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_diagnostic.IDE0041.severity = %value% # IDE0042 -csharp_style_deconstructed_variable_declaration = true:suggestion +dotnet_diagnostic.IDE0042.severity = %value% # IDE0043 dotnet_diagnostic.IDE0043.severity = %value% # IDE0044 -dotnet_style_readonly_field = true:suggestion +dotnet_diagnostic.IDE0044.severity = %value% # IDE0045 -dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_diagnostic.IDE0045.severity = %value% # IDE0046 -dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_diagnostic.IDE0046.severity = %value% # IDE0047 dotnet_diagnostic.IDE0047.severity = %value% @@ -310,46 +293,46 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0052.severity = %value% # IDE0053 -csharp_style_expression_bodied_lambdas = true:silent +dotnet_diagnostic.IDE0053.severity = %value% # IDE0054 -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_diagnostic.IDE0054.severity = %value% # IDE0055 dotnet_diagnostic.IDE0055.severity = %value% # IDE0056 -csharp_style_prefer_index_operator = true:suggestion +dotnet_diagnostic.IDE0056.severity = %value% # IDE0057 -csharp_style_prefer_range_operator = true:suggestion +dotnet_diagnostic.IDE0057.severity = %value% # IDE0058 -csharp_style_unused_value_expression_statement_preference = discard_variable:silent +dotnet_diagnostic.IDE0058.severity = %value% # IDE0059 -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +dotnet_diagnostic.IDE0059.severity = %value% # IDE0060 -dotnet_code_quality_unused_parameters = all:suggestion +dotnet_diagnostic.IDE0060.severity = %value% # IDE0061 -csharp_style_expression_bodied_local_functions = false:silent +dotnet_diagnostic.IDE0061.severity = %value% # IDE0062 -csharp_prefer_static_local_function = true:suggestion +dotnet_diagnostic.IDE0062.severity = %value% # IDE0063 -csharp_prefer_simple_using_statement = true:suggestion +dotnet_diagnostic.IDE0063.severity = %value% # IDE0064 dotnet_diagnostic.IDE0064.severity = %value% # IDE0065 -csharp_using_directive_placement = outside_namespace:silent +dotnet_diagnostic.IDE0065.severity = %value% # IDE0066 -csharp_style_prefer_switch_expression = true:suggestion +dotnet_diagnostic.IDE0066.severity = %value% # IDE0067 dotnet_diagnostic.IDE0067.severity = %value% @@ -364,7 +347,7 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0070.severity = %value% # IDE0071 -dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_diagnostic.IDE0071.severity = %value% # IDE0072 dotnet_diagnostic.IDE0072.severity = %value% @@ -373,10 +356,10 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0073.severity = %value% # IDE0074 -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_diagnostic.IDE0074.severity = %value% # IDE0075 -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_diagnostic.IDE0075.severity = %value% # IDE0076 dotnet_diagnostic.IDE0076.severity = %value% @@ -385,7 +368,7 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0077.severity = %value% # IDE0078 -csharp_style_prefer_pattern_matching = true:silent +dotnet_diagnostic.IDE0078.severity = %value% # IDE0079 dotnet_diagnostic.IDE0079.severity = %value% @@ -397,16 +380,16 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0082.severity = %value% # IDE0083 -csharp_style_prefer_not_pattern = true:suggestion +dotnet_diagnostic.IDE0083.severity = %value% # IDE0090 -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +dotnet_diagnostic.IDE0090.severity = %value% # IDE0100 dotnet_diagnostic.IDE0100.severity = %value% # IDE1005 -csharp_style_conditional_delegate_call = true:suggestion +dotnet_diagnostic.IDE1005.severity = %value% # IDE1006 dotnet_diagnostic.IDE1006.severity = %value% @@ -447,25 +430,25 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0010.severity = %value% # IDE0017 -dotnet_style_object_initializer = true:suggestion +dotnet_diagnostic.IDE0017.severity = %value% # IDE0028 -dotnet_style_collection_initializer = true:suggestion +dotnet_diagnostic.IDE0028.severity = %value% # IDE0029 -dotnet_style_coalesce_expression = true:suggestion +dotnet_diagnostic.IDE0029.severity = %value% # IDE0030 -dotnet_style_coalesce_expression = true:suggestion +dotnet_diagnostic.IDE0030.severity = %value% # IDE0031 -dotnet_style_null_propagation = true:suggestion +dotnet_diagnostic.IDE0031.severity = %value% # IDE0032 -dotnet_style_prefer_auto_properties = true:silent +dotnet_diagnostic.IDE0032.severity = %value% # IDE0033 -dotnet_style_explicit_tuple_names = true:suggestion +dotnet_diagnostic.IDE0033.severity = %value% # IDE0036 dotnet_diagnostic.IDE0036.severity = %value% @@ -474,22 +457,22 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0037.severity = %value% # IDE0040 -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_diagnostic.IDE0040.severity = %value% # IDE0041 -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_diagnostic.IDE0041.severity = %value% # IDE0043 dotnet_diagnostic.IDE0043.severity = %value% # IDE0044 -dotnet_style_readonly_field = true:suggestion +dotnet_diagnostic.IDE0044.severity = %value% # IDE0045 -dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_diagnostic.IDE0045.severity = %value% # IDE0046 -dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_diagnostic.IDE0046.severity = %value% # IDE0047 dotnet_diagnostic.IDE0047.severity = %value% @@ -510,19 +493,19 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0052.severity = %value% # IDE0054 -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_diagnostic.IDE0054.severity = %value% # IDE0055 dotnet_diagnostic.IDE0055.severity = %value% # IDE0058 -visual_basic_style_unused_value_expression_statement_preference = unused_local_variable:silent +dotnet_diagnostic.IDE0058.severity = %value% # IDE0059 -visual_basic_style_unused_value_assignment_preference = unused_local_variable:suggestion +dotnet_diagnostic.IDE0059.severity = %value% # IDE0060 -dotnet_code_quality_unused_parameters = all:suggestion +dotnet_diagnostic.IDE0060.severity = %value% # IDE0067 dotnet_diagnostic.IDE0067.severity = %value% @@ -537,13 +520,13 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0070.severity = %value% # IDE0071 -dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_diagnostic.IDE0071.severity = %value% # IDE0073 dotnet_diagnostic.IDE0073.severity = %value% # IDE0075 -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_diagnostic.IDE0075.severity = %value% # IDE0076 dotnet_diagnostic.IDE0076.severity = %value% @@ -561,7 +544,7 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable() dotnet_diagnostic.IDE0082.severity = %value% # IDE0084 -visual_basic_style_prefer_isnot_expression = true:suggestion +dotnet_diagnostic.IDE0084.severity = %value% # IDE0100 dotnet_diagnostic.IDE0100.severity = %value% @@ -684,16 +667,16 @@ No editorconfig based code style option No editorconfig based code style option # IDE0003, QualifyEventAccess -dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_event = false # IDE0003, QualifyFieldAccess -dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_field = false # IDE0003, QualifyMethodAccess -dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_method = false # IDE0003, QualifyPropertyAccess -dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_property = false # IDE0004 No editorconfig based code style option @@ -702,157 +685,157 @@ No editorconfig based code style option No editorconfig based code style option # IDE0007, VarElsewhere -csharp_style_var_elsewhere = false:silent +csharp_style_var_elsewhere = false # IDE0007, VarForBuiltInTypes -csharp_style_var_for_built_in_types = false:silent +csharp_style_var_for_built_in_types = false # IDE0007, VarWhenTypeIsApparent -csharp_style_var_when_type_is_apparent = false:silent +csharp_style_var_when_type_is_apparent = false # IDE0008, VarElsewhere -csharp_style_var_elsewhere = false:silent +csharp_style_var_elsewhere = false # IDE0008, VarForBuiltInTypes -csharp_style_var_for_built_in_types = false:silent +csharp_style_var_for_built_in_types = false # IDE0008, VarWhenTypeIsApparent -csharp_style_var_when_type_is_apparent = false:silent +csharp_style_var_when_type_is_apparent = false # IDE0009, QualifyEventAccess -dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_event = false # IDE0009, QualifyFieldAccess -dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_field = false # IDE0009, QualifyMethodAccess -dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_method = false # IDE0009, QualifyPropertyAccess -dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_property = false # IDE0010 No editorconfig based code style option # IDE0011, PreferBraces -csharp_prefer_braces = true:silent +csharp_prefer_braces = true # IDE0016, PreferThrowExpression -csharp_style_throw_expression = true:suggestion +csharp_style_throw_expression = true # IDE0017, PreferObjectInitializer -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true # IDE0018, PreferInlinedVariableDeclaration -csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true # IDE0019, PreferPatternMatchingOverAsWithNullCheck -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true # IDE0020, PreferPatternMatchingOverIsWithCastCheck -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true # IDE0021, PreferExpressionBodiedConstructors -csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_constructors = false # IDE0022, PreferExpressionBodiedMethods -csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_methods = false # IDE0023, PreferExpressionBodiedOperators -csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_operators = false # IDE0024, PreferExpressionBodiedOperators -csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_operators = false # IDE0025, PreferExpressionBodiedProperties -csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_properties = true # IDE0026, PreferExpressionBodiedIndexers -csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_indexers = true # IDE0027, PreferExpressionBodiedAccessors -csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_accessors = true # IDE0028, PreferCollectionInitializer -dotnet_style_collection_initializer = true:suggestion +dotnet_style_collection_initializer = true # IDE0029, PreferCoalesceExpression -dotnet_style_coalesce_expression = true:suggestion +dotnet_style_coalesce_expression = true # IDE0030, PreferCoalesceExpression -dotnet_style_coalesce_expression = true:suggestion +dotnet_style_coalesce_expression = true # IDE0031, PreferNullPropagation -dotnet_style_null_propagation = true:suggestion +dotnet_style_null_propagation = true # IDE0032, PreferAutoProperties -dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_auto_properties = true # IDE0033, PreferExplicitTupleNames -dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_explicit_tuple_names = true # IDE0034, PreferSimpleDefaultExpression -csharp_prefer_simple_default_expression = true:suggestion +csharp_prefer_simple_default_expression = true # IDE0035 No editorconfig based code style option # IDE0036, PreferredModifierOrder -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async # IDE0037, PreferInferredTupleNames -dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true # IDE0037, PreferInferredAnonymousTypeMemberNames -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true # IDE0038 No editorconfig based code style option # IDE0039, PreferLocalOverAnonymousFunction -csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true # IDE0040, RequireAccessibilityModifiers -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members # IDE0041, PreferIsNullCheckOverReferenceEqualityMethod -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true # IDE0042, PreferDeconstructedVariableDeclaration -csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true # IDE0043 No editorconfig based code style option # IDE0044, PreferReadonly -dotnet_style_readonly_field = true:suggestion +dotnet_style_readonly_field = true # IDE0045, PreferConditionalExpressionOverAssignment -dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true # IDE0046, PreferConditionalExpressionOverReturn -dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_conditional_expression_over_return = true # IDE0047 No editorconfig based code style option # IDE0048, ArithmeticBinaryParentheses -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity # IDE0048, OtherBinaryParentheses -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity # IDE0048, OtherParentheses -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary # IDE0048, RelationalBinaryParentheses -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity # IDE0049, PreferIntrinsicPredefinedTypeKeywordInDeclaration -dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true # IDE0049, PreferIntrinsicPredefinedTypeKeywordInMemberAccess -dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_predefined_type_for_member_access = true # IDE0050 No editorconfig based code style option @@ -864,46 +847,46 @@ No editorconfig based code style option No editorconfig based code style option # IDE0053, PreferExpressionBodiedLambdas -csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_lambdas = true # IDE0054, PreferCompoundAssignment -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_compound_assignment = true # IDE0055 No editorconfig based code style option # IDE0056, PreferIndexOperator -csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_index_operator = true # IDE0057, PreferRangeOperator -csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_range_operator = true # IDE0058, UnusedValueExpressionStatement -csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_expression_statement_preference = discard_variable # IDE0059, UnusedValueAssignment -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable # IDE0060, UnusedParameters -dotnet_code_quality_unused_parameters = all:suggestion +dotnet_code_quality_unused_parameters = all # IDE0061, PreferExpressionBodiedLocalFunctions -csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_local_functions = false # IDE0062, PreferStaticLocalFunction -csharp_prefer_static_local_function = true:suggestion +csharp_prefer_static_local_function = true # IDE0063, PreferSimpleUsingStatement -csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_simple_using_statement = true # IDE0064 No editorconfig based code style option # IDE0065, PreferredUsingDirectivePlacement -csharp_using_directive_placement = outside_namespace:silent +csharp_using_directive_placement = outside_namespace # IDE0066, PreferSwitchExpression -csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_switch_expression = true # IDE0067 No editorconfig based code style option @@ -918,7 +901,7 @@ No editorconfig based code style option No editorconfig based code style option # IDE0071, PreferSimplifiedInterpolation -dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_simplified_interpolation = true # IDE0072 No editorconfig based code style option @@ -927,10 +910,10 @@ No editorconfig based code style option file_header_template = unset # IDE0074, PreferCompoundAssignment -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_compound_assignment = true # IDE0075, PreferSimplifiedBooleanExpressions -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true # IDE0076 No editorconfig based code style option @@ -939,7 +922,7 @@ No editorconfig based code style option No editorconfig based code style option # IDE0078, PreferPatternMatching -csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_pattern_matching = true # IDE0079 No editorconfig based code style option @@ -951,16 +934,16 @@ No editorconfig based code style option No editorconfig based code style option # IDE0083, PreferNotPattern -csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_not_pattern = true # IDE0090, ImplicitObjectCreationWhenTypeIsApparent -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true # IDE0100 No editorconfig based code style option # IDE1005, PreferConditionalDelegateCall -csharp_style_conditional_delegate_call = true:suggestion +csharp_style_conditional_delegate_call = true # IDE1006 No editorconfig based code style option @@ -986,16 +969,16 @@ No editorconfig based code style option No editorconfig based code style option # IDE0003, QualifyEventAccess -dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_event = false # IDE0003, QualifyFieldAccess -dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_field = false # IDE0003, QualifyMethodAccess -dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_method = false # IDE0003, QualifyPropertyAccess -dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_property = false # IDE0004 No editorconfig based code style option @@ -1004,88 +987,88 @@ No editorconfig based code style option No editorconfig based code style option # IDE0009, QualifyEventAccess -dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_event = false # IDE0009, QualifyFieldAccess -dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_field = false # IDE0009, QualifyMethodAccess -dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_method = false # IDE0009, QualifyPropertyAccess -dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_property = false # IDE0010 No editorconfig based code style option # IDE0017, PreferObjectInitializer -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true # IDE0028, PreferCollectionInitializer -dotnet_style_collection_initializer = true:suggestion +dotnet_style_collection_initializer = true # IDE0029, PreferCoalesceExpression -dotnet_style_coalesce_expression = true:suggestion +dotnet_style_coalesce_expression = true # IDE0030, PreferCoalesceExpression -dotnet_style_coalesce_expression = true:suggestion +dotnet_style_coalesce_expression = true # IDE0031, PreferNullPropagation -dotnet_style_null_propagation = true:suggestion +dotnet_style_null_propagation = true # IDE0032, PreferAutoProperties -dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_auto_properties = true # IDE0033, PreferExplicitTupleNames -dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_explicit_tuple_names = true # IDE0036, PreferredModifierOrder -visual_basic_preferred_modifier_order = partial,default,private,protected,public,friend,notoverridable,overridable,mustoverride,overloads,overrides,mustinherit,notinheritable,static,shared,shadows,readonly,writeonly,dim,const,withevents,widening,narrowing,custom,async,iterator:silent +visual_basic_preferred_modifier_order = partial,default,private,protected,public,friend,notoverridable,overridable,mustoverride,overloads,overrides,mustinherit,notinheritable,static,shared,shadows,readonly,writeonly,dim,const,withevents,widening,narrowing,custom,async,iterator # IDE0037, PreferInferredTupleNames -dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true # IDE0037, PreferInferredAnonymousTypeMemberNames -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true # IDE0040, RequireAccessibilityModifiers -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members # IDE0041, PreferIsNullCheckOverReferenceEqualityMethod -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true # IDE0043 No editorconfig based code style option # IDE0044, PreferReadonly -dotnet_style_readonly_field = true:suggestion +dotnet_style_readonly_field = true # IDE0045, PreferConditionalExpressionOverAssignment -dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true # IDE0046, PreferConditionalExpressionOverReturn -dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_conditional_expression_over_return = true # IDE0047 No editorconfig based code style option # IDE0048, ArithmeticBinaryParentheses -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity # IDE0048, OtherBinaryParentheses -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity # IDE0048, OtherParentheses -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary # IDE0048, RelationalBinaryParentheses -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity # IDE0049, PreferIntrinsicPredefinedTypeKeywordInDeclaration -dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true # IDE0049, PreferIntrinsicPredefinedTypeKeywordInMemberAccess -dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_predefined_type_for_member_access = true # IDE0050 No editorconfig based code style option @@ -1097,19 +1080,19 @@ No editorconfig based code style option No editorconfig based code style option # IDE0054, PreferCompoundAssignment -dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_compound_assignment = true # IDE0055 No editorconfig based code style option # IDE0058, UnusedValueExpressionStatement -visual_basic_style_unused_value_expression_statement_preference = unused_local_variable:silent +visual_basic_style_unused_value_expression_statement_preference = unused_local_variable # IDE0059, UnusedValueAssignment -visual_basic_style_unused_value_assignment_preference = unused_local_variable:suggestion +visual_basic_style_unused_value_assignment_preference = unused_local_variable # IDE0060, UnusedParameters -dotnet_code_quality_unused_parameters = all:suggestion +dotnet_code_quality_unused_parameters = all # IDE0067 No editorconfig based code style option @@ -1124,13 +1107,13 @@ No editorconfig based code style option No editorconfig based code style option # IDE0071, PreferSimplifiedInterpolation -dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_simplified_interpolation = true # IDE0073, FileHeaderTemplate file_header_template = unset # IDE0075, PreferSimplifiedBooleanExpressions -dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true # IDE0076 No editorconfig based code style option @@ -1148,7 +1131,7 @@ No editorconfig based code style option No editorconfig based code style option # IDE0084, PreferIsNotExpression -visual_basic_style_prefer_isnot_expression = true:suggestion +visual_basic_style_prefer_isnot_expression = true # IDE0100 No editorconfig based code style option diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.vb index aa4f59e949b14..f98929f756ee5 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/Configuration/ConfigureCodeStyle/BooleanCodeStyleOptionConfigurationTests.vb @@ -92,7 +92,7 @@ End Class [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true " @@ -219,7 +219,7 @@ dotnet_style_object_initializer = true:none [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true " @@ -344,7 +344,7 @@ End Class dotnet_style_object_initializer_error = true:none # IDE0017: Simplify object initialization -dotnet_style_object_initializer = true:suggestion +dotnet_style_object_initializer = true " @@ -415,7 +415,7 @@ End Class [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false " @@ -483,6 +483,67 @@ dotnet_style_object_initializer = false:silent Await TestInRegularAndScriptAsync(input, expected, CodeActionIndex) End Function + + Public Async Function ConfigureEditorconfig_RuleExists_False_WithoutSeveritySuffix() As Task + Dim input = " + + + +Class Program1 + Private Shared Sub Main() + ' dotnet_style_object_initializer = true + Dim obj = New Customer() With { + ._age = 21 + } + ' dotnet_style_object_initializer = false + Dim obj2 As Customer = [|New Customer()|] + obj2._age = 21 + End Sub + + Friend Class Customer + Public _age As Integer + + Public Sub New() + End Sub + End Class +End Class + + [*.vb] +dotnet_style_object_initializer = true + + +" + Dim expected = " + + + +Class Program1 + Private Shared Sub Main() + ' dotnet_style_object_initializer = true + Dim obj = New Customer() With { + ._age = 21 + } + ' dotnet_style_object_initializer = false + Dim obj2 As Customer = [|New Customer()|] + obj2._age = 21 + End Sub + + Friend Class Customer + Public _age As Integer + + Public Sub New() + End Sub + End Class +End Class + + [*.vb] +dotnet_style_object_initializer = false + + +" + Await TestInRegularAndScriptAsync(input, expected, CodeActionIndex) + End Function + Public Async Function ConfigureEditorconfig_InvalidHeader_False() As Task Dim input = " @@ -542,7 +603,7 @@ dotnet_style_object_initializer = true:suggestion [*.{cs,vb}] # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false " @@ -667,7 +728,7 @@ End Class dotnet_style_object_initializer_error = true:suggestion # IDE0017: Simplify object initialization -dotnet_style_object_initializer = false:suggestion +dotnet_style_object_initializer = false " diff --git a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigurationUpdater.cs b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigurationUpdater.cs index 47744282ac42e..59dbc060ba7a7 100644 --- a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigurationUpdater.cs +++ b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigurationUpdater.cs @@ -47,15 +47,19 @@ private enum ConfigurationKind private static readonly Regex s_headerPattern = new(@"\[(\*|[^ #;\[\]]+\.({[^ #;{}\.\[\]]+}|[^ #;{}\.\[\]]+))\]\s*([#;].*)?"); // Regular expression for .editorconfig code style option entry. - // For example: "dotnet_style_object_initializer = true:suggestion # Optional comment" - private static readonly Regex s_optionBasedEntryPattern = new(@"([\w ]+)=([\w, ]+):[ ]*([\w]+)([ ]*[;#].*)?"); - - // Regular expression for .editorconfig diagnostic severity configuration entry. // For example: - // 1. "dotnet_diagnostic.CA2000.severity = suggestion # Optional comment" - // 2. "dotnet_analyzer_diagnostic.category-Security.severity = suggestion # Optional comment" - // 3. "dotnet_analyzer_diagnostic.severity = suggestion # Optional comment" - private static readonly Regex s_severityBasedEntryPattern = new(@"([\w- \.]+)=[ ]*([\w]+)([ ]*[;#].*)?"); + // 1. "dotnet_style_object_initializer = true # Optional comment" + // 2. "dotnet_style_object_initializer = true:suggestion ; Optional comment" + // 3. "dotnet_diagnostic.CA2000.severity = suggestion # Optional comment" + // 4. "dotnet_analyzer_diagnostic.category-Security.severity = suggestion # Optional comment" + // 5. "dotnet_analyzer_diagnostic.severity = suggestion # Optional comment" + // + // Regex groups: + // 1. Option key + // 2. Option value + // 3. Optional severity suffix in option value, i.e. ':severity' suffix + // 4. Optional comment suffix + private static readonly Regex s_optionEntryPattern = new($@"(.*)=([\w, ]*)(:[\w]+)?([ ]*[;#].*)?"); private readonly string? _optionNameOpt; private readonly string? _newOptionValueOpt; @@ -372,7 +376,7 @@ internal static bool TryGetEditorConfigStringParts( var editorConfigString = editorConfigLocation.GetEditorConfigString(codeStyleOption, optionSet); if (!string.IsNullOrEmpty(editorConfigString)) { - var match = s_optionBasedEntryPattern.Match(editorConfigString); + var match = s_optionEntryPattern.Match(editorConfigString); if (match.Success) { parts = (optionName: match.Groups[1].Value.Trim(), @@ -474,23 +478,20 @@ internal static bool TryGetEditorConfigStringParts( { var curLineText = curLine.ToString(); - // We might have a diagnostic ID configuration entry based on either s_optionBasedEntryPattern or - // s_severityBasedEntryPattern. Both of these are considered valid severity configurations. - var isOptionBasedMatch = s_optionBasedEntryPattern.IsMatch(curLineText); - - // We want to detect severity based entry only when we are configuring severity and have no option name specified. - var isSeverityBasedMatch = _configurationKind != ConfigurationKind.OptionValue && - _optionNameOpt == null && - !isOptionBasedMatch && - s_severityBasedEntryPattern.IsMatch(curLineText); - if (isOptionBasedMatch || isSeverityBasedMatch) + if (s_optionEntryPattern.IsMatch(curLineText)) { - var groups = isOptionBasedMatch - ? s_optionBasedEntryPattern.Match(curLineText).Groups - : s_severityBasedEntryPattern.Match(curLineText).Groups; - var key = groups[1].Value.ToString().Trim(); - var commentIndex = isOptionBasedMatch ? 4 : 3; - var commentValue = groups[commentIndex].Value.ToString(); + var groups = s_optionEntryPattern.Match(curLineText).Groups; + + // Regex groups: + // 1. Option key + // 2. Option value + // 3. Optional severity suffix, i.e. ':severity' suffix + // 4. Optional comment suffix + var untrimmedKey = groups[1].Value.ToString(); + var key = untrimmedKey.Trim(); + var value = groups[2].Value.ToString(); + var severitySuffixInValue = groups[3].Value.ToString(); + var commentValue = groups[4].Value.ToString(); // Verify the most recent header is a valid header if (mostRecentHeader != null && @@ -498,70 +499,75 @@ internal static bool TryGetEditorConfigStringParts( mostRecentHeader.Equals(lastValidHeader)) { // We found the rule in the file -- replace it with updated option value/severity. - if (isOptionBasedMatch && key.Equals(_optionNameOpt)) + if (key.Equals(_optionNameOpt)) { - // We found a rule configuration entry of option based form: + // We found an option configuration entry of form: + // "%option_name% = %option_value% + // OR // "%option_name% = %option_value%:%severity% - var currentOptionValue = groups[2].Value.ToString().Trim(); - var currentSeverityValue = groups[3].Value.ToString().Trim(); - var newOptionValue = _configurationKind == ConfigurationKind.OptionValue ? _newOptionValueOpt : currentOptionValue; - var newSeverityValue = _configurationKind == ConfigurationKind.Severity ? _newSeverity : currentSeverityValue; + var newOptionValue = _configurationKind == ConfigurationKind.OptionValue + ? $"{value.GetLeadingWhitespace()}{_newOptionValueOpt}{value.GetTrailingWhitespace()}" + : value; + var newSeverityValue = _configurationKind == ConfigurationKind.Severity && severitySuffixInValue.Length > 0 ? $":{_newSeverity}" : severitySuffixInValue; - textChange = new TextChange(curLine.Span, $"{key} = {newOptionValue}:{newSeverityValue}{commentValue}"); + textChange = new TextChange(curLine.Span, $"{untrimmedKey}={newOptionValue}{newSeverityValue}{commentValue}"); } - else if (isSeverityBasedMatch) + else { - // We found a rule configuration entry of severity based form: - // "dotnet_diagnostic.<%DiagnosticId%>.severity = %severity% - // OR - // "dotnet_analyzer_diagnostic.severity = %severity% - // OR - // "dotnet_analyzer_diagnostic.category-<%DiagnosticCategory%>.severity = %severity% - - switch (_configurationKind) + // We want to detect severity based entry only when we are configuring severity and have no option name specified. + if (_configurationKind != ConfigurationKind.OptionValue && + _optionNameOpt == null && + severitySuffixInValue.Length == 0 && + key.EndsWith(SeveritySuffix)) { - case ConfigurationKind.Severity: - RoslynDebug.Assert(_diagnostic != null); - if (key.StartsWith(DiagnosticOptionPrefix, StringComparison.Ordinal) && - key.EndsWith(SeveritySuffix, StringComparison.Ordinal)) - { - var diagIdLength = key.Length - (DiagnosticOptionPrefix.Length + SeveritySuffix.Length); - if (diagIdLength > 0) + // We found a rule configuration entry of severity based form: + // "dotnet_diagnostic.<%DiagnosticId%>.severity = %severity% + // OR + // "dotnet_analyzer_diagnostic.severity = %severity% + // OR + // "dotnet_analyzer_diagnostic.category-<%DiagnosticCategory%>.severity = %severity% + + var foundMatch = false; + switch (_configurationKind) + { + case ConfigurationKind.Severity: + RoslynDebug.Assert(_diagnostic != null); + if (key.StartsWith(DiagnosticOptionPrefix, StringComparison.Ordinal)) { - var diagId = key.Substring(DiagnosticOptionPrefix.Length, diagIdLength); - if (string.Equals(diagId, _diagnostic.Id, StringComparison.OrdinalIgnoreCase)) + var diagIdLength = key.Length - (DiagnosticOptionPrefix.Length + SeveritySuffix.Length); + if (diagIdLength > 0) { - textChange = new TextChange(curLine.Span, $"{key} = {_newSeverity}{commentValue}"); + var diagId = key.Substring(DiagnosticOptionPrefix.Length, diagIdLength); + foundMatch = string.Equals(diagId, _diagnostic.Id, StringComparison.OrdinalIgnoreCase); } } - } - break; + break; - case ConfigurationKind.BulkConfigure: - RoslynDebug.Assert(_categoryToBulkConfigure != null); - if (_categoryToBulkConfigure == AllAnalyzerDiagnosticsCategory) - { - if (key == BulkConfigureAllAnalyzerDiagnosticsOptionKey) + case ConfigurationKind.BulkConfigure: + RoslynDebug.Assert(_categoryToBulkConfigure != null); + if (_categoryToBulkConfigure == AllAnalyzerDiagnosticsCategory) { - textChange = new TextChange(curLine.Span, $"{key} = {_newSeverity}{commentValue}"); + foundMatch = key == BulkConfigureAllAnalyzerDiagnosticsOptionKey; } - } - else - { - if (key.StartsWith(BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix, StringComparison.Ordinal) && - key.EndsWith(SeveritySuffix, StringComparison.Ordinal)) + else { - var categoryLength = key.Length - (BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix.Length + SeveritySuffix.Length); - var category = key.Substring(BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix.Length, categoryLength); - if (string.Equals(category, _categoryToBulkConfigure, StringComparison.OrdinalIgnoreCase)) + if (key.StartsWith(BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix, StringComparison.Ordinal)) { - textChange = new TextChange(curLine.Span, $"{key} = {_newSeverity}{commentValue}"); + var categoryLength = key.Length - (BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix.Length + SeveritySuffix.Length); + var category = key.Substring(BulkConfigureAnalyzerDiagnosticsByCategoryOptionPrefix.Length, categoryLength); + foundMatch = string.Equals(category, _categoryToBulkConfigure, StringComparison.OrdinalIgnoreCase); } } - } - break; + break; + } + + if (foundMatch) + { + var newSeverityValue = $"{value.GetLeadingWhitespace()}{_newSeverity}{value.GetTrailingWhitespace()}"; + textChange = new TextChange(curLine.Span, $"{untrimmedKey}={newSeverityValue}{commentValue}"); + } } } } @@ -692,7 +698,7 @@ internal static bool TryGetEditorConfigStringParts( // 2. Category configuration: "dotnet_analyzer_diagnostic.category-<%DiagnosticCategory%>.severity = %severity% var newEntry = !string.IsNullOrEmpty(_optionNameOpt) && !string.IsNullOrEmpty(_newOptionValueOpt) - ? $"{_optionNameOpt} = {_newOptionValueOpt}:{_newSeverity}" + ? $"{_optionNameOpt} = {_newOptionValueOpt}" : _diagnostic != null ? $"{DiagnosticOptionPrefix}{_diagnostic.Id}{SeveritySuffix} = {_newSeverity}" : _categoryToBulkConfigure == AllAnalyzerDiagnosticsCategory diff --git a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs index 340e6679b3e3e..5ac06f3682c3c 100644 --- a/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs +++ b/src/Features/Core/Portable/CodeFixes/Configuration/ConfigureCodeStyle/ConfigureCodeStyleOptionCodeFixProvider.cs @@ -119,7 +119,6 @@ TopLevelConfigureCodeStyleOptionCodeAction GetCodeActionForCodeStyleOption( using var _ = ArrayBuilder.GetInstance(out var nestedActions); - var severity = codeStyleOption.Notification.ToEditorConfigString(); string optionName = null; if (codeStyleOption.Value is bool) { diff --git a/src/Workspaces/CSharpTest/CodeStyle/CSharpEditorConfigCodeStyleParserTests.cs b/src/Workspaces/CSharpTest/CodeStyle/CSharpEditorConfigCodeStyleParserTests.cs index db127419007a7..d00083e4e736c 100644 --- a/src/Workspaces/CSharpTest/CodeStyle/CSharpEditorConfigCodeStyleParserTests.cs +++ b/src/Workspaces/CSharpTest/CodeStyle/CSharpEditorConfigCodeStyleParserTests.cs @@ -4,6 +4,7 @@ #nullable disable +using Microsoft.CodeAnalysis.AddImports; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Formatting; @@ -47,14 +48,35 @@ public void TestParseLabelPositioning(string rawValue, LabelPositionOptions pars [InlineData("false : none", (int)ExpressionBodyPreference.Never, ReportDiagnostic.Suppress)] [InlineData("true : warning", (int)ExpressionBodyPreference.WhenPossible, ReportDiagnostic.Warn)] [InlineData("when_on_single_line : error", (int)ExpressionBodyPreference.WhenOnSingleLine, ReportDiagnostic.Error)] - public void TestParseExpressionBodyPreference(string optionString, int parsedValue, ReportDiagnostic severity) + + [InlineData("false", (int)ExpressionBodyPreference.Never, ReportDiagnostic.Suppress)] + [InlineData("true", (int)ExpressionBodyPreference.WhenPossible, null)] + [InlineData("when_on_single_line", (int)ExpressionBodyPreference.WhenOnSingleLine, null)] + public void TestParseExpressionBodyPreference(string optionString, int parsedValue, ReportDiagnostic? severity) { var defaultValue = new CodeStyleOption2(ExpressionBodyPreference.Never, NotificationOption2.Error); + severity ??= ReportDiagnostic.Error; var codeStyleOption = CSharpCodeStyleOptions.ParseExpressionBodyPreference(optionString, defaultValue); Assert.NotSame(defaultValue, codeStyleOption); Assert.Equal((ExpressionBodyPreference)parsedValue, codeStyleOption.Value); Assert.Equal(severity, codeStyleOption.Notification.Severity); } + + [Theory] + [InlineData("inside_namespace:warning", AddImportPlacement.InsideNamespace, ReportDiagnostic.Warn)] + [InlineData("outside_namespace:suggestion", AddImportPlacement.OutsideNamespace, ReportDiagnostic.Info)] + [InlineData("inside_namespace", AddImportPlacement.InsideNamespace, null)] + [InlineData("outside_namespace", AddImportPlacement.OutsideNamespace, null)] + internal void TestParseUsingDirectivesPlacement(string optionString, AddImportPlacement parsedValue, ReportDiagnostic? severity) + { + var defaultValue = new CodeStyleOption2(AddImportPlacement.InsideNamespace, NotificationOption2.Error); + severity ??= ReportDiagnostic.Error; + var codeStyleOption = CSharpCodeStyleOptions.ParseUsingDirectivesPlacement(optionString, defaultValue); + + Assert.NotSame(defaultValue, codeStyleOption); + Assert.Equal(parsedValue, codeStyleOption.Value); + Assert.Equal(severity, codeStyleOption.Notification.Severity); + } } } diff --git a/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs b/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs index fcf5c1400bb5f..6985c5d8ccbcb 100644 --- a/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs +++ b/src/Workspaces/CoreTest/CodeStyle/EditorConfigCodeStyleParserTests.cs @@ -21,7 +21,7 @@ public class EditorConfigCodeStyleParserTests [InlineData("true:suggestion", true, ReportDiagnostic.Info)] [InlineData("true:warning", true, ReportDiagnostic.Warn)] [InlineData("true:error", true, ReportDiagnostic.Error)] - [InlineData("true", false, ReportDiagnostic.Hidden)] + [InlineData("true", true, ReportDiagnostic.Hidden)] [InlineData("false:none", false, ReportDiagnostic.Suppress)] [InlineData("false:refactoring", false, ReportDiagnostic.Hidden)] [InlineData("false:silent", false, ReportDiagnostic.Hidden)] @@ -39,7 +39,7 @@ public class EditorConfigCodeStyleParserTests [InlineData("false : error", false, ReportDiagnostic.Error)] public void TestParseEditorConfigCodeStyleOption(string args, bool isEnabled, ReportDiagnostic severity) { - CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(args, out var result); + CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(args, defaultValue: CodeStyleOption2.Default, out var result); Assert.True(result.Value == isEnabled, $"Expected {nameof(isEnabled)} to be {isEnabled}, was {result.Value}"); Assert.True(result.Notification.Severity == severity, diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs index 231299b5fbb92..fa2a3581b0360 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs @@ -25,103 +25,95 @@ internal static partial class CSharpCodeStyleOptions private static Option2 CreateOption(OptionGroup group, string name, T defaultValue, params OptionStorageLocation2[] storageLocations) => CodeStyleHelpers.CreateOption(group, nameof(CSharpCodeStyleOptions), name, defaultValue, s_allOptionsBuilder, storageLocations); + private static Option2> CreateOption(OptionGroup group, string name, CodeStyleOption2 defaultValue, string editorconfigKeyName, string roamingProfileStorageKeyName) + => CreateOption(group, name, defaultValue, EditorConfigStorageLocation.ForBoolCodeStyleOption(editorconfigKeyName, defaultValue), new RoamingProfileStorageLocation(roamingProfileStorageKeyName)); + + private static Option2> CreateOption(OptionGroup group, string name, CodeStyleOption2 defaultValue, string editorconfigKeyName, string roamingProfileStorageKeyName) + => CreateOption(group, name, defaultValue, EditorConfigStorageLocation.ForStringCodeStyleOption(editorconfigKeyName, defaultValue), new RoamingProfileStorageLocation(roamingProfileStorageKeyName)); + public static readonly Option2> VarForBuiltInTypes = CreateOption( CSharpCodeStyleOptionGroups.VarPreferences, nameof(VarForBuiltInTypes), defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_var_for_built_in_types"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.UseImplicitTypeForIntrinsicTypes")}); + "csharp_style_var_for_built_in_types", + "TextEditor.CSharp.Specific.UseImplicitTypeForIntrinsicTypes"); public static readonly Option2> VarWhenTypeIsApparent = CreateOption( CSharpCodeStyleOptionGroups.VarPreferences, nameof(VarWhenTypeIsApparent), defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_var_when_type_is_apparent"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.UseImplicitTypeWhereApparent")}); + "csharp_style_var_when_type_is_apparent", + "TextEditor.CSharp.Specific.UseImplicitTypeWhereApparent"); public static readonly Option2> VarElsewhere = CreateOption( CSharpCodeStyleOptionGroups.VarPreferences, nameof(VarElsewhere), defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_var_elsewhere"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.UseImplicitTypeWherePossible")}); + "csharp_style_var_elsewhere", + "TextEditor.CSharp.Specific.UseImplicitTypeWherePossible"); public static readonly Option2> PreferConditionalDelegateCall = CreateOption( CSharpCodeStyleOptionGroups.NullCheckingPreferences, nameof(PreferConditionalDelegateCall), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_conditional_delegate_call"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferConditionalDelegateCall")}); + "csharp_style_conditional_delegate_call", + "TextEditor.CSharp.Specific.PreferConditionalDelegateCall"); public static readonly Option2> PreferSwitchExpression = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferSwitchExpression), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_switch_expression"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferSwitchExpression)}")}); + "csharp_style_prefer_switch_expression", + $"TextEditor.CSharp.Specific.{nameof(PreferSwitchExpression)}"); public static readonly Option2> PreferPatternMatching = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatching), defaultValue: s_trueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_pattern_matching"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferPatternMatching)}")}); + "csharp_style_prefer_pattern_matching", + $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatching)}"); public static readonly Option2> PreferPatternMatchingOverAsWithNullCheck = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatchingOverAsWithNullCheck), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_pattern_matching_over_as_with_null_check"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverAsWithNullCheck)}")}); + "csharp_style_pattern_matching_over_as_with_null_check", + $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverAsWithNullCheck)}"); public static readonly Option2> PreferPatternMatchingOverIsWithCastCheck = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferPatternMatchingOverIsWithCastCheck), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_pattern_matching_over_is_with_cast_check"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverIsWithCastCheck)}")}); + "csharp_style_pattern_matching_over_is_with_cast_check", + $"TextEditor.CSharp.Specific.{nameof(PreferPatternMatchingOverIsWithCastCheck)}"); public static readonly Option2> PreferNotPattern = CreateOption( CSharpCodeStyleOptionGroups.PatternMatching, nameof(PreferNotPattern), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_not_pattern"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferNotPattern)}")}); + "csharp_style_prefer_not_pattern", + $"TextEditor.CSharp.Specific.{nameof(PreferNotPattern)}"); public static readonly Option2> PreferThrowExpression = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferThrowExpression), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_throw_expression"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferThrowExpression")}); + "csharp_style_throw_expression", + "TextEditor.CSharp.Specific.PreferThrowExpression"); public static readonly Option2> PreferInlinedVariableDeclaration = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInlinedVariableDeclaration), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_inlined_variable_declaration"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferInlinedVariableDeclaration") }); + "csharp_style_inlined_variable_declaration", + "TextEditor.CSharp.Specific.PreferInlinedVariableDeclaration"); public static readonly Option2> PreferDeconstructedVariableDeclaration = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferDeconstructedVariableDeclaration), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_deconstructed_variable_declaration"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferDeconstructedVariableDeclaration)}")}); + "csharp_style_deconstructed_variable_declaration", + $"TextEditor.CSharp.Specific.{nameof(PreferDeconstructedVariableDeclaration)}"); public static readonly Option2> PreferIndexOperator = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferIndexOperator), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_index_operator"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferIndexOperator")}); + "csharp_style_prefer_index_operator", + "TextEditor.CSharp.Specific.PreferIndexOperator"); public static readonly Option2> PreferRangeOperator = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferRangeOperator), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_prefer_range_operator"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.PreferRangeOperator")}); + "csharp_style_prefer_range_operator", + "TextEditor.CSharp.Specific.PreferRangeOperator"); public static readonly CodeStyleOption2 NeverWithSilentEnforcement = new(ExpressionBodyPreference.Never, NotificationOption2.Silent); @@ -141,102 +133,65 @@ private static Option2 CreateOption(OptionGroup group, string name, T defa public static readonly CodeStyleOption2 UseBracesWithSilentEnforcement = new(PreferBracesPreference.Always, NotificationOption2.Silent); - public static readonly Option2> PreferExpressionBodiedConstructors = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedConstructors), - defaultValue: NeverWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_constructors", - s => ParseExpressionBodyPreference(s, NeverWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedConstructors)}")}); - - public static readonly Option2> PreferExpressionBodiedMethods = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedMethods), - defaultValue: NeverWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_methods", - s => ParseExpressionBodyPreference(s, NeverWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedMethods)}")}); - - public static readonly Option2> PreferExpressionBodiedOperators = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedOperators), - defaultValue: NeverWithSilentEnforcement, + private static Option2> CreatePreferExpressionBodyOption( + string optionName, + CodeStyleOption2 defaultValue, + string editorconfigKeyName) + => CreateOption( + CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, optionName, + defaultValue, storageLocations: new OptionStorageLocation2[] { new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_operators", - s => ParseExpressionBodyPreference(s, NeverWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedOperators)}")}); - - public static readonly Option2> PreferExpressionBodiedProperties = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedProperties), - defaultValue: WhenPossibleWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_properties", - s => ParseExpressionBodyPreference(s, WhenPossibleWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedProperties)}")}); - - public static readonly Option2> PreferExpressionBodiedIndexers = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedIndexers), - defaultValue: WhenPossibleWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_indexers", - s => ParseExpressionBodyPreference(s, WhenPossibleWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedIndexers)}")}); - - public static readonly Option2> PreferExpressionBodiedAccessors = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedAccessors), - defaultValue: WhenPossibleWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_accessors", - s => ParseExpressionBodyPreference(s, WhenPossibleWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedAccessors)}")}); - - public static readonly Option2> PreferExpressionBodiedLambdas = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedLambdas), - defaultValue: WhenPossibleWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_lambdas", - s => ParseExpressionBodyPreference(s, WhenPossibleWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedLambdas)}")}); - - public static readonly Option2> PreferExpressionBodiedLocalFunctions = CreateOption( - CSharpCodeStyleOptionGroups.ExpressionBodiedMembers, nameof(PreferExpressionBodiedLocalFunctions), - defaultValue: NeverWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - new EditorConfigStorageLocation>( - "csharp_style_expression_bodied_local_functions", - s => ParseExpressionBodyPreference(s, NeverWithSilentEnforcement), - GetExpressionBodyPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferExpressionBodiedLocalFunctions)}")}); - - public static readonly Option2> PreferBraces = CreateOption( - CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferBraces), - defaultValue: UseBracesWithSilentEnforcement, + editorconfigKeyName, + s => ParseExpressionBodyPreference(s, defaultValue), + v => GetExpressionBodyPreferenceEditorConfigString(v, defaultValue)), + new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{optionName}")}); + + public static readonly Option2> PreferExpressionBodiedConstructors = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedConstructors), defaultValue: NeverWithSilentEnforcement, "csharp_style_expression_bodied_constructors"); + + public static readonly Option2> PreferExpressionBodiedMethods = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedMethods), defaultValue: NeverWithSilentEnforcement, "csharp_style_expression_bodied_methods"); + + public static readonly Option2> PreferExpressionBodiedOperators = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedOperators), defaultValue: NeverWithSilentEnforcement, "csharp_style_expression_bodied_operators"); + + public static readonly Option2> PreferExpressionBodiedProperties = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedProperties), defaultValue: WhenPossibleWithSilentEnforcement, "csharp_style_expression_bodied_properties"); + + public static readonly Option2> PreferExpressionBodiedIndexers = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedIndexers), defaultValue: WhenPossibleWithSilentEnforcement, "csharp_style_expression_bodied_indexers"); + + public static readonly Option2> PreferExpressionBodiedAccessors = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedAccessors), defaultValue: WhenPossibleWithSilentEnforcement, "csharp_style_expression_bodied_accessors"); + + public static readonly Option2> PreferExpressionBodiedLambdas = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedLambdas), defaultValue: WhenPossibleWithSilentEnforcement, "csharp_style_expression_bodied_lambdas"); + + public static readonly Option2> PreferExpressionBodiedLocalFunctions = CreatePreferExpressionBodyOption( + nameof(PreferExpressionBodiedLocalFunctions), defaultValue: NeverWithSilentEnforcement, "csharp_style_expression_bodied_local_functions"); + + private static Option2> CreatePreferBracesOption( + string optionName, + CodeStyleOption2 defaultValue, + string editorconfigKeyName) + => CreateOption( + CSharpCodeStyleOptionGroups.CodeBlockPreferences, optionName, + defaultValue, storageLocations: new OptionStorageLocation2[] { new EditorConfigStorageLocation>( - "csharp_prefer_braces", - s => ParsePreferBracesPreference(s, UseBracesWithSilentEnforcement), - GetPreferBracesPreferenceEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferBraces)}")}); + editorconfigKeyName, + s => ParsePreferBracesPreference(s, defaultValue), + v => GetPreferBracesPreferenceEditorConfigString(v, defaultValue)), + new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{optionName}")}); + public static readonly Option2> PreferBraces = CreatePreferBracesOption( + nameof(PreferBraces), defaultValue: UseBracesWithSilentEnforcement, "csharp_prefer_braces"); public static readonly Option2> PreferSimpleDefaultExpression = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSimpleDefaultExpression), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_prefer_simple_default_expression"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferSimpleDefaultExpression)}")}); + "csharp_prefer_simple_default_expression", + $"TextEditor.CSharp.Specific.{nameof(PreferSimpleDefaultExpression)}"); private static readonly SyntaxKind[] s_preferredModifierOrderDefault = { @@ -254,43 +209,42 @@ private static Option2 CreateOption(OptionGroup group, string name, T defa public static readonly Option2> PreferredModifierOrder = CreateOption( CSharpCodeStyleOptionGroups.Modifier, nameof(PreferredModifierOrder), defaultValue: new CodeStyleOption2(string.Join(",", s_preferredModifierOrderDefault.Select(SyntaxFacts.GetText)), NotificationOption2.Silent), - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForStringCodeStyleOption("csharp_preferred_modifier_order"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferredModifierOrder)}")}); + "csharp_preferred_modifier_order", + $"TextEditor.CSharp.Specific.{nameof(PreferredModifierOrder)}"); public static readonly Option2> PreferStaticLocalFunction = CreateOption( CSharpCodeStyleOptionGroups.Modifier, nameof(PreferStaticLocalFunction), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_prefer_static_local_function"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferStaticLocalFunction)}")}); + "csharp_prefer_static_local_function", + $"TextEditor.CSharp.Specific.{nameof(PreferStaticLocalFunction)}"); public static readonly Option2> PreferSimpleUsingStatement = CreateOption( CSharpCodeStyleOptionGroups.CodeBlockPreferences, nameof(PreferSimpleUsingStatement), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_prefer_simple_using_statement"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferSimpleUsingStatement)}")}); + "csharp_prefer_simple_using_statement", + $"TextEditor.CSharp.Specific.{nameof(PreferSimpleUsingStatement)}"); public static readonly Option2> PreferLocalOverAnonymousFunction = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferLocalOverAnonymousFunction), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_pattern_local_over_anonymous_function"), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferLocalOverAnonymousFunction)}")}); + "csharp_style_pattern_local_over_anonymous_function", + $"TextEditor.CSharp.Specific.{nameof(PreferLocalOverAnonymousFunction)}"); public static readonly CodeStyleOption2 PreferOutsidePlacementWithSilentEnforcement = new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent); - public static readonly Option2> PreferredUsingDirectivePlacement = CreateOption( - CSharpCodeStyleOptionGroups.UsingDirectivePreferences, nameof(PreferredUsingDirectivePlacement), - defaultValue: PreferOutsidePlacementWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[]{ + private static Option2> CreateUsingDirectivePlacementOption(string optionName, CodeStyleOption2 defaultValue, string editorconfigKeyName) + => CreateOption( + CSharpCodeStyleOptionGroups.UsingDirectivePreferences, optionName, + defaultValue, + storageLocations: new OptionStorageLocation2[] { new EditorConfigStorageLocation>( - "csharp_using_directive_placement", - s => ParseUsingDirectivesPlacement(s, PreferOutsidePlacementWithSilentEnforcement), - GetUsingDirectivesPlacementEditorConfigString), - new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{nameof(PreferredUsingDirectivePlacement)}") }); + editorconfigKeyName, + s => ParseUsingDirectivesPlacement(s, defaultValue), + v => GetUsingDirectivesPlacementEditorConfigString(v, defaultValue)), + new RoamingProfileStorageLocation($"TextEditor.CSharp.Specific.{optionName}")}); + public static readonly Option2> PreferredUsingDirectivePlacement = CreateUsingDirectivePlacementOption( + nameof(PreferredUsingDirectivePlacement), defaultValue: PreferOutsidePlacementWithSilentEnforcement, "csharp_using_directive_placement"); internal static readonly Option2> UnusedValueExpressionStatement = CodeStyleHelpers.CreateUnusedExpressionAssignmentOption( @@ -313,18 +267,16 @@ private static Option2 CreateOption(OptionGroup group, string name, T defa public static readonly Option2> ImplicitObjectCreationWhenTypeIsApparent = CreateOption( CSharpCodeStyleOptionGroups.ExpressionLevelPreferences, nameof(ImplicitObjectCreationWhenTypeIsApparent), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_implicit_object_creation_when_type_is_apparent"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.ImplicitObjectCreationWhenTypeIsApparent")}); + "csharp_style_implicit_object_creation_when_type_is_apparent", + "TextEditor.CSharp.Specific.ImplicitObjectCreationWhenTypeIsApparent"); #if false public static readonly Option2> VarElsewhere = CreateOption( CSharpCodeStyleOptionGroups.VarPreferences, nameof(VarElsewhere), defaultValue: s_trueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("csharp_style_var_elsewhere"), - new RoamingProfileStorageLocation("TextEditor.CSharp.Specific.UseImplicitTypeWherePossible")}); + "csharp_style_var_elsewhere", + "TextEditor.CSharp.Specific.UseImplicitTypeWherePossible"); #endif diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions_Parsing.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions_Parsing.cs index 489ad0d101717..ec1169e3cc556 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions_Parsing.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions_Parsing.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using Microsoft.CodeAnalysis.AddImports; using Microsoft.CodeAnalysis.CodeStyle; @@ -18,36 +16,32 @@ public static CodeStyleOption2 ParseExpressionBodyPref { // optionString must be similar to true:error or when_on_single_line:suggestion. if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(optionString, - out var value, out var notificationOpt)) + @default.Notification, out var value, out var notification)) { - // A notification value must be provided. - if (notificationOpt != null) + if (bool.TryParse(value, out var boolValue)) { - if (bool.TryParse(value, out var boolValue)) - { - return boolValue - ? new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, notificationOpt) - : new CodeStyleOption2(ExpressionBodyPreference.Never, notificationOpt); - } + return boolValue + ? new CodeStyleOption2(ExpressionBodyPreference.WhenPossible, notification) + : new CodeStyleOption2(ExpressionBodyPreference.Never, notification); + } - if (value == "when_on_single_line") - { - return new CodeStyleOption2(ExpressionBodyPreference.WhenOnSingleLine, notificationOpt); - } + if (value == "when_on_single_line") + { + return new CodeStyleOption2(ExpressionBodyPreference.WhenOnSingleLine, notification); } } return @default; } - private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOption2 value) + private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOption2 value, CodeStyleOption2 defaultValue) { - var notificationString = value.Notification.ToEditorConfigString(); + var notificationString = CodeStyleHelpers.GetEditorConfigStringNotificationPart(value, defaultValue); return value.Value switch { - ExpressionBodyPreference.Never => $"false:{notificationString}", - ExpressionBodyPreference.WhenPossible => $"true:{notificationString}", - ExpressionBodyPreference.WhenOnSingleLine => $"when_on_single_line:{notificationString}", + ExpressionBodyPreference.Never => $"false{notificationString}", + ExpressionBodyPreference.WhenPossible => $"true{notificationString}", + ExpressionBodyPreference.WhenOnSingleLine => $"when_on_single_line{notificationString}", _ => throw new NotSupportedException(), }; } @@ -55,32 +49,27 @@ private static string GetExpressionBodyPreferenceEditorConfigString(CodeStyleOpt public static CodeStyleOption2 ParseUsingDirectivesPlacement( string optionString, CodeStyleOption2 @default) { - // optionString must be similar to outside_namespace:error or inside_namespace:suggestion. if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification( - optionString, out var value, out var notificationOpt)) + optionString, @default.Notification, out var value, out var notification)) { - // A notification value must be provided. - if (notificationOpt != null) + return value switch { - return value switch - { - "inside_namespace" => new CodeStyleOption2(AddImportPlacement.InsideNamespace, notificationOpt), - "outside_namespace" => new CodeStyleOption2(AddImportPlacement.OutsideNamespace, notificationOpt), - _ => throw new NotSupportedException(), - }; - } + "inside_namespace" => new CodeStyleOption2(AddImportPlacement.InsideNamespace, notification), + "outside_namespace" => new CodeStyleOption2(AddImportPlacement.OutsideNamespace, notification), + _ => throw new NotSupportedException(), + }; } return @default; } - public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOption2 value) + public static string GetUsingDirectivesPlacementEditorConfigString(CodeStyleOption2 value, CodeStyleOption2 defaultValue) { - var notificationString = value.Notification.ToEditorConfigString(); + var notificationString = CodeStyleHelpers.GetEditorConfigStringNotificationPart(value, defaultValue); return value.Value switch { - AddImportPlacement.InsideNamespace => $"inside_namespace:{notificationString}", - AddImportPlacement.OutsideNamespace => $"outside_namespace:{notificationString}", + AddImportPlacement.InsideNamespace => $"inside_namespace{notificationString}", + AddImportPlacement.OutsideNamespace => $"outside_namespace{notificationString}", _ => throw new NotSupportedException(), }; } @@ -91,17 +80,15 @@ private static CodeStyleOption2 ParsePreferBracesPrefere { if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification( optionString, + defaultValue.Notification, out var value, out var notificationOption)) { - if (notificationOption != null) + if (bool.TryParse(value, out var boolValue)) { - if (bool.TryParse(value, out var boolValue)) - { - return boolValue - ? new CodeStyleOption2(PreferBracesPreference.Always, notificationOption) - : new CodeStyleOption2(PreferBracesPreference.None, notificationOption); - } + return boolValue + ? new CodeStyleOption2(PreferBracesPreference.Always, notificationOption) + : new CodeStyleOption2(PreferBracesPreference.None, notificationOption); } if (value == "when_multiline") @@ -113,14 +100,14 @@ private static CodeStyleOption2 ParsePreferBracesPrefere return defaultValue; } - private static string GetPreferBracesPreferenceEditorConfigString(CodeStyleOption2 value) + private static string GetPreferBracesPreferenceEditorConfigString(CodeStyleOption2 value, CodeStyleOption2 defaultValue) { - var notificationString = value.Notification.ToEditorConfigString(); + var notificationString = CodeStyleHelpers.GetEditorConfigStringNotificationPart(value, defaultValue); return value.Value switch { - PreferBracesPreference.None => $"false:{notificationString}", - PreferBracesPreference.WhenMultiline => $"when_multiline:{notificationString}", - PreferBracesPreference.Always => $"true:{notificationString}", + PreferBracesPreference.None => $"false{notificationString}", + PreferBracesPreference.WhenMultiline => $"when_multiline{notificationString}", + PreferBracesPreference.Always => $"true{notificationString}", _ => throw ExceptionUtilities.Unreachable, }; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs index 1c18cad2c072f..96aa6ee0ea1b2 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleHelpers.cs @@ -2,10 +2,9 @@ // 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.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Options; using Roslyn.Utilities; @@ -13,12 +12,12 @@ namespace Microsoft.CodeAnalysis.CodeStyle { internal static class CodeStyleHelpers { - public static bool TryParseStringEditorConfigCodeStyleOption(string arg, out CodeStyleOption2 option) + public static bool TryParseStringEditorConfigCodeStyleOption(string arg, CodeStyleOption2 defaultValue, [NotNullWhen(true)] out CodeStyleOption2? option) { if (TryGetCodeStyleValueAndOptionalNotification( - arg, out var value, out var notificationOpt)) + arg, defaultValue.Notification, out var value, out var notification)) { - option = new CodeStyleOption2(value, notificationOpt ?? NotificationOption2.Silent); + option = new CodeStyleOption2(value, notification); return true; } @@ -26,55 +25,50 @@ public static bool TryParseStringEditorConfigCodeStyleOption(string arg, out Cod return false; } - public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, out CodeStyleOption2 option) + public static bool TryParseBoolEditorConfigCodeStyleOption(string arg, CodeStyleOption2 defaultValue, out CodeStyleOption2 option) { if (TryGetCodeStyleValueAndOptionalNotification( - arg, out var value, out var notificationOpt)) + arg, defaultValue.Notification, out var value, out var notification)) { // First value has to be true or false. Anything else is unsupported. if (bool.TryParse(value, out var isEnabled)) { - // We allow 'false' to be provided without a notification option. However, - // 'true' must always be provided with a notification option. - if (isEnabled == false) - { - notificationOpt ??= NotificationOption2.Silent; - option = new CodeStyleOption2(false, notificationOpt); - return true; - } - else if (notificationOpt != null) - { - option = new CodeStyleOption2(true, notificationOpt); - return true; - } + option = new CodeStyleOption2(isEnabled, notification); + return true; } } - option = CodeStyleOption2.Default; + option = defaultValue; return false; } + /// + /// Given an editor-config code-style-option, gives back the core value part of the + /// option. For example, if the option is "true:error" or "true" then "true" will be returned + /// in . + /// + public static bool TryGetCodeStyleValue( + string arg, [NotNullWhen(true)] out string? value) + => TryGetCodeStyleValueAndOptionalNotification(arg, defaultNotification: NotificationOption2.None, out value, out _); + /// /// Given an editor-config code-style-option, gives back the constituent parts of the /// option. For example, if the option is "true:error" then "true" will be returned /// in and will be returned - /// in . Note that users are allowed to not provide - /// a NotificationOption, so may be null. The caller - /// of this method must decide what to do in that case. + /// in . Note that users are allowed to not provide + /// a NotificationOption, so will default to . /// public static bool TryGetCodeStyleValueAndOptionalNotification( - string arg, out string value, out NotificationOption2 notificationOpt) + string arg, NotificationOption2 defaultNotification, [NotNullWhen(true)] out string? value, [NotNullWhen(true)] out NotificationOption2? notification) { var args = arg.Split(':'); Debug.Assert(args.Length > 0); - // We allow a single value to be provided in some cases. For example users - // can provide 'false' without supplying a notification as well. Allow the - // caller of this to determine what to do in this case. + // We allow a single value to be provided without an explicit notification. if (args.Length == 1) { value = args[0].Trim(); - notificationOpt = null; + notification = defaultNotification; return true; } @@ -85,18 +79,18 @@ public static bool TryGetCodeStyleValueAndOptionalNotification( if (TryParseNotification(args[1], out var localNotification)) { value = args[0].Trim(); - notificationOpt = localNotification; + notification = localNotification; return true; } } // We only support 0 or 1 args. Anything else can't be parsed properly. value = null; - notificationOpt = null; + notification = null; return false; } - public static bool TryParseNotification(string value, out NotificationOption2 notification) + private static bool TryParseNotification(string value, out NotificationOption2 notification) { switch (value.Trim()) { @@ -158,7 +152,7 @@ public static Option2> CreateUnusedExpre new EditorConfigStorageLocation>( editorConfigName, s => ParseUnusedExpressionAssignmentPreference(s, defaultValue), - o => GetUnusedExpressionAssignmentPreferenceEditorConfigString(o, defaultValue.Value)), + o => GetUnusedExpressionAssignmentPreferenceEditorConfigString(o, defaultValue)), new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{name}Preference")}); private static Optional> ParseUnusedExpressionAssignmentPreference( @@ -166,20 +160,25 @@ private static Optional> ParseUnusedExpr CodeStyleOption2 defaultCodeStyleOption) { if (TryGetCodeStyleValueAndOptionalNotification(optionString, - out var value, out var notificationOpt)) + defaultCodeStyleOption.Notification, out var value, out var notification)) { return new CodeStyleOption2( - s_unusedExpressionAssignmentPreferenceMap.GetValueOrDefault(value), notificationOpt ?? defaultCodeStyleOption.Notification); + s_unusedExpressionAssignmentPreferenceMap.GetValueOrDefault(value), notification); } return s_preferNoneUnusedValuePreference; } - private static string GetUnusedExpressionAssignmentPreferenceEditorConfigString(CodeStyleOption2 option, UnusedValuePreference defaultPreference) + private static string GetUnusedExpressionAssignmentPreferenceEditorConfigString(CodeStyleOption2 option, CodeStyleOption2 defaultValue) { Debug.Assert(s_unusedExpressionAssignmentPreferenceMap.ContainsValue(option.Value)); - var value = s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(defaultPreference); - return $"{value}:{option.Notification.ToEditorConfigString()}"; + var value = s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedExpressionAssignmentPreferenceMap.GetKeyOrDefault(defaultValue.Value); + return $"{value}{GetEditorConfigStringNotificationPart(option, defaultValue)}"; } + + internal static string GetEditorConfigStringNotificationPart(CodeStyleOption2 option, CodeStyleOption2 defaultValue) + => option.Notification != defaultValue.Notification + ? $":{option.Notification.ToEditorConfigString()}" + : string.Empty; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs index 7538bffc15f77..5c022eb7b427d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/CodeStyleOptions2.cs @@ -30,6 +30,9 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, return option; } + private static PerLanguageOption2> CreateOption(OptionGroup group, string name, CodeStyleOption2 defaultValue, string editorconfigKeyName, string roamingProfileStorageKeyName) + => CreateOption(group, name, defaultValue, EditorConfigStorageLocation.ForBoolCodeStyleOption(editorconfigKeyName, defaultValue), new RoamingProfileStorageLocation(roamingProfileStorageKeyName)); + /// /// When user preferences are not yet set for a style, we fall back to the default value. /// One such default(s), is that the feature is turned on, so that codegen consumes it, @@ -40,45 +43,37 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, internal static readonly CodeStyleOption2 TrueWithSuggestionEnforcement = new(value: true, notification: NotificationOption2.Suggestion); internal static readonly CodeStyleOption2 FalseWithSuggestionEnforcement = new(value: false, notification: NotificationOption2.Suggestion); + private static PerLanguageOption2> CreateQualifyAccessOption(string optionName, string editorconfigKeyName) + => CreateOption( + CodeStyleOptionGroups.ThisOrMe, + optionName, + defaultValue: CodeStyleOption2.Default, + editorconfigKeyName, + $"TextEditor.%LANGUAGE%.Specific.{optionName}"); + /// /// This option says if we should simplify away the . or . in field access expressions. /// - public static readonly PerLanguageOption2> QualifyFieldAccess = CreateOption( - CodeStyleOptionGroups.ThisOrMe, nameof(QualifyFieldAccess), - defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_qualification_for_field"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyFieldAccess")}); + public static readonly PerLanguageOption2> QualifyFieldAccess = CreateQualifyAccessOption( + nameof(QualifyFieldAccess), "dotnet_style_qualification_for_field"); /// /// This option says if we should simplify away the . or . in property access expressions. /// - public static readonly PerLanguageOption2> QualifyPropertyAccess = CreateOption( - CodeStyleOptionGroups.ThisOrMe, nameof(QualifyPropertyAccess), - defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_qualification_for_property"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyPropertyAccess")}); + public static readonly PerLanguageOption2> QualifyPropertyAccess = CreateQualifyAccessOption( + nameof(QualifyPropertyAccess), "dotnet_style_qualification_for_property"); /// /// This option says if we should simplify away the . or . in method access expressions. /// - public static readonly PerLanguageOption2> QualifyMethodAccess = CreateOption( - CodeStyleOptionGroups.ThisOrMe, nameof(QualifyMethodAccess), - defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_qualification_for_method"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyMethodAccess")}); + public static readonly PerLanguageOption2> QualifyMethodAccess = CreateQualifyAccessOption( + nameof(QualifyMethodAccess), "dotnet_style_qualification_for_method"); /// /// This option says if we should simplify away the . or . in event access expressions. /// - public static readonly PerLanguageOption2> QualifyEventAccess = CreateOption( - CodeStyleOptionGroups.ThisOrMe, nameof(QualifyEventAccess), - defaultValue: CodeStyleOption2.Default, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_qualification_for_event"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyEventAccess")}); + public static readonly PerLanguageOption2> QualifyEventAccess = CreateQualifyAccessOption( + nameof(QualifyEventAccess), "dotnet_style_qualification_for_event"); /// /// This option says if we should prefer keyword for Intrinsic Predefined Types in Declarations @@ -86,9 +81,8 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, public static readonly PerLanguageOption2> PreferIntrinsicPredefinedTypeKeywordInDeclaration = CreateOption( CodeStyleOptionGroups.PredefinedTypeNameUsage, nameof(PreferIntrinsicPredefinedTypeKeywordInDeclaration), defaultValue: TrueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_predefined_type_for_locals_parameters_members"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInDeclaration.CodeStyle")}); + "dotnet_style_predefined_type_for_locals_parameters_members", + "TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInDeclaration.CodeStyle"); /// /// This option says if we should prefer keyword for Intrinsic Predefined Types in Member Access Expression @@ -96,23 +90,20 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, public static readonly PerLanguageOption2> PreferIntrinsicPredefinedTypeKeywordInMemberAccess = CreateOption( CodeStyleOptionGroups.PredefinedTypeNameUsage, nameof(PreferIntrinsicPredefinedTypeKeywordInMemberAccess), defaultValue: TrueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_predefined_type_for_member_access"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInMemberAccess.CodeStyle")}); + "dotnet_style_predefined_type_for_member_access", + "TextEditor.%LANGUAGE%.Specific.PreferIntrinsicPredefinedTypeKeywordInMemberAccess.CodeStyle"); internal static readonly PerLanguageOption2> PreferObjectInitializer = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferObjectInitializer), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_object_initializer"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer")}); + "dotnet_style_object_initializer", + "TextEditor.%LANGUAGE%.Specific.PreferObjectInitializer"); internal static readonly PerLanguageOption2> PreferCollectionInitializer = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCollectionInitializer), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_collection_initializer"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.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( @@ -128,9 +119,8 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, internal static readonly PerLanguageOption2> PreferSimplifiedBooleanExpressions = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSimplifiedBooleanExpressions), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_simplified_boolean_expressions"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferSimplifiedBooleanExpressions")}); + "dotnet_style_prefer_simplified_boolean_expressions", + "TextEditor.%LANGUAGE%.Specific.PreferSimplifiedBooleanExpressions"); internal static readonly PerLanguageOption2 OperatorPlacementWhenWrapping = CreateOption( @@ -146,83 +136,70 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, internal static readonly PerLanguageOption2> PreferCoalesceExpression = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCoalesceExpression), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_coalesce_expression"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferCoalesceExpression") }); + "dotnet_style_coalesce_expression", + "TextEditor.%LANGUAGE%.Specific.PreferCoalesceExpression"); internal static readonly PerLanguageOption2> PreferNullPropagation = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferNullPropagation), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_null_propagation"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferNullPropagation") }); + "dotnet_style_null_propagation", + "TextEditor.%LANGUAGE%.Specific.PreferNullPropagation"); internal static readonly PerLanguageOption2> PreferExplicitTupleNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferExplicitTupleNames), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_explicit_tuple_names"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferExplicitTupleNames") }); + "dotnet_style_explicit_tuple_names", + "TextEditor.%LANGUAGE%.Specific.PreferExplicitTupleNames"); internal static readonly PerLanguageOption2> PreferAutoProperties = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferAutoProperties), defaultValue: TrueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_auto_properties"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferAutoProperties") }); + "dotnet_style_prefer_auto_properties", + "TextEditor.%LANGUAGE%.Specific.PreferAutoProperties"); internal static readonly PerLanguageOption2> PreferInferredTupleNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInferredTupleNames), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_inferred_tuple_names"), - new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredTupleNames)}") }); + "dotnet_style_prefer_inferred_tuple_names", + $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredTupleNames)}"); internal static readonly PerLanguageOption2> PreferInferredAnonymousTypeMemberNames = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferInferredAnonymousTypeMemberNames), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[] { - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_inferred_anonymous_type_member_names"), - new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredAnonymousTypeMemberNames)}") }); + "dotnet_style_prefer_inferred_anonymous_type_member_names", + $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferInferredAnonymousTypeMemberNames)}"); internal static readonly PerLanguageOption2> PreferIsNullCheckOverReferenceEqualityMethod = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferIsNullCheckOverReferenceEqualityMethod), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_is_null_check_over_reference_equality_method"), - new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(PreferIsNullCheckOverReferenceEqualityMethod)}") }); + "dotnet_style_prefer_is_null_check_over_reference_equality_method", + $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferIsNullCheckOverReferenceEqualityMethod)}"); internal static readonly PerLanguageOption2> PreferConditionalExpressionOverAssignment = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferConditionalExpressionOverAssignment), defaultValue: TrueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_conditional_expression_over_assignment"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverAssignment")}); + "dotnet_style_prefer_conditional_expression_over_assignment", + "TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverAssignment"); internal static readonly PerLanguageOption2> PreferConditionalExpressionOverReturn = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferConditionalExpressionOverReturn), defaultValue: TrueWithSilentEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_conditional_expression_over_return"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverReturn")}); + "dotnet_style_prefer_conditional_expression_over_return", + "TextEditor.%LANGUAGE%.Specific.PreferConditionalExpressionOverReturn"); internal static readonly PerLanguageOption2> PreferCompoundAssignment = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCompoundAssignment), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_compound_assignment"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferCompoundAssignment") }); + "dotnet_style_prefer_compound_assignment", + "TextEditor.%LANGUAGE%.Specific.PreferCompoundAssignment"); internal static readonly PerLanguageOption2> PreferSimplifiedInterpolation = CreateOption( CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferSimplifiedInterpolation), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_prefer_simplified_interpolation"), - new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(PreferSimplifiedInterpolation)}") }); + "dotnet_style_prefer_simplified_interpolation", + $"TextEditor.%LANGUAGE%.Specific.{nameof(PreferSimplifiedInterpolation)}"); - private static readonly CodeStyleOption2 s_preferNoneUnusedParametersPreference = - new(default, NotificationOption2.None); private static readonly CodeStyleOption2 s_preferAllMethodsUnusedParametersPreference = new(UnusedParametersPreference.AllMethods, NotificationOption2.Suggestion); @@ -235,8 +212,8 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, storageLocations: new OptionStorageLocation2[]{ new EditorConfigStorageLocation>( "dotnet_code_quality_unused_parameters", - ParseUnusedParametersPreference, - o => GetUnusedParametersPreferenceEditorConfigString(o, s_preferAllMethodsUnusedParametersPreference.Value)), + s => ParseUnusedParametersPreference(s, s_preferAllMethodsUnusedParametersPreference), + o => GetUnusedParametersPreferenceEditorConfigString(o, s_preferAllMethodsUnusedParametersPreference)), new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{nameof(UnusedParameters)}Preference") }); private static readonly CodeStyleOption2 s_requireAccessibilityModifiersDefault = @@ -249,16 +226,15 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, storageLocations: new OptionStorageLocation2[]{ new EditorConfigStorageLocation>( "dotnet_style_require_accessibility_modifiers", - s => ParseAccessibilityModifiersRequired(s), - GetAccessibilityModifiersRequiredEditorConfigString), + s => ParseAccessibilityModifiersRequired(s, s_requireAccessibilityModifiersDefault), + v => GetAccessibilityModifiersRequiredEditorConfigString(v, s_requireAccessibilityModifiersDefault)), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.RequireAccessibilityModifiers")}); internal static readonly PerLanguageOption2> PreferReadonly = CreateOption( CodeStyleOptionGroups.Field, nameof(PreferReadonly), defaultValue: TrueWithSuggestionEnforcement, - storageLocations: new OptionStorageLocation2[]{ - EditorConfigStorageLocation.ForBoolCodeStyleOption("dotnet_style_readonly_field"), - new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferReadonly") }); + "dotnet_style_readonly_field", + "TextEditor.%LANGUAGE%.Specific.PreferReadonly"); internal static readonly Option2 FileHeaderTemplate = CreateCommonOption( CodeStyleOptionGroups.Usings, nameof(FileHeaderTemplate), @@ -282,28 +258,19 @@ private static Option2 CreateCommonOption(OptionGroup group, string name, KeyValuePairUtil.Create("omit_if_default", AccessibilityModifiersRequired.OmitIfDefault), }); - private static CodeStyleOption2 ParseAccessibilityModifiersRequired(string optionString) + private static CodeStyleOption2 ParseAccessibilityModifiersRequired(string optionString, CodeStyleOption2 defaultValue) { if (TryGetCodeStyleValueAndOptionalNotification(optionString, - out var value, out var notificationOpt)) + defaultValue.Notification, out var value, out var notificationOpt)) { - if (value == "never") - { - // If they provide 'never', they don't need a notification level. - notificationOpt ??= NotificationOption2.Silent; - } - - if (notificationOpt is object) - { - Debug.Assert(s_accessibilityModifiersRequiredMap.ContainsKey(value)); - return new CodeStyleOption2(s_accessibilityModifiersRequiredMap.GetValueOrDefault(value), notificationOpt); - } + Debug.Assert(s_accessibilityModifiersRequiredMap.ContainsKey(value)); + return new CodeStyleOption2(s_accessibilityModifiersRequiredMap.GetValueOrDefault(value), notificationOpt); } return s_requireAccessibilityModifiersDefault; } - private static string GetAccessibilityModifiersRequiredEditorConfigString(CodeStyleOption2 option) + private static string GetAccessibilityModifiersRequiredEditorConfigString(CodeStyleOption2 option, CodeStyleOption2 defaultValue) { // If they provide 'never', they don't need a notification level. if (option.Notification == null) @@ -313,7 +280,7 @@ private static string GetAccessibilityModifiersRequiredEditorConfigString(CodeSt } Debug.Assert(s_accessibilityModifiersRequiredMap.ContainsValue(option.Value)); - return $"{s_accessibilityModifiersRequiredMap.GetKeyOrDefault(option.Value)}:{option.Notification.ToEditorConfigString()}"; + return $"{s_accessibilityModifiersRequiredMap.GetKeyOrDefault(option.Value)}{GetEditorConfigStringNotificationPart(option, defaultValue)}"; } private static readonly CodeStyleOption2 s_alwaysForClarityPreference = @@ -332,7 +299,7 @@ private static PerLanguageOption2> Creat new EditorConfigStorageLocation>( styleName, s => ParseParenthesesPreference(s, defaultValue), - v => GetParenthesesPreferenceEditorConfigString(v)), + v => GetParenthesesPreferenceEditorConfigString(v, defaultValue)), new RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{fieldName}Preference")}); } @@ -388,44 +355,42 @@ static CodeStyleOptions2() AllOptions = s_allOptionsBuilder.ToImmutable(); } - private static Optional> ParseParenthesesPreference( - string optionString, Optional> defaultValue) + private static CodeStyleOption2 ParseParenthesesPreference( + string optionString, CodeStyleOption2 defaultValue) { if (TryGetCodeStyleValueAndOptionalNotification(optionString, - out var value, out var notificationOpt)) + defaultValue.Notification, out var value, out var notification)) { Debug.Assert(s_parenthesesPreferenceMap.ContainsKey(value)); - return new CodeStyleOption2(s_parenthesesPreferenceMap.GetValueOrDefault(value), - notificationOpt ?? NotificationOption2.Silent); + return new CodeStyleOption2(s_parenthesesPreferenceMap.GetValueOrDefault(value), notification); } return defaultValue; } - private static string GetParenthesesPreferenceEditorConfigString(CodeStyleOption2 option) + private static string GetParenthesesPreferenceEditorConfigString(CodeStyleOption2 option, CodeStyleOption2 defaultValue) { Debug.Assert(s_parenthesesPreferenceMap.ContainsValue(option.Value)); var value = s_parenthesesPreferenceMap.GetKeyOrDefault(option.Value) ?? s_parenthesesPreferenceMap.GetKeyOrDefault(ParenthesesPreference.AlwaysForClarity); - return option.Notification == null ? value : $"{value}:{option.Notification.ToEditorConfigString()}"; + return option.Notification == null ? value : $"{value}{GetEditorConfigStringNotificationPart(option, defaultValue)}"; } - private static Optional> ParseUnusedParametersPreference(string optionString) + private static CodeStyleOption2 ParseUnusedParametersPreference(string optionString, CodeStyleOption2 defaultValue) { if (TryGetCodeStyleValueAndOptionalNotification(optionString, - out var value, out var notificationOpt)) + defaultValue.Notification, out var value, out var notification)) { - return new CodeStyleOption2( - s_unusedParametersPreferenceMap.GetValueOrDefault(value), notificationOpt ?? NotificationOption2.Suggestion); + return new CodeStyleOption2(s_unusedParametersPreferenceMap.GetValueOrDefault(value), notification); } - return s_preferNoneUnusedParametersPreference; + return defaultValue; } - private static string GetUnusedParametersPreferenceEditorConfigString(CodeStyleOption2 option, UnusedParametersPreference defaultPreference) + private static string GetUnusedParametersPreferenceEditorConfigString(CodeStyleOption2 option, CodeStyleOption2 defaultValue) { Debug.Assert(s_unusedParametersPreferenceMap.ContainsValue(option.Value)); - var value = s_unusedParametersPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedParametersPreferenceMap.GetKeyOrDefault(defaultPreference); - return option.Notification == null ? value : $"{value}:{option.Notification.ToEditorConfigString()}"; + var value = s_unusedParametersPreferenceMap.GetKeyOrDefault(option.Value) ?? s_unusedParametersPreferenceMap.GetKeyOrDefault(defaultValue.Value); + return option.Notification == null ? value : $"{value}{GetEditorConfigStringNotificationPart(option, defaultValue)}"; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/OperatorPlacementWhenWrappingPreference.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/OperatorPlacementWhenWrappingPreference.cs index 3077a91c26647..3daec21b060b4 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/OperatorPlacementWhenWrappingPreference.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CodeStyle/OperatorPlacementWhenWrappingPreference.cs @@ -23,8 +23,7 @@ public static string GetEditorConfigString(OperatorPlacementWhenWrappingPreferen public static Optional Parse(string optionString) { - if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification( - optionString, out var value, out _)) + if (CodeStyleHelpers.TryGetCodeStyleValue(optionString, out var value)) { switch (value) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/StringExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/StringExtensions.cs index 40b6c034dcbe9..5278f26f4b276 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/StringExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/StringExtensions.cs @@ -26,6 +26,21 @@ internal static class StringExtensions return null; } + public static int? GetLastNonWhitespaceOffset(this string line) + { + Contract.ThrowIfNull(line); + + for (var i = line.Length - 1; i >= 0; i--) + { + if (!char.IsWhiteSpace(line[i])) + { + return i; + } + } + + return null; + } + public static string GetLeadingWhitespace(this string lineText) { Contract.ThrowIfNull(lineText); @@ -37,6 +52,17 @@ public static string GetLeadingWhitespace(this string lineText) : lineText; } + public static string GetTrailingWhitespace(this string lineText) + { + Contract.ThrowIfNull(lineText); + + var lastOffset = lineText.GetLastNonWhitespaceOffset(); + + return lastOffset.HasValue && lastOffset.Value < lineText.Length + ? lineText.Substring(lastOffset.Value + 1) + : string.Empty; + } + public static int GetTextColumn(this string text, int tabSize, int initialColumn) { var lineText = text.GetLastLineText(); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Options/EditorConfig/EditorConfigStorageLocation.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Options/EditorConfig/EditorConfigStorageLocation.cs index a9f3bb9009823..2fd26e4d3dbe7 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Options/EditorConfig/EditorConfigStorageLocation.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Options/EditorConfig/EditorConfigStorageLocation.cs @@ -18,11 +18,11 @@ public static EditorConfigStorageLocation ForInt32Option(string keyName) public static EditorConfigStorageLocation ForStringOption(string keyName, string emptyStringRepresentation) => new(keyName, s_parseString, (string value) => string.IsNullOrEmpty(value) ? emptyStringRepresentation : s_getStringEditorConfigStringForValue(value)); - public static EditorConfigStorageLocation> ForBoolCodeStyleOption(string keyName) - => new(keyName, s_parseBoolCodeStyleOption, s_getBoolCodeStyleOptionEditorConfigStringForValue); + public static EditorConfigStorageLocation> ForBoolCodeStyleOption(string keyName, CodeStyleOption2 defaultValue) + => new(keyName, str => ParseBoolCodeStyleOption(str, defaultValue), value => GetBoolCodeStyleOptionEditorConfigStringForValue(value, defaultValue)); - public static EditorConfigStorageLocation> ForStringCodeStyleOption(string keyName) - => new(keyName, s_parseStringCodeStyleOption, s_getStringCodeStyleOptionEditorConfigStringForValue); + public static EditorConfigStorageLocation> ForStringCodeStyleOption(string keyName, CodeStyleOption2 defaultValue) + => new(keyName, str => ParseStringCodeStyleOption(str, defaultValue), value => GetStringCodeStyleOptionEditorConfigStringForValue(value, defaultValue)); private static readonly Func> s_parseBool = ParseBool; private static Optional ParseBool(string str) @@ -52,18 +52,14 @@ private static Optional ParseString(string str) private static readonly Func s_getStringEditorConfigStringForValue = GetStringEditorConfigStringForValue; private static string GetStringEditorConfigStringForValue(string value) => value.ToString().Replace("\r", "\\r").Replace("\n", "\\n"); - private static readonly Func>> s_parseBoolCodeStyleOption = ParseBoolCodeStyleOption; - private static Optional> ParseBoolCodeStyleOption(string str) - => CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(str, out var result) ? result : new Optional>(); - private static readonly Func, string> s_getBoolCodeStyleOptionEditorConfigStringForValue = GetBoolCodeStyleOptionEditorConfigStringForValue; - private static string GetBoolCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2 value) - => $"{(value.Value ? "true" : "false")}:{value.Notification.ToEditorConfigString()}"; + private static Optional> ParseBoolCodeStyleOption(string str, CodeStyleOption2 defaultValue) + => CodeStyleHelpers.TryParseBoolEditorConfigCodeStyleOption(str, defaultValue, out var result) ? result : new Optional>(); + private static string GetBoolCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2 value, CodeStyleOption2 defaultValue) + => $"{(value.Value ? "true" : "false")}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(value, defaultValue)}"; - private static readonly Func>> s_parseStringCodeStyleOption = ParseStringCodeStyleOption; - private static Optional> ParseStringCodeStyleOption(string str) - => CodeStyleHelpers.TryParseStringEditorConfigCodeStyleOption(str, out var result) ? result : new Optional>(); - private static readonly Func, string> s_getStringCodeStyleOptionEditorConfigStringForValue = GetStringCodeStyleOptionEditorConfigStringForValue; - private static string GetStringCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2 value) - => $"{value.Value.ToLowerInvariant()}:{value.Notification.ToEditorConfigString()}"; + private static Optional> ParseStringCodeStyleOption(string str, CodeStyleOption2 defaultValue) + => CodeStyleHelpers.TryParseStringEditorConfigCodeStyleOption(str, defaultValue, out var result) ? result : new Optional>(); + private static string GetStringCodeStyleOptionEditorConfigStringForValue(CodeStyleOption2 value, CodeStyleOption2 defaultValue) + => $"{value.Value.ToLowerInvariant()}{CodeStyleHelpers.GetEditorConfigStringNotificationPart(value, defaultValue)}"; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb index f39146343614c..43be5115ca79b 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/CodeStyle/VisualBasicCodeStyleOptions.vb @@ -18,6 +18,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle Return CodeStyleHelpers.CreateOption(group, NameOf(VisualBasicCodeStyleOptions), name, defaultValue, s_allOptionsBuilder, storageLocations) End Function + Private Shared Function CreateOption(group As OptionGroup, name As String, defaultValue As CodeStyleOption2(Of Boolean), editorconfigKeyName As String, roamingProfileStorageKeyName As String) As [Option2](Of CodeStyleOption2(Of Boolean)) + Return CreateOption(group, name, defaultValue, EditorConfigStorageLocation.ForBoolCodeStyleOption(editorconfigKeyName, defaultValue), New RoamingProfileStorageLocation(roamingProfileStorageKeyName)) + End Function + + Private Shared Function CreateOption(group As OptionGroup, name As String, defaultValue As CodeStyleOption2(Of String), editorconfigKeyName As String, roamingProfileStorageKeyName As String) As [Option2](Of CodeStyleOption2(Of String)) + Return CreateOption(group, name, defaultValue, EditorConfigStorageLocation.ForStringCodeStyleOption(editorconfigKeyName, defaultValue), New RoamingProfileStorageLocation(roamingProfileStorageKeyName)) + End Function + Public Shared ReadOnly Property AllOptions As ImmutableArray(Of IOption2) Public Shared ReadOnly PreferredModifierOrderDefault As ImmutableArray(Of SyntaxKind) = @@ -33,14 +41,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeStyle 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), - EditorConfigStorageLocation.ForStringCodeStyleOption("visual_basic_preferred_modifier_order"), - New RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{NameOf(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), - EditorConfigStorageLocation.ForBoolCodeStyleOption("visual_basic_style_prefer_isnot_expression"), - New RoamingProfileStorageLocation($"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferIsNotExpression)}")) + "visual_basic_style_prefer_isnot_expression", + $"TextEditor.%LANGUAGE%.Specific.{NameOf(PreferIsNotExpression)}") Public Shared ReadOnly UnusedValueExpressionStatement As [Option2](Of CodeStyleOption2(Of UnusedValuePreference)) = CodeStyleHelpers.CreateUnusedExpressionAssignmentOption(