提交 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 @@
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Shared.Naming;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
......@@ -217,9 +216,7 @@ private Glyph GetGlyph(SymbolKind kind, Accessibility? declaredAccessibility)
Document document,
CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingStyleOptions.CreateRules().NamingRules.Concat(s_BuiltInRules);
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.CompletionOfferingRules, cancellationToken).ConfigureAwait(false);
var result = new Dictionary<string, SymbolKind>();
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.
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
......@@ -16,8 +15,9 @@
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Naming;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty
......@@ -54,26 +54,10 @@ internal override SyntaxNode GetProperty(SyntaxToken token)
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);
}
/// <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)
{
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.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
......@@ -10,41 +8,16 @@
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Shared.Naming;
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<
TParameterSyntax,
TStatementSyntax,
......@@ -109,7 +82,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
// Get the parts of the parameter name and the appropriate naming rules so
// that we can name the field/property accordingly.
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 property = CreateProperty(parameter, rules, parameterNameParts);
......@@ -401,7 +374,7 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
// 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.
var rules = await GetNamingRulesAsync(document, cancellationToken).ConfigureAwait(false);
var rules = await document.GetNamingRulesAsync(FallbackNamingRules.RefactoringMatchLookupRules, cancellationToken).ConfigureAwait(false);
var parameterWords = GetParameterWordParts(parameter);
var containingType = parameter.ContainingType;
......@@ -468,18 +441,6 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
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>
/// Get the individual words in the parameter name. This way we can generate
/// appropriate field/property names based on the user's preference.
......
......@@ -2,10 +2,13 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Extensions
......@@ -94,5 +97,25 @@ public static IEnumerable<Document> GetLinkedDocuments(this Document document)
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 @@
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.NamingStyles;
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()
{
s_BuiltInRules = ImmutableArray.Create(
CreateCamelCaseFieldsAndParametersRule(),
CreateEndWithAsyncRule(),
CreateGetAsyncRule(),
CreateMethodStartsWithGetRule());
}
/// <summary>
/// Standard name rules for name suggestion/completion utilities.
/// </summary>
internal static readonly ImmutableArray<NamingRule> CompletionOfferingRules = ImmutableArray.Create(
CreateCamelCaseFieldsAndParametersRule(),
CreateEndWithAsyncRule(),
CreateGetAsyncRule(),
CreateMethodStartsWithGetRule());
private static NamingRule CreateGetAsyncRule()
{
......@@ -27,7 +43,7 @@ private static NamingRule CreateGetAsyncRule()
var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync));
return new NamingRule(
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);
}
......@@ -36,7 +52,7 @@ private static NamingRule CreateCamelCaseFieldsAndParametersRule()
var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field), new SymbolKindOrTypeKind(SymbolKind.Parameter), new SymbolKindOrTypeKind(SymbolKind.Local));
return new NamingRule(
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);
}
......@@ -46,7 +62,7 @@ private static NamingRule CreateEndWithAsyncRule()
var modifiers = ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsAsync));
return new NamingRule(
new SymbolSpecification(Guid.NewGuid(), "endswithasynct", kinds, accessibilityList: default, modifiers),
new NamingStyles.NamingStyle(Guid.NewGuid(), suffix: "Async"),
new NamingStyle(Guid.NewGuid(), suffix: "Async"),
ReportDiagnostic.Info);
}
......@@ -55,7 +71,7 @@ private static NamingRule CreateMethodStartsWithGetRule()
var kinds = ImmutableArray.Create(new SymbolKindOrTypeKind(MethodKind.Ordinary));
return new NamingRule(
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);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册