diff --git a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs index ed3df972d2c97..bc4c5048dcc2b 100644 --- a/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs +++ b/src/Features/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs @@ -13,7 +13,6 @@ using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.ImplementType; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -1713,7 +1712,7 @@ void Goo() { } public override int Prop => throw new System.NotImplementedException(); } - """, globalOptions: options); + """, options: options); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/17274")] @@ -1910,7 +1909,7 @@ class C : AbstractClass public override int ReadWriteProp { get; set; } public override int WriteOnlyProp { set => throw new System.NotImplementedException(); } } - """, parameters: new TestParameters(globalOptions: options)); + """, parameters: new TestParameters(options: options)); } [Theory, CombinatorialData] diff --git a/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionOrUserDiagnosticTest_NoEditor.cs b/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionOrUserDiagnosticTest_NoEditor.cs index 7d7a155a89239..90e3da1b21eb3 100644 --- a/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionOrUserDiagnosticTest_NoEditor.cs +++ b/src/Features/DiagnosticsTestUtilities/CodeActionsLegacy/AbstractCodeActionOrUserDiagnosticTest_NoEditor.cs @@ -411,7 +411,6 @@ internal Task TestInRegularAndScriptAsync( CodeActionPriority? priority = null, CompilationOptions compilationOptions = null, OptionsCollectionAlias options = null, - OptionsCollectionAlias globalOptions = null, object fixProviderData = null, ParseOptions parseOptions = null, string title = null, @@ -419,7 +418,7 @@ internal Task TestInRegularAndScriptAsync( { return TestInRegularAndScript1Async( initialMarkup, expectedMarkup, - new TestParameters(parseOptions, compilationOptions, options, globalOptions, fixProviderData, index, priority, title: title, testHost: testHost)); + new TestParameters(parseOptions, compilationOptions, options, globalOptions: null, fixProviderData, index, priority, title: title, testHost: testHost)); } internal Task TestInRegularAndScript1Async( diff --git a/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb b/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb index 5ebe68a2a6a6c..423354c18c0ca 100644 --- a/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb +++ b/src/Features/VisualBasicTest/ImplementInterface/ImplementInterfaceTests.vb @@ -4532,7 +4532,7 @@ class Class Throw New System.NotImplementedException() End Set End Property -end class", parameters:=New TestParameters(globalOptions:=[Option](ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties))) +end class", parameters:=New TestParameters(options:=[Option](ImplementTypeOptionsStorage.PropertyGenerationBehavior, ImplementTypePropertyGenerationBehavior.PreferAutoProperties))) End Function End Class End Namespace diff --git a/src/LanguageServer/ProtocolUnitTests/Configuration/DidChangeConfigurationNotificationHandlerTest.cs b/src/LanguageServer/ProtocolUnitTests/Configuration/DidChangeConfigurationNotificationHandlerTest.cs index 394ad082190e0..36898682172ab 100644 --- a/src/LanguageServer/ProtocolUnitTests/Configuration/DidChangeConfigurationNotificationHandlerTest.cs +++ b/src/LanguageServer/ProtocolUnitTests/Configuration/DidChangeConfigurationNotificationHandlerTest.cs @@ -107,13 +107,13 @@ public class A { }"; public void VerifyLspClientOptionNames() { var actualNames = DidChangeConfigurationNotificationHandler.SupportedOptions.Select( - DidChangeConfigurationNotificationHandler.GenerateFullNameForOption).OrderBy(name => name).ToArray(); - // These options are persist in the LSP client. Please make sure also modify the LSP client code if these strings are changed. + DidChangeConfigurationNotificationHandler.GenerateFullNameForOption); + // These options are persisted by the LSP client. Please make sure also modify the LSP client code if these strings are changed. var expectedNames = new[] { "symbol_search.dotnet_search_reference_assemblies", - "implement_type.dotnet_member_insertion_location", - "implement_type.dotnet_property_generation_behavior", + "code_actions.type_members.dotnet_member_insertion_location", + "code_actions.type_members.dotnet_property_generation_behavior", "completion.dotnet_show_name_completion_suggestions", "completion.dotnet_provide_regex_completions", "completion.dotnet_show_completion_items_from_unimported_namespaces", @@ -145,9 +145,9 @@ public void VerifyLspClientOptionNames() "code_lens.dotnet_enable_tests_code_lens", "projects.dotnet_binary_log_path", "projects.dotnet_enable_automatic_restore" - }.OrderBy(name => name); + }; - Assert.Equal(expectedNames, actualNames); + AssertEx.SetEqual(expectedNames, actualNames); } private static void VerifyValuesInServer(EditorTestWorkspace workspace, List expectedValues) diff --git a/src/Workspaces/CoreTest/Options/OptionSerializerTests.cs b/src/Workspaces/CoreTest/Options/OptionSerializerTests.cs index 80dcdc11fd448..6d3d47b0897ab 100644 --- a/src/Workspaces/CoreTest/Options/OptionSerializerTests.cs +++ b/src/Workspaces/CoreTest/Options/OptionSerializerTests.cs @@ -4,10 +4,10 @@ using System; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Editor.InlineDiagnostics; using Microsoft.CodeAnalysis.Editor.Shared.Options; -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.ImplementType; using Microsoft.CodeAnalysis.InheritanceMargin; using Microsoft.CodeAnalysis.Options; @@ -69,8 +69,6 @@ public void SerializationAndDeserializationForEnum() InlineDiagnosticsOptionsStorage.Location, SolutionCrawlerOptionsStorage.BackgroundAnalysisScopeOption, SolutionCrawlerOptionsStorage.CompilerDiagnosticsScopeOption, - ImplementTypeOptionsStorage.InsertionBehavior, - ImplementTypeOptionsStorage.PropertyGenerationBehavior, CompletionOptionsStorage.EnterKeyBehavior, CompletionOptionsStorage.SnippetsBehavior, }; @@ -80,7 +78,7 @@ public void SerializationAndDeserializationForEnum() var defaultValue = option.DefaultValue; // The default value for Enum option should not be null. Contract.ThrowIfNull(defaultValue, $"Option: {option.Name}"); - VerifyEnumValues(option, defaultValue.GetType()); + VerifyEnumValues(option, defaultValue.GetType(), allowsPacalCase: true, allowsSnakeCase: false); // Test invalid cases VerifyEnumInvalidParse(option, defaultValue.GetType()); @@ -103,7 +101,7 @@ public void SerializationAndDeserializationForNullableEnum() Contract.ThrowIfNull(enumType, $"Option: {option.Name}"); // Test enum values - VerifyEnumValues(option, enumType); + VerifyEnumValues(option, enumType, allowsPacalCase: true, allowsSnakeCase: false); // Test null var serializer = option.Definition.Serializer; @@ -118,17 +116,75 @@ public void SerializationAndDeserializationForNullableEnum() } } - private static void VerifyEnumValues(IOption2 option, Type enumType) + [Fact] + public void SerializationAndDeserializationForEnum_SnakeCase() + { + var options = new IOption2[] + { + ImplementTypeOptionsStorage.InsertionBehavior, + ImplementTypeOptionsStorage.PropertyGenerationBehavior, + }; + + foreach (var option in options) + { + var defaultValue = option.DefaultValue; + // The default value for Enum option should not be null. + Contract.ThrowIfNull(defaultValue, $"Option: {option.Name}"); + VerifyEnumValues(option, defaultValue.GetType(), allowsPacalCase: true, allowsSnakeCase: true); + + // Test invalid cases + VerifyEnumInvalidParse(option, defaultValue.GetType()); + } + } + + private static string PascalToSnakeCase(string str) + { + var builder = new StringBuilder(); + var prevIsLower = false; + foreach (var c in str) + { + var lower = char.ToLowerInvariant(c); + var isLower = lower == c; + + if (prevIsLower && !isLower && builder.Length > 0) + { + builder.Append('_'); + } + + builder.Append(lower); + prevIsLower = isLower; + } + + return builder.ToString(); + } + + private static void VerifyEnumValues(IOption2 option, Type enumType, bool allowsSnakeCase, bool allowsPacalCase) { var serializer = option.Definition.Serializer; var possibleEnumValues = enumType.GetEnumValues(); foreach (var enumValue in possibleEnumValues) { var serializedValue = serializer.Serialize(enumValue); - Assert.Equal(enumValue.ToString(), serializedValue); - var success = serializer.TryParse(serializedValue, out var deserializedResult); - Assert.True(success, $"Can't parse option: {option.Name}, value: {serializedValue}"); - Assert.Equal(enumValue, deserializedResult); + var expectedPascalCase = enumValue.ToString()!; + var expectedSnakeCase = PascalToSnakeCase(expectedPascalCase); + + // if option allows snake case it should use it for serialization: + Assert.Equal(allowsSnakeCase ? expectedSnakeCase : expectedPascalCase, serializedValue); + + if (allowsPacalCase) + VerifyParsing(expectedPascalCase); + + if (allowsSnakeCase) + VerifyParsing(expectedSnakeCase); + + void VerifyParsing(string value) + { + Assert.True( + serializer.TryParse(value, out var deserializedResult), + $"Can't parse option: {option.Name}, value: {value}"); + + Assert.Equal(enumValue, deserializedResult); + } } }