未验证 提交 06943b06 编写于 作者: S Sam Harwell 提交者: GitHub

Merge pull request #28013 from wachulski/fix/26992/to-full-prop-refactoring-naming-alignment

Fix naming consistency of ConvertAutoPropertyToFullProperty refactoring
......@@ -22,25 +22,25 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
public async Task SimpleAutoPropertyTest()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -52,26 +52,26 @@ public int Goo
public async Task ExtraLineAfterProperty()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
......@@ -84,25 +84,25 @@ public int Goo
public async Task WithInitialValue()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; } = 2
}
";
var expected = @"
class goo
class TestClass
{
private int _goo = 2;
private int goo = 2;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -114,27 +114,27 @@ public int Goo
public async Task WithCalculatedInitialValue()
{
var text = @"
class goo
class TestClass
{
const int num = 345;
public int G[||]oo { get; set; } = 2*num
}
";
var expected = @"
class goo
class TestClass
{
const int num = 345;
private int _goo = 2 * num;
private int goo = 2 * num;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -146,25 +146,25 @@ public int Goo
public async Task WithPrivateSetter()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; private set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
private set
{
_goo = value;
goo = value;
}
}
}
......@@ -176,28 +176,28 @@ private set
public async Task WithFieldNameAlreadyUsed()
{
var text = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int G[||]oo { get; private set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int _goo1;
private int goo;
private int goo1;
public int Goo
{
get
{
return _goo1;
return goo1;
}
private set
{
_goo1 = value;
goo1 = value;
}
}
}
......@@ -209,7 +209,7 @@ private set
public async Task WithComments()
{
var text = @"
class goo
class TestClass
{
// Comments before
public int G[||]oo { get; private set; } //Comments during
......@@ -217,20 +217,20 @@ class goo
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
// Comments before
public int Goo
{
get
{
return _goo;
return goo;
}
private set
{
_goo = value;
goo = value;
}
} //Comments during
//Comments after
......@@ -243,17 +243,17 @@ private set
public async Task WithExpressionBody()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo { get => _goo; set => _goo = value; }
public int Goo { get => goo; set => goo = value; }
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiedAccessorsWhenPossible);
......@@ -263,17 +263,17 @@ class goo
public async Task WithExpressionBodyWhenOnSingleLine()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo { get => _goo; set => _goo = value; }
public int Goo { get => goo; set => goo = value; }
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiedAccessorsWhenOnSingleLine);
......@@ -283,7 +283,7 @@ class goo
public async Task WithExpressionBodyWhenOnSingleLine2()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo
{
......@@ -293,14 +293,14 @@ class goo
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get => _goo;
set => _goo = value;
get => goo;
set => goo = value;
}
}
";
......@@ -311,17 +311,17 @@ public int Goo
public async Task WithExpressionBodyWithTrivia()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get /* test */ ; set /* test2 */ ; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo { get /* test */ => _goo; set /* test2 */ => _goo = value; }
public int Goo { get /* test */ => goo; set /* test2 */ => goo = value; }
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiedAccessorsWhenPossible);
......@@ -331,24 +331,24 @@ class goo
public async Task WithPropertyOpenBraceOnSameLine()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo {
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -360,23 +360,23 @@ class goo
public async Task WithAccessorOpenBraceOnSameLine()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get {
return _goo;
return goo;
}
set {
_goo = value;
goo = value;
}
}
}
......@@ -388,25 +388,25 @@ public int Goo
public async Task StaticProperty()
{
var text = @"
class goo
class TestClass
{
public static int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private static int s_goo;
private static int goo;
public static int Goo
{
get
{
return s_goo;
return goo;
}
set
{
s_goo = value;
goo = value;
}
}
}
......@@ -418,25 +418,25 @@ public static int Goo
public async Task ProtectedProperty()
{
var text = @"
class goo
class TestClass
{
protected int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
protected int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -448,25 +448,25 @@ protected int Goo
public async Task InternalProperty()
{
var text = @"
class goo
class TestClass
{
internal int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
internal int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -478,27 +478,27 @@ internal int Goo
public async Task WithAttributes()
{
var text = @"
class goo
class TestClass
{
[A]
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
[A]
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -510,31 +510,31 @@ public int Goo
public async Task CommentsInAccessors()
{
var text = @"
class goo
class TestClass
{
/// <summary>
/// test stuff here
/// </summary>
public int testg[||]oo { /* test1 */ get /* test2 */; /* test3 */ set /* test4 */; /* test5 */ } /* test6 */
public int Testg[||]oo { /* test1 */ get /* test2 */; /* test3 */ set /* test4 */; /* test5 */ } /* test6 */
}
";
var expected = @"
class goo
class TestClass
{
private int _testgoo;
private int testgoo;
/// <summary>
/// test stuff here
/// </summary>
public int testgoo
public int Testgoo
{ /* test1 */
get /* test2 */
{
return _testgoo;
return testgoo;
} /* test3 */
set /* test4 */
{
_testgoo = value;
testgoo = value;
} /* test5 */
} /* test6 */
}
......@@ -564,17 +564,17 @@ class MyBaseClass
class MyDerivedClass : MyBaseClass
{
private string _name;
private string name;
public override string Name
{
get
{
return _name;
return name;
}
set
{
_name = value;
name = value;
}
}
}
......@@ -594,17 +594,17 @@ class MyClass
var expected = @"
class MyClass
{
private string _name;
private string name;
public sealed string Name
{
get
{
return _name;
return name;
}
set
{
_name = value;
name = value;
}
}
}
......@@ -629,17 +629,17 @@ class MyDerivedClass : MyBaseClass
var expected = @"
class MyBaseClass
{
private string _name;
private string name;
public virtual string Name
{
get
{
return _name;
return name;
}
set
{
_name = value;
name = value;
}
}
}
......@@ -664,17 +664,17 @@ class MyClass
var expected = @"
class MyClass
{
private string _name;
private string name;
private string Name
{
get
{
return _name;
return name;
}
set
{
_name = value;
name = value;
}
}
}
......@@ -715,21 +715,21 @@ class MyBaseClass
public async Task GetterOnly()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get;}
}
";
var expected = @"
class goo
class TestClass
{
private readonly int _goo;
private readonly int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
}
}
......@@ -741,17 +741,17 @@ public int Goo
public async Task GetterOnlyExpressionBodies()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get;}
}
";
var expected = @"
class goo
class TestClass
{
private readonly int _goo;
private readonly int goo;
public int Goo => _goo;
public int Goo => goo;
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiesOnAccessorsAndMethods);
......@@ -761,7 +761,7 @@ class goo
public async Task SetterOnly()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo
{
......@@ -776,11 +776,11 @@ class goo
public async Task ExpressionBodiedAccessors()
{
var text = @"
class goo
class TestClass
{
private int _testgoo;
private int testgoo;
public int testg[||]oo {get => _testgoo; set => _testgoo = value; }
public int testg[||]oo {get => testgoo; set => testgoo = value; }
}
";
await TestMissingAsync(text);
......@@ -790,25 +790,25 @@ class goo
public async Task CursorAtBeginning()
{
var text = @"
class goo
class TestClass
{
[||]public int Goo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -820,25 +820,25 @@ public int Goo
public async Task CursorAtEnd()
{
var text = @"
class goo
class TestClass
{
public int Goo[||] { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -850,7 +850,7 @@ public int Goo
public async Task CursorOnAccessors()
{
var text = @"
class goo
class TestClass
{
public int Goo { g[||]et; set; }
}
......@@ -862,7 +862,7 @@ class goo
public async Task MoreThanOneGetter()
{
var text = @"
class goo
class TestClass
{
public int Goo { g[||]et; get; }
}
......@@ -874,7 +874,7 @@ class goo
public async Task MoreThanOneSetter()
{
var text = @"
class goo
class TestClass
{
public int Goo { get; s[||]et; set; }
}
......@@ -886,13 +886,13 @@ class goo
public async Task CustomFieldName()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int testingGoo;
......@@ -912,17 +912,18 @@ public int Goo
await TestInRegularAndScriptAsync(text, expected, options: UseCustomFieldName);
}
[WorkItem(28013, "https://github.com/dotnet/roslyn/issues/26992")]
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task NonStaticPropertyWithCustomStaticFieldName()
public async Task UnderscorePrefixedFieldName()
{
var text = @"
class goo
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private int _goo;
......@@ -938,6 +939,57 @@ public int Goo
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: UseUnderscorePrefixedFieldName);
}
[WorkItem(28013, "https://github.com/dotnet/roslyn/issues/26992")]
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task PropertyNameEqualsToClassNameExceptFirstCharCasingWhichCausesFieldNameCollisionByDefault()
{
var text = @"
class stranger
{
public int S[||]tranger { get; set; }
}
";
var expected = @"
class stranger
{
private int stranger;
public int Stranger { get => stranger; set => stranger = value; }
}
";
await TestInRegularAndScriptAsync(text, expected);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task NonStaticPropertyWithCustomStaticFieldName()
{
var text = @"
class TestClass
{
public int G[||]oo { get; set; }
}
";
var expected = @"
class TestClass
{
private int goo;
public int Goo
{
get
{
return goo;
}
set
{
goo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: UseCustomStaticFieldName);
}
......@@ -946,13 +998,13 @@ public int Goo
public async Task StaticPropertyWithCustomStaticFieldName()
{
var text = @"
class goo
class TestClass
{
public static int G[||]oo { get; set; }
}
";
var expected = @"
class goo
class TestClass
{
private static int staticfieldtestGoo;
......@@ -996,17 +1048,17 @@ struct goo
var expected = @"
struct goo
{
private int _goo;
private int goo;
public int Goo
{
get
{
return _goo;
return goo;
}
set
{
_goo = value;
goo = value;
}
}
}
......@@ -1037,9 +1089,9 @@ partial class Program
partial class Program
{
private int _q;
private int q;
int Q { get => _q; set => _q = value; }
int Q { get => q; set => q = value; }
}
";
await TestInRegularAndScriptAsync(text, expected);
......@@ -1062,9 +1114,9 @@ partial class Program
var file1AfterRefactor = @"
partial class Program
{
private int _p;
private int p;
int P { get => _p; set => _p = value; }
int P { get => p; set => p = value; }
}";
var xmlString = string.Format(@"
......@@ -1108,9 +1160,9 @@ partial class Program
var file2AfterRefactor = @"
partial class Program
{
private int _q;
private int q;
int Q { get => _q; set => _q = value; }
int Q { get => q; set => q = value; }
}";
var xmlString = string.Format(@"
......
......@@ -46,6 +46,11 @@ public partial class ConvertAutoPropertyToFullPropertyTests : AbstractCSharpCode
SingleOption(SimplificationOptions.NamingPreferences, CreateCustomFieldNamingStylePreference()),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseUnderscorePrefixedFieldName
=> OptionsSet(
SingleOption(SimplificationOptions.NamingPreferences, CreateUnderscorePrefixedFieldNamingStylePreference()),
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseCustomStaticFieldName
=> OptionsSet(
SingleOption(SimplificationOptions.NamingPreferences, CreateCustomStaticFieldNamingStylePreference()),
......@@ -83,6 +88,38 @@ private NamingStylePreferences CreateCustomFieldNamingStylePreference()
return info;
}
private NamingStylePreferences CreateUnderscorePrefixedFieldNamingStylePreference()
{
var symbolSpecification = new SymbolSpecification(
null,
"Name",
ImmutableArray.Create(new SymbolKindOrTypeKind(SymbolKind.Field)),
accessibilityList: default,
modifiers: default);
var namingStyle = new NamingStyle(
Guid.NewGuid(),
capitalizationScheme: Capitalization.CamelCase,
name: "CustomFieldTest",
prefix: "_",
suffix: "",
wordSeparator: "");
var namingRule = new SerializableNamingRule()
{
SymbolSpecificationID = symbolSpecification.ID,
NamingStyleID = namingStyle.ID,
EnforcementLevel = ReportDiagnostic.Error
};
var info = new NamingStylePreferences(
ImmutableArray.Create(symbolSpecification),
ImmutableArray.Create(namingStyle),
ImmutableArray.Create(namingRule));
return info;
}
private NamingStylePreferences CreateCustomStaticFieldNamingStylePreference()
{
var symbolSpecification = new SymbolSpecification(
......
......@@ -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
{
......@@ -218,9 +217,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,48 +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)
{
const string defaultStaticFieldPrefix = "s_";
const string defaultFieldPrefix = "_";
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingPreferencesOption = optionSet.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingPreferencesOption.CreateRules().NamingRules
.AddRange(CreateNewRule(ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsStatic)), defaultStaticFieldPrefix))
.AddRange(CreateNewRule(modifiers: default, defaultFieldPrefix));
return rules;
}
private static ImmutableArray<NamingRule> CreateNewRule(
ImmutableArray<ModifierKind> modifiers,
string prefix)
{
return ImmutableArray.Create(
new NamingRule(
new SymbolSpecification(
Guid.NewGuid(),
"Field",
ImmutableArray.Create(new SymbolSpecification.SymbolKindOrTypeKind(SymbolKind.Field)),
modifiers: modifiers),
new NamingStyles.NamingStyle(
Guid.NewGuid(),
prefix: prefix,
capitalizationScheme: Capitalization.CamelCase),
ReportDiagnostic.Hidden));
}
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.Immutable;
using System.Linq;
using System.Threading;
......@@ -14,9 +13,9 @@
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
{
......@@ -37,27 +36,6 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
protected abstract Accessibility DetermineDefaultPropertyAccessibility();
// 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.
private static readonly ImmutableArray<NamingRule> s_builtInRules = 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));
protected override async Task<ImmutableArray<CodeAction>> GetRefactoringsAsync(
Document document, IParameterSymbol parameter, SyntaxNode functionDeclaration, IMethodSymbol method,
IBlockOperation blockStatementOpt, CancellationToken cancellationToken)
......@@ -109,7 +87,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 options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var requireAccessibilityModifiers = options.GetOption(CodeStyleOptions.RequireAccessibilityModifiers);
......@@ -430,7 +408,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;
......@@ -497,18 +475,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(s_builtInRules);
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.
先完成此消息的编辑!
想要评论请 注册