From 8178d9cd07a077ab048a5113895608750636e197 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Wed, 16 Nov 2016 21:32:06 -0800 Subject: [PATCH 1/8] moving naming styles types into the workspace layer. Teaching abstract options serialization service about naming styles. --- .../NamingStylesTests_OptionSets.cs | 8 +- .../NamingStyleDiagnosticAnalyzerBase.cs | 10 +- .../SerializableNamingStylePreferencesInfo.cs | 133 ------ src/Features/Core/Portable/Features.csproj | 9 +- .../Portable/FeaturesResources.Designer.cs | 81 ---- .../Core/Portable/FeaturesResources.resx | 27 -- .../CSharp/Impl/Options/AutomationObject.cs | 5 +- .../NamingStyleOptionPageControl.xaml.cs | 8 +- .../AbstractOptionsSerializationService.cs | 45 +- .../Portable}/NamingStyles/Capitalization.cs | 0 .../Core/Portable}/NamingStyles/NamingRule.cs | 0 .../NamingStylePreferencesInfo.cs | 0 .../NamingStyles/Serialization/NamingStyle.cs | 18 +- .../Serialization/SerializableNamingRule.cs | 0 .../SerializableNamingStylePreferencesInfo.cs | 423 ++++++++++++++++++ .../Serialization/SymbolSpecification.cs | 0 .../Core/Portable/PublicAPI.Unshipped.txt | 1 - .../Simplification/SimplificationOptions.cs | 254 +---------- .../Core/Portable/Workspaces.csproj | 7 + .../Portable/WorkspacesResources.Designer.cs | 81 ++++ .../Core/Portable/WorkspacesResources.resx | 28 +- 21 files changed, 604 insertions(+), 534 deletions(-) rename src/Features/Core/Portable/Diagnostics/Analyzers/{NamingStyles => }/NamingStyleDiagnosticAnalyzerBase.cs (84%) delete mode 100644 src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/Capitalization.cs (100%) rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/NamingRule.cs (100%) rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/NamingStylePreferencesInfo.cs (100%) rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/Serialization/NamingStyle.cs (89%) rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/Serialization/SerializableNamingRule.cs (100%) create mode 100644 src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs rename src/{Features/Core/Portable/Diagnostics/Analyzers => Workspaces/Core/Portable}/NamingStyles/Serialization/SymbolSpecification.cs (100%) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs index 4a1dce430c4cf..38e5b7e497272 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs @@ -27,7 +27,7 @@ private IDictionary Options(OptionKey option, object value) return options; } - private string ClassNamesArePascalCaseOptionString() + private SerializableNamingStylePreferencesInfo ClassNamesArePascalCaseOptionString() { var symbolSpecification = new SymbolSpecification( Guid.NewGuid(), @@ -54,10 +54,10 @@ private string ClassNamesArePascalCaseOptionString() info.NamingStyles.Add(namingStyle); info.NamingRules.Add(namingRule); - return info.CreateXElement().ToString(); + return info; } - private string MethodNamesArePascalCaseOptionString() + private SerializableNamingStylePreferencesInfo MethodNamesArePascalCaseOptionString() { var symbolSpecification = new SymbolSpecification( Guid.NewGuid(), @@ -84,7 +84,7 @@ private string MethodNamesArePascalCaseOptionString() info.NamingStyles.Add(namingStyle); info.NamingRules.Add(namingRule); - return info.CreateXElement().ToString(); + return info; } } } \ No newline at end of file diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingStyleDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs similarity index 84% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingStyleDiagnosticAnalyzerBase.cs rename to src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs index 88091d72cdf2d..9e8a0820e1088 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs @@ -42,16 +42,10 @@ private void CompilationStartAction(CompilationStartAnalysisContext context) { var workspace = (context.Options as WorkspaceAnalyzerOptions)?.Workspace; var optionSet = (context.Options as WorkspaceAnalyzerOptions)?.Workspace.Options; - var currentValue = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); + var viewModel = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); - if (!string.IsNullOrEmpty(currentValue)) + if (viewModel != null) { - // Deserializing the naming preference info on every CompilationStart is expensive. - // Instead, the diagnostic engine should listen for option changes and have the - // ability to create the new SerializableNamingStylePreferencesInfo when it detects - // any change. The overall system would then only deserialize & allocate when - // actually necessary. - var viewModel = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(currentValue)); var preferencesInfo = viewModel.GetPreferencesInfo(); context.RegisterSymbolAction( symbolContext => SymbolAction(symbolContext, preferencesInfo), diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs deleted file mode 100644 index 46533044d9dbe..0000000000000 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Microsoft.CodeAnalysis.Simplification; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Xml.Linq; - -namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles -{ - /// - /// Contains all information related to Naming Style Preferences. - /// 1. Symbol Specifications - /// 2. Name Style - /// 3. Naming Rule (points to Symbol Specification IDs) - /// - internal class SerializableNamingStylePreferencesInfo - { - public List SymbolSpecifications; - public List NamingStyles; - public List NamingRules; - private readonly static int s_serializationVersion = 3; - - internal SerializableNamingStylePreferencesInfo() - { - SymbolSpecifications = new List(); - NamingStyles = new List(); - NamingRules = new List(); - } - - internal NamingStyle GetNamingStyle(Guid namingStyleID) - { - return NamingStyles.Single(s => s.ID == namingStyleID); - } - - internal SymbolSpecification GetSymbolSpecification(Guid symbolSpecificationID) - { - return SymbolSpecifications.Single(s => s.ID == symbolSpecificationID); - } - - public NamingStylePreferencesInfo GetPreferencesInfo() - { - return new NamingStylePreferencesInfo(NamingRules.Select(r => r.GetRule(this)).ToImmutableArray()); - } - - internal XElement CreateXElement() - { - return new XElement("NamingPreferencesInfo", - new XAttribute("SerializationVersion", s_serializationVersion), - CreateSymbolSpecificationListXElement(), - CreateNamingStyleListXElement(), - CreateNamingRuleTreeXElement()); - } - - private XElement CreateNamingRuleTreeXElement() - { - var namingRulesElement = new XElement(nameof(NamingRules)); - - foreach (var namingRule in NamingRules) - { - namingRulesElement.Add(namingRule.CreateXElement()); - } - - return namingRulesElement; - } - - private XElement CreateNamingStyleListXElement() - { - var namingStylesElement = new XElement(nameof(NamingStyles)); - - foreach (var namingStyle in NamingStyles) - { - namingStylesElement.Add(namingStyle.CreateXElement()); - } - - return namingStylesElement; - } - - private XElement CreateSymbolSpecificationListXElement() - { - var symbolSpecificationsElement = new XElement(nameof(SymbolSpecifications)); - - foreach (var symbolSpecification in SymbolSpecifications) - { - symbolSpecificationsElement.Add(symbolSpecification.CreateXElement()); - } - - return symbolSpecificationsElement; - } - - internal static SerializableNamingStylePreferencesInfo FromXElement(XElement namingPreferencesInfoElement) - { - var namingPreferencesInfo = new SerializableNamingStylePreferencesInfo(); - - var serializationVersion = int.Parse(namingPreferencesInfoElement.Attribute("SerializationVersion").Value); - if (serializationVersion != s_serializationVersion) - { - namingPreferencesInfoElement = XElement.Parse(SimplificationOptions.NamingPreferences.DefaultValue); - } - - namingPreferencesInfo.SetSymbolSpecificationListFromXElement(namingPreferencesInfoElement.Element(nameof(SymbolSpecifications))); - namingPreferencesInfo.SetNamingStyleListFromXElement(namingPreferencesInfoElement.Element(nameof(NamingStyles))); - namingPreferencesInfo.SetNamingRuleTreeFromXElement(namingPreferencesInfoElement.Element(nameof(NamingRules))); - - return namingPreferencesInfo; - } - - private void SetSymbolSpecificationListFromXElement(XElement symbolSpecificationsElement) - { - foreach (var symbolSpecificationElement in symbolSpecificationsElement.Elements(nameof(SymbolSpecification))) - { - SymbolSpecifications.Add(SymbolSpecification.FromXElement(symbolSpecificationElement)); - } - } - - private void SetNamingStyleListFromXElement(XElement namingStylesElement) - { - foreach (var namingStyleElement in namingStylesElement.Elements(nameof(NamingStyle))) - { - NamingStyles.Add(NamingStyle.FromXElement(namingStyleElement)); - } - } - - private void SetNamingRuleTreeFromXElement(XElement namingRulesElement) - { - foreach (var namingRuleElement in namingRulesElement.Elements(nameof(SerializableNamingRule))) - { - NamingRules.Add(SerializableNamingRule.FromXElement(namingRuleElement)); - } - } - } -} diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj index b3bacc9cddbab..d6c6f65127688 100644 --- a/src/Features/Core/Portable/Features.csproj +++ b/src/Features/Core/Portable/Features.csproj @@ -306,7 +306,6 @@ - @@ -328,13 +327,7 @@ - - - - - - - + diff --git a/src/Features/Core/Portable/FeaturesResources.Designer.cs b/src/Features/Core/Portable/FeaturesResources.Designer.cs index 2eb2d0216710b..cc0d45ea718a1 100644 --- a/src/Features/Core/Portable/FeaturesResources.Designer.cs +++ b/src/Features/Core/Portable/FeaturesResources.Designer.cs @@ -1755,24 +1755,6 @@ internal static string Methods { } } - /// - /// Looks up a localized string similar to Missing prefix: '{0}'. - /// - internal static string Missing_prefix_colon_0 { - get { - return ResourceManager.GetString("Missing_prefix_colon_0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing suffix: '{0}'. - /// - internal static string Missing_suffix_colon_0 { - get { - return ResourceManager.GetString("Missing_suffix_colon_0", resourceCulture); - } - } - /// /// Looks up a localized string similar to Modifying '{0}' which contains a static variable will prevent the debug session from continuing.. /// @@ -2574,24 +2556,6 @@ internal static string The_assembly_0_does_not_contain_any_analyzers { } } - /// - /// Looks up a localized string similar to The first word, '{0}', must begin with a lower case character. - /// - internal static string The_first_word_0_must_begin_with_a_lower_case_character { - get { - return ResourceManager.GetString("The_first_word_0_must_begin_with_a_lower_case_character", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The first word, '{0}', must begin with an upper case character. - /// - internal static string The_first_word_0_must_begin_with_an_upper_case_character { - get { - return ResourceManager.GetString("The_first_word_0_must_begin_with_an_upper_case_character", resourceCulture); - } - } - /// /// Looks up a localized string similar to The member is defined in metadata.. /// @@ -2628,51 +2592,6 @@ internal static string The_symbol_does_not_have_an_icon { } } - /// - /// Looks up a localized string similar to These non-leading words must begin with a lowercase letter: {0}. - /// - internal static string These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0 { - get { - return ResourceManager.GetString("These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to These non-leading words must begin with an upper case letter: {0}. - /// - internal static string These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0 { - get { - return ResourceManager.GetString("These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to These words cannot contain lower case characters: {0}. - /// - internal static string These_words_cannot_contain_lower_case_characters_colon_0 { - get { - return ResourceManager.GetString("These_words_cannot_contain_lower_case_characters_colon_0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to These words cannot contain upper case characters: {0}. - /// - internal static string These_words_cannot_contain_upper_case_characters_colon_0 { - get { - return ResourceManager.GetString("These_words_cannot_contain_upper_case_characters_colon_0", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to These words must begin with upper case characters: {0}. - /// - internal static string These_words_must_begin_with_upper_case_characters_colon_0 { - get { - return ResourceManager.GetString("These_words_must_begin_with_upper_case_characters_colon_0", resourceCulture); - } - } - /// /// Looks up a localized string similar to This signature does not contain parameters that can be changed.. /// diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 043d9bd9c1e0d..0d1dd5af9878e 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -898,33 +898,6 @@ Do you want to continue? Naming rule violation: {0} {0} is the rule title, {1} is the way in which the rule was violated - - The first word, '{0}', must begin with a lower case character - - - The first word, '{0}', must begin with an upper case character - - - Missing prefix: '{0}' - - - Missing suffix: '{0}' - - - These non-leading words must begin with a lowercase letter: {0} - - - These non-leading words must begin with an upper case letter: {0} - - - These words cannot contain lower case characters: {0} - - - These words cannot contain upper case characters: {0} - - - These words must begin with upper case characters: {0} - Naming Styles diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs index 1b5b53e718c0f..8bfd5efdaa22a 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.Completion; using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.ExtractMethod; @@ -533,12 +534,12 @@ public string Style_NamingPreferences { get { - return _workspace.Options.GetOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp); + return _workspace.Options.GetOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp).CreateXElement().ToString(); } set { - _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, value); + _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(value))); } } diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs index a44aedfa5381f..c51c5e5a19188 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs @@ -165,7 +165,7 @@ internal override void SaveSettings() } var oldOptions = OptionService.GetOptions(); - var newOptions = oldOptions.WithChangedOption(SimplificationOptions.NamingPreferences, _languageName, info.CreateXElement().ToString()); + var newOptions = oldOptions.WithChangedOption(SimplificationOptions.NamingPreferences, _languageName, info); OptionService.SetOptions(newOptions); OptionLogger.Log(oldOptions, newOptions); } @@ -174,14 +174,12 @@ internal override void LoadSettings() { base.LoadSettings(); - var options = OptionService.GetOption(SimplificationOptions.NamingPreferences, _languageName); - if (string.IsNullOrEmpty(options)) + var preferencesInfo = this.OptionService.GetOption(SimplificationOptions.NamingPreferences, _languageName); + if (preferencesInfo == null) { return; } - var namingPreferencesXml = this.OptionService.GetOption(SimplificationOptions.NamingPreferences, _languageName); - var preferencesInfo = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(namingPreferencesXml)); _viewModel = new NamingStyleOptionPageViewModel(preferencesInfo); this.DataContext = _viewModel; } diff --git a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs index a04df227e7865..8c0cc044d486a 100644 --- a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs @@ -9,6 +9,8 @@ using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Options; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.Execution { @@ -222,7 +224,6 @@ protected void WriteOptionSetTo(OptionSet options, string language, ObjectWriter WriteOptionTo(options, language, CodeStyleOptions.QualifyEventAccess, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, writer, cancellationToken); - WriteOptionTo(options, language, CodeStyleOptions.PreferCoalesceExpression, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferCollectionInitializer, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferExplicitTupleNames, writer, cancellationToken); @@ -230,6 +231,7 @@ protected void WriteOptionSetTo(OptionSet options, string language, ObjectWriter WriteOptionTo(options, language, CodeStyleOptions.PreferNullPropagation, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferObjectInitializer, writer, cancellationToken); WriteOptionTo(options, language, CodeStyleOptions.PreferThrowExpression, writer, cancellationToken); + WriteOptionTo(options, language, SimplificationOptions.NamingPreferences, writer, cancellationToken); } protected OptionSet ReadOptionSetFrom(OptionSet options, string language, ObjectReader reader, CancellationToken cancellationToken) @@ -242,7 +244,6 @@ protected OptionSet ReadOptionSetFrom(OptionSet options, string language, Object options = ReadOptionFrom(options, language, CodeStyleOptions.QualifyEventAccess, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, reader, cancellationToken); - options = ReadOptionFrom(options, language, CodeStyleOptions.PreferCoalesceExpression, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferCollectionInitializer, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferExplicitTupleNames, reader, cancellationToken); @@ -250,7 +251,7 @@ protected OptionSet ReadOptionSetFrom(OptionSet options, string language, Object options = ReadOptionFrom(options, language, CodeStyleOptions.PreferNullPropagation, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferObjectInitializer, reader, cancellationToken); options = ReadOptionFrom(options, language, CodeStyleOptions.PreferThrowExpression, reader, cancellationToken); - + options = ReadOptionFrom(options, language, SimplificationOptions.NamingPreferences, reader, cancellationToken); return options; } @@ -290,6 +291,42 @@ private OptionSet ReadOptionFrom(OptionSet options, string language, PerLangu return options.WithChangedOption(option, language, value); } + protected void WriteOptionTo(OptionSet options, Option option, ObjectWriter writer, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var value = options.GetOption(option); + writer.WriteString(value.CreateXElement().ToString()); + } + + protected OptionSet ReadOptionFrom(OptionSet options, Option option, ObjectReader reader, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var xmlText = reader.ReadString(); + var value = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(xmlText)); + + return options.WithChangedOption(option, value); + } + + private void WriteOptionTo(OptionSet options, string language, PerLanguageOption option, ObjectWriter writer, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var value = options.GetOption(option, language); + writer.WriteString(value.CreateXElement().ToString()); + } + + private OptionSet ReadOptionFrom(OptionSet options, string language, PerLanguageOption option, ObjectReader reader, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var xmlText = reader.ReadString(); + var value = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(xmlText)); + + return options.WithChangedOption(option, language, value); + } + /// /// this is not real option set. it doesn't have all options defined in host. but only those /// we pre-selected. @@ -325,7 +362,7 @@ internal override IEnumerable GetChangedOptions(OptionSet optionSet) foreach (var kvp in _values) { var currentValue = optionSet.GetOption(kvp.Key); - if (!object.Equals(currentValue, kvp.Value)) + if (currentValue?.Equals(kvp.Value) == false) { yield return kvp.Key; } diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Capitalization.cs b/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs similarity index 100% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Capitalization.cs rename to src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/NamingRule.cs similarity index 100% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingRule.cs rename to src/Workspaces/Core/Portable/NamingStyles/NamingRule.cs diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs similarity index 100% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/NamingStylePreferencesInfo.cs rename to src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs similarity index 89% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/NamingStyle.cs rename to src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs index 0fccebc974a28..afacd0b533560 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs @@ -68,13 +68,13 @@ public bool IsNameCompliant(string name, out string failureReason) if (!name.StartsWith(Prefix)) { - failureReason = string.Format(FeaturesResources.Missing_prefix_colon_0, Prefix); + failureReason = string.Format(WorkspacesResources.Missing_prefix_colon_0, Prefix); return false; } if (!name.EndsWith(Suffix)) { - failureReason = string.Format(FeaturesResources.Missing_suffix_colon_0, Suffix); + failureReason = string.Format(WorkspacesResources.Missing_suffix_colon_0, Suffix); return false; } @@ -104,7 +104,7 @@ public bool IsNameCompliant(string name, out string failureReason) else { var violations = words.Where(w => !char.IsUpper(w[0])); - failureReason = string.Format(FeaturesResources.These_words_must_begin_with_upper_case_characters_colon_0, string.Join(", ", violations)); + failureReason = string.Format(WorkspacesResources.These_words_must_begin_with_upper_case_characters_colon_0, string.Join(", ", violations)); return false; } case Capitalization.CamelCase: @@ -116,7 +116,7 @@ public bool IsNameCompliant(string name, out string failureReason) { if (!char.IsLower(words.First()[0])) { - failureReason = string.Format(FeaturesResources.The_first_word_0_must_begin_with_a_lower_case_character, words.First()); + failureReason = string.Format(WorkspacesResources.The_first_word_0_must_begin_with_a_lower_case_character, words.First()); } var violations = words.Skip(1).Where(w => !char.IsUpper(w[0])); @@ -127,7 +127,7 @@ public bool IsNameCompliant(string name, out string failureReason) failureReason += Environment.NewLine; } - failureReason += string.Format(FeaturesResources.These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0, string.Join(", ", violations)); + failureReason += string.Format(WorkspacesResources.These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0, string.Join(", ", violations)); } return false; @@ -141,7 +141,7 @@ public bool IsNameCompliant(string name, out string failureReason) { if (!char.IsUpper(words.First()[0])) { - failureReason = string.Format(FeaturesResources.The_first_word_0_must_begin_with_an_upper_case_character, words.First()); + failureReason = string.Format(WorkspacesResources.The_first_word_0_must_begin_with_an_upper_case_character, words.First()); } var violations = words.Skip(1).Where(w => !char.IsLower(w[0])); @@ -152,7 +152,7 @@ public bool IsNameCompliant(string name, out string failureReason) failureReason += Environment.NewLine; } - failureReason += string.Format(FeaturesResources.These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0, string.Join(", ", violations)); + failureReason += string.Format(WorkspacesResources.These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0, string.Join(", ", violations)); } return false; @@ -165,7 +165,7 @@ public bool IsNameCompliant(string name, out string failureReason) else { var violations = words.Where(w => !w.ToCharArray().All(c => char.IsUpper(c))); - failureReason = string.Format(FeaturesResources.These_words_cannot_contain_lower_case_characters_colon_0, string.Join(", ", violations)); + failureReason = string.Format(WorkspacesResources.These_words_cannot_contain_lower_case_characters_colon_0, string.Join(", ", violations)); return false; } case Capitalization.AllLower: @@ -176,7 +176,7 @@ public bool IsNameCompliant(string name, out string failureReason) else { var violations = words.Where(w => !w.ToCharArray().All(c => char.IsLower(c))); - failureReason = string.Format(FeaturesResources.These_words_cannot_contain_upper_case_characters_colon_0, string.Join(", ", violations)); + failureReason = string.Format(WorkspacesResources.These_words_cannot_contain_upper_case_characters_colon_0, string.Join(", ", violations)); return false; } default: diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs similarity index 100% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SerializableNamingRule.cs rename to src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs new file mode 100644 index 0000000000000..bd39cc61caccc --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs @@ -0,0 +1,423 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Simplification; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Xml.Linq; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + /// + /// Contains all information related to Naming Style Preferences. + /// 1. Symbol Specifications + /// 2. Name Style + /// 3. Naming Rule (points to Symbol Specification IDs) + /// + internal class SerializableNamingStylePreferencesInfo : IEquatable + { + public List SymbolSpecifications; + public List NamingStyles; + public List NamingRules; + private readonly static int s_serializationVersion = 3; + + internal SerializableNamingStylePreferencesInfo() + { + SymbolSpecifications = new List(); + NamingStyles = new List(); + NamingRules = new List(); + } + + public static SerializableNamingStylePreferencesInfo Default => FromXElement(XElement.Parse(DefaultNamingPreferencesString)); + + public static string DefaultNamingPreferencesString => _defaultNamingPreferencesString; + + internal NamingStyle GetNamingStyle(Guid namingStyleID) + { + return NamingStyles.Single(s => s.ID == namingStyleID); + } + + internal SymbolSpecification GetSymbolSpecification(Guid symbolSpecificationID) + { + return SymbolSpecifications.Single(s => s.ID == symbolSpecificationID); + } + + public NamingStylePreferencesInfo GetPreferencesInfo() + { + return new NamingStylePreferencesInfo(NamingRules.Select(r => r.GetRule(this)).ToImmutableArray()); + } + + internal XElement CreateXElement() + { + return new XElement("NamingPreferencesInfo", + new XAttribute("SerializationVersion", s_serializationVersion), + CreateSymbolSpecificationListXElement(), + CreateNamingStyleListXElement(), + CreateNamingRuleTreeXElement()); + } + + private XElement CreateNamingRuleTreeXElement() + { + var namingRulesElement = new XElement(nameof(NamingRules)); + + foreach (var namingRule in NamingRules) + { + namingRulesElement.Add(namingRule.CreateXElement()); + } + + return namingRulesElement; + } + + private XElement CreateNamingStyleListXElement() + { + var namingStylesElement = new XElement(nameof(NamingStyles)); + + foreach (var namingStyle in NamingStyles) + { + namingStylesElement.Add(namingStyle.CreateXElement()); + } + + return namingStylesElement; + } + + private XElement CreateSymbolSpecificationListXElement() + { + var symbolSpecificationsElement = new XElement(nameof(SymbolSpecifications)); + + foreach (var symbolSpecification in SymbolSpecifications) + { + symbolSpecificationsElement.Add(symbolSpecification.CreateXElement()); + } + + return symbolSpecificationsElement; + } + + internal static SerializableNamingStylePreferencesInfo FromXElement(XElement namingPreferencesInfoElement) + { + var namingPreferencesInfo = new SerializableNamingStylePreferencesInfo(); + + var serializationVersion = int.Parse(namingPreferencesInfoElement.Attribute("SerializationVersion").Value); + if (serializationVersion != s_serializationVersion) + { + namingPreferencesInfoElement = XElement.Parse(DefaultNamingPreferencesString); + } + + namingPreferencesInfo.SetSymbolSpecificationListFromXElement(namingPreferencesInfoElement.Element(nameof(SymbolSpecifications))); + namingPreferencesInfo.SetNamingStyleListFromXElement(namingPreferencesInfoElement.Element(nameof(NamingStyles))); + namingPreferencesInfo.SetNamingRuleTreeFromXElement(namingPreferencesInfoElement.Element(nameof(NamingRules))); + + return namingPreferencesInfo; + } + + private void SetSymbolSpecificationListFromXElement(XElement symbolSpecificationsElement) + { + foreach (var symbolSpecificationElement in symbolSpecificationsElement.Elements(nameof(SymbolSpecification))) + { + SymbolSpecifications.Add(SymbolSpecification.FromXElement(symbolSpecificationElement)); + } + } + + private void SetNamingStyleListFromXElement(XElement namingStylesElement) + { + foreach (var namingStyleElement in namingStylesElement.Elements(nameof(NamingStyle))) + { + NamingStyles.Add(NamingStyle.FromXElement(namingStyleElement)); + } + } + + private void SetNamingRuleTreeFromXElement(XElement namingRulesElement) + { + foreach (var namingRuleElement in namingRulesElement.Elements(nameof(SerializableNamingRule))) + { + NamingRules.Add(SerializableNamingRule.FromXElement(namingRuleElement)); + } + } + + public override bool Equals(object obj) + => Equals(obj as SerializableNamingStylePreferencesInfo); + + public bool Equals(SerializableNamingStylePreferencesInfo other) + { + if (object.ReferenceEquals(other, null)) + { + return false; + } + + return this.CreateXElement().ToString() == other.CreateXElement().ToString(); + } + + public static bool operator ==(SerializableNamingStylePreferencesInfo left, SerializableNamingStylePreferencesInfo right) + { + bool leftIsNull = object.ReferenceEquals(left, null); + bool rightIsNull = object.ReferenceEquals(right, null); + if (leftIsNull && rightIsNull) + { + return true; + } + else if(leftIsNull) + { + return false; + } + else if(rightIsNull) + { + return false; + } + + return left.Equals(right); + } + + public static bool operator !=(SerializableNamingStylePreferencesInfo left, SerializableNamingStylePreferencesInfo right) + => !(left == right); + + private static readonly string _defaultNamingPreferencesString = $@" + + + + + Class + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Interface + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Struct + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Enum + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Delegate + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Event + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Method + + + Public + + + + + + Method + + + Private + + + + + + Method + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + IsAbstract + + + + + Method + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + IsStatic + + + + + Method + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + IsAsync + + + + + Property + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Field + + + Public + Protected + + + + + + Field + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + IsStatic + + + + + Field + + + Internal + Private + + + + + + Field + + + Internal + Private + + + IsStatic + + + + + Class + Struct + Interface + Enum + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + Property + Method + Event + + + Public + Internal + Private + Protected + ProtectedOrInternal + + + + + + + + + + + + + + + + +"; + } +} diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs similarity index 100% rename from src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyles/Serialization/SymbolSpecification.cs rename to src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs diff --git a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt index e284a3921e28b..e886562c62411 100644 --- a/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Workspaces/Core/Portable/PublicAPI.Unshipped.txt @@ -84,7 +84,6 @@ override Microsoft.CodeAnalysis.Options.DocumentOptionSet.WithChangedOption(Micr override Microsoft.CodeAnalysis.XmlDocumentationProvider.GetDocumentationForSymbol(string documentationMemberID, System.Globalization.CultureInfo preferredCulture, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> string static Microsoft.CodeAnalysis.CodeStyle.CodeStyleOption.Default.get -> Microsoft.CodeAnalysis.CodeStyle.CodeStyleOption static Microsoft.CodeAnalysis.CodeStyle.CodeStyleOption.FromXElement(System.Xml.Linq.XElement element) -> Microsoft.CodeAnalysis.CodeStyle.CodeStyleOption -static Microsoft.CodeAnalysis.Simplification.SimplificationOptions.NamingPreferences.get -> Microsoft.CodeAnalysis.Options.PerLanguageOption static Microsoft.CodeAnalysis.Simplification.SimplificationOptions.QualifyEventAccess.get -> Microsoft.CodeAnalysis.Options.PerLanguageOption static Microsoft.CodeAnalysis.Simplification.SimplificationOptions.QualifyFieldAccess.get -> Microsoft.CodeAnalysis.Options.PerLanguageOption static Microsoft.CodeAnalysis.Simplification.SimplificationOptions.QualifyMethodAccess.get -> Microsoft.CodeAnalysis.Options.PerLanguageOption diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs index b2ab809620fd3..718d7f2a62176 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs @@ -2,6 +2,8 @@ using System; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using System.Xml.Linq; namespace Microsoft.CodeAnalysis.Simplification { @@ -95,261 +97,11 @@ public static class SimplificationOptions [Obsolete] public static PerLanguageOption PreferIntrinsicPredefinedTypeKeywordInMemberAccess { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(PreferIntrinsicPredefinedTypeKeywordInMemberAccess), defaultValue: true); - private static string _defaultNamingPreferences = $@" - - - - - Class - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Interface - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Struct - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Enum - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Delegate - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Event - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Method - - - Public - - - - - - Method - - - Private - - - - - - Method - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - IsAbstract - - - - - Method - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - IsStatic - - - - - Method - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - IsAsync - - - - - Property - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Field - - - Public - Protected - - - - - - Field - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - IsStatic - - - - - Field - - - Internal - Private - - - - - - Field - - - Internal - Private - - - IsStatic - - - - - Class - Struct - Interface - Enum - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - Property - Method - Event - - - Public - Internal - Private - Protected - ProtectedOrInternal - - - - - - - - - - - - - - - - -"; - /// /// This option describes the naming rules that should be applied to specified categories of symbols, /// and the level to which those rules should be enforced. /// - public static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: _defaultNamingPreferences, + internal static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: SerializableNamingStylePreferencesInfo.Default, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NamingPreferences")); } } diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index dd11095bd6c4a..a0e043bf8b4bc 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -385,6 +385,13 @@ + + + + + + + diff --git a/src/Workspaces/Core/Portable/WorkspacesResources.Designer.cs b/src/Workspaces/Core/Portable/WorkspacesResources.Designer.cs index 59df8f8b22b3b..e544de1bb05dd 100644 --- a/src/Workspaces/Core/Portable/WorkspacesResources.Designer.cs +++ b/src/Workspaces/Core/Portable/WorkspacesResources.Designer.cs @@ -881,6 +881,24 @@ internal static string Method { } } + /// + /// Looks up a localized string similar to Missing prefix: '{0}'. + /// + internal static string Missing_prefix_colon_0 { + get { + return ResourceManager.GetString("Missing_prefix_colon_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing suffix: '{0}'. + /// + internal static string Missing_suffix_colon_0 { + get { + return ResourceManager.GetString("Missing_suffix_colon_0", resourceCulture); + } + } + /// /// Looks up a localized string similar to Name can be simplified.. /// @@ -1207,6 +1225,24 @@ internal static string Temporary_storage_cannot_be_written_more_than_once { } } + /// + /// Looks up a localized string similar to The first word, '{0}', must begin with a lower case character. + /// + internal static string The_first_word_0_must_begin_with_a_lower_case_character { + get { + return ResourceManager.GetString("The_first_word_0_must_begin_with_a_lower_case_character", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The first word, '{0}', must begin with an upper case character. + /// + internal static string The_first_word_0_must_begin_with_an_upper_case_character { + get { + return ResourceManager.GetString("The_first_word_0_must_begin_with_an_upper_case_character", resourceCulture); + } + } + /// /// Looks up a localized string similar to The language '{0}' is not supported.. /// @@ -1324,6 +1360,51 @@ internal static string The_type_0_is_not_understood_by_the_serialization_binder } } + /// + /// Looks up a localized string similar to These non-leading words must begin with a lowercase letter: {0}. + /// + internal static string These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0 { + get { + return ResourceManager.GetString("These_non_leading_words_must_begin_with_a_lowercase_letter_colon_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to These non-leading words must begin with an upper case letter: {0}. + /// + internal static string These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0 { + get { + return ResourceManager.GetString("These_non_leading_words_must_begin_with_an_upper_case_letter_colon_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to These words cannot contain lower case characters: {0}. + /// + internal static string These_words_cannot_contain_lower_case_characters_colon_0 { + get { + return ResourceManager.GetString("These_words_cannot_contain_lower_case_characters_colon_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to These words cannot contain upper case characters: {0}. + /// + internal static string These_words_cannot_contain_upper_case_characters_colon_0 { + get { + return ResourceManager.GetString("These_words_cannot_contain_upper_case_characters_colon_0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to These words must begin with upper case characters: {0}. + /// + internal static string These_words_must_begin_with_upper_case_characters_colon_0 { + get { + return ResourceManager.GetString("These_words_must_begin_with_upper_case_characters_colon_0", resourceCulture); + } + } + /// /// Looks up a localized string similar to This submission already references another submission project.. /// diff --git a/src/Workspaces/Core/Portable/WorkspacesResources.resx b/src/Workspaces/Core/Portable/WorkspacesResources.resx index b98f52a9e29a5..93ba5399acc1e 100644 --- a/src/Workspaces/Core/Portable/WorkspacesResources.resx +++ b/src/Workspaces/Core/Portable/WorkspacesResources.resx @@ -578,14 +578,40 @@ Method {locked:method} unless the capitalization should be handled differently + + Missing prefix: '{0}' + Error None + + Missing suffix: '{0}' + + + These non-leading words must begin with an upper case letter: {0} + Suggestion + + These non-leading words must begin with a lowercase letter: {0} + + + These words cannot contain lower case characters: {0} + + + These words cannot contain upper case characters: {0} + + + These words must begin with upper case characters: {0} + + + The first word, '{0}', must begin with an upper case character + + + The first word, '{0}', must begin with a lower case character + - From d70c687f1908299980584e165f7a111db4bdf48a Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Thu, 17 Nov 2016 02:27:26 -0800 Subject: [PATCH 2/8] Implementing naming styles support for editorconfig --- .../CSharpEditorServicesTest.csproj | 1 + .../EditorConfigNamingStyleParserTests.cs | 244 +++++++++++++++++ ...DocumentOptionsProvider.DocumentOptions.cs | 25 +- .../EditorConfigDocumentOptionsProvider.cs | 11 +- ...ingStyleTests.IdentifierCreation.Casing.vb | 12 +- ...leTests.IdentifierCreation.ComplexTests.vb | 2 +- ...tyleTests.IdentifierCreation.Compliance.vb | 16 +- .../NamingStyleDiagnosticAnalyzerBase.cs | 22 +- ...eferFrameworkTypeDiagnosticAnalyzerBase.cs | 4 +- .../SymbolAnalysisContextExtensions.cs | 34 +++ src/Features/Core/Portable/Features.csproj | 1 + .../NamingStyles/NamingStyleViewModel.cs | 2 +- .../Portable/NamingStyles/Capitalization.cs | 2 +- ...ditorConfigNamingStyleParser.NamingRule.cs | 50 ++++ ...itorConfigNamingStyleParser.NamingStyle.cs | 104 ++++++++ ...ditorConfigNamingStyleParser.SymbolSpec.cs | 252 ++++++++++++++++++ .../EditorConfigNamingStyleParser.cs | 68 +++++ .../NamingStyles/Serialization/NamingStyle.cs | 4 +- .../SerializableNamingStylePreferencesInfo.cs | 11 + .../Serialization/SymbolSpecification.cs | 78 +++++- .../Options/EditorConfigStorageLocation.cs | 28 ++ .../NamingEditorConfigStorageLocation.cs | 14 + .../Simplification/SimplificationOptions.cs | 10 +- .../Core/Portable/Workspaces.csproj | 5 + 24 files changed, 946 insertions(+), 54 deletions(-) create mode 100644 src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs create mode 100644 src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs create mode 100644 src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs create mode 100644 src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs create mode 100644 src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs create mode 100644 src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs create mode 100644 src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj index f019d78976fe7..03a078fbc759d 100644 --- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj +++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj @@ -217,6 +217,7 @@ + diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs new file mode 100644 index 0000000000000..d5e3c662a53f9 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs @@ -0,0 +1,244 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Roslyn.Test.Utilities; +using Xunit; +using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.EditorConfigNamingStyleParser; +using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.NamingStyles +{ + public partial class EditorConfigNamingStyleParserTests + { + + [Fact] + static void TestPascalCaseRule() + { + var dictionary = new Dictionary() + { + ["dotnet_naming_rule.methods_and_properties_must_be_pascal_case.severity"] = "warning", + ["dotnet_naming_rule.methods_and_properties_must_be_pascal_case.symbols"] = "method_and_property_symbols", + ["dotnet_naming_rule.methods_and_properties_must_be_pascal_case.style"] = "pascal_case_style", + ["dotnet_naming_symbols.method_and_property_symbols.applicable_kinds"] = "method,property", + ["dotnet_naming_symbols.method_and_property_symbols.applicable_accessibilities"] = "*", + ["dotnet_naming_style.pascal_case_style.capitalization"] = "pascal_case" + }; + + var result = ParseDictionary(dictionary); + + Assert.Single(result.NamingRules); + var namingRule = result.NamingRules.Single(); + + Assert.Single(result.NamingStyles); + var namingStyle = result.NamingStyles.Single(); + + Assert.Single(result.SymbolSpecifications); + var symbolSpec = result.SymbolSpecifications.Single(); + + Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); + Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); + + Assert.Equal(DiagnosticSeverity.Warning, namingRule.EnforcementLevel); + + Assert.Equal("method_and_property_symbols", symbolSpec.Name); + + var expectedApplicableSymbolKindList = new[] + { + new SymbolKindOrTypeKind(SymbolKind.Method), + new SymbolKindOrTypeKind(SymbolKind.Property) + }; + AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); + + Assert.Empty(symbolSpec.RequiredModifierList); + + var expectedApplicableAccessibilityList = new[] + { + new AccessibilityKind(Accessibility.Public), + new AccessibilityKind(Accessibility.Internal), + new AccessibilityKind(Accessibility.Private), + new AccessibilityKind(Accessibility.Protected), + new AccessibilityKind(Accessibility.ProtectedOrInternal) + }; + AssertEx.SetEqual(expectedApplicableAccessibilityList, symbolSpec.ApplicableAccessibilityList); + + Assert.Equal("pascal_case_style", namingStyle.Name); + Assert.Equal("", namingStyle.Prefix); + Assert.Equal("", namingStyle.Suffix); + Assert.Equal("", namingStyle.WordSeparator); + Assert.Equal(Capitalization.PascalCase, namingStyle.CapitalizationScheme); + } + + [Fact] + static void TestAsyncMethodsRule() + { + var dictionary = new Dictionary() + { + ["dotnet_naming_rule.async_methods_must_end_with_async.severity"] = "error", + ["dotnet_naming_rule.async_methods_must_end_with_async.symbols"] = "method_symbols", + ["dotnet_naming_rule.async_methods_must_end_with_async.style"] = "end_in_async_style", + ["dotnet_naming_symbols.method_symbols.applicable_kinds"] = "method", + ["dotnet_naming_symbols.method_symbols.required_modifiers"] = "async", + ["dotnet_naming_style.end_in_async_style.capitalization "] = "pascal_case", + ["dotnet_naming_style.end_in_async_style.required_suffix"] = "Async", + }; + + var result = ParseDictionary(dictionary); + + Assert.Single(result.NamingRules); + var namingRule = result.NamingRules.Single(); + + Assert.Single(result.NamingStyles); + var namingStyle = result.NamingStyles.Single(); + + Assert.Single(result.SymbolSpecifications); + var symbolSpec = result.SymbolSpecifications.Single(); + + Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); + Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); + Assert.Equal(DiagnosticSeverity.Error, namingRule.EnforcementLevel); + + Assert.Equal("method_symbols", symbolSpec.Name); + + Assert.Single(symbolSpec.ApplicableSymbolKindList); + Assert.Contains(new SymbolKindOrTypeKind(SymbolKind.Method), symbolSpec.ApplicableSymbolKindList); + + Assert.Single(symbolSpec.RequiredModifierList); + Assert.Contains(new ModifierKind(ModifierKindEnum.IsAsync), symbolSpec.RequiredModifierList); + + Assert.Empty(symbolSpec.ApplicableAccessibilityList); + + Assert.Equal("end_in_async_style", namingStyle.Name); + Assert.Equal("", namingStyle.Prefix); + Assert.Equal("Async", namingStyle.Suffix); + Assert.Equal("", namingStyle.WordSeparator); + Assert.Equal(Capitalization.PascalCase, namingStyle.CapitalizationScheme); + } + + + [Fact] + static void TestPublicMembersCapitalizedRule() + { + var dictionary = new Dictionary() + { + ["dotnet_naming_rule.public_members_must_be_capitalized.severity"] = "suggestion", + ["dotnet_naming_rule.public_members_must_be_capitalized.symbols"] = "public_symbols", + ["dotnet_naming_rule.public_members_must_be_capitalized.style"] = "first_word_upper_case_style", + ["dotnet_naming_symbols.public_symbols.applicable_kinds"] = "property,method,field,event,delegate", + ["dotnet_naming_symbols.public_symbols.applicable_accessibilities"] = "public,internal,protected,protected_internal", + ["dotnet_naming_style.first_word_upper_case_style.capitalization"] = "first_word_upper", + }; + + var result = ParseDictionary(dictionary); + + Assert.Single(result.NamingRules); + var namingRule = result.NamingRules.Single(); + + Assert.Single(result.NamingStyles); + var namingStyle = result.NamingStyles.Single(); + + Assert.Single(result.SymbolSpecifications); + var symbolSpec = result.SymbolSpecifications.Single(); + + Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); + Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); + Assert.Equal(DiagnosticSeverity.Info, namingRule.EnforcementLevel); + + Assert.Equal("public_symbols", symbolSpec.Name); + + + var expectedApplicableSymbolKindList = new[] + { + new SymbolKindOrTypeKind(SymbolKind.Property), + new SymbolKindOrTypeKind(SymbolKind.Method), + new SymbolKindOrTypeKind(SymbolKind.Field), + new SymbolKindOrTypeKind(SymbolKind.Event), + new SymbolKindOrTypeKind(TypeKind.Delegate) + }; + AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); + + + var expectedApplicableAccessibilityList = new[] + { + new AccessibilityKind(Accessibility.Public), + new AccessibilityKind(Accessibility.Internal), + new AccessibilityKind(Accessibility.Protected), + new AccessibilityKind(Accessibility.ProtectedOrInternal) + }; + AssertEx.SetEqual(expectedApplicableAccessibilityList, symbolSpec.ApplicableAccessibilityList); + + Assert.Empty(symbolSpec.RequiredModifierList); + + Assert.Equal("first_word_upper_case_style", namingStyle.Name); + Assert.Equal("", namingStyle.Prefix); + Assert.Equal("", namingStyle.Suffix); + Assert.Equal("", namingStyle.WordSeparator); + Assert.Equal(Capitalization.FirstWordUpper, namingStyle.CapitalizationScheme); + } + + [Fact] + static void TestNonPublicMembersLowerCaseRule() + { + var dictionary = new Dictionary() + { + ["dotnet_naming_rule.non_public_members_must_be_lower_case.severity"] = "incorrect", + ["dotnet_naming_rule.non_public_members_must_be_lower_case.symbols "] = "non_public_symbols", + ["dotnet_naming_rule.non_public_members_must_be_lower_case.style "] = "all_lower_case_style", + ["dotnet_naming_symbols.non_public_symbols.applicable_kinds "] = "property,method,field,event,delegate", + ["dotnet_naming_symbols.non_public_symbols.applicable_accessibilities"] = "private", + ["dotnet_naming_style.all_lower_case_style.capitalization"] = "all_lower", + }; + + var result = ParseDictionary(dictionary); + + Assert.Single(result.NamingRules); + var namingRule = result.NamingRules.Single(); + Assert.Single(result.NamingStyles); + var namingStyle = result.NamingStyles.Single(); + Assert.Single(result.SymbolSpecifications); + var symbolSpec = result.SymbolSpecifications.Single(); + Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); + Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); + Assert.Equal(DiagnosticSeverity.Hidden, namingRule.EnforcementLevel); + + Assert.Equal("non_public_symbols", symbolSpec.Name); + + var expectedApplicableSymbolKindList = new[] + { + new SymbolKindOrTypeKind(SymbolKind.Property), + new SymbolKindOrTypeKind(SymbolKind.Method), + new SymbolKindOrTypeKind(SymbolKind.Field), + new SymbolKindOrTypeKind(SymbolKind.Event), + new SymbolKindOrTypeKind(TypeKind.Delegate) + }; + AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); + + Assert.Single(symbolSpec.ApplicableAccessibilityList); + Assert.Contains(new AccessibilityKind(Accessibility.Private), symbolSpec.ApplicableAccessibilityList); + + Assert.Empty(symbolSpec.RequiredModifierList); + + Assert.Equal("all_lower_case_style", namingStyle.Name); + Assert.Equal("", namingStyle.Prefix); + Assert.Equal("", namingStyle.Suffix); + Assert.Equal("", namingStyle.WordSeparator); + Assert.Equal(Capitalization.AllLower, namingStyle.CapitalizationScheme); + } + + [Fact] + static void TestNoRulesAreReturned() + { + var dictionary = new Dictionary() + { + ["dotnet_naming_symbols.non_public_symbols.applicable_kinds "] = "property,method,field,event,delegate", + ["dotnet_naming_symbols.non_public_symbols.applicable_accessibilities"] = "private", + ["dotnet_naming_style.all_lower_case_style.capitalization"] = "all_lower", + }; + + var result = ParseDictionary(dictionary); + + Assert.Empty(result.NamingRules); + Assert.Empty(result.NamingStyles); + Assert.Empty(result.SymbolSpecifications); + } + } +} diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs index 343dd2084d925..e67b4ffffb1fe 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs @@ -2,6 +2,8 @@ using System.Linq; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualStudio.CodingConventions; +using Microsoft.CodeAnalysis.ErrorLogger; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; namespace Microsoft.CodeAnalysis.Editor.Options { @@ -10,37 +12,42 @@ internal sealed partial class EditorConfigDocumentOptionsProvider : IDocumentOpt private class DocumentOptions : IDocumentOptions { private ICodingConventionsSnapshot _codingConventionSnapshot; + private readonly IErrorLoggerService _errorLogger; - public DocumentOptions(ICodingConventionsSnapshot codingConventionSnapshot) + public DocumentOptions(ICodingConventionsSnapshot codingConventionSnapshot, IErrorLoggerService errorLogger) { _codingConventionSnapshot = codingConventionSnapshot; + _errorLogger = errorLogger; } public bool TryGetDocumentOption(Document document, OptionKey option, out object value) { var editorConfigPersistence = option.Option.StorageLocations.OfType().SingleOrDefault(); + var namingEditorConfigPersistence = option.Option.StorageLocations.OfType().SingleOrDefault(); - if (editorConfigPersistence == null) + if (editorConfigPersistence == null && namingEditorConfigPersistence == null) { value = null; return false; } - if (_codingConventionSnapshot.TryGetConventionValue(editorConfigPersistence.KeyName, out value)) + var allRawConventions = _codingConventionSnapshot.AllRawConventions; + try { - try + if (namingEditorConfigPersistence != null) { - value = editorConfigPersistence.ParseValue(value.ToString(), option.Option.Type); + value = EditorConfigNamingStyleParser.GetNamingStylesStringFromDictionary(allRawConventions); return true; } - catch (Exception) + else { - // TODO: report this somewhere? - return false; + return editorConfigPersistence.TryParseReadonlyDictionary(allRawConventions, option.Option.Type, out value); } } - else + catch (Exception ex) { + _errorLogger?.LogException(this, ex); + value = null; return false; } } diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs index 4198bcb84d2c1..3c72cf4249f52 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.ErrorLogger; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.VisualStudio.CodingConventions; @@ -22,10 +25,12 @@ internal sealed partial class EditorConfigDocumentOptionsProvider : IDocumentOpt private readonly Dictionary> _openDocumentContexts = new Dictionary>(); private readonly ICodingConventionsManager _codingConventionsManager; + private readonly IErrorLoggerService _errorLogger; internal EditorConfigDocumentOptionsProvider(Workspace workspace) { _codingConventionsManager = CodingConventionsManagerFactory.CreateCodingConventionsManager(); + _errorLogger = workspace.Services.GetService(); workspace.DocumentOpened += Workspace_DocumentOpened; workspace.DocumentClosed += Workspace_DocumentClosed; @@ -78,7 +83,7 @@ public async Task GetOptionsForDocumentAsync(Document document TaskScheduler.Default); var context = await cancellableContextTask.ConfigureAwait(false); - return new DocumentOptions(context.CurrentConventions); + return new DocumentOptions(context.CurrentConventions, _errorLogger); } else { @@ -105,7 +110,7 @@ public async Task GetOptionsForDocumentAsync(Document document using (var context = await conventionsAsync.ConfigureAwait(false)) { - return new DocumentOptions(context.CurrentConventions); + return new DocumentOptions(context.CurrentConventions, _errorLogger); } } } diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb index 2d74b87dea7ad..c473d1b3b8164 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb @@ -77,37 +77,37 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests #Region "Firstupper" Public Sub TestFirstUpperWithZeroWords() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "") End Sub Public Sub TestFirstUpperWithOneConformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "First", "First") End Sub Public Sub TestFirstUpperWithOneNonconformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "First", "first") End Sub Public Sub TestFirstUpperCapitalizationOfFirstCharacter() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "Firstupper", "first", "upper") End Sub Public Sub TestFirstUpperDecapitalizationOfAppropriateFirstCharacter() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "Firstupper", "First", "Upper") End Sub Public Sub TestFirstUpperLeavesSubsequentCharactersAlone() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "FiRstupper", "fiRst", "upper") End Sub #End Region diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb index bb0c894b01f3a..22e2d059c4d2c 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests Public Sub TestFirstUpperComplex1() - Dim namingStyle = CreateNamingStyle(prefix:="p_", suffix:="_s", wordSeparator:="__", capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(prefix:="p_", suffix:="_s", wordSeparator:="__", capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCreation(namingStyle, "p_P_one__two__thRee_s", "p_one", "Two", "thRee") End Sub diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb index 9376fcb0e796f..d443563397ca6 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb @@ -145,49 +145,49 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests #Region "Firstupper" Public Sub TestFirstUpperComplianceWithZeroWords() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCompliance(namingStyle, "") End Sub Public Sub TestFirstUpperComplianceWithOneConformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCompliance(namingStyle, "First") End Sub Public Sub TestFirstUpperNoncomplianceWithOneNonconformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "first", "First") End Sub Public Sub TestFirstUpperComplianceWithCorrectCapitalizationOfFirstCharacters() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCompliance(namingStyle, "Firstupper") End Sub Public Sub TestFirstUpperNoncomplianceWithNoncapitalizationOfFirstCharacter() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstWordUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "first_upper", "First_upper") End Sub Public Sub TestFirstUpperNoncomplianceWithCapitalizationOfFirstCharacterOfSubsequentWords() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstWordUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "First_Upper", "First_upper") End Sub Public Sub TestFirstUpperIgnoresSeeminglyNoncompliantPrefixOrSuffix() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", prefix:="t_", suffix:="_T", capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", prefix:="t_", suffix:="_T", capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCompliance(namingStyle, "t_First_upper_T") End Sub Public Sub TestFirstUpperIgnoresSeeminglyNoncompliantWordSeparator() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_T_", capitalizationScheme:=Capitalization.FirstUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_T_", capitalizationScheme:=Capitalization.FirstWordUpper) TestNameCompliance(namingStyle, "First_T_upper") End Sub #End Region diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs index 9e8a0820e1088..9d7c0bf2216e9 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs @@ -5,10 +5,11 @@ using System.Xml.Linq; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Simplification; +using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { - internal abstract class NamingStyleDiagnosticAnalyzerBase : + internal abstract class NamingStyleDiagnosticAnalyzerBase : AbstractCodeStyleDiagnosticAnalyzer, IBuiltInAnalyzer { private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(FeaturesResources.Naming_Styles), FeaturesResources.ResourceManager, typeof(FeaturesResources)); @@ -36,25 +37,16 @@ protected NamingStyleDiagnosticAnalyzerBase() public bool OpenFileOnly(Workspace workspace) => true; protected override void InitializeWorker(AnalysisContext context) - => context.RegisterCompilationStartAction(CompilationStartAction); + => context.RegisterSymbolAction(SymbolAction, _symbolKinds); - private void CompilationStartAction(CompilationStartAnalysisContext context) + private void SymbolAction(SymbolAnalysisContext context) { - var workspace = (context.Options as WorkspaceAnalyzerOptions)?.Workspace; - var optionSet = (context.Options as WorkspaceAnalyzerOptions)?.Workspace.Options; - var viewModel = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); - - if (viewModel != null) + var preferences = context.GetNamingStylePreferencesAsync().GetAwaiter().GetResult(); + if (preferences == null) { - var preferencesInfo = viewModel.GetPreferencesInfo(); - context.RegisterSymbolAction( - symbolContext => SymbolAction(symbolContext, preferencesInfo), - _symbolKinds); + return; } - } - private void SymbolAction(SymbolAnalysisContext context, NamingStylePreferencesInfo preferences) - { if (preferences.TryGetApplicableRule(context.Symbol, out var applicableRule)) { if (applicableRule.EnforcementLevel != DiagnosticSeverity.Hidden && diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs index 5bff02784b827..d5ba991abc05a 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Immutable; +using System.Diagnostics; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Options; @@ -77,11 +78,12 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context) var syntaxTree = context.Node.SyntaxTree; var cancellationToken = context.CancellationToken; var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); + Debug.Assert(optionSet != null, "Unable to get options naming styles"); if (optionSet == null) { return; } - + var semanticModel = context.SemanticModel; var language = semanticModel.Language; diff --git a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs new file mode 100644 index 0000000000000..93f2a3689b2c5 --- /dev/null +++ b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; +using Microsoft.CodeAnalysis.Simplification; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static class SymbolAnalysisContextExtensions + { + public static async Task GetNamingStylePreferencesAsync(this SymbolAnalysisContext context) + { + var location = context.Symbol.Locations.FirstOrDefault(); + if (location == null) + { + return null; + } + + var cancellationToken = context.CancellationToken; + var syntaxTree = location.SourceTree; + var options = context.Options; + var optionSet = await options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).ConfigureAwait(false); + string language = context.Compilation.Language; + var viewModel = optionSet.GetOption(SimplificationOptions.NamingPreferences, language); + if (viewModel == null) + { + return null; + } + + var preferences = viewModel.GetPreferencesInfo(); + return preferences; + } + } +} diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj index d6c6f65127688..4d32a8a96eb2b 100644 --- a/src/Features/Core/Portable/Features.csproj +++ b/src/Features/Core/Portable/Features.csproj @@ -103,6 +103,7 @@ + diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs index 7847a4ad9781e..9571be58fa41e 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs @@ -29,7 +29,7 @@ public NamingStyleViewModel(NamingStyle style, bool canBeDeleted, INotificationS { new CapitalizationDisplay(Capitalization.PascalCase, ServicesVSResources.Pascal_Case_Name), new CapitalizationDisplay(Capitalization.CamelCase, ServicesVSResources.camel_Case_Name), - new CapitalizationDisplay(Capitalization.FirstUpper, ServicesVSResources.First_word_upper), + new CapitalizationDisplay(Capitalization.FirstWordUpper, ServicesVSResources.First_word_upper), new CapitalizationDisplay(Capitalization.AllUpper, ServicesVSResources.ALL_UPPER), new CapitalizationDisplay(Capitalization.AllLower, ServicesVSResources.all_lower) }; diff --git a/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs b/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs index f675c0fd64726..754071074b617 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs @@ -17,7 +17,7 @@ internal enum Capitalization /// /// Only the first word is capitalized /// - FirstUpper, + FirstWordUpper, /// /// Every character is capitalized diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs new file mode 100644 index 0000000000000..f1b4d213b5fef --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Linq; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static partial class EditorConfigNamingStyleParser + { + private static bool TryGetSerializableNamingRule( + string namingRuleTitle, + SymbolSpecification symbolSpec, + NamingStyle namingStyle, + IReadOnlyDictionary conventionsDictionary, + out SerializableNamingRule serializableNamingRule) + { + var severity= GetRuleSeverity(namingRuleTitle, conventionsDictionary); + serializableNamingRule = new SerializableNamingRule() + { + EnforcementLevel = severity, + NamingStyleID = namingStyle.ID, + SymbolSpecificationID = symbolSpec.ID + }; + return true; + } + + private static DiagnosticSeverity GetRuleSeverity( + string namingRuleName, + IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_rule.{namingRuleName}.severity", out object result)) + { + return ParseEnforcementLevel(result as string ?? string.Empty); + } + + return default(DiagnosticSeverity); ; + } + + private static DiagnosticSeverity ParseEnforcementLevel(string ruleSeverity) + { + switch (ruleSeverity) + { + case "silent": return DiagnosticSeverity.Hidden; + case "suggestion": return DiagnosticSeverity.Info; + case "warning": return DiagnosticSeverity.Warning; + case "error": return DiagnosticSeverity.Error; + default: return DiagnosticSeverity.Hidden; + } + } + } +} diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs new file mode 100644 index 0000000000000..c0e0c7ca8afc6 --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Linq; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static partial class EditorConfigNamingStyleParser + { + private static bool TryGetNamingStyleData( + string namingRuleName, + IReadOnlyDictionary allRawConventions, + out NamingStyle namingStyle) + { + namingStyle = null; + if (!TryGetNamingStyleTitle(namingRuleName, allRawConventions, out string namingStyleTitle)) + { + return false; + } + + string requiredPrefix = GetNamingRequiredPrefix(namingStyleTitle, allRawConventions); + string requiredSuffix = GetNamingRequiredSuffix(namingStyleTitle, allRawConventions); + string wordSeparator = GetNamingWordSeparator(namingStyleTitle, allRawConventions); + var capitalization = GetNamingCapitalization(namingStyleTitle, allRawConventions); + + namingStyle = new NamingStyle() + { + Name = namingStyleTitle, + Prefix = requiredPrefix, + Suffix = requiredSuffix, + WordSeparator = wordSeparator, + CapitalizationScheme = capitalization + }; + return true; + } + + private static bool TryGetNamingStyleTitle( + string namingRuleName, + IReadOnlyDictionary conventionsDictionary, + out string namingStyleName) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_rule.{namingRuleName}.style", out object result)) + { + namingStyleName = result as string; + return namingStyleName != null; + } + + namingStyleName = null; + return false; + } + + private static string GetNamingRequiredPrefix(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.required_prefix", out var result)) + { + return result as string ?? string.Empty; + } + + return string.Empty; + } + + private static string GetNamingRequiredSuffix(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.required_suffix", out object result)) + { + return result as string ?? string.Empty; + } + + return string.Empty; + } + + private static string GetNamingWordSeparator(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.word_separator", out object result)) + { + return result as string ?? string.Empty; + } + + return string.Empty; + } + + private static Capitalization GetNamingCapitalization(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.capitalization", out object result)) + { + return ParseCapitalizationScheme(result as string ?? string.Empty); + } + + return default(Capitalization); + } + + private static Capitalization ParseCapitalizationScheme(string namingStyleCapitalization) + { + switch (namingStyleCapitalization) + { + case "pascal_case": return Capitalization.PascalCase; + case "camel_case": return Capitalization.CamelCase; + case "first_word_upper": return Capitalization.FirstWordUpper; + case "all_upper": return Capitalization.AllUpper; + case "all_lower": return Capitalization.AllLower; + default: return default(Capitalization); + } + } + } +} diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs new file mode 100644 index 0000000000000..6419c6585c142 --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs @@ -0,0 +1,252 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Roslyn.Utilities; +using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static partial class EditorConfigNamingStyleParser + { + private static bool TryGetSymbolSpec( + string namingRuleTitle, + IReadOnlyDictionary conventionsDictionary, + out SymbolSpecification symbolSpec) + { + symbolSpec = null; + if (!TryGetSymbolSpecNameForNamingRule(namingRuleTitle, conventionsDictionary, out string symbolSpecName)) + { + return false; + } + + var applicableKinds = GetSymbolsApplicableKinds(symbolSpecName, conventionsDictionary); + var applicableAccessibilities = GetSymbolsApplicableAccessibilities(symbolSpecName, conventionsDictionary); + var requiredModifiers = GetSymbolsRequiredModifiers(symbolSpecName, conventionsDictionary); + + symbolSpec = new SymbolSpecification( + Guid.NewGuid(), + symbolSpecName, + symbolKindList: applicableKinds, + accessibilityKindList: applicableAccessibilities, + modifiers: requiredModifiers); + return true; + } + + private static bool TryGetSymbolSpecNameForNamingRule( + string namingRuleName, + IReadOnlyDictionary conventionsDictionary, + out string symbolSpecName) + { + symbolSpecName = null; + if (conventionsDictionary.TryGetValue($"dotnet_naming_rule.{namingRuleName}.symbols", out object result)) + { + symbolSpecName = result as string; + return symbolSpecName != null; ; + } + + return false; + } + + private static ImmutableArray GetSymbolsApplicableKinds( + string symbolSpecName, + IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_symbols.{symbolSpecName}.applicable_kinds", out object result)) + { + return ParseSymbolKindList(result as string ?? string.Empty); + } + + return ImmutableArray.Empty; + } + + private static readonly SymbolKindOrTypeKind _class = new SymbolKindOrTypeKind(TypeKind.Class); + private static readonly SymbolKindOrTypeKind _struct = new SymbolKindOrTypeKind(TypeKind.Struct); + private static readonly SymbolKindOrTypeKind _interface = new SymbolKindOrTypeKind(TypeKind.Interface); + private static readonly SymbolKindOrTypeKind _enum = new SymbolKindOrTypeKind(TypeKind.Enum); + private static readonly SymbolKindOrTypeKind _property = new SymbolKindOrTypeKind(SymbolKind.Property); + private static readonly SymbolKindOrTypeKind _method = new SymbolKindOrTypeKind(SymbolKind.Method); + private static readonly SymbolKindOrTypeKind _field = new SymbolKindOrTypeKind(SymbolKind.Field); + private static readonly SymbolKindOrTypeKind _event = new SymbolKindOrTypeKind(SymbolKind.Event); + private static readonly SymbolKindOrTypeKind _namespace = new SymbolKindOrTypeKind(SymbolKind.Namespace); + private static readonly SymbolKindOrTypeKind _delegate = new SymbolKindOrTypeKind(TypeKind.Delegate); + private static readonly SymbolKindOrTypeKind _typeParameter = new SymbolKindOrTypeKind(SymbolKind.TypeParameter); + + private static ImmutableArray ParseSymbolKindList(string symbolSpecApplicableKinds) + { + if (symbolSpecApplicableKinds == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + if (symbolSpecApplicableKinds.Trim() == "*") + { + builder.AddRange(_class, _struct, _interface, _enum, _property, _method, _field, _event, _namespace, _delegate, _typeParameter); + return builder.ToImmutableAndFree(); + } + + foreach (var symbolSpecApplicableKind in symbolSpecApplicableKinds.Split(',').Select(x => x.Trim())) + { + switch (symbolSpecApplicableKind) + { + case "class": + builder.Add(_class); + break; + case "struct": + builder.Add(_struct); + break; + case "interface": + builder.Add(_interface); + break; + case "enum": + builder.Add(_enum); + break; + case "property": + builder.Add(_property); + break; + case "method": + builder.Add(_method); + break; + case "field": + builder.Add(_field); + break; + case "event": + builder.Add(_event); + break; + case "namespace": + builder.Add(_namespace); + break; + case "delegate": + builder.Add(_delegate); + break; + case "type_parameter": + builder.Add(_typeParameter); + break; + default: + break; + } + } + + return builder.ToImmutableAndFree(); + } + + private static ImmutableArray GetSymbolsApplicableAccessibilities( + string symbolSpecName, + IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_symbols.{symbolSpecName}.applicable_accessibilities", out object result)) + { + return ParseAccessibilityKindList(result as string ?? string.Empty); + } + + return ImmutableArray.Empty; + } + + private static readonly AccessibilityKind _publicAccessibilityKind = new AccessibilityKind(Accessibility.Public); + private static readonly AccessibilityKind _internalAccessibilityKind = new AccessibilityKind(Accessibility.Internal); + private static readonly AccessibilityKind _privateAccessibilityKind = new AccessibilityKind(Accessibility.Private); + private static readonly AccessibilityKind _protectedAccessibilityKind = new AccessibilityKind(Accessibility.Protected); + private static readonly AccessibilityKind _protectedOrInternalAccessibilityKind = new AccessibilityKind(Accessibility.ProtectedOrInternal); + + private static ImmutableArray ParseAccessibilityKindList(string symbolSpecApplicableAccessibilities) + { + if (symbolSpecApplicableAccessibilities == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + if (symbolSpecApplicableAccessibilities.Trim() == "*") + { + builder.AddRange(_publicAccessibilityKind, _internalAccessibilityKind, _privateAccessibilityKind, _protectedAccessibilityKind, _protectedOrInternalAccessibilityKind); + return builder.ToImmutableAndFree(); + } + + foreach (var symbolSpecApplicableAccessibility in symbolSpecApplicableAccessibilities.Split(',').Select(x => x.Trim())) + { + switch (symbolSpecApplicableAccessibility) + { + case "public": + builder.Add(_publicAccessibilityKind); + break; + case "internal": + builder.Add(_internalAccessibilityKind); + break; + case "private": + builder.Add(_privateAccessibilityKind); + break; + case "protected": + builder.Add(_protectedAccessibilityKind); + break; + case "protected_internal": + builder.Add(_protectedOrInternalAccessibilityKind); + break; + default: + break; + } + } + + return builder.ToImmutableAndFree(); + } + + private static ImmutableArray GetSymbolsRequiredModifiers( + string symbolSpecName, + IReadOnlyDictionary conventionsDictionary) + { + if (conventionsDictionary.TryGetValue($"dotnet_naming_symbols.{symbolSpecName}.required_modifiers", out object result)) + { + return ParseModifiers(result as string ?? string.Empty); + } + + return ImmutableArray.Empty; + } + + private static readonly ModifierKind _abstractModifierKind = new ModifierKind(ModifierKindEnum.IsAbstract); + private static readonly ModifierKind _asyncModifierKind = new ModifierKind(ModifierKindEnum.IsAsync); + private static readonly ModifierKind _constModifierKind = new ModifierKind(ModifierKindEnum.IsConst); + private static readonly ModifierKind _readonlyModifierKind = new ModifierKind(ModifierKindEnum.IsReadOnly); + private static readonly ModifierKind _staticModifierKind = new ModifierKind(ModifierKindEnum.IsStatic); + + private static ImmutableArray ParseModifiers(string symbolSpecRequiredModifiers) + { + if (symbolSpecRequiredModifiers == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + if (symbolSpecRequiredModifiers.Trim() == "*") + { + builder.AddRange(_abstractModifierKind, _asyncModifierKind, _constModifierKind, _readonlyModifierKind, _staticModifierKind); + return builder.ToImmutableAndFree(); + } + + foreach (var symbolSpecRequiredModifier in symbolSpecRequiredModifiers.Split(',').Select(x => x.Trim())) + { + switch (symbolSpecRequiredModifier) + { + case "abstract": + builder.Add(_abstractModifierKind); + break; + case "async": + builder.Add(_asyncModifierKind); + break; + case "const": + builder.Add(_constModifierKind); + break; + case "readonly": + builder.Add(_readonlyModifierKind); + break; + case "static": + builder.Add(_staticModifierKind); + break; + default: + break; + } + } + + return builder.ToImmutableAndFree(); + } + } +} diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs new file mode 100644 index 0000000000000..d1bd3519c957b --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static partial class EditorConfigNamingStyleParser + { + /// + /// The dictionary we get from the VS editorconfig API uses the same dictionary object if there are no changes, so we can cache based on dictionary + /// + private static readonly ConditionalWeakTable, SerializableNamingStylePreferencesInfo> _cache = new ConditionalWeakTable, SerializableNamingStylePreferencesInfo>(); + private static readonly object _cacheLock = new object(); + + public static SerializableNamingStylePreferencesInfo GetNamingStylesStringFromDictionary(IReadOnlyDictionary allRawConventions) + { + if (!_cache.TryGetValue(allRawConventions, out var value)) + { + lock (_cacheLock) + { + if (!_cache.TryGetValue(allRawConventions, out value)) + { + value = ParseDictionary(allRawConventions); + _cache.Add(allRawConventions, value); + } + } + } + return value; + } + + public static SerializableNamingStylePreferencesInfo ParseDictionary(IReadOnlyDictionary allRawConventions) + { + var symbolSpecifications = new List(); + var namingStyles = new List(); + var namingRules = new List(); + var trimmedDictionary = allRawConventions + .Select(x => new KeyValuePair(x.Key.Trim(), x.Value)) + .ToDictionary(x => x.Key, x => x.Value); + foreach (var namingRuleTitle in GetRuleTitles(trimmedDictionary)) + { + if (TryGetSymbolSpec(namingRuleTitle, trimmedDictionary, out var symbolSpec)) + { + symbolSpecifications.Add(symbolSpec); + } + + if (TryGetNamingStyleData(namingRuleTitle, trimmedDictionary, out var namingStyle)) + { + namingStyles.Add(namingStyle); + } + + if (TryGetSerializableNamingRule(namingRuleTitle, symbolSpec, namingStyle, trimmedDictionary, out var serializableNamingRule)) + { + namingRules.Add(serializableNamingRule); + } + } + + return new SerializableNamingStylePreferencesInfo(symbolSpecifications, namingStyles, namingRules); + } + + private static IEnumerable GetRuleTitles(IReadOnlyDictionary allRawConventions) + => (from kvp in allRawConventions + where kvp.Key.Trim().StartsWith("dotnet_naming_rule.") + let nameSplit = kvp.Key.Split('.') + where nameSplit.Length == 3 + select nameSplit[1]) + .Distinct(); + } +} diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs index afacd0b533560..728647347000b 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs @@ -39,7 +39,7 @@ private IEnumerable ApplyCapitalization(IEnumerable words) return words.Select(CapitalizeFirstLetter); case Capitalization.CamelCase: return words.Take(1).Select(DecapitalizeFirstLetter).Concat(words.Skip(1).Select(CapitalizeFirstLetter)); - case Capitalization.FirstUpper: + case Capitalization.FirstWordUpper: return words.Take(1).Select(CapitalizeFirstLetter).Concat(words.Skip(1).Select(DecapitalizeFirstLetter)); case Capitalization.AllUpper: return words.Select(w => w.ToUpper()); @@ -132,7 +132,7 @@ public bool IsNameCompliant(string name, out string failureReason) return false; } - case Capitalization.FirstUpper: + case Capitalization.FirstWordUpper: if (char.IsUpper(words.First()[0]) && words.Skip(1).All(w => char.IsLower(w[0]))) { return true; diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs index bd39cc61caccc..74e499347558e 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs @@ -22,6 +22,14 @@ internal class SerializableNamingStylePreferencesInfo : IEquatable NamingRules; private readonly static int s_serializationVersion = 3; + + internal SerializableNamingStylePreferencesInfo(List symbolSpecifications, List namingStyles, List namingRules) + { + SymbolSpecifications = symbolSpecifications; + NamingStyles = namingStyles; + NamingRules = namingRules; + } + internal SerializableNamingStylePreferencesInfo() { SymbolSpecifications = new List(); @@ -170,6 +178,9 @@ public bool Equals(SerializableNamingStylePreferencesInfo other) public static bool operator !=(SerializableNamingStylePreferencesInfo left, SerializableNamingStylePreferencesInfo right) => !(left == right); + public override int GetHashCode() + => this.CreateXElement().ToString().GetHashCode(); + private static readonly string _defaultNamingPreferencesString = $@" diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs index 59167c706c4c5..88de8c0a3175a 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs @@ -6,6 +6,7 @@ using System.Xml.Linq; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { @@ -179,7 +180,7 @@ private void PopulateModifierListFromXElement(XElement modifierListElement) } } - public class SymbolKindOrTypeKind + public class SymbolKindOrTypeKind : IEquatable { public SymbolKind? SymbolKind { get; set; } public TypeKind? TypeKind { get; set; } @@ -228,9 +229,35 @@ internal static SymbolKindOrTypeKind AddTypeKindFromXElement(XElement typeKindEl { return new SymbolKindOrTypeKind((TypeKind)Enum.Parse(typeof(TypeKind), typeKindElement.Value)); } + + public override bool Equals(object obj) + { + return Equals(obj as SymbolKindOrTypeKind); + } + + public bool Equals(SymbolKindOrTypeKind other) + { + return other != null && + this.SymbolKind == other.SymbolKind && + this.TypeKind == other.TypeKind; + } + + public override int GetHashCode() + { + if (this.SymbolKind.HasValue && this.TypeKind.HasValue) + { + return Hash.Combine(this.SymbolKind.Value.GetHashCode(), this.TypeKind.Value.GetHashCode()); + } + else if (this.SymbolKind.HasValue) + { + return this.SymbolKind.Value.GetHashCode(); + } + + return this.TypeKind.Value.GetHashCode(); + } } - public class AccessibilityKind + public struct AccessibilityKind : IEquatable { public Accessibility Accessibility { get; set; } @@ -253,9 +280,30 @@ internal static AccessibilityKind FromXElement(XElement accessibilityElement) { return new AccessibilityKind((Accessibility)Enum.Parse(typeof(Accessibility), accessibilityElement.Value)); } + + public override bool Equals(object obj) + { + return Equals((AccessibilityKind)obj); + } + + public bool Equals(AccessibilityKind other) + { + return this.Accessibility == other.Accessibility; + } + + public static bool operator ==(AccessibilityKind left, AccessibilityKind right) + => left.Equals(right); + + public static bool operator !=(AccessibilityKind left, AccessibilityKind right) + => !left.Equals(right); + + public override int GetHashCode() + { + return this.Accessibility.GetHashCode(); + } } - public class ModifierKind + public struct ModifierKind : IEquatable { public ModifierKindEnum ModifierKindWrapper; @@ -309,11 +357,14 @@ internal DeclarationModifiers Modifier public ModifierKind(DeclarationModifiers modifier) { + ModifierKindWrapper = default(ModifierKindEnum); + _modifier = default(DeclarationModifiers); this.Modifier = modifier; } public ModifierKind(ModifierKindEnum modifierKind) { + _modifier = default(DeclarationModifiers); ModifierKindWrapper = modifierKind; } @@ -356,6 +407,27 @@ internal static ModifierKind FromXElement(XElement modifierElement) { return new ModifierKind((ModifierKindEnum)(ModifierKindEnum)Enum.Parse((Type)typeof(ModifierKindEnum), (string)modifierElement.Value)); } + + public override bool Equals(object obj) + { + return Equals((ModifierKind)obj); + } + + public bool Equals(ModifierKind other) + { + return this.Modifier == other.Modifier; + } + + public static bool operator ==(ModifierKind left, ModifierKind right) + => left.Equals(right); + + public static bool operator !=(ModifierKind left, ModifierKind right) + => !left.Equals(right); + + public override int GetHashCode() + { + return this.Modifier.GetHashCode(); + } } public enum ModifierKindEnum { diff --git a/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs b/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs index d8e433b2ec414..38fe2aeff663b 100644 --- a/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs +++ b/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeStyle; using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers; @@ -15,8 +16,30 @@ internal sealed class EditorConfigStorageLocation : OptionStorageLocation private Func _parseValue; + private Func, object> _parseDictionary; + public object ParseValue(string s, Type type) => _parseValue(s, type); + public bool TryParseReadonlyDictionary(IReadOnlyDictionary allRawConventions, Type type, out object result) + { + if (_parseValue != null && KeyName != null) + { + if (allRawConventions.TryGetValue(KeyName, out object value)) + { + result = _parseValue(value.ToString(), type); + return true; + } + } + else if (_parseDictionary != null) + { + result = _parseDictionary(allRawConventions); + return true; + } + + result = null; + return false; + } + public EditorConfigStorageLocation(string keyName) { KeyName = keyName; @@ -49,5 +72,10 @@ public EditorConfigStorageLocation(string keyName, Func parseVal // If we're explicitly given a parsing function we can throw away the type when parsing _parseValue = (s, type) => parseValue(s); } + + public EditorConfigStorageLocation(Func, object> parseDictionary) + { + _parseDictionary = parseDictionary; + } } } diff --git a/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs b/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs new file mode 100644 index 0000000000000..8ac47b37fe70d --- /dev/null +++ b/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.Options +{ + /// + /// This type is used when you need to indicate that the entire editorconfig options + /// dictionary should be handled by EditorConfigNamingStyleParser + /// + internal sealed class NamingEditorConfigStorageLocation : OptionStorageLocation { } +} diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs index 718d7f2a62176..36983705a63bc 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs @@ -68,21 +68,21 @@ public static class SimplificationOptions /// This option says if we should simplify away the . or . in property access expressions. /// [Obsolete] - public static PerLanguageOption QualifyPropertyAccess{ get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyPropertyAccess), defaultValue: false, + public static PerLanguageOption QualifyPropertyAccess { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyPropertyAccess), defaultValue: false, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyPropertyAccess")); /// /// This option says if we should simplify away the . or . in method access expressions. /// [Obsolete] - public static PerLanguageOption QualifyMethodAccess{ get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyMethodAccess), defaultValue: false, + public static PerLanguageOption QualifyMethodAccess { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyMethodAccess), defaultValue: false, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyMethodAccess")); /// /// This option says if we should simplify away the . or . in event access expressions. /// [Obsolete] - public static PerLanguageOption QualifyEventAccess{ get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyEventAccess), defaultValue: false, + public static PerLanguageOption QualifyEventAccess { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(QualifyEventAccess), defaultValue: false, storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.QualifyEventAccess")); /// @@ -102,6 +102,8 @@ public static class SimplificationOptions /// and the level to which those rules should be enforced. /// internal static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: SerializableNamingStylePreferencesInfo.Default, - storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NamingPreferences")); + storageLocations: new OptionStorageLocation[]{ + new NamingEditorConfigStorageLocation(), + new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NamingPreferences")}); } } diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index a0e043bf8b4bc..1d27f5cf67c71 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -370,6 +370,11 @@ + + + + + From aec0e2919e805b33307d09a878fbea28c9c20899 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Sat, 3 Dec 2016 07:14:16 -0800 Subject: [PATCH 3/8] responding to david's PR feedback --- .../EditorConfigNamingStyleParserTests.cs | 18 +++++++++--------- .../EditorConfigDocumentOptionsProvider.cs | 4 +++- ...itorConfigDocumentOptionsProviderFactory.cs | 4 +++- ...mingStyleTests.IdentifierCreation.Casing.vb | 12 ++++++------ ...yleTests.IdentifierCreation.ComplexTests.vb | 2 +- ...StyleTests.IdentifierCreation.Compliance.vb | 16 ++++++++-------- ...referFrameworkTypeDiagnosticAnalyzerBase.cs | 2 +- .../SymbolAnalysisContextExtensions.cs | 4 ++-- .../NamingStyles/NamingStyleViewModel.cs | 2 +- .../Portable/CodeStyle/CodeStyleHelpers.cs | 8 ++++---- .../AbstractOptionsSerializationService.cs | 5 ++--- .../Portable/NamingStyles/Capitalization.cs | 2 +- ...EditorConfigNamingStyleParser.NamingRule.cs | 15 ++++++++------- ...ditorConfigNamingStyleParser.NamingStyle.cs | 9 +++++---- ...EditorConfigNamingStyleParser.SymbolSpec.cs | 5 +++-- .../EditorConfigNamingStyleParser.cs | 4 +++- .../EditorConfigSeverityStrings.cs | 12 ++++++++++++ .../NamingStyles/Serialization/NamingStyle.cs | 4 ++-- .../Simplification/SimplificationOptions.cs | 3 +-- src/Workspaces/Core/Portable/Workspaces.csproj | 1 + 20 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigSeverityStrings.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs index d5e3c662a53f9..828bbf7cf10fa 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Roslyn.Test.Utilities; @@ -10,9 +12,8 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.NamingStyle { public partial class EditorConfigNamingStyleParserTests { - [Fact] - static void TestPascalCaseRule() + public static void TestPascalCaseRule() { var dictionary = new Dictionary() { @@ -69,7 +70,7 @@ static void TestPascalCaseRule() } [Fact] - static void TestAsyncMethodsRule() + public static void TestAsyncMethodsRule() { var dictionary = new Dictionary() { @@ -114,9 +115,8 @@ static void TestAsyncMethodsRule() Assert.Equal(Capitalization.PascalCase, namingStyle.CapitalizationScheme); } - [Fact] - static void TestPublicMembersCapitalizedRule() + public static void TestPublicMembersCapitalizedRule() { var dictionary = new Dictionary() { @@ -172,11 +172,11 @@ static void TestPublicMembersCapitalizedRule() Assert.Equal("", namingStyle.Prefix); Assert.Equal("", namingStyle.Suffix); Assert.Equal("", namingStyle.WordSeparator); - Assert.Equal(Capitalization.FirstWordUpper, namingStyle.CapitalizationScheme); + Assert.Equal(Capitalization.FirstUpper, namingStyle.CapitalizationScheme); } [Fact] - static void TestNonPublicMembersLowerCaseRule() + public static void TestNonPublicMembersLowerCaseRule() { var dictionary = new Dictionary() { @@ -225,7 +225,7 @@ static void TestNonPublicMembersLowerCaseRule() } [Fact] - static void TestNoRulesAreReturned() + public static void TestNoRulesAreReturned() { var dictionary = new Dictionary() { diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs index 3c72cf4249f52..e7b75d23f74cb 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProviderFactory.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProviderFactory.cs index 2af4538f68f58..32b650532d414 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProviderFactory.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProviderFactory.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.ComponentModel.Composition; using Microsoft.CodeAnalysis.Options; diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb index c473d1b3b8164..2d74b87dea7ad 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Casing.vb @@ -77,37 +77,37 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests #Region "Firstupper" Public Sub TestFirstUpperWithZeroWords() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "") End Sub Public Sub TestFirstUpperWithOneConformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "First", "First") End Sub Public Sub TestFirstUpperWithOneNonconformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "First", "first") End Sub Public Sub TestFirstUpperCapitalizationOfFirstCharacter() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "Firstupper", "first", "upper") End Sub Public Sub TestFirstUpperDecapitalizationOfAppropriateFirstCharacter() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "Firstupper", "First", "Upper") End Sub Public Sub TestFirstUpperLeavesSubsequentCharactersAlone() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "FiRstupper", "fiRst", "upper") End Sub #End Region diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb index 22e2d059c4d2c..bb0c894b01f3a 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.ComplexTests.vb @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests Public Sub TestFirstUpperComplex1() - Dim namingStyle = CreateNamingStyle(prefix:="p_", suffix:="_s", wordSeparator:="__", capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(prefix:="p_", suffix:="_s", wordSeparator:="__", capitalizationScheme:=Capitalization.FirstUpper) TestNameCreation(namingStyle, "p_P_one__two__thRee_s", "p_one", "Two", "thRee") End Sub diff --git a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb index d443563397ca6..9376fcb0e796f 100644 --- a/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb +++ b/src/EditorFeatures/Test2/Diagnostics/NamingStyles/NamingStyleTests.IdentifierCreation.Compliance.vb @@ -145,49 +145,49 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests #Region "Firstupper" Public Sub TestFirstUpperComplianceWithZeroWords() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCompliance(namingStyle, "") End Sub Public Sub TestFirstUpperComplianceWithOneConformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCompliance(namingStyle, "First") End Sub Public Sub TestFirstUpperNoncomplianceWithOneNonconformingWord() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "first", "First") End Sub Public Sub TestFirstUpperComplianceWithCorrectCapitalizationOfFirstCharacters() - Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(capitalizationScheme:=Capitalization.FirstUpper) TestNameCompliance(namingStyle, "Firstupper") End Sub Public Sub TestFirstUpperNoncomplianceWithNoncapitalizationOfFirstCharacter() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "first_upper", "First_upper") End Sub Public Sub TestFirstUpperNoncomplianceWithCapitalizationOfFirstCharacterOfSubsequentWords() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", capitalizationScheme:=Capitalization.FirstUpper) TestNameNoncomplianceAndFixedNames(namingStyle, "First_Upper", "First_upper") End Sub Public Sub TestFirstUpperIgnoresSeeminglyNoncompliantPrefixOrSuffix() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_", prefix:="t_", suffix:="_T", capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_", prefix:="t_", suffix:="_T", capitalizationScheme:=Capitalization.FirstUpper) TestNameCompliance(namingStyle, "t_First_upper_T") End Sub Public Sub TestFirstUpperIgnoresSeeminglyNoncompliantWordSeparator() - Dim namingStyle = CreateNamingStyle(wordSeparator:="_T_", capitalizationScheme:=Capitalization.FirstWordUpper) + Dim namingStyle = CreateNamingStyle(wordSeparator:="_T_", capitalizationScheme:=Capitalization.FirstUpper) TestNameCompliance(namingStyle, "First_T_upper") End Sub #End Region diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs index d5ba991abc05a..4090d3fe55516 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs @@ -78,7 +78,7 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context) var syntaxTree = context.Node.SyntaxTree; var cancellationToken = context.CancellationToken; var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); - Debug.Assert(optionSet != null, "Unable to get options naming styles"); + Debug.Assert(optionSet != null, $"Unable to get {nameof(OptionSet)}"); if (optionSet == null) { return; diff --git a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs index 93f2a3689b2c5..f6980d855d49e 100644 --- a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs +++ b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Linq; using System.Threading.Tasks; -using System.Xml.Linq; using Microsoft.CodeAnalysis.Simplification; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs index 9571be58fa41e..7847a4ad9781e 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs @@ -29,7 +29,7 @@ public NamingStyleViewModel(NamingStyle style, bool canBeDeleted, INotificationS { new CapitalizationDisplay(Capitalization.PascalCase, ServicesVSResources.Pascal_Case_Name), new CapitalizationDisplay(Capitalization.CamelCase, ServicesVSResources.camel_Case_Name), - new CapitalizationDisplay(Capitalization.FirstWordUpper, ServicesVSResources.First_word_upper), + new CapitalizationDisplay(Capitalization.FirstUpper, ServicesVSResources.First_word_upper), new CapitalizationDisplay(Capitalization.AllUpper, ServicesVSResources.ALL_UPPER), new CapitalizationDisplay(Capitalization.AllLower, ServicesVSResources.all_lower) }; diff --git a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleHelpers.cs b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleHelpers.cs index de5f268ac09c0..8e9586ecfab30 100644 --- a/src/Workspaces/Core/Portable/CodeStyle/CodeStyleHelpers.cs +++ b/src/Workspaces/Core/Portable/CodeStyle/CodeStyleHelpers.cs @@ -31,10 +31,10 @@ public static CodeStyleOption ParseEditorConfigCodeStyleOption(string arg) switch (args[1].Trim()) { - case "silent": return new CodeStyleOption(value: isEnabled, notification: NotificationOption.None); - case "suggestion": return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Suggestion); - case "warning": return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Warning); - case "error": return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Error); + case EditorConfigSeverityStrings.Silent: return new CodeStyleOption(value: isEnabled, notification: NotificationOption.None); + case EditorConfigSeverityStrings.Suggestion: return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Suggestion); + case EditorConfigSeverityStrings.Warning: return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Warning); + case EditorConfigSeverityStrings.Error: return new CodeStyleOption(value: isEnabled, notification: NotificationOption.Error); default: return new CodeStyleOption(value: isEnabled, notification: NotificationOption.None); } } diff --git a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs index 8c0cc044d486a..af91875327e0b 100644 --- a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs @@ -1,16 +1,15 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Xml.Linq; using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.Options; -using Roslyn.Utilities; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; +using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Simplification; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Execution { diff --git a/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs b/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs index 754071074b617..f675c0fd64726 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Capitalization.cs @@ -17,7 +17,7 @@ internal enum Capitalization /// /// Only the first word is capitalized /// - FirstWordUpper, + FirstUpper, /// /// Every character is capitalized diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs index f1b4d213b5fef..a2ff85af13c87 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; -using System.Linq; -using Roslyn.Utilities; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { @@ -20,6 +20,7 @@ private static bool TryGetSerializableNamingRule( NamingStyleID = namingStyle.ID, SymbolSpecificationID = symbolSpec.ID }; + return true; } @@ -39,10 +40,10 @@ private static DiagnosticSeverity ParseEnforcementLevel(string ruleSeverity) { switch (ruleSeverity) { - case "silent": return DiagnosticSeverity.Hidden; - case "suggestion": return DiagnosticSeverity.Info; - case "warning": return DiagnosticSeverity.Warning; - case "error": return DiagnosticSeverity.Error; + case EditorConfigSeverityStrings.Silent: return DiagnosticSeverity.Hidden; + case EditorConfigSeverityStrings.Suggestion: return DiagnosticSeverity.Info; + case EditorConfigSeverityStrings.Warning: return DiagnosticSeverity.Warning; + case EditorConfigSeverityStrings.Error: return DiagnosticSeverity.Error; default: return DiagnosticSeverity.Hidden; } } diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs index c0e0c7ca8afc6..69d3ec8e2f8df 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; -using System.Linq; -using Roslyn.Utilities; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { @@ -30,6 +30,7 @@ private static bool TryGetNamingStyleData( WordSeparator = wordSeparator, CapitalizationScheme = capitalization }; + return true; } @@ -94,7 +95,7 @@ private static Capitalization ParseCapitalizationScheme(string namingStyleCapita { case "pascal_case": return Capitalization.PascalCase; case "camel_case": return Capitalization.CamelCase; - case "first_word_upper": return Capitalization.FirstWordUpper; + case "first_word_upper": return Capitalization.FirstUpper; case "all_upper": return Capitalization.AllUpper; case "all_lower": return Capitalization.AllLower; default: return default(Capitalization); diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs index 6419c6585c142..99402ccef0119 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs @@ -1,8 +1,9 @@ -using System; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Roslyn.Utilities; using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs index d1bd3519c957b..651c97cfd82e2 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigSeverityStrings.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigSeverityStrings.cs new file mode 100644 index 0000000000000..2349bd5985633 --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigSeverityStrings.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis +{ + internal static class EditorConfigSeverityStrings + { + public const string Silent = "silent"; + public const string Suggestion = "suggestion"; + public const string Warning = "warning"; + public const string Error = "error"; + } +} diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs index 728647347000b..afacd0b533560 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStyle.cs @@ -39,7 +39,7 @@ private IEnumerable ApplyCapitalization(IEnumerable words) return words.Select(CapitalizeFirstLetter); case Capitalization.CamelCase: return words.Take(1).Select(DecapitalizeFirstLetter).Concat(words.Skip(1).Select(CapitalizeFirstLetter)); - case Capitalization.FirstWordUpper: + case Capitalization.FirstUpper: return words.Take(1).Select(CapitalizeFirstLetter).Concat(words.Skip(1).Select(DecapitalizeFirstLetter)); case Capitalization.AllUpper: return words.Select(w => w.ToUpper()); @@ -132,7 +132,7 @@ public bool IsNameCompliant(string name, out string failureReason) return false; } - case Capitalization.FirstWordUpper: + case Capitalization.FirstUpper: if (char.IsUpper(words.First()[0]) && words.Skip(1).All(w => char.IsLower(w[0]))) { return true; diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs index 36983705a63bc..363a3e22b6205 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs @@ -1,9 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; -using System.Xml.Linq; +using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.Simplification { diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 1d27f5cf67c71..74af4ca415e94 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -370,6 +370,7 @@ + From a2107f6571a4651ea99dd34644ba8be5edb85d35 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Wed, 7 Dec 2016 11:30:56 -0800 Subject: [PATCH 4/8] responding to Jason's feedback --- .../NamingStylesTests_OptionSets.cs | 8 ++--- .../EditorConfigDocumentOptionsProvider.cs | 2 ++ ...eferFrameworkTypeDiagnosticAnalyzerBase.cs | 5 ---- .../SymbolAnalysisContextExtensions.cs | 12 +++----- .../CSharp/Impl/Options/AutomationObject.cs | 2 +- .../NamingStyleOptionPageControl.xaml.cs | 2 +- .../NamingStyleOptionPageViewModel.cs | 2 +- .../AbstractOptionsSerializationService.cs | 12 ++++---- ...ditorConfigNamingStyleParser.NamingRule.cs | 4 +-- ...itorConfigNamingStyleParser.NamingStyle.cs | 23 ++++---------- ...ditorConfigNamingStyleParser.SymbolSpec.cs | 7 ++--- .../EditorConfigNamingStyleParser.cs | 27 +++++++++-------- .../Serialization/SerializableNamingRule.cs | 2 +- .../SerializableNamingStylePreferencesInfo.cs | 20 ++++++------- .../Serialization/SymbolSpecification.cs | 30 +++++++------------ .../Simplification/SimplificationOptions.cs | 2 +- 16 files changed, 68 insertions(+), 92 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs index 38e5b7e497272..4a15180c7458e 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs @@ -27,7 +27,7 @@ private IDictionary Options(OptionKey option, object value) return options; } - private SerializableNamingStylePreferencesInfo ClassNamesArePascalCaseOptionString() + private NamingStylePreferences ClassNamesArePascalCaseOptionString() { var symbolSpecification = new SymbolSpecification( Guid.NewGuid(), @@ -49,7 +49,7 @@ private SerializableNamingStylePreferencesInfo ClassNamesArePascalCaseOptionStri namingRule.NamingStyleID = namingStyle.ID; namingRule.EnforcementLevel = DiagnosticSeverity.Error; - var info = new SerializableNamingStylePreferencesInfo(); + var info = new NamingStylePreferences(); info.SymbolSpecifications.Add(symbolSpecification); info.NamingStyles.Add(namingStyle); info.NamingRules.Add(namingRule); @@ -57,7 +57,7 @@ private SerializableNamingStylePreferencesInfo ClassNamesArePascalCaseOptionStri return info; } - private SerializableNamingStylePreferencesInfo MethodNamesArePascalCaseOptionString() + private NamingStylePreferences MethodNamesArePascalCaseOptionString() { var symbolSpecification = new SymbolSpecification( Guid.NewGuid(), @@ -79,7 +79,7 @@ private SerializableNamingStylePreferencesInfo MethodNamesArePascalCaseOptionStr namingRule.NamingStyleID = namingStyle.ID; namingRule.EnforcementLevel = DiagnosticSeverity.Error; - var info = new SerializableNamingStylePreferencesInfo(); + var info = new NamingStylePreferences(); info.SymbolSpecifications.Add(symbolSpecification); info.NamingStyles.Add(namingStyle); info.NamingRules.Add(namingRule); diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs index e7b75d23f74cb..06503065ac12a 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs @@ -122,6 +122,8 @@ private Task GetConventionContextAsync(string path, Ca return IOUtilities.PerformIOAsync( () => _codingConventionsManager.GetConventionContextAsync(path, cancellationToken), defaultValue: EmptyCodingConventionContext.Instance); + value = null; + value = null; } } } diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs index 4090d3fe55516..696e15fbee33b 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/PreferFrameworkTypeDiagnosticAnalyzerBase.cs @@ -78,11 +78,6 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context) var syntaxTree = context.Node.SyntaxTree; var cancellationToken = context.CancellationToken; var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); - Debug.Assert(optionSet != null, $"Unable to get {nameof(OptionSet)}"); - if (optionSet == null) - { - return; - } var semanticModel = context.SemanticModel; var language = semanticModel.Language; diff --git a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs index f6980d855d49e..e89a019ae79a5 100644 --- a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs +++ b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs @@ -16,18 +16,14 @@ public static async Task GetNamingStylePreferencesAs return null; } - var cancellationToken = context.CancellationToken; - var syntaxTree = location.SourceTree; - var options = context.Options; - var optionSet = await options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).ConfigureAwait(false); - string language = context.Compilation.Language; - var viewModel = optionSet.GetOption(SimplificationOptions.NamingPreferences, language); - if (viewModel == null) + var optionSet = await context.Options.GetDocumentOptionSetAsync(location.SourceTree, context.CancellationToken).ConfigureAwait(false); + var namimgStylePreferences = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); + if (namimgStylePreferences == null) { return null; } - var preferences = viewModel.GetPreferencesInfo(); + var preferences = namimgStylePreferences.GetPreferencesInfo(); return preferences; } } diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs index 8bfd5efdaa22a..fb65f0fbed1f7 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs @@ -539,7 +539,7 @@ public string Style_NamingPreferences set { - _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(value))); + _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, NamingStylePreferences.FromXElement(XElement.Parse(value))); } } diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs index c51c5e5a19188..8c101c54d3b1f 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs @@ -135,7 +135,7 @@ private void SetFocusToSelectedRow() internal override void SaveSettings() { - var info = new SerializableNamingStylePreferencesInfo(); + var info = new NamingStylePreferences(); foreach (var item in _viewModel.CodeStyleItems) { diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs index 3c675f851e59a..0677dd62b3adf 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs @@ -28,7 +28,7 @@ internal class NamingStyleOptionPageViewModel : AbstractNotifyPropertyChanged public ObservableCollection Specifications { get; set; } public ObservableCollection NamingStyles { get; set; } - public NamingStyleOptionPageViewModel(SerializableNamingStylePreferencesInfo info) + public NamingStyleOptionPageViewModel(NamingStylePreferences info) { var viewModels = new List(); foreach (var namingRule in info.NamingRules) diff --git a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs index af91875327e0b..15f4b65be4018 100644 --- a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs @@ -290,7 +290,7 @@ private OptionSet ReadOptionFrom(OptionSet options, string language, PerLangu return options.WithChangedOption(option, language, value); } - protected void WriteOptionTo(OptionSet options, Option option, ObjectWriter writer, CancellationToken cancellationToken) + protected void WriteOptionTo(OptionSet options, Option option, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -298,17 +298,17 @@ protected void WriteOptionTo(OptionSet options, Option option, ObjectReader reader, CancellationToken cancellationToken) + protected OptionSet ReadOptionFrom(OptionSet options, Option option, ObjectReader reader, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var xmlText = reader.ReadString(); - var value = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(xmlText)); + var value = NamingStylePreferences.FromXElement(XElement.Parse(xmlText)); return options.WithChangedOption(option, value); } - private void WriteOptionTo(OptionSet options, string language, PerLanguageOption option, ObjectWriter writer, CancellationToken cancellationToken) + private void WriteOptionTo(OptionSet options, string language, PerLanguageOption option, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -316,12 +316,12 @@ private void WriteOptionTo(OptionSet options, string language, PerLanguageOption writer.WriteString(value.CreateXElement().ToString()); } - private OptionSet ReadOptionFrom(OptionSet options, string language, PerLanguageOption option, ObjectReader reader, CancellationToken cancellationToken) + private OptionSet ReadOptionFrom(OptionSet options, string language, PerLanguageOption option, ObjectReader reader, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var xmlText = reader.ReadString(); - var value = SerializableNamingStylePreferencesInfo.FromXElement(XElement.Parse(xmlText)); + var value = NamingStylePreferences.FromXElement(XElement.Parse(xmlText)); return options.WithChangedOption(option, language, value); } diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs index a2ff85af13c87..5c836072af662 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs @@ -13,7 +13,7 @@ private static bool TryGetSerializableNamingRule( IReadOnlyDictionary conventionsDictionary, out SerializableNamingRule serializableNamingRule) { - var severity= GetRuleSeverity(namingRuleTitle, conventionsDictionary); + var severity = GetRuleSeverity(namingRuleTitle, conventionsDictionary); serializableNamingRule = new SerializableNamingRule() { EnforcementLevel = severity, @@ -33,7 +33,7 @@ private static DiagnosticSeverity GetRuleSeverity( return ParseEnforcementLevel(result as string ?? string.Empty); } - return default(DiagnosticSeverity); ; + return default(DiagnosticSeverity); } private static DiagnosticSeverity ParseEnforcementLevel(string ruleSeverity) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs index 69d3ec8e2f8df..fbbb1502d4608 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs @@ -50,28 +50,17 @@ private static bool TryGetNamingStyleTitle( } private static string GetNamingRequiredPrefix(string namingStyleName, IReadOnlyDictionary conventionsDictionary) - { - if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.required_prefix", out var result)) - { - return result as string ?? string.Empty; - } - - return string.Empty; - } + => GetStringFromConventionsDictionary(namingStyleName, "required_prefix", conventionsDictionary); private static string GetNamingRequiredSuffix(string namingStyleName, IReadOnlyDictionary conventionsDictionary) - { - if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.required_suffix", out object result)) - { - return result as string ?? string.Empty; - } - - return string.Empty; - } + => GetStringFromConventionsDictionary(namingStyleName, "required_suffix", conventionsDictionary); private static string GetNamingWordSeparator(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + => GetStringFromConventionsDictionary(namingStyleName, "word_separator", conventionsDictionary); + + private static string GetStringFromConventionsDictionary(string namingStyleName, string optionName, IReadOnlyDictionary conventionsDictionary) { - if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.word_separator", out object result)) + if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.{optionName}", out object result)) { return result as string ?? string.Empty; } diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs index 99402ccef0119..7c85cfef0ac3f 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs @@ -43,7 +43,7 @@ private static bool TryGetSymbolSpecNameForNamingRule( if (conventionsDictionary.TryGetValue($"dotnet_naming_rule.{namingRuleName}.symbols", out object result)) { symbolSpecName = result as string; - return symbolSpecName != null; ; + return symbolSpecName != null; } return false; @@ -72,7 +72,7 @@ private static ImmutableArray GetSymbolsApplicableKinds( private static readonly SymbolKindOrTypeKind _namespace = new SymbolKindOrTypeKind(SymbolKind.Namespace); private static readonly SymbolKindOrTypeKind _delegate = new SymbolKindOrTypeKind(TypeKind.Delegate); private static readonly SymbolKindOrTypeKind _typeParameter = new SymbolKindOrTypeKind(SymbolKind.TypeParameter); - + private static readonly ImmutableArray _all = ImmutableArray.Create(_class, _struct, _interface, _enum, _property, _method, _field, _event, _namespace, _delegate, _typeParameter); private static ImmutableArray ParseSymbolKindList(string symbolSpecApplicableKinds) { if (symbolSpecApplicableKinds == null) @@ -83,8 +83,7 @@ private static ImmutableArray ParseSymbolKindList(string s var builder = ArrayBuilder.GetInstance(); if (symbolSpecApplicableKinds.Trim() == "*") { - builder.AddRange(_class, _struct, _interface, _enum, _property, _method, _field, _event, _namespace, _delegate, _typeParameter); - return builder.ToImmutableAndFree(); + return _all; } foreach (var symbolSpecApplicableKind in symbolSpecApplicableKinds.Split(',').Select(x => x.Trim())) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs index 651c97cfd82e2..a588b5c64b7f1 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs @@ -11,26 +11,29 @@ internal static partial class EditorConfigNamingStyleParser /// /// The dictionary we get from the VS editorconfig API uses the same dictionary object if there are no changes, so we can cache based on dictionary /// - private static readonly ConditionalWeakTable, SerializableNamingStylePreferencesInfo> _cache = new ConditionalWeakTable, SerializableNamingStylePreferencesInfo>(); + private static readonly ConditionalWeakTable, NamingStylePreferences> _cache = new ConditionalWeakTable, NamingStylePreferences>(); private static readonly object _cacheLock = new object(); - public static SerializableNamingStylePreferencesInfo GetNamingStylesStringFromDictionary(IReadOnlyDictionary allRawConventions) + public static NamingStylePreferences GetNamingStylesStringFromDictionary(IReadOnlyDictionary allRawConventions) { - if (!_cache.TryGetValue(allRawConventions, out var value)) + if (_cache.TryGetValue(allRawConventions, out var value)) { - lock (_cacheLock) + return value; + } + + lock (_cacheLock) + { + if (!_cache.TryGetValue(allRawConventions, out value)) { - if (!_cache.TryGetValue(allRawConventions, out value)) - { - value = ParseDictionary(allRawConventions); - _cache.Add(allRawConventions, value); - } + value = ParseDictionary(allRawConventions); + _cache.Add(allRawConventions, value); } + + return value; } - return value; } - public static SerializableNamingStylePreferencesInfo ParseDictionary(IReadOnlyDictionary allRawConventions) + public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary allRawConventions) { var symbolSpecifications = new List(); var namingStyles = new List(); @@ -56,7 +59,7 @@ public static SerializableNamingStylePreferencesInfo ParseDictionary(IReadOnlyDi } } - return new SerializableNamingStylePreferencesInfo(symbolSpecifications, namingStyles, namingRules); + return new NamingStylePreferences(symbolSpecifications, namingStyles, namingRules); } private static IEnumerable GetRuleTitles(IReadOnlyDictionary allRawConventions) diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs index 6c83fda21d011..853da08383e6b 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingRule.cs @@ -11,7 +11,7 @@ internal class SerializableNamingRule public Guid NamingStyleID; public DiagnosticSeverity EnforcementLevel; - public NamingRule GetRule(SerializableNamingStylePreferencesInfo info) + public NamingRule GetRule(NamingStylePreferences info) { return new NamingRule( info.GetSymbolSpecification(SymbolSpecificationID), diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs index 74e499347558e..b0e824f0395e3 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles /// 2. Name Style /// 3. Naming Rule (points to Symbol Specification IDs) /// - internal class SerializableNamingStylePreferencesInfo : IEquatable + internal class NamingStylePreferences : IEquatable { public List SymbolSpecifications; public List NamingStyles; @@ -23,21 +23,21 @@ internal class SerializableNamingStylePreferencesInfo : IEquatable symbolSpecifications, List namingStyles, List namingRules) + internal NamingStylePreferences(List symbolSpecifications, List namingStyles, List namingRules) { SymbolSpecifications = symbolSpecifications; NamingStyles = namingStyles; NamingRules = namingRules; } - internal SerializableNamingStylePreferencesInfo() + internal NamingStylePreferences() { SymbolSpecifications = new List(); NamingStyles = new List(); NamingRules = new List(); } - public static SerializableNamingStylePreferencesInfo Default => FromXElement(XElement.Parse(DefaultNamingPreferencesString)); + public static NamingStylePreferences Default => FromXElement(XElement.Parse(DefaultNamingPreferencesString)); public static string DefaultNamingPreferencesString => _defaultNamingPreferencesString; @@ -101,9 +101,9 @@ private XElement CreateSymbolSpecificationListXElement() return symbolSpecificationsElement; } - internal static SerializableNamingStylePreferencesInfo FromXElement(XElement namingPreferencesInfoElement) + internal static NamingStylePreferences FromXElement(XElement namingPreferencesInfoElement) { - var namingPreferencesInfo = new SerializableNamingStylePreferencesInfo(); + var namingPreferencesInfo = new NamingStylePreferences(); var serializationVersion = int.Parse(namingPreferencesInfoElement.Attribute("SerializationVersion").Value); if (serializationVersion != s_serializationVersion) @@ -143,9 +143,9 @@ private void SetNamingRuleTreeFromXElement(XElement namingRulesElement) } public override bool Equals(object obj) - => Equals(obj as SerializableNamingStylePreferencesInfo); + => Equals(obj as NamingStylePreferences); - public bool Equals(SerializableNamingStylePreferencesInfo other) + public bool Equals(NamingStylePreferences other) { if (object.ReferenceEquals(other, null)) { @@ -155,7 +155,7 @@ public bool Equals(SerializableNamingStylePreferencesInfo other) return this.CreateXElement().ToString() == other.CreateXElement().ToString(); } - public static bool operator ==(SerializableNamingStylePreferencesInfo left, SerializableNamingStylePreferencesInfo right) + public static bool operator ==(NamingStylePreferences left, NamingStylePreferences right) { bool leftIsNull = object.ReferenceEquals(left, null); bool rightIsNull = object.ReferenceEquals(right, null); @@ -175,7 +175,7 @@ public bool Equals(SerializableNamingStylePreferencesInfo other) return left.Equals(right); } - public static bool operator !=(SerializableNamingStylePreferencesInfo left, SerializableNamingStylePreferencesInfo right) + public static bool operator !=(NamingStylePreferences left, NamingStylePreferences right) => !(left == right); public override int GetHashCode() diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs index 88de8c0a3175a..83436b6733ea7 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs @@ -180,7 +180,7 @@ private void PopulateModifierListFromXElement(XElement modifierListElement) } } - public class SymbolKindOrTypeKind : IEquatable + public struct SymbolKindOrTypeKind : IEquatable { public SymbolKind? SymbolKind { get; set; } public TypeKind? TypeKind { get; set; } @@ -188,10 +188,12 @@ public class SymbolKindOrTypeKind : IEquatable public SymbolKindOrTypeKind(SymbolKind symbolKind) { SymbolKind = symbolKind; + TypeKind = null; } public SymbolKindOrTypeKind(TypeKind typeKind) { + SymbolKind = null; TypeKind = typeKind; } @@ -232,28 +234,18 @@ internal static SymbolKindOrTypeKind AddTypeKindFromXElement(XElement typeKindEl public override bool Equals(object obj) { - return Equals(obj as SymbolKindOrTypeKind); + return Equals((SymbolKindOrTypeKind)obj); } public bool Equals(SymbolKindOrTypeKind other) { - return other != null && - this.SymbolKind == other.SymbolKind && - this.TypeKind == other.TypeKind; + return SymbolKind == other.SymbolKind && + TypeKind == other.TypeKind; } public override int GetHashCode() { - if (this.SymbolKind.HasValue && this.TypeKind.HasValue) - { - return Hash.Combine(this.SymbolKind.Value.GetHashCode(), this.TypeKind.Value.GetHashCode()); - } - else if (this.SymbolKind.HasValue) - { - return this.SymbolKind.Value.GetHashCode(); - } - - return this.TypeKind.Value.GetHashCode(); + return Hash.Combine(SymbolKind.GetHashCode(), TypeKind.GetHashCode()); } } @@ -288,7 +280,7 @@ public override bool Equals(object obj) public bool Equals(AccessibilityKind other) { - return this.Accessibility == other.Accessibility; + return Accessibility == other.Accessibility; } public static bool operator ==(AccessibilityKind left, AccessibilityKind right) @@ -299,7 +291,7 @@ public bool Equals(AccessibilityKind other) public override int GetHashCode() { - return this.Accessibility.GetHashCode(); + return Accessibility.GetHashCode(); } } @@ -359,7 +351,7 @@ public ModifierKind(DeclarationModifiers modifier) { ModifierKindWrapper = default(ModifierKindEnum); _modifier = default(DeclarationModifiers); - this.Modifier = modifier; + Modifier = modifier; } public ModifierKind(ModifierKindEnum modifierKind) @@ -426,7 +418,7 @@ public bool Equals(ModifierKind other) public override int GetHashCode() { - return this.Modifier.GetHashCode(); + return Modifier.GetHashCode(); } } public enum ModifierKindEnum diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs index 363a3e22b6205..7a172728addc2 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs @@ -100,7 +100,7 @@ public static class SimplificationOptions /// This option describes the naming rules that should be applied to specified categories of symbols, /// and the level to which those rules should be enforced. /// - internal static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: SerializableNamingStylePreferencesInfo.Default, + internal static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: NamingStylePreferences.Default, storageLocations: new OptionStorageLocation[]{ new NamingEditorConfigStorageLocation(), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NamingPreferences")}); From 1aa1518f03119f86e68181b047b50b540000b399 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Sat, 10 Dec 2016 13:41:40 -0800 Subject: [PATCH 5/8] responding to Jason's feedback part 2 --- .../EditorConfigNamingStyleParserTests.cs | 62 +++----------- .../NamingStylesTests_OptionSets.cs | 74 +++++++++-------- ...DocumentOptionsProvider.DocumentOptions.cs | 2 +- .../EditorConfigDocumentOptionsProvider.cs | 2 - .../SymbolAnalysisContextExtensions.cs | 10 +-- ...amingVisualStudioProfileOptionPersister.cs | 43 +++++++--- .../NamingStyleOptionPageViewModel.cs | 24 +++--- .../NamingStyles/NamingStyleViewModel.cs | 16 ++-- .../SymbolSpecificationViewModel.cs | 16 ++-- ...itorConfigNamingStyleParser.NamingStyle.cs | 22 ++--- ...ditorConfigNamingStyleParser.SymbolSpec.cs | 31 +++---- .../EditorConfigNamingStyleParser.cs | 2 +- .../NamingStylePreferencesInfo.cs | 10 +-- .../Serialization/AccessibilityExtensions.cs | 25 ++++++ .../SerializableNamingStylePreferencesInfo.cs | 12 +-- .../Serialization/SymbolSpecification.cs | 83 +++++-------------- .../Core/Portable/Workspaces.csproj | 1 + 17 files changed, 189 insertions(+), 246 deletions(-) create mode 100644 src/Workspaces/Core/Portable/NamingStyles/Serialization/AccessibilityExtensions.cs diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs index 828bbf7cf10fa..2858246f023b6 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/EditorConfigNamingStyleParserTests.cs @@ -24,44 +24,33 @@ public static void TestPascalCaseRule() ["dotnet_naming_symbols.method_and_property_symbols.applicable_accessibilities"] = "*", ["dotnet_naming_style.pascal_case_style.capitalization"] = "pascal_case" }; - var result = ParseDictionary(dictionary); - Assert.Single(result.NamingRules); var namingRule = result.NamingRules.Single(); - Assert.Single(result.NamingStyles); var namingStyle = result.NamingStyles.Single(); - Assert.Single(result.SymbolSpecifications); var symbolSpec = result.SymbolSpecifications.Single(); - Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); - Assert.Equal(DiagnosticSeverity.Warning, namingRule.EnforcementLevel); - Assert.Equal("method_and_property_symbols", symbolSpec.Name); - var expectedApplicableSymbolKindList = new[] { new SymbolKindOrTypeKind(SymbolKind.Method), new SymbolKindOrTypeKind(SymbolKind.Property) }; AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); - Assert.Empty(symbolSpec.RequiredModifierList); - var expectedApplicableAccessibilityList = new[] { - new AccessibilityKind(Accessibility.Public), - new AccessibilityKind(Accessibility.Internal), - new AccessibilityKind(Accessibility.Private), - new AccessibilityKind(Accessibility.Protected), - new AccessibilityKind(Accessibility.ProtectedOrInternal) + Accessibility.Public, + Accessibility.Internal, + Accessibility.Private, + Accessibility.Protected, + Accessibility.ProtectedOrInternal }; AssertEx.SetEqual(expectedApplicableAccessibilityList, symbolSpec.ApplicableAccessibilityList); - Assert.Equal("pascal_case_style", namingStyle.Name); Assert.Equal("", namingStyle.Prefix); Assert.Equal("", namingStyle.Suffix); @@ -82,32 +71,22 @@ public static void TestAsyncMethodsRule() ["dotnet_naming_style.end_in_async_style.capitalization "] = "pascal_case", ["dotnet_naming_style.end_in_async_style.required_suffix"] = "Async", }; - var result = ParseDictionary(dictionary); - Assert.Single(result.NamingRules); var namingRule = result.NamingRules.Single(); - Assert.Single(result.NamingStyles); var namingStyle = result.NamingStyles.Single(); - Assert.Single(result.SymbolSpecifications); var symbolSpec = result.SymbolSpecifications.Single(); - Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); Assert.Equal(DiagnosticSeverity.Error, namingRule.EnforcementLevel); - Assert.Equal("method_symbols", symbolSpec.Name); - Assert.Single(symbolSpec.ApplicableSymbolKindList); Assert.Contains(new SymbolKindOrTypeKind(SymbolKind.Method), symbolSpec.ApplicableSymbolKindList); - Assert.Single(symbolSpec.RequiredModifierList); Assert.Contains(new ModifierKind(ModifierKindEnum.IsAsync), symbolSpec.RequiredModifierList); - Assert.Empty(symbolSpec.ApplicableAccessibilityList); - Assert.Equal("end_in_async_style", namingStyle.Name); Assert.Equal("", namingStyle.Prefix); Assert.Equal("Async", namingStyle.Suffix); @@ -127,25 +106,17 @@ public static void TestPublicMembersCapitalizedRule() ["dotnet_naming_symbols.public_symbols.applicable_accessibilities"] = "public,internal,protected,protected_internal", ["dotnet_naming_style.first_word_upper_case_style.capitalization"] = "first_word_upper", }; - var result = ParseDictionary(dictionary); - Assert.Single(result.NamingRules); var namingRule = result.NamingRules.Single(); - Assert.Single(result.NamingStyles); var namingStyle = result.NamingStyles.Single(); - Assert.Single(result.SymbolSpecifications); var symbolSpec = result.SymbolSpecifications.Single(); - Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); Assert.Equal(DiagnosticSeverity.Info, namingRule.EnforcementLevel); - Assert.Equal("public_symbols", symbolSpec.Name); - - var expectedApplicableSymbolKindList = new[] { new SymbolKindOrTypeKind(SymbolKind.Property), @@ -155,19 +126,15 @@ public static void TestPublicMembersCapitalizedRule() new SymbolKindOrTypeKind(TypeKind.Delegate) }; AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); - - var expectedApplicableAccessibilityList = new[] { - new AccessibilityKind(Accessibility.Public), - new AccessibilityKind(Accessibility.Internal), - new AccessibilityKind(Accessibility.Protected), - new AccessibilityKind(Accessibility.ProtectedOrInternal) + Accessibility.Public, + Accessibility.Internal, + Accessibility.Protected, + Accessibility.ProtectedOrInternal }; AssertEx.SetEqual(expectedApplicableAccessibilityList, symbolSpec.ApplicableAccessibilityList); - Assert.Empty(symbolSpec.RequiredModifierList); - Assert.Equal("first_word_upper_case_style", namingStyle.Name); Assert.Equal("", namingStyle.Prefix); Assert.Equal("", namingStyle.Suffix); @@ -187,9 +154,7 @@ public static void TestNonPublicMembersLowerCaseRule() ["dotnet_naming_symbols.non_public_symbols.applicable_accessibilities"] = "private", ["dotnet_naming_style.all_lower_case_style.capitalization"] = "all_lower", }; - var result = ParseDictionary(dictionary); - Assert.Single(result.NamingRules); var namingRule = result.NamingRules.Single(); Assert.Single(result.NamingStyles); @@ -199,9 +164,7 @@ public static void TestNonPublicMembersLowerCaseRule() Assert.Equal(namingStyle.ID, namingRule.NamingStyleID); Assert.Equal(symbolSpec.ID, namingRule.SymbolSpecificationID); Assert.Equal(DiagnosticSeverity.Hidden, namingRule.EnforcementLevel); - Assert.Equal("non_public_symbols", symbolSpec.Name); - var expectedApplicableSymbolKindList = new[] { new SymbolKindOrTypeKind(SymbolKind.Property), @@ -211,12 +174,9 @@ public static void TestNonPublicMembersLowerCaseRule() new SymbolKindOrTypeKind(TypeKind.Delegate) }; AssertEx.SetEqual(expectedApplicableSymbolKindList, symbolSpec.ApplicableSymbolKindList); - Assert.Single(symbolSpec.ApplicableAccessibilityList); - Assert.Contains(new AccessibilityKind(Accessibility.Private), symbolSpec.ApplicableAccessibilityList); - + Assert.Contains(Accessibility.Private, symbolSpec.ApplicableAccessibilityList); Assert.Empty(symbolSpec.RequiredModifierList); - Assert.Equal("all_lower_case_style", namingStyle.Name); Assert.Equal("", namingStyle.Prefix); Assert.Equal("", namingStyle.Suffix); @@ -233,9 +193,7 @@ public static void TestNoRulesAreReturned() ["dotnet_naming_symbols.non_public_symbols.applicable_accessibilities"] = "private", ["dotnet_naming_style.all_lower_case_style.capitalization"] = "all_lower", }; - var result = ParseDictionary(dictionary); - Assert.Empty(result.NamingRules); Assert.Empty(result.NamingStyles); Assert.Empty(result.SymbolSpecifications); diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs index 4a15180c7458e..3a403944c8f2e 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/NamingStyles/NamingStylesTests_OptionSets.cs @@ -15,40 +15,42 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.NamingStyle public partial class NamingStylesTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest { private IDictionary ClassNamesArePascalCase => - Options(new OptionKey(SimplificationOptions.NamingPreferences, LanguageNames.CSharp), ClassNamesArePascalCaseOptionString()); + Options(new OptionKey(SimplificationOptions.NamingPreferences, LanguageNames.CSharp), ClassNamesArePascalCaseOption()); private IDictionary MethodNamesArePascalCase => - Options(new OptionKey(SimplificationOptions.NamingPreferences, LanguageNames.CSharp), MethodNamesArePascalCaseOptionString()); + Options(new OptionKey(SimplificationOptions.NamingPreferences, LanguageNames.CSharp), MethodNamesArePascalCaseOption()); private IDictionary Options(OptionKey option, object value) { - var options = new Dictionary(); - options.Add(option, value); + var options = new Dictionary + { + { option, value } + }; return options; } - private NamingStylePreferences ClassNamesArePascalCaseOptionString() + private NamingStylePreferences ClassNamesArePascalCaseOption() { var symbolSpecification = new SymbolSpecification( - Guid.NewGuid(), "Name", SpecializedCollections.SingletonEnumerable(new SymbolSpecification.SymbolKindOrTypeKind(TypeKind.Class)).ToList(), - SpecializedCollections.EmptyList(), + SpecializedCollections.EmptyList(), SpecializedCollections.EmptyList()); - var namingStyle = new NamingStyle(); - namingStyle.CapitalizationScheme = Capitalization.PascalCase; - namingStyle.Name = "Name"; - namingStyle.Prefix = ""; - namingStyle.Suffix = ""; - namingStyle.WordSeparator = ""; - - - var namingRule = new SerializableNamingRule(); - namingRule.SymbolSpecificationID = symbolSpecification.ID; - namingRule.NamingStyleID = namingStyle.ID; - namingRule.EnforcementLevel = DiagnosticSeverity.Error; - + var namingStyle = new NamingStyle() + { + CapitalizationScheme = Capitalization.PascalCase, + Name = "Name", + Prefix = "", + Suffix = "", + WordSeparator = "" + }; + var namingRule = new SerializableNamingRule() + { + SymbolSpecificationID = symbolSpecification.ID, + NamingStyleID = namingStyle.ID, + EnforcementLevel = DiagnosticSeverity.Error + }; var info = new NamingStylePreferences(); info.SymbolSpecifications.Add(symbolSpecification); info.NamingStyles.Add(namingStyle); @@ -57,28 +59,28 @@ private NamingStylePreferences ClassNamesArePascalCaseOptionString() return info; } - private NamingStylePreferences MethodNamesArePascalCaseOptionString() + private NamingStylePreferences MethodNamesArePascalCaseOption() { var symbolSpecification = new SymbolSpecification( - Guid.NewGuid(), "Name", SpecializedCollections.SingletonEnumerable(new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Method)).ToList(), - SpecializedCollections.EmptyList(), + SpecializedCollections.EmptyList(), SpecializedCollections.EmptyList()); - var namingStyle = new NamingStyle(); - namingStyle.CapitalizationScheme = Capitalization.PascalCase; - namingStyle.Name = "Name"; - namingStyle.Prefix = ""; - namingStyle.Suffix = ""; - namingStyle.WordSeparator = ""; - - - var namingRule = new SerializableNamingRule(); - namingRule.SymbolSpecificationID = symbolSpecification.ID; - namingRule.NamingStyleID = namingStyle.ID; - namingRule.EnforcementLevel = DiagnosticSeverity.Error; - + var namingStyle = new NamingStyle() + { + CapitalizationScheme = Capitalization.PascalCase, + Name = "Name", + Prefix = "", + Suffix = "", + WordSeparator = "" + }; + var namingRule = new SerializableNamingRule() + { + SymbolSpecificationID = symbolSpecification.ID, + NamingStyleID = namingStyle.ID, + EnforcementLevel = DiagnosticSeverity.Error + }; var info = new NamingStylePreferences(); info.SymbolSpecifications.Add(symbolSpecification); info.NamingStyles.Add(namingStyle); diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs index e67b4ffffb1fe..b0e457eb141ef 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs @@ -36,7 +36,7 @@ public bool TryGetDocumentOption(Document document, OptionKey option, out object { if (namingEditorConfigPersistence != null) { - value = EditorConfigNamingStyleParser.GetNamingStylesStringFromDictionary(allRawConventions); + value = EditorConfigNamingStyleParser.GetNamingStylesFromDictionary(allRawConventions); return true; } else diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs index 06503065ac12a..e7b75d23f74cb 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.cs @@ -122,8 +122,6 @@ private Task GetConventionContextAsync(string path, Ca return IOUtilities.PerformIOAsync( () => _codingConventionsManager.GetConventionContextAsync(path, cancellationToken), defaultValue: EmptyCodingConventionContext.Instance); - value = null; - value = null; } } } diff --git a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs index e89a019ae79a5..c99f0f6a1d8a9 100644 --- a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs +++ b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { internal static class SymbolAnalysisContextExtensions { - public static async Task GetNamingStylePreferencesAsync(this SymbolAnalysisContext context) + public static async Task GetNamingStylePreferencesAsync(this SymbolAnalysisContext context) { var location = context.Symbol.Locations.FirstOrDefault(); if (location == null) @@ -18,13 +18,7 @@ public static async Task GetNamingStylePreferencesAs var optionSet = await context.Options.GetDocumentOptionSetAsync(location.SourceTree, context.CancellationToken).ConfigureAwait(false); var namimgStylePreferences = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); - if (namimgStylePreferences == null) - { - return null; - } - - var preferences = namimgStylePreferences.GetPreferencesInfo(); - return preferences; + return namimgStylePreferences.GetNamingStyleRules(); } } } diff --git a/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs b/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs index dbe7602705d25..9d44ddfa6868a 100644 --- a/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs +++ b/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs @@ -16,6 +16,7 @@ using Microsoft.VisualStudio.Settings; using Microsoft.VisualStudio.Shell; using Roslyn.Utilities; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options { @@ -47,15 +48,15 @@ public RoamingVisualStudioProfileOptionPersister(IGlobalOptionService globalOpti { Contract.ThrowIfNull(globalOptionService); - this._settingManager = (ISettingsManager)serviceProvider.GetService(typeof(SVsSettingsPersistenceManager)); + _settingManager = (ISettingsManager)serviceProvider.GetService(typeof(SVsSettingsPersistenceManager)); _globalOptionService = globalOptionService; // While the settings persistence service should be available in all SKUs it is possible an ISO shell author has undefined the // contributing package. In that case persistence of settings won't work (we don't bother with a backup solution for persistence // as the scenario seems exceedingly unlikely), but we shouldn't crash the IDE. - if (this._settingManager != null) + if (_settingManager != null) { - ISettingsSubset settingsSubset = this._settingManager.GetSubset("*"); + var settingsSubset = _settingManager.GetSubset("*"); settingsSubset.SettingChangedAsync += OnSettingChangedAsync; } } @@ -81,7 +82,7 @@ private System.Threading.Tasks.Task OnSettingChangedAsync(object sender, Propert public bool TryFetch(OptionKey optionKey, out object value) { - if (this._settingManager == null) + if (_settingManager == null) { Debug.Fail("Manager field is unexpectedly null."); value = null; @@ -101,7 +102,7 @@ public bool TryFetch(OptionKey optionKey, out object value) RecordObservedValueToWatchForChanges(optionKey, storageKey); - value = this._settingManager.GetValueOrDefault(storageKey, optionKey.Option.DefaultValue); + value = _settingManager.GetValueOrDefault(storageKey, optionKey.Option.DefaultValue); // VS's ISettingsManager has some quirks around storing enums. Specifically, // it *can* persist and retrieve enums, but only if you properly call @@ -122,9 +123,7 @@ public bool TryFetch(OptionKey optionKey, out object value) else if (optionKey.Option.Type == typeof(CodeStyleOption)) { // We store these as strings, so deserialize - var serializedValue = value as string; - - if (serializedValue != null) + if (value is string serializedValue) { value = CodeStyleOption.FromXElement(XElement.Parse(serializedValue)); } @@ -134,6 +133,19 @@ public bool TryFetch(OptionKey optionKey, out object value) return false; } } + else if (optionKey.Option.Type ==typeof(NamingStylePreferences)) + { + // We store these as strings, so deserialize + if (value is string serializedValue) + { + value = NamingStylePreferences.FromXElement(XElement.Parse(serializedValue)); + } + else + { + value = null; + return false; + } + } else if (optionKey.Option.Type == typeof(bool) && value is int intValue) { // TypeScript used to store some booleans as integers. We now handle them properly for legacy sync scenarios. @@ -172,7 +184,7 @@ private void RecordObservedValueToWatchForChanges(OptionKey optionKey, string st public bool TryPersist(OptionKey optionKey, object value) { - if (this._settingManager == null) + if (_settingManager == null) { Debug.Fail("Manager field is unexpectedly null."); return false; @@ -202,7 +214,18 @@ public bool TryPersist(OptionKey optionKey, object value) } } - this._settingManager.SetValueAsync(storageKey, value, isMachineLocal: false); + if (optionKey.Option.Type == typeof(NamingStylePreferences)) + { + // We store these as strings, so serialize + var valueToSerialize = value as NamingStylePreferences; + + if (value != null) + { + value = valueToSerialize.CreateXElement().ToString(); + } + } + + _settingManager.SetValueAsync(storageKey, value, isMachineLocal: false); return true; } } diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs index 0677dd62b3adf..048126905c2f2 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageViewModel.cs @@ -33,12 +33,12 @@ public NamingStyleOptionPageViewModel(NamingStylePreferences info) var viewModels = new List(); foreach (var namingRule in info.NamingRules) { - var viewModel = new NamingRuleViewModel(); - - viewModel.NamingStyles = new ObservableCollection(info.NamingStyles); - viewModel.Specifications = new ObservableCollection(info.SymbolSpecifications); - viewModel.NotificationPreferences = new List(_notifications); - + var viewModel = new NamingRuleViewModel() + { + NamingStyles = new ObservableCollection(info.NamingStyles), + Specifications = new ObservableCollection(info.SymbolSpecifications), + NotificationPreferences = new List(_notifications) + }; viewModel.SelectedSpecification = viewModel.Specifications.Single(s => s.ID == namingRule.SymbolSpecificationID); viewModel.SelectedStyle= viewModel.NamingStyles.Single(s => s.ID == namingRule.NamingStyleID); viewModel.SelectedNotificationPreference = viewModel.NotificationPreferences.Single(n => n.Notification.Value == namingRule.EnforcementLevel); @@ -87,11 +87,11 @@ internal void RemoveItem(NamingRuleViewModel namingRuleViewModel) internal void UpdateSpecificationList(ManageSymbolSpecificationsDialogViewModel viewModel) { var symbolSpecifications = viewModel.Items.Cast().Select(n => new SymbolSpecification( - n.ID, - n.ItemName, - n.SymbolKindList.Where(s => s.IsChecked).Select(k => k.CreateSymbolKindOrTypeKind()).ToList(), - n.AccessibilityList.Where(s => s.IsChecked).Select(a => new SymbolSpecification.AccessibilityKind(a._accessibility)).ToList(), - n.ModifierList.Where(s => s.IsChecked).Select(m => new SymbolSpecification.ModifierKind(m._modifier)).ToList())); + id: n.ID, + symbolSpecName: n.ItemName, + symbolKindList: n.SymbolKindList.Where(s => s.IsChecked).Select(k => k.CreateSymbolKindOrTypeKind()).ToList(), + accessibilityList: n.AccessibilityList.Where(s => s.IsChecked).Select(a => a._accessibility).ToList(), + modifiers: n.ModifierList.Where(s => s.IsChecked).Select(m => new SymbolSpecification.ModifierKind(m._modifier)).ToList())); Specifications.Clear(); foreach (var specification in symbolSpecifications) @@ -132,7 +132,7 @@ internal void MoveItem(int oldSelectedIndex, int newSelectedIndex) private void SetMoveArrowStatuses() { - for (int i = 0; i < CodeStyleItems.Count; i++) + for (var i = 0; i < CodeStyleItems.Count; i++) { CodeStyleItems[i].CanMoveUp = true; CodeStyleItems[i].CanMoveDown = true; diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs index 7847a4ad9781e..11b87cfc85783 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyles/NamingStyleViewModel.cs @@ -18,12 +18,12 @@ public NamingStyleViewModel(NamingStyle style, bool canBeDeleted, INotificationS { _notificationService = notificationService; _style = style; - this.ID = style.ID; - this.RequiredPrefix = style.Prefix; - this.RequiredSuffix = style.Suffix; - this.WordSeparator = style.WordSeparator; - this.ItemName = style.Name; - this.CanBeDeleted = canBeDeleted; + ID = style.ID; + RequiredPrefix = style.Prefix; + RequiredSuffix = style.Suffix; + WordSeparator = style.WordSeparator; + ItemName = style.Name; + CanBeDeleted = canBeDeleted; CapitalizationSchemes = new List { @@ -156,8 +156,8 @@ public class CapitalizationDisplay public CapitalizationDisplay(Capitalization capitalization, string name) { - this.Capitalization = capitalization; - this.Name = name; + Capitalization = capitalization; + Name = name; } } } diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/SymbolSpecification/SymbolSpecificationViewModel.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/SymbolSpecification/SymbolSpecificationViewModel.cs index aeac550b840cf..62840cd1d99f8 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/SymbolSpecification/SymbolSpecificationViewModel.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/SymbolSpecification/SymbolSpecificationViewModel.cs @@ -122,11 +122,11 @@ public string ItemName internal SymbolSpecification GetSymbolSpecification() { return new SymbolSpecification( - ID, - ItemName, - SymbolKindList.Where(s => s.IsChecked).Select(s => s.CreateSymbolKindOrTypeKind()).ToList(), - AccessibilityList.Where(a => a.IsChecked).Select(a => new SymbolSpecification.AccessibilityKind(a._accessibility)).ToList(), - ModifierList.Where(m => m.IsChecked).Select(m => new ModifierKind(m._modifier)).ToList()); + id: ID, + symbolSpecName: ItemName, + symbolKindList: SymbolKindList.Where(s => s.IsChecked).Select(s => s.CreateSymbolKindOrTypeKind()).ToList(), + accessibilityList: AccessibilityList.Where(a => a.IsChecked).Select(a => a._accessibility).ToList(), + modifiers: ModifierList.Where(m => m.IsChecked).Select(m => new ModifierKind(m._modifier)).ToList()); } internal bool TrySubmit() @@ -161,14 +161,14 @@ public bool IsChecked public SymbolKindViewModel(SymbolKind symbolKind, string name, SymbolSpecification specification) { - this._symbolKind = symbolKind; + _symbolKind = symbolKind; Name = name; IsChecked = specification.ApplicableSymbolKindList.Any(k => k.SymbolKind == symbolKind); } public SymbolKindViewModel(TypeKind typeKind, string name, SymbolSpecification specification) { - this._typeKind = typeKind; + _typeKind = typeKind; Name = name; IsChecked = specification.ApplicableSymbolKindList.Any(k => k.TypeKind == typeKind); } @@ -204,7 +204,7 @@ public AccessibilityViewModel(Accessibility accessibility, string name, SymbolSp _accessibility = accessibility; Name = name; - IsChecked = specification.ApplicableAccessibilityList.Any(a => a.Accessibility == accessibility); + IsChecked = specification.ApplicableAccessibilityList.Any(a => a == accessibility); } } diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs index fbbb1502d4608..c4f0b12d2d95f 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs @@ -17,9 +17,9 @@ private static bool TryGetNamingStyleData( return false; } - string requiredPrefix = GetNamingRequiredPrefix(namingStyleTitle, allRawConventions); - string requiredSuffix = GetNamingRequiredSuffix(namingStyleTitle, allRawConventions); - string wordSeparator = GetNamingWordSeparator(namingStyleTitle, allRawConventions); + var requiredPrefix = GetNamingRequiredPrefix(namingStyleTitle, allRawConventions); + var requiredSuffix = GetNamingRequiredSuffix(namingStyleTitle, allRawConventions); + var wordSeparator = GetNamingWordSeparator(namingStyleTitle, allRawConventions); var capitalization = GetNamingCapitalization(namingStyleTitle, allRawConventions); namingStyle = new NamingStyle() @@ -58,6 +58,12 @@ private static string GetNamingRequiredSuffix(string namingStyleName, IReadOnlyD private static string GetNamingWordSeparator(string namingStyleName, IReadOnlyDictionary conventionsDictionary) => GetStringFromConventionsDictionary(namingStyleName, "word_separator", conventionsDictionary); + private static Capitalization GetNamingCapitalization(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + { + var result = GetStringFromConventionsDictionary(namingStyleName, "capitalization", conventionsDictionary); + return ParseCapitalizationScheme(result); + } + private static string GetStringFromConventionsDictionary(string namingStyleName, string optionName, IReadOnlyDictionary conventionsDictionary) { if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.{optionName}", out object result)) @@ -68,16 +74,6 @@ private static string GetStringFromConventionsDictionary(string namingStyleName, return string.Empty; } - private static Capitalization GetNamingCapitalization(string namingStyleName, IReadOnlyDictionary conventionsDictionary) - { - if (conventionsDictionary.TryGetValue($"dotnet_naming_style.{namingStyleName}.capitalization", out object result)) - { - return ParseCapitalizationScheme(result as string ?? string.Empty); - } - - return default(Capitalization); - } - private static Capitalization ParseCapitalizationScheme(string namingStyleCapitalization) { switch (namingStyleCapitalization) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs index 7c85cfef0ac3f..c3baa20c2db49 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs @@ -26,10 +26,9 @@ private static bool TryGetSymbolSpec( var requiredModifiers = GetSymbolsRequiredModifiers(symbolSpecName, conventionsDictionary); symbolSpec = new SymbolSpecification( - Guid.NewGuid(), symbolSpecName, symbolKindList: applicableKinds, - accessibilityKindList: applicableAccessibilities, + accessibilityList: applicableAccessibilities, modifiers: requiredModifiers); return true; } @@ -131,7 +130,7 @@ private static ImmutableArray ParseSymbolKindList(string s return builder.ToImmutableAndFree(); } - private static ImmutableArray GetSymbolsApplicableAccessibilities( + private static ImmutableArray GetSymbolsApplicableAccessibilities( string symbolSpecName, IReadOnlyDictionary conventionsDictionary) { @@ -140,26 +139,20 @@ private static ImmutableArray GetSymbolsApplicableAccessibili return ParseAccessibilityKindList(result as string ?? string.Empty); } - return ImmutableArray.Empty; + return ImmutableArray.Empty; } - private static readonly AccessibilityKind _publicAccessibilityKind = new AccessibilityKind(Accessibility.Public); - private static readonly AccessibilityKind _internalAccessibilityKind = new AccessibilityKind(Accessibility.Internal); - private static readonly AccessibilityKind _privateAccessibilityKind = new AccessibilityKind(Accessibility.Private); - private static readonly AccessibilityKind _protectedAccessibilityKind = new AccessibilityKind(Accessibility.Protected); - private static readonly AccessibilityKind _protectedOrInternalAccessibilityKind = new AccessibilityKind(Accessibility.ProtectedOrInternal); - - private static ImmutableArray ParseAccessibilityKindList(string symbolSpecApplicableAccessibilities) + private static ImmutableArray ParseAccessibilityKindList(string symbolSpecApplicableAccessibilities) { if (symbolSpecApplicableAccessibilities == null) { - return ImmutableArray.Empty; + return ImmutableArray.Empty; } - var builder = ArrayBuilder.GetInstance(); + var builder = ArrayBuilder.GetInstance(); if (symbolSpecApplicableAccessibilities.Trim() == "*") { - builder.AddRange(_publicAccessibilityKind, _internalAccessibilityKind, _privateAccessibilityKind, _protectedAccessibilityKind, _protectedOrInternalAccessibilityKind); + builder.AddRange(Accessibility.Public, Accessibility.Internal, Accessibility.Private, Accessibility.Protected, Accessibility.ProtectedOrInternal); return builder.ToImmutableAndFree(); } @@ -168,19 +161,19 @@ private static ImmutableArray ParseAccessibilityKindList(stri switch (symbolSpecApplicableAccessibility) { case "public": - builder.Add(_publicAccessibilityKind); + builder.Add(Accessibility.Public); break; case "internal": - builder.Add(_internalAccessibilityKind); + builder.Add(Accessibility.Internal); break; case "private": - builder.Add(_privateAccessibilityKind); + builder.Add(Accessibility.Private); break; case "protected": - builder.Add(_protectedAccessibilityKind); + builder.Add(Accessibility.Protected); break; case "protected_internal": - builder.Add(_protectedOrInternalAccessibilityKind); + builder.Add(Accessibility.ProtectedOrInternal); break; default: break; diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs index a588b5c64b7f1..571ef3e4470e2 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs @@ -14,7 +14,7 @@ internal static partial class EditorConfigNamingStyleParser private static readonly ConditionalWeakTable, NamingStylePreferences> _cache = new ConditionalWeakTable, NamingStylePreferences>(); private static readonly object _cacheLock = new object(); - public static NamingStylePreferences GetNamingStylesStringFromDictionary(IReadOnlyDictionary allRawConventions) + public static NamingStylePreferences GetNamingStylesFromDictionary(IReadOnlyDictionary allRawConventions) { if (_cache.TryGetValue(allRawConventions, out var value)) { diff --git a/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs index f0b4ee23d8a14..dabd2a228b1f6 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs @@ -5,11 +5,11 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { - internal class NamingStylePreferencesInfo + internal class NamingStyleRules { public ImmutableArray NamingRules { get; } - public NamingStylePreferencesInfo(ImmutableArray namingRules) + public NamingStyleRules(ImmutableArray namingRules) { NamingRules = namingRules; } @@ -45,8 +45,7 @@ private bool IsSymbolNameAnalyzable(ISymbol symbol) { if (symbol.Kind == SymbolKind.Method) { - var methodSymbol = symbol as IMethodSymbol; - if (methodSymbol != null && methodSymbol.MethodKind != MethodKind.Ordinary) + if (symbol is IMethodSymbol methodSymbol && methodSymbol.MethodKind != MethodKind.Ordinary) { return false; } @@ -54,8 +53,7 @@ private bool IsSymbolNameAnalyzable(ISymbol symbol) if (symbol.Kind == SymbolKind.Property) { - var propertySymbol = symbol as IPropertySymbol; - if (propertySymbol != null && propertySymbol.IsIndexer) + if (symbol is IPropertySymbol propertySymbol && propertySymbol.IsIndexer) { return false; } diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/AccessibilityExtensions.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/AccessibilityExtensions.cs new file mode 100644 index 0000000000000..70ba22431ed5b --- /dev/null +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/AccessibilityExtensions.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Xml.Linq; + +namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles +{ + internal static class AccessibilityExtensions + { + internal static bool MatchesSymbol(this Accessibility accessibility, ISymbol symbol) + { + return symbol.DeclaredAccessibility == accessibility; + } + + internal static XElement CreateXElement(this Accessibility accessibility) + { + return new XElement("AccessibilityKind", accessibility); + } + + internal static Accessibility FromXElement(XElement accessibilityElement) + { + return (Accessibility)Enum.Parse(typeof(Accessibility), accessibilityElement.Value); + } + } +} \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs index b0e824f0395e3..9ef6a2d815f1e 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs @@ -51,9 +51,9 @@ internal SymbolSpecification GetSymbolSpecification(Guid symbolSpecificationID) return SymbolSpecifications.Single(s => s.ID == symbolSpecificationID); } - public NamingStylePreferencesInfo GetPreferencesInfo() + public NamingStyleRules GetNamingStyleRules() { - return new NamingStylePreferencesInfo(NamingRules.Select(r => r.GetRule(this)).ToImmutableArray()); + return new NamingStyleRules(NamingRules.Select(r => r.GetRule(this)).ToImmutableArray()); } internal XElement CreateXElement() @@ -152,13 +152,13 @@ public bool Equals(NamingStylePreferences other) return false; } - return this.CreateXElement().ToString() == other.CreateXElement().ToString(); + return CreateXElement().ToString() == other.CreateXElement().ToString(); } public static bool operator ==(NamingStylePreferences left, NamingStylePreferences right) { - bool leftIsNull = object.ReferenceEquals(left, null); - bool rightIsNull = object.ReferenceEquals(right, null); + var leftIsNull = object.ReferenceEquals(left, null); + var rightIsNull = object.ReferenceEquals(right, null); if (leftIsNull && rightIsNull) { return true; @@ -179,7 +179,7 @@ public bool Equals(NamingStylePreferences other) => !(left == right); public override int GetHashCode() - => this.CreateXElement().ToString().GetHashCode(); + => CreateXElement().ToString().GetHashCode(); private static readonly string _defaultNamingPreferencesString = $@" diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs index 83436b6733ea7..22c6e0a24cafb 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs @@ -10,13 +10,13 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { - internal class SymbolSpecification + internal partial class SymbolSpecification { public Guid ID { get; private set; } public string Name { get; private set; } public IList ApplicableSymbolKindList { get; private set; } - public IList ApplicableAccessibilityList { get; private set; } + public IList ApplicableAccessibilityList { get; private set; } public IList RequiredModifierList { get; private set; } internal SymbolSpecification() @@ -40,27 +40,28 @@ internal SymbolSpecification() new SymbolKindOrTypeKind(SymbolKind.Event), }; - ApplicableAccessibilityList = new List + ApplicableAccessibilityList = new List { - new AccessibilityKind(Accessibility.Public), - new AccessibilityKind(Accessibility.Internal), - new AccessibilityKind(Accessibility.Private), - new AccessibilityKind(Accessibility.Protected), - new AccessibilityKind(Accessibility.ProtectedAndInternal), - new AccessibilityKind(Accessibility.ProtectedOrInternal), + Accessibility.Public, + Accessibility.Internal, + Accessibility.Private, + Accessibility.Protected, + Accessibility.ProtectedAndInternal, + Accessibility.ProtectedOrInternal, }; RequiredModifierList = new List(); } - public SymbolSpecification(Guid id, string symbolSpecName, + public SymbolSpecification(string symbolSpecName, IList symbolKindList, - IList accessibilityKindList, - IList modifiers) + IList accessibilityList, + IList modifiers, + Guid? id = null) { - ID = id; + ID = id ?? Guid.NewGuid(); Name = symbolSpecName; - ApplicableAccessibilityList = accessibilityKindList; + ApplicableAccessibilityList = accessibilityList; RequiredModifierList = modifiers; ApplicableSymbolKindList = symbolKindList; } @@ -163,10 +164,10 @@ private void PopulateSymbolKindListFromXElement(XElement symbolKindListElement) private void PopulateAccessibilityListFromXElement(XElement accessibilityListElement) { - var applicableAccessibilityList = new List(); - foreach (var accessibilityElement in accessibilityListElement.Elements(nameof(AccessibilityKind))) + var applicableAccessibilityList = new List(); + foreach (var accessibilityElement in accessibilityListElement.Elements("AccessibilityKind")) { - applicableAccessibilityList.Add(AccessibilityKind.FromXElement(accessibilityElement)); + applicableAccessibilityList.Add(AccessibilityExtensions.FromXElement(accessibilityElement)); } ApplicableAccessibilityList = applicableAccessibilityList; } @@ -249,52 +250,6 @@ public override int GetHashCode() } } - public struct AccessibilityKind : IEquatable - { - public Accessibility Accessibility { get; set; } - - public AccessibilityKind(Accessibility accessibility) - { - Accessibility = accessibility; - } - - public bool MatchesSymbol(ISymbol symbol) - { - return symbol.DeclaredAccessibility == Accessibility; - } - - internal XElement CreateXElement() - { - return new XElement(nameof(AccessibilityKind), Accessibility); - } - - internal static AccessibilityKind FromXElement(XElement accessibilityElement) - { - return new AccessibilityKind((Accessibility)Enum.Parse(typeof(Accessibility), accessibilityElement.Value)); - } - - public override bool Equals(object obj) - { - return Equals((AccessibilityKind)obj); - } - - public bool Equals(AccessibilityKind other) - { - return Accessibility == other.Accessibility; - } - - public static bool operator ==(AccessibilityKind left, AccessibilityKind right) - => left.Equals(right); - - public static bool operator !=(AccessibilityKind left, AccessibilityKind right) - => !left.Equals(right); - - public override int GetHashCode() - { - return Accessibility.GetHashCode(); - } - } - public struct ModifierKind : IEquatable { public ModifierKindEnum ModifierKindWrapper; @@ -407,7 +362,7 @@ public override bool Equals(object obj) public bool Equals(ModifierKind other) { - return this.Modifier == other.Modifier; + return Modifier == other.Modifier; } public static bool operator ==(ModifierKind left, ModifierKind right) diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 74af4ca415e94..6aed71780121b 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -375,6 +375,7 @@ + From 04621ac16c8e38c5124941a40d32572ab7dc2290 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Tue, 13 Dec 2016 18:47:20 -0800 Subject: [PATCH 6/8] addressing the latest set of comments from David --- ...=> EditorConfigNamingStyleParser_NamingRule.cs} | 0 ...> EditorConfigNamingStyleParser_NamingStyle.cs} | 0 ...=> EditorConfigNamingStyleParser_SymbolSpec.cs} | 14 +++++--------- ...StylePreferencesInfo.cs => NamingStyleRules.cs} | 0 ...referencesInfo.cs => NamingStylePreferences.cs} | 0 .../Serialization/SymbolSpecification.cs | 8 +++++++- src/Workspaces/Core/Portable/Workspaces.csproj | 10 +++++----- 7 files changed, 17 insertions(+), 15 deletions(-) rename src/Workspaces/Core/Portable/NamingStyles/EditorConfig/{EditorConfigNamingStyleParser.NamingRule.cs => EditorConfigNamingStyleParser_NamingRule.cs} (100%) rename src/Workspaces/Core/Portable/NamingStyles/EditorConfig/{EditorConfigNamingStyleParser.NamingStyle.cs => EditorConfigNamingStyleParser_NamingStyle.cs} (100%) rename src/Workspaces/Core/Portable/NamingStyles/EditorConfig/{EditorConfigNamingStyleParser.SymbolSpec.cs => EditorConfigNamingStyleParser_SymbolSpec.cs} (94%) rename src/Workspaces/Core/Portable/NamingStyles/{NamingStylePreferencesInfo.cs => NamingStyleRules.cs} (100%) rename src/Workspaces/Core/Portable/NamingStyles/Serialization/{SerializableNamingStylePreferencesInfo.cs => NamingStylePreferences.cs} (100%) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs similarity index 100% rename from src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingRule.cs rename to src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs similarity index 100% rename from src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.NamingStyle.cs rename to src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs similarity index 94% rename from src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs rename to src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs index c3baa20c2db49..b5d0602c1d0fe 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.SymbolSpec.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs @@ -68,10 +68,8 @@ private static ImmutableArray GetSymbolsApplicableKinds( private static readonly SymbolKindOrTypeKind _method = new SymbolKindOrTypeKind(SymbolKind.Method); private static readonly SymbolKindOrTypeKind _field = new SymbolKindOrTypeKind(SymbolKind.Field); private static readonly SymbolKindOrTypeKind _event = new SymbolKindOrTypeKind(SymbolKind.Event); - private static readonly SymbolKindOrTypeKind _namespace = new SymbolKindOrTypeKind(SymbolKind.Namespace); private static readonly SymbolKindOrTypeKind _delegate = new SymbolKindOrTypeKind(TypeKind.Delegate); - private static readonly SymbolKindOrTypeKind _typeParameter = new SymbolKindOrTypeKind(SymbolKind.TypeParameter); - private static readonly ImmutableArray _all = ImmutableArray.Create(_class, _struct, _interface, _enum, _property, _method, _field, _event, _namespace, _delegate, _typeParameter); + private static readonly ImmutableArray _all = ImmutableArray.Create(_class, _struct, _interface, _enum, _property, _method, _field, _event, _delegate); private static ImmutableArray ParseSymbolKindList(string symbolSpecApplicableKinds) { if (symbolSpecApplicableKinds == null) @@ -113,15 +111,9 @@ private static ImmutableArray ParseSymbolKindList(string s case "event": builder.Add(_event); break; - case "namespace": - builder.Add(_namespace); - break; case "delegate": builder.Add(_delegate); break; - case "type_parameter": - builder.Add(_typeParameter); - break; default: break; } @@ -164,6 +156,7 @@ private static ImmutableArray ParseAccessibilityKindList(string s builder.Add(Accessibility.Public); break; case "internal": + case "friend": builder.Add(Accessibility.Internal); break; case "private": @@ -173,6 +166,7 @@ private static ImmutableArray ParseAccessibilityKindList(string s builder.Add(Accessibility.Protected); break; case "protected_internal": + case "protected_friend": builder.Add(Accessibility.ProtectedOrInternal); break; default: @@ -220,6 +214,7 @@ private static ImmutableArray ParseModifiers(string symbolSpecRequ switch (symbolSpecRequiredModifier) { case "abstract": + case "must_inherit ": builder.Add(_abstractModifierKind); break; case "async": @@ -232,6 +227,7 @@ private static ImmutableArray ParseModifiers(string symbolSpecRequ builder.Add(_readonlyModifierKind); break; case "static": + case "shared": builder.Add(_staticModifierKind); break; default: diff --git a/src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/NamingStyleRules.cs similarity index 100% rename from src/Workspaces/Core/Portable/NamingStyles/NamingStylePreferencesInfo.cs rename to src/Workspaces/Core/Portable/NamingStyles/NamingStyleRules.cs diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStylePreferences.cs similarity index 100% rename from src/Workspaces/Core/Portable/NamingStyles/Serialization/SerializableNamingStylePreferencesInfo.cs rename to src/Workspaces/Core/Portable/NamingStyles/Serialization/NamingStylePreferences.cs diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs index 22c6e0a24cafb..25d17cd9f1d8a 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs @@ -10,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { - internal partial class SymbolSpecification + internal class SymbolSpecification { public Guid ID { get; private set; } public string Name { get; private set; } @@ -244,6 +244,12 @@ public bool Equals(SymbolKindOrTypeKind other) TypeKind == other.TypeKind; } + public static bool operator ==(SymbolKindOrTypeKind left, SymbolKindOrTypeKind right) + => left.Equals(right); + + public static bool operator !=(SymbolKindOrTypeKind left, SymbolKindOrTypeKind right) + => !left.Equals(right); + public override int GetHashCode() { return Hash.Combine(SymbolKind.GetHashCode(), TypeKind.GetHashCode()); diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 6aed71780121b..3bd53a89bf6d2 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -372,9 +372,9 @@ - - - + + + @@ -394,10 +394,10 @@ - + - + From 998425e73db762dd121847c44425460552265906 Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Tue, 13 Dec 2016 21:26:47 -0800 Subject: [PATCH 7/8] addressing Jason's comments --- ...DocumentOptionsProvider.DocumentOptions.cs | 14 ++-------- .../NamingStyleDiagnosticAnalyzerBase.cs | 6 ++--- .../SymbolAnalysisContextExtensions.cs | 6 ++--- ...amingVisualStudioProfileOptionPersister.cs | 25 ++++++++++++++---- .../NamingStyleOptionPageControl.xaml.cs | 16 ++++++------ .../AbstractOptionsSerializationService.cs | 2 +- .../Options/EditorConfigStorageLocation.cs | 26 +++++++++++++++---- .../NamingEditorConfigStorageLocation.cs | 14 ---------- .../Simplification/SimplificationOptions.cs | 2 +- .../Core/Portable/Workspaces.csproj | 1 - 10 files changed, 59 insertions(+), 53 deletions(-) delete mode 100644 src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs diff --git a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs index b0e457eb141ef..fc77ada4ceb59 100644 --- a/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs +++ b/src/EditorFeatures/Next/Options/EditorConfigDocumentOptionsProvider.DocumentOptions.cs @@ -23,9 +23,7 @@ public DocumentOptions(ICodingConventionsSnapshot codingConventionSnapshot, IErr public bool TryGetDocumentOption(Document document, OptionKey option, out object value) { var editorConfigPersistence = option.Option.StorageLocations.OfType().SingleOrDefault(); - var namingEditorConfigPersistence = option.Option.StorageLocations.OfType().SingleOrDefault(); - - if (editorConfigPersistence == null && namingEditorConfigPersistence == null) + if (editorConfigPersistence == null) { value = null; return false; @@ -34,15 +32,7 @@ public bool TryGetDocumentOption(Document document, OptionKey option, out object var allRawConventions = _codingConventionSnapshot.AllRawConventions; try { - if (namingEditorConfigPersistence != null) - { - value = EditorConfigNamingStyleParser.GetNamingStylesFromDictionary(allRawConventions); - return true; - } - else - { - return editorConfigPersistence.TryParseReadonlyDictionary(allRawConventions, option.Option.Type, out value); - } + return editorConfigPersistence.TryParseReadonlyDictionary(allRawConventions, option.Option.Type, out value); } catch (Exception ex) { diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs index 9d7c0bf2216e9..5b17e02f32482 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs @@ -41,13 +41,13 @@ protected override void InitializeWorker(AnalysisContext context) private void SymbolAction(SymbolAnalysisContext context) { - var preferences = context.GetNamingStylePreferencesAsync().GetAwaiter().GetResult(); - if (preferences == null) + var namingStyleRules = context.GetNamingStyleRulesAsync().GetAwaiter().GetResult(); + if (namingStyleRules == null) { return; } - if (preferences.TryGetApplicableRule(context.Symbol, out var applicableRule)) + if (namingStyleRules.TryGetApplicableRule(context.Symbol, out var applicableRule)) { if (applicableRule.EnforcementLevel != DiagnosticSeverity.Hidden && !applicableRule.IsNameCompliant(context.Symbol.Name, out var failureReason)) diff --git a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs index c99f0f6a1d8a9..7d01e368067a8 100644 --- a/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs +++ b/src/Features/Core/Portable/Diagnostics/SymbolAnalysisContextExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { internal static class SymbolAnalysisContextExtensions { - public static async Task GetNamingStylePreferencesAsync(this SymbolAnalysisContext context) + public static async Task GetNamingStyleRulesAsync(this SymbolAnalysisContext context) { var location = context.Symbol.Locations.FirstOrDefault(); if (location == null) @@ -17,8 +17,8 @@ public static async Task GetNamingStylePreferencesAsync(this S } var optionSet = await context.Options.GetDocumentOptionSetAsync(location.SourceTree, context.CancellationToken).ConfigureAwait(false); - var namimgStylePreferences = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); - return namimgStylePreferences.GetNamingStyleRules(); + var namimgPreferences = optionSet.GetOption(SimplificationOptions.NamingPreferences, context.Compilation.Language); + return namimgPreferences.GetNamingStyleRules(); } } } diff --git a/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs b/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs index 9d44ddfa6868a..475b36ab5c7ec 100644 --- a/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs +++ b/src/VisualStudio/Core/Def/Implementation/Options/RoamingVisualStudioProfileOptionPersister.cs @@ -125,7 +125,15 @@ public bool TryFetch(OptionKey optionKey, out object value) // We store these as strings, so deserialize if (value is string serializedValue) { - value = CodeStyleOption.FromXElement(XElement.Parse(serializedValue)); + try + { + value = CodeStyleOption.FromXElement(XElement.Parse(serializedValue)); + } + catch (Exception) + { + value = null; + return false; + } } else { @@ -133,12 +141,20 @@ public bool TryFetch(OptionKey optionKey, out object value) return false; } } - else if (optionKey.Option.Type ==typeof(NamingStylePreferences)) + else if (optionKey.Option.Type == typeof(NamingStylePreferences)) { // We store these as strings, so deserialize if (value is string serializedValue) { - value = NamingStylePreferences.FromXElement(XElement.Parse(serializedValue)); + try + { + value = NamingStylePreferences.FromXElement(XElement.Parse(serializedValue)); + } + catch (Exception) + { + value = null; + return false; + } } else { @@ -213,8 +229,7 @@ public bool TryPersist(OptionKey optionKey, object value) value = valueToSerialize.ToXElement().ToString(); } } - - if (optionKey.Option.Type == typeof(NamingStylePreferences)) + else if (optionKey.Option.Type == typeof(NamingStylePreferences)) { // We store these as strings, so serialize var valueToSerialize = value as NamingStylePreferences; diff --git a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs index 8c101c54d3b1f..df63a57c768de 100644 --- a/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs +++ b/src/VisualStudio/Core/Impl/Options/Style/NamingPreferences/NamingStyleOptionPageControl.xaml.cs @@ -84,7 +84,7 @@ private void ManageStylesButton_Click(object sender, RoutedEventArgs e) private void MoveUp_Click(object sender, EventArgs e) { - int oldSelectedIndex = CodeStyleMembers.SelectedIndex; + var oldSelectedIndex = CodeStyleMembers.SelectedIndex; if (oldSelectedIndex > 0) { _viewModel.MoveItem(oldSelectedIndex, oldSelectedIndex - 1); @@ -95,7 +95,7 @@ private void MoveUp_Click(object sender, EventArgs e) private void MoveDown_Click(object sender, EventArgs e) { - int oldSelectedIndex = CodeStyleMembers.SelectedIndex; + var oldSelectedIndex = CodeStyleMembers.SelectedIndex; if (oldSelectedIndex < CodeStyleMembers.Items.Count - 1) { _viewModel.MoveItem(oldSelectedIndex, oldSelectedIndex + 1); @@ -115,7 +115,7 @@ private void SetFocusToSelectedRow() { if (CodeStyleMembers.SelectedIndex >= 0) { - DataGridRow row = CodeStyleMembers.ItemContainerGenerator.ContainerFromIndex(CodeStyleMembers.SelectedIndex) as DataGridRow; + var row = CodeStyleMembers.ItemContainerGenerator.ContainerFromIndex(CodeStyleMembers.SelectedIndex) as DataGridRow; if (row == null) { CodeStyleMembers.ScrollIntoView(CodeStyleMembers.SelectedItem); @@ -124,7 +124,7 @@ private void SetFocusToSelectedRow() if (row != null) { - DataGridCell cell = row.FindDescendant(); + var cell = row.FindDescendant(); if (cell != null) { cell.Focus(); @@ -174,14 +174,14 @@ internal override void LoadSettings() { base.LoadSettings(); - var preferencesInfo = this.OptionService.GetOption(SimplificationOptions.NamingPreferences, _languageName); - if (preferencesInfo == null) + var preferences = OptionService.GetOption(SimplificationOptions.NamingPreferences, _languageName); + if (preferences == null) { return; } - _viewModel = new NamingStyleOptionPageViewModel(preferencesInfo); - this.DataContext = _viewModel; + _viewModel = new NamingStyleOptionPageViewModel(preferences); + DataContext = _viewModel; } internal bool ContainsErrors() diff --git a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs index 15f4b65be4018..cf6709b1362f1 100644 --- a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs @@ -361,7 +361,7 @@ internal override IEnumerable GetChangedOptions(OptionSet optionSet) foreach (var kvp in _values) { var currentValue = optionSet.GetOption(kvp.Key); - if (currentValue?.Equals(kvp.Value) == false) + if (!object.Equals(currentValue, kvp.Value)) { yield return kvp.Key; } diff --git a/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs b/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs index 38fe2aeff663b..3402d739a5ddc 100644 --- a/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs +++ b/src/Workspaces/Core/Portable/Options/EditorConfigStorageLocation.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using static Microsoft.CodeAnalysis.CodeStyle.CodeStyleHelpers; namespace Microsoft.CodeAnalysis.Options @@ -16,9 +17,7 @@ internal sealed class EditorConfigStorageLocation : OptionStorageLocation private Func _parseValue; - private Func, object> _parseDictionary; - - public object ParseValue(string s, Type type) => _parseValue(s, type); + private Func, Type, object> _parseDictionary; public bool TryParseReadonlyDictionary(IReadOnlyDictionary allRawConventions, Type type, out object result) { @@ -32,7 +31,7 @@ public bool TryParseReadonlyDictionary(IReadOnlyDictionary allRa } else if (_parseDictionary != null) { - result = _parseDictionary(allRawConventions); + result = _parseDictionary(allRawConventions, type); return true; } @@ -73,9 +72,26 @@ public EditorConfigStorageLocation(string keyName, Func parseVal _parseValue = (s, type) => parseValue(s); } + public EditorConfigStorageLocation() + { + // If the user didn't pass a keyName assume we need to parse the entire dictionary + _parseDictionary = (dictionary, type) => + { + if (type == typeof(NamingStylePreferences)) + { + return EditorConfigNamingStyleParser.GetNamingStylesFromDictionary(dictionary); + } + else + { + throw new NotSupportedException(WorkspacesResources.Option_0_has_an_unsupported_type_to_use_with_1_You_should_specify_a_parsing_function); + } + }; + } + public EditorConfigStorageLocation(Func, object> parseDictionary) { - _parseDictionary = parseDictionary; + // If we're explicitly given a parsing function we can throw away the type when parsing + _parseDictionary = (dictionary, type) => parseDictionary(dictionary); } } } diff --git a/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs b/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs deleted file mode 100644 index 8ac47b37fe70d..0000000000000 --- a/src/Workspaces/Core/Portable/Options/NamingEditorConfigStorageLocation.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Microsoft.CodeAnalysis.Options -{ - /// - /// This type is used when you need to indicate that the entire editorconfig options - /// dictionary should be handled by EditorConfigNamingStyleParser - /// - internal sealed class NamingEditorConfigStorageLocation : OptionStorageLocation { } -} diff --git a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs index 7a172728addc2..c79aa1e25d09f 100644 --- a/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs +++ b/src/Workspaces/Core/Portable/Simplification/SimplificationOptions.cs @@ -102,7 +102,7 @@ public static class SimplificationOptions /// internal static PerLanguageOption NamingPreferences { get; } = new PerLanguageOption(nameof(SimplificationOptions), nameof(NamingPreferences), defaultValue: NamingStylePreferences.Default, storageLocations: new OptionStorageLocation[]{ - new NamingEditorConfigStorageLocation(), + new EditorConfigStorageLocation(), new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.NamingPreferences")}); } } diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 3bd53a89bf6d2..399599b839463 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -376,7 +376,6 @@ - From 92e3d189f273fc4f01eb1614467cf6ed6d088d5f Mon Sep 17 00:00:00 2001 From: Jonathon Marolf Date: Sun, 18 Dec 2016 20:05:34 -0800 Subject: [PATCH 8/8] addressing Kevin's comments --- .../NamingStyleDiagnosticAnalyzerBase.cs | 2 -- .../CSharp/Impl/Options/AutomationObject.cs | 8 ++++- .../AbstractOptionsSerializationService.cs | 23 +++++++++--- .../EditorConfigNamingStyleParser.cs | 21 ++++++++--- ...ditorConfigNamingStyleParser_NamingRule.cs | 18 +++++++--- ...itorConfigNamingStyleParser_NamingStyle.cs | 36 +++++++++++++------ ...ditorConfigNamingStyleParser_SymbolSpec.cs | 15 ++++---- .../Serialization/SymbolSpecification.cs | 14 ++++++-- 8 files changed, 101 insertions(+), 36 deletions(-) diff --git a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs index 5b17e02f32482..af8d66ff29b23 100644 --- a/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs +++ b/src/Features/Core/Portable/Diagnostics/Analyzers/NamingStyleDiagnosticAnalyzerBase.cs @@ -2,10 +2,8 @@ using System.Collections.Immutable; using System.Linq; -using System.Xml.Linq; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Simplification; -using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles { diff --git a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs index fb65f0fbed1f7..ebc6d69c1e4b9 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AutomationObject.cs @@ -539,7 +539,13 @@ public string Style_NamingPreferences set { - _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, NamingStylePreferences.FromXElement(XElement.Parse(value))); + try + { + _workspace.Options = _workspace.Options.WithChangedOption(SimplificationOptions.NamingPreferences, LanguageNames.CSharp, NamingStylePreferences.FromXElement(XElement.Parse(value))); + } + catch (Exception) + { + } } } diff --git a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs index cf6709b1362f1..e73b0aec060a8 100644 --- a/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs +++ b/src/Workspaces/Core/Portable/Execution/AbstractOptionsSerializationService.cs @@ -303,9 +303,15 @@ protected OptionSet ReadOptionFrom(OptionSet options, Option option, ObjectWriter writer, CancellationToken cancellationToken) @@ -321,9 +327,16 @@ private OptionSet ReadOptionFrom(OptionSet options, string language, PerLanguage cancellationToken.ThrowIfCancellationRequested(); var xmlText = reader.ReadString(); - var value = NamingStylePreferences.FromXElement(XElement.Parse(xmlText)); + try + { + var value = NamingStylePreferences.FromXElement(XElement.Parse(xmlText)); + return options.WithChangedOption(option, language, value); - return options.WithChangedOption(option, language, value); + } + catch (System.Exception) + { + return options; + } } /// diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs index 571ef3e4470e2..a20d3e78030ec 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; @@ -38,9 +39,8 @@ public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary(); var namingStyles = new List(); var namingRules = new List(); - var trimmedDictionary = allRawConventions - .Select(x => new KeyValuePair(x.Key.Trim(), x.Value)) - .ToDictionary(x => x.Key, x => x.Value); + var trimmedDictionary = TrimDictionary(allRawConventions); + foreach (var namingRuleTitle in GetRuleTitles(trimmedDictionary)) { if (TryGetSymbolSpec(namingRuleTitle, trimmedDictionary, out var symbolSpec)) @@ -62,9 +62,22 @@ public static NamingStylePreferences ParseDictionary(IReadOnlyDictionary TrimDictionary(IReadOnlyDictionary allRawConventions) + { + var trimmedDictionary = new Dictionary(allRawConventions.Count); + foreach (var item in allRawConventions) + { + var key = item.Key.Trim(); + var value = item.Value; + trimmedDictionary[key] = value; + } + + return trimmedDictionary; + } + private static IEnumerable GetRuleTitles(IReadOnlyDictionary allRawConventions) => (from kvp in allRawConventions - where kvp.Key.Trim().StartsWith("dotnet_naming_rule.") + where kvp.Key.Trim().StartsWith("dotnet_naming_rule.", StringComparison.Ordinal) let nameSplit = kvp.Key.Split('.') where nameSplit.Length == 3 select nameSplit[1]) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs index 5c836072af662..607b2c33f9809 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingRule.cs @@ -13,7 +13,12 @@ private static bool TryGetSerializableNamingRule( IReadOnlyDictionary conventionsDictionary, out SerializableNamingRule serializableNamingRule) { - var severity = GetRuleSeverity(namingRuleTitle, conventionsDictionary); + if(!TryGetRuleSeverity(namingRuleTitle, conventionsDictionary, out var severity)) + { + serializableNamingRule = null; + return false; + } + serializableNamingRule = new SerializableNamingRule() { EnforcementLevel = severity, @@ -24,16 +29,19 @@ private static bool TryGetSerializableNamingRule( return true; } - private static DiagnosticSeverity GetRuleSeverity( + private static bool TryGetRuleSeverity( string namingRuleName, - IReadOnlyDictionary conventionsDictionary) + IReadOnlyDictionary conventionsDictionary, + out DiagnosticSeverity severity) { if (conventionsDictionary.TryGetValue($"dotnet_naming_rule.{namingRuleName}.severity", out object result)) { - return ParseEnforcementLevel(result as string ?? string.Empty); + severity = ParseEnforcementLevel(result as string ?? string.Empty); + return true; } - return default(DiagnosticSeverity); + severity = default(DiagnosticSeverity); + return false; } private static DiagnosticSeverity ParseEnforcementLevel(string ruleSeverity) diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs index c4f0b12d2d95f..957b3df5c2db3 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_NamingStyle.cs @@ -20,7 +20,11 @@ private static bool TryGetNamingStyleData( var requiredPrefix = GetNamingRequiredPrefix(namingStyleTitle, allRawConventions); var requiredSuffix = GetNamingRequiredSuffix(namingStyleTitle, allRawConventions); var wordSeparator = GetNamingWordSeparator(namingStyleTitle, allRawConventions); - var capitalization = GetNamingCapitalization(namingStyleTitle, allRawConventions); + if(!TryGetNamingCapitalization(namingStyleTitle, allRawConventions, out var capitalization)) + { + namingStyle = null; + return false; + } namingStyle = new NamingStyle() { @@ -58,10 +62,10 @@ private static string GetNamingRequiredSuffix(string namingStyleName, IReadOnlyD private static string GetNamingWordSeparator(string namingStyleName, IReadOnlyDictionary conventionsDictionary) => GetStringFromConventionsDictionary(namingStyleName, "word_separator", conventionsDictionary); - private static Capitalization GetNamingCapitalization(string namingStyleName, IReadOnlyDictionary conventionsDictionary) + private static bool TryGetNamingCapitalization(string namingStyleName, IReadOnlyDictionary conventionsDictionary, out Capitalization capitalization) { var result = GetStringFromConventionsDictionary(namingStyleName, "capitalization", conventionsDictionary); - return ParseCapitalizationScheme(result); + return TryParseCapitalizationScheme(result, out capitalization); } private static string GetStringFromConventionsDictionary(string namingStyleName, string optionName, IReadOnlyDictionary conventionsDictionary) @@ -74,16 +78,28 @@ private static string GetStringFromConventionsDictionary(string namingStyleName, return string.Empty; } - private static Capitalization ParseCapitalizationScheme(string namingStyleCapitalization) + private static bool TryParseCapitalizationScheme(string namingStyleCapitalization, out Capitalization capitalization) { switch (namingStyleCapitalization) { - case "pascal_case": return Capitalization.PascalCase; - case "camel_case": return Capitalization.CamelCase; - case "first_word_upper": return Capitalization.FirstUpper; - case "all_upper": return Capitalization.AllUpper; - case "all_lower": return Capitalization.AllLower; - default: return default(Capitalization); + case "pascal_case": + capitalization = Capitalization.PascalCase; + return true; + case "camel_case": + capitalization = Capitalization.CamelCase; + return true; + case "first_word_upper": + capitalization = Capitalization.FirstUpper; + return true; + case "all_upper": + capitalization = Capitalization.AllUpper; + return true; + case "all_lower": + capitalization = Capitalization.AllLower; + return true; + default: + capitalization = default(Capitalization); + return false; } } } diff --git a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs index b5d0602c1d0fe..b57ea38a0372e 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/EditorConfig/EditorConfigNamingStyleParser_SymbolSpec.cs @@ -77,12 +77,12 @@ private static ImmutableArray ParseSymbolKindList(string s return ImmutableArray.Empty; } - var builder = ArrayBuilder.GetInstance(); if (symbolSpecApplicableKinds.Trim() == "*") { return _all; } + var builder = ArrayBuilder.GetInstance(); foreach (var symbolSpecApplicableKind in symbolSpecApplicableKinds.Split(',').Select(x => x.Trim())) { switch (symbolSpecApplicableKind) @@ -134,6 +134,8 @@ private static ImmutableArray GetSymbolsApplicableAccessibilities return ImmutableArray.Empty; } + private static readonly ImmutableArray _allAccessibility = ImmutableArray.Create(Accessibility.Public, Accessibility.Internal, Accessibility.Private, Accessibility.Protected, Accessibility.ProtectedOrInternal); + private static ImmutableArray ParseAccessibilityKindList(string symbolSpecApplicableAccessibilities) { if (symbolSpecApplicableAccessibilities == null) @@ -141,13 +143,12 @@ private static ImmutableArray ParseAccessibilityKindList(string s return ImmutableArray.Empty; } - var builder = ArrayBuilder.GetInstance(); if (symbolSpecApplicableAccessibilities.Trim() == "*") { - builder.AddRange(Accessibility.Public, Accessibility.Internal, Accessibility.Private, Accessibility.Protected, Accessibility.ProtectedOrInternal); - return builder.ToImmutableAndFree(); + return _allAccessibility; } + var builder = ArrayBuilder.GetInstance(); foreach (var symbolSpecApplicableAccessibility in symbolSpecApplicableAccessibilities.Split(',').Select(x => x.Trim())) { switch (symbolSpecApplicableAccessibility) @@ -194,6 +195,7 @@ private static ImmutableArray GetSymbolsRequiredModifiers( private static readonly ModifierKind _constModifierKind = new ModifierKind(ModifierKindEnum.IsConst); private static readonly ModifierKind _readonlyModifierKind = new ModifierKind(ModifierKindEnum.IsReadOnly); private static readonly ModifierKind _staticModifierKind = new ModifierKind(ModifierKindEnum.IsStatic); + private static readonly ImmutableArray _allModifierKind = ImmutableArray.Create(_abstractModifierKind, _asyncModifierKind, _constModifierKind, _readonlyModifierKind, _staticModifierKind); private static ImmutableArray ParseModifiers(string symbolSpecRequiredModifiers) { @@ -202,13 +204,12 @@ private static ImmutableArray ParseModifiers(string symbolSpecRequ return ImmutableArray.Empty; } - var builder = ArrayBuilder.GetInstance(); if (symbolSpecRequiredModifiers.Trim() == "*") { - builder.AddRange(_abstractModifierKind, _asyncModifierKind, _constModifierKind, _readonlyModifierKind, _staticModifierKind); - return builder.ToImmutableAndFree(); + return _allModifierKind; } + var builder = ArrayBuilder.GetInstance(); foreach (var symbolSpecRequiredModifier in symbolSpecRequiredModifiers.Split(',').Select(x => x.Trim())) { switch (symbolSpecRequiredModifier) diff --git a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs index 25d17cd9f1d8a..d1fc37b1ecc4c 100644 --- a/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs +++ b/src/Workspaces/Core/Portable/NamingStyles/Serialization/SymbolSpecification.cs @@ -235,7 +235,12 @@ internal static SymbolKindOrTypeKind AddTypeKindFromXElement(XElement typeKindEl public override bool Equals(object obj) { - return Equals((SymbolKindOrTypeKind)obj); + if (obj is SymbolKindOrTypeKind symbolKindOrTypeKind) + { + return Equals(symbolKindOrTypeKind); + } + + return false; } public bool Equals(SymbolKindOrTypeKind other) @@ -363,7 +368,12 @@ internal static ModifierKind FromXElement(XElement modifierElement) public override bool Equals(object obj) { - return Equals((ModifierKind)obj); + if (obj is ModifierKind modifierKind) + { + return Equals(modifierKind); + } + + return false; } public bool Equals(ModifierKind other)