提交 91d9bfef 编写于 作者: M Marcin Wachulski

Refactor: extract built-in naming rules and utility to get naming rules for document

Extract fallback default naming rules for a few refactorings.
Add document extension method utility to get naming rules for document
(both user preferences and built-in).

The goal is also to gather all built-in default fallback naming rules
in a single location (FallbackNamingRules.cs) to have a good foundation for further
consistency/simplification improvements.
上级 e74ae06f
...@@ -12,10 +12,9 @@ ...@@ -12,10 +12,9 @@
using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Shared.Naming;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{ {
...@@ -217,9 +216,7 @@ private Glyph GetGlyph(SymbolKind kind, Accessibility? declaredAccessibility) ...@@ -217,9 +216,7 @@ private Glyph GetGlyph(SymbolKind kind, Accessibility? declaredAccessibility)
Document document, Document document,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var rules = await document.GetNamingRulesAsync(FallbackNamingRules.CompletionOfferingRules, cancellationToken).ConfigureAwait(false);
var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingStyleOptions.CreateRules().NamingRules.Concat(s_BuiltInRules);
var result = new Dictionary<string, SymbolKind>(); var result = new Dictionary<string, SymbolKind>();
foreach (var kind in declarationInfo.PossibleSymbolKinds) foreach (var kind in declarationInfo.PossibleSymbolKinds)
{ {
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Immutable; using System.Collections.Immutable;
using System.Composition; using System.Composition;
using System.Linq; using System.Linq;
...@@ -16,8 +15,9 @@ ...@@ -16,8 +15,9 @@
using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Naming;
using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty namespace Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty
...@@ -54,26 +54,10 @@ internal override SyntaxNode GetProperty(SyntaxToken token) ...@@ -54,26 +54,10 @@ internal override SyntaxNode GetProperty(SyntaxToken token)
internal override async Task<string> GetFieldNameAsync(Document document, IPropertySymbol propertySymbol, CancellationToken cancellationToken) internal override async Task<string> GetFieldNameAsync(Document document, IPropertySymbol propertySymbol, CancellationToken cancellationToken)
{ {
var rules = await GetNamingRulesAsync(document, cancellationToken).ConfigureAwait(false); var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
return GenerateFieldName(propertySymbol, rules); return GenerateFieldName(propertySymbol, rules);
} }
/// <summary>
/// Get the user-specified naming rules, then add standard default naming rules
/// for both static and non-static fields. The standard naming rules are added at the end
/// so they will only be used if the user hasn't specified a preference.
/// </summary>
private static async Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(
Document document,
CancellationToken cancellationToken)
{
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingPreferencesOption = optionSet.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingPreferencesOption.CreateRules().NamingRules
.AddRange(CodeAnalysis.InitializeParameter.FallbackNamingRules.Rules);
return rules;
}
private string GenerateFieldName(IPropertySymbol property, ImmutableArray<NamingRule> rules) private string GenerateFieldName(IPropertySymbol property, ImmutableArray<NamingRule> rules)
{ {
var propertyName = property.Name; var propertyName = property.Name;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
...@@ -10,41 +8,16 @@ ...@@ -10,41 +8,16 @@
using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Shared.Naming;
namespace Microsoft.CodeAnalysis.InitializeParameter namespace Microsoft.CodeAnalysis.InitializeParameter
{ {
internal static class FallbackNamingRules
{
// Standard field/property names we look for when we have a parameter with a given name.
// We also use the rules to help generate fresh fields/properties. Note that we always
// look at these rules *after* the user's own rules. That way we respect user naming, but
// also have a reasonably fallback if they don't have any specified preferences.
internal static readonly ImmutableArray<NamingRule> Rules = ImmutableArray.Create(
new NamingRule(new SymbolSpecification(
Guid.NewGuid(), "Property",
ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Property))),
new NamingStyles.NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.PascalCase),
enforcementLevel: ReportDiagnostic.Hidden),
new NamingRule(new SymbolSpecification(
Guid.NewGuid(), "Field",
ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Field))),
new NamingStyles.NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden),
new NamingRule(new SymbolSpecification(
Guid.NewGuid(), "FieldWithUnderscore",
ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Field))),
new NamingStyles.NamingStyle(Guid.NewGuid(), prefix: "_", capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden));
}
internal abstract partial class AbstractInitializeMemberFromParameterCodeRefactoringProvider< internal abstract partial class AbstractInitializeMemberFromParameterCodeRefactoringProvider<
TParameterSyntax, TParameterSyntax,
TStatementSyntax, TStatementSyntax,
...@@ -109,7 +82,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto ...@@ -109,7 +82,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
// Get the parts of the parameter name and the appropriate naming rules so // Get the parts of the parameter name and the appropriate naming rules so
// that we can name the field/property accordingly. // that we can name the field/property accordingly.
var parameterNameParts = this.GetParameterWordParts(parameter); var parameterNameParts = this.GetParameterWordParts(parameter);
var rules = await this.GetNamingRulesAsync(document, cancellationToken).ConfigureAwait(false); var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var field = CreateField(parameter, rules, parameterNameParts); var field = CreateField(parameter, rules, parameterNameParts);
var property = CreateProperty(parameter, rules, parameterNameParts); var property = CreateProperty(parameter, rules, parameterNameParts);
...@@ -401,7 +374,7 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa ...@@ -401,7 +374,7 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
// Look for a field/property that really looks like it corresponds to this parameter. // Look for a field/property that really looks like it corresponds to this parameter.
// Use a variety of heuristics around the name/type to see if this is a match. // Use a variety of heuristics around the name/type to see if this is a match.
var rules = await GetNamingRulesAsync(document, cancellationToken).ConfigureAwait(false); var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var parameterWords = GetParameterWordParts(parameter); var parameterWords = GetParameterWordParts(parameter);
var containingType = parameter.ContainingType; var containingType = parameter.ContainingType;
...@@ -468,18 +441,6 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa ...@@ -468,18 +441,6 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
return false; return false;
} }
private async Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(
Document document, CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
// Add our built-in-rules at the end so that we always respect user naming rules
// first, but we always have something to fall-back upon if there are no matches.
var rules = namingStyleOptions.CreateRules().NamingRules.AddRange(FallbackNamingRules.Rules);
return rules;
}
/// <summary> /// <summary>
/// Get the individual words in the parameter name. This way we can generate /// Get the individual words in the parameter name. This way we can generate
/// appropriate field/property names based on the user's preference. /// appropriate field/property names based on the user's preference.
......
...@@ -2,10 +2,13 @@ ...@@ -2,10 +2,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Extensions namespace Microsoft.CodeAnalysis.Shared.Extensions
...@@ -94,5 +97,25 @@ public static IEnumerable<Document> GetLinkedDocuments(this Document document) ...@@ -94,5 +97,25 @@ public static IEnumerable<Document> GetLinkedDocuments(this Document document)
yield return solution.GetDocument(linkedDocumentId); yield return solution.GetDocument(linkedDocumentId);
} }
} }
/// <summary>
/// Get the user-specified naming rules, then add standard default naming rules (if provided). The standard
/// naming rules (fallback rules) are added at the end so they will only be used if the user hasn't specified
/// a preference.
/// </summary>
internal static async Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(this Document document,
ImmutableArray<NamingRule> defaultRules, CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingStyleOptions.CreateRules().NamingRules;
if (defaultRules.Length > 0)
{
rules = rules.AddRange(defaultRules);
}
return rules;
}
} }
} }
...@@ -3,23 +3,39 @@ ...@@ -3,23 +3,39 @@
using System; using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles; using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Roslyn.Utilities; using Microsoft.CodeAnalysis.NamingStyles;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification; using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers namespace Microsoft.CodeAnalysis.Shared.Naming
{ {
internal partial class DeclarationNameCompletionProvider internal static class FallbackNamingRules
{ {
private static ImmutableArray<NamingRule> s_BuiltInRules; /// <summary>
/// Standard field/property names a refactoring look for given a named symbol that is the subject of refactoring.
/// The refactoring will try to find existing matching symbol and if not found, it will generate one.
/// </summary>
internal static readonly ImmutableArray<NamingRule> RefactoringMatchLookupRules = ImmutableArray.Create(
new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "Property", ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Property))),
new NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.PascalCase),
enforcementLevel: ReportDiagnostic.Hidden),
new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "Field", ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field))),
new NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden),
new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "FieldWithUnderscore", ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field))),
new NamingStyle(Guid.NewGuid(), prefix: "_", capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden));
static DeclarationNameCompletionProvider() /// <summary>
{ /// Standard name rules for name suggestion/completion utilities.
s_BuiltInRules = ImmutableArray.Create( /// </summary>
CreateCamelCaseFieldsAndParametersRule(), internal static readonly ImmutableArray<NamingRule> CompletionOfferingRules = ImmutableArray.Create(
CreateEndWithAsyncRule(), CreateCamelCaseFieldsAndParametersRule(),
CreateGetAsyncRule(), CreateEndWithAsyncRule(),
CreateMethodStartsWithGetRule()); CreateGetAsyncRule(),
} CreateMethodStartsWithGetRule());
private static NamingRule CreateGetAsyncRule() private static NamingRule CreateGetAsyncRule()
{ {
...@@ -27,7 +43,7 @@ private static NamingRule CreateGetAsyncRule() ...@@ -27,7 +43,7 @@ private static NamingRule CreateGetAsyncRule()
var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync)); var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync));
return new NamingRule( return new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "endswithasync", kinds, accessibilityList: default, modifiers), new SymbolSpecification(Guid.NewGuid(), "endswithasync", kinds, accessibilityList: default, modifiers),
new NamingStyles.NamingStyle(Guid.NewGuid(), prefix: "Get", suffix: "Async"), new NamingStyle(Guid.NewGuid(), prefix: "Get", suffix: "Async"),
ReportDiagnostic.Info); ReportDiagnostic.Info);
} }
...@@ -36,7 +52,7 @@ private static NamingRule CreateCamelCaseFieldsAndParametersRule() ...@@ -36,7 +52,7 @@ private static NamingRule CreateCamelCaseFieldsAndParametersRule()
var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field), new SymbolKindOrTypeKind(SymbolKind.Parameter), new SymbolKindOrTypeKind(SymbolKind.Local)); var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field), new SymbolKindOrTypeKind(SymbolKind.Parameter), new SymbolKindOrTypeKind(SymbolKind.Local));
return new NamingRule( return new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "camelcasefields", kinds, accessibilityList: default, modifiers: default), new SymbolSpecification(Guid.NewGuid(), "camelcasefields", kinds, accessibilityList: default, modifiers: default),
new NamingStyles.NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.CamelCase), new NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.CamelCase),
ReportDiagnostic.Info); ReportDiagnostic.Info);
} }
...@@ -46,7 +62,7 @@ private static NamingRule CreateEndWithAsyncRule() ...@@ -46,7 +62,7 @@ private static NamingRule CreateEndWithAsyncRule()
var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync)); var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync));
return new NamingRule( return new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "endswithasynct", kinds, accessibilityList: default, modifiers), new SymbolSpecification(Guid.NewGuid(), "endswithasynct", kinds, accessibilityList: default, modifiers),
new NamingStyles.NamingStyle(Guid.NewGuid(), suffix: "Async"), new NamingStyle(Guid.NewGuid(), suffix: "Async"),
ReportDiagnostic.Info); ReportDiagnostic.Info);
} }
...@@ -55,7 +71,7 @@ private static NamingRule CreateMethodStartsWithGetRule() ...@@ -55,7 +71,7 @@ private static NamingRule CreateMethodStartsWithGetRule()
var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(MethodKind.Ordinary)); var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(MethodKind.Ordinary));
return new NamingRule( return new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "startswithget", kinds, accessibilityList: default, modifiers: default), new SymbolSpecification(Guid.NewGuid(), "startswithget", kinds, accessibilityList: default, modifiers: default),
new NamingStyles.NamingStyle(Guid.NewGuid(), prefix: "Get"), new NamingStyle(Guid.NewGuid(), prefix: "Get"),
ReportDiagnostic.Info); ReportDiagnostic.Info);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册