未验证 提交 d0966be5 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #42663 from CyrusNajmabadi/simplifyNaming

Simplify code for figuring out the name for a symbol in a feature.
......@@ -33,28 +33,15 @@ public CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider()
{
}
internal override async Task<string> GetFieldNameAsync(Document document, IPropertySymbol propertySymbol, CancellationToken cancellationToken)
internal override async Task<string> GetFieldNameAsync(Document document, IPropertySymbol property, CancellationToken cancellationToken)
{
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
return GenerateFieldName(propertySymbol, rules);
}
private string GenerateFieldName(IPropertySymbol property, ImmutableArray<NamingRule> rules)
{
var propertyName = property.Name;
var fieldName = "";
foreach (var rule in rules)
{
if (rule.SymbolSpecification.AppliesTo(
new SymbolKindOrTypeKind(SymbolKind.Field),
property.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None,
Accessibility.Private))
{
fieldName = rule.NamingStyle.MakeCompliant(propertyName).First();
break;
}
}
var rule = await document.GetApplicableNamingRuleAsync(
new SymbolKindOrTypeKind(SymbolKind.Field),
property.IsStatic ? DeclarationModifiers.Static : DeclarationModifiers.None,
Accessibility.Private,
cancellationToken).ConfigureAwait(false);
var fieldName = rule.NamingStyle.MakeCompliant(property.Name).First();
return NameGenerator.GenerateUniqueName(fieldName, n => !property.ContainingType.GetMembers(n).Any());
}
......
......@@ -45,7 +45,7 @@ private class State
{
ContainingType = selectedMembers[0].ContainingType;
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
var parametersForSelectedMembers = service.DetermineParameters(selectedMembers, rules);
if (!selectedMembers.All(IsWritableInstanceFieldOrProperty) ||
......
......@@ -62,7 +62,7 @@ private class State
return false;
}
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
Parameters = service.DetermineParameters(selectedMembers, rules);
MatchingConstructor = GetMatchingConstructorBasedOnParameterTypes(ContainingType, Parameters);
// We are going to create a new contructor and pass part of the parameters into DelegatedConstructor,
......
......@@ -84,13 +84,13 @@ private partial class Editor
internal async Task<(Document, bool addedFields)> GetEditAsync()
{
var document = _document.Document;
// Get naming rule for generating fields and parameters
var rules = await _document.Document.GetNamingRulesAsync(
FallbackNamingRules.RefactoringMatchLookupRules, _cancellationToken).ConfigureAwait(false);
var fieldNamingRule = rules.Where(c => c.SymbolSpecification.AppliesTo(new SymbolKindOrTypeKind(SymbolKind.Field),
DeclarationModifiers.None, Accessibility.Private)).First();
var parameterNamingRule = rules.Where(c => c.SymbolSpecification.AppliesTo(new SymbolKindOrTypeKind(SymbolKind.Parameter),
DeclarationModifiers.None, Accessibility.NotApplicable)).First();
var fieldNamingRule = await document.GetApplicableNamingRuleAsync(
SymbolKind.Field, Accessibility.Private, _cancellationToken).ConfigureAwait(false);
var parameterNamingRule = await document.GetApplicableNamingRuleAsync(
SymbolKind.Parameter, Accessibility.NotApplicable, _cancellationToken).ConfigureAwait(false);
// See if there's an accessible base constructor that would accept these
// types, then just call into that instead of generating fields.
......
......@@ -319,7 +319,8 @@ public override string Title
INamedTypeSymbol containingType,
CancellationToken cancellationToken)
{
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var rule = await document.GetApplicableNamingRuleAsync(
SymbolKind.Field, Accessibility.Private, cancellationToken).ConfigureAwait(false);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var requireAccessiblity = options.GetOption(CodeStyleOptions.RequireAccessibilityModifiers);
......@@ -329,23 +330,13 @@ public override string Title
? Accessibility.NotApplicable
: Accessibility.Private;
foreach (var rule in rules)
{
if (rule.SymbolSpecification.AppliesTo(SymbolKind.Field, Accessibility.Private))
{
var uniqueName = GenerateUniqueNameForDisposedValueField(containingType, rule);
return CodeGenerationSymbolFactory.CreateFieldSymbol(
default,
accessibilityLevel,
DeclarationModifiers.None,
boolType, uniqueName);
}
}
var uniqueName = GenerateUniqueNameForDisposedValueField(containingType, rule);
// We place a special rule in s_builtInRules that matches all fields. So we should
// always find a matching rule.
throw ExceptionUtilities.Unreachable;
return CodeGenerationSymbolFactory.CreateFieldSymbol(
default,
accessibilityLevel,
DeclarationModifiers.None,
boolType, uniqueName);
}
private static string GenerateUniqueNameForDisposedValueField(INamedTypeSymbol containingType, NamingRule rule)
......
......@@ -65,7 +65,7 @@ protected override Task<ImmutableArray<CodeAction>> GetRefactoringsForAllParamet
// to an existing matching field/prop if we can find one, or add a new field/prop
// if we can't.
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
var parameterNameParts = IdentifierNameParts.CreateIdentifierNameParts(parameter, rules);
if (parameterNameParts.BaseName == "")
{
......
......@@ -10,8 +10,11 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Naming;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.Shared.Extensions
{
......@@ -91,23 +94,63 @@ public static bool ShouldHideAdvancedMembers(this Document document)
}
/// <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.
/// Gets the set of naming rules the user has set for this document. Will include a set of default naming rules
/// that match if the user hasn't specified any for a particular symbol type. The are added at the end so they
/// will only be used if the user hasn't specified a preference.
/// </summary>
internal static async Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(this Document document,
public static Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(
this Document document, CancellationToken cancellationToken)
=> document.GetNamingRulesAsync(FallbackNamingRules.Default, cancellationToken);
/// <summary>
/// Get the user-specified naming rules, with the added <paramref name="defaultRules"/>.
/// </summary>
public 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(NamingStyleOptions.NamingPreferences);
var rules = namingStyleOptions.CreateRules().NamingRules;
if (defaultRules.Length > 0)
return defaultRules.IsDefaultOrEmpty ? rules : rules.AddRange(defaultRules);
}
public static async Task<NamingRule> GetApplicableNamingRuleAsync(this Document document, ISymbol symbol, CancellationToken cancellationToken)
{
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
foreach (var rule in rules)
{
if (rule.SymbolSpecification.AppliesTo(symbol))
return rule;
}
throw ExceptionUtilities.Unreachable;
}
public static async Task<NamingRule> GetApplicableNamingRuleAsync(
this Document document, SymbolKind symbolKind, Accessibility accessibility, CancellationToken cancellationToken)
{
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
foreach (var rule in rules)
{
if (rule.SymbolSpecification.AppliesTo(symbolKind, accessibility))
return rule;
}
throw ExceptionUtilities.Unreachable;
}
public static async Task<NamingRule> GetApplicableNamingRuleAsync(
this Document document, SymbolKindOrTypeKind kind, DeclarationModifiers modifiers, Accessibility? accessibility, CancellationToken cancellationToken)
{
var rules = await document.GetNamingRulesAsync(cancellationToken).ConfigureAwait(false);
foreach (var rule in rules)
{
rules = rules.AddRange(defaultRules);
if (rule.SymbolSpecification.AppliesTo(kind, modifiers, accessibility))
return rule;
}
return rules;
throw ExceptionUtilities.Unreachable;
}
}
}
......@@ -13,21 +13,34 @@ namespace Microsoft.CodeAnalysis.Shared.Naming
internal static class FallbackNamingRules
{
/// <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.
/// Standard symbol names if the user doesn't have any existing naming rules.
/// </summary>
internal static readonly ImmutableArray<NamingRule> RefactoringMatchLookupRules = ImmutableArray.Create(
public static readonly ImmutableArray<NamingRule> Default = ImmutableArray.Create(
// Symbols that should be camel cased.
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 SymbolKindOrTypeKind(SymbolKind.Parameter))),
new SymbolSpecification(
Guid.NewGuid(),
nameof(Capitalization.CamelCase),
ImmutableArray.Create(
new SymbolKindOrTypeKind(SymbolKind.Field),
new SymbolKindOrTypeKind(SymbolKind.Local),
new SymbolKindOrTypeKind(SymbolKind.Parameter),
new SymbolKindOrTypeKind(SymbolKind.RangeVariable))),
new NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden),
// Include an entry for _ prefixed fields (.Net style). That way features that are looking to see if
// there's a potential matching field for a particular name will find these as well.
new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "FieldWithUnderscore", ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field))),
new SymbolSpecification(
Guid.NewGuid(),
"CamelCaseWithUnderscore",
ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field))),
new NamingStyle(Guid.NewGuid(), prefix: "_", capitalizationScheme: Capitalization.CamelCase),
enforcementLevel: ReportDiagnostic.Hidden),
// Everything else should be pascal cased.
new NamingRule(
CreateDefaultSymbolSpecification(),
new NamingStyle(Guid.NewGuid(), capitalizationScheme: Capitalization.PascalCase),
enforcementLevel: ReportDiagnostic.Hidden));
/// <summary>
......
......@@ -80,17 +80,15 @@ public static SymbolSpecification CreateDefaultSymbolSpecification()
modifiers: ImmutableArray<ModifierKind>.Empty);
}
internal bool AppliesTo(ISymbol symbol)
{
return AnyMatches(this.ApplicableSymbolKindList, symbol) &&
AllMatches(this.RequiredModifierList, symbol) &&
AnyMatches(this.ApplicableAccessibilityList, symbol);
}
public bool AppliesTo(ISymbol symbol)
=> AnyMatches(this.ApplicableSymbolKindList, symbol) &&
AllMatches(this.RequiredModifierList, symbol) &&
AnyMatches(this.ApplicableAccessibilityList, symbol);
internal bool AppliesTo(SymbolKind symbolKind, Accessibility accessibility)
public bool AppliesTo(SymbolKind symbolKind, Accessibility accessibility)
=> this.AppliesTo(new SymbolKindOrTypeKind(symbolKind), new DeclarationModifiers(), accessibility);
internal bool AppliesTo(SymbolKindOrTypeKind kind, DeclarationModifiers modifiers, Accessibility? accessibility)
public bool AppliesTo(SymbolKindOrTypeKind kind, DeclarationModifiers modifiers, Accessibility? accessibility)
{
if (!ApplicableSymbolKindList.Any(k => k.Equals(kind)))
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册