提交 f0488333 编写于 作者: C chborl

First draft PR - Convert Auto Property To Full Property Refactoring

上级 b7ad676d
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty;
using Microsoft.CodeAnalysis.CSharp.Formatting;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertAutoPropertyToFullProperty
{
public class ConvertAutoPropertyToFullPropertyTests : AbstractCSharpCodeActionTest
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider();
private IDictionary<OptionKey, object> PreferExpressionBodiedAccessors =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement));
private IDictionary<OptionKey, object> DoNotPreferExpressionBodiedAccessors =>
OptionsSet(SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement));
private IDictionary<OptionKey, object> DoNotPreferExpressionBodiedAccessorsAndPropertyOpenBraceOnSameLine =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpFormattingOptions.NewLinesForBracesInProperties, false));
private IDictionary<OptionKey, object> DoNotPreferExpressionBodiedAccessorsAndAccessorOpenBraceOnSameLine =>
OptionsSet(
SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithNoneEnforcement),
SingleOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, false));
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task SimpleAutoPropertyTest()
{
var text = @"
class foo
{
public int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo
{
get
{
return _foo;
}
set
{
_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task AutoPropertyWithPrivateSetter()
{
var text = @"
class foo
{
public int F[||]oo { get; private set; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo
{
get
{
return _foo;
}
private set
{
_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task AutoPropertyWithFieldNameAlreadyUsed()
{
var text = @"
class foo
{
private int _foo;
public int F[||]oo { get; private set; }
}
";
var expected = @"
class foo
{
private int _foo;
private int _foo1;
public int Foo
{
get
{
return _foo1;
}
private set
{
_foo1 = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task WithComments()
{
var text = @"
class foo
{
// Comments before
public int F[||]oo { get; private set; } //Comments during
//Comments after
}
";
var expected = @"
class foo
{
private int _foo;
// Comments before
public int Foo
{
get
{
return _foo;
}
private set
{
_foo = value;
}
} //Comments during
//Comments after
}
";
await TestInRegularAndScriptAsync(text, expected, options:DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task WithExpressionBody()
{
var text = @"
class foo
{
public int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo { get => _foo; set => _foo = value; }
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task WithExpressionBodyWithTrivia()
{
var text = @"
class foo
{
public int F[||]oo { get /* test */ ; set /* test2 */ ; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo { get /* test */ => _foo; set /* test2 */ => _foo = value; }
}
";
await TestInRegularAndScriptAsync(text, expected, options: PreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task WithPropertyOpenBraceOnSameLine()
{
var text = @"
class foo
{
public int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo {
get
{
return _foo;
}
set
{
_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessorsAndPropertyOpenBraceOnSameLine, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task WithAccessorOpenBraceOnSameLine()
{
var text = @"
class foo
{
public int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private int _foo;
public int Foo
{
get {
return _foo;
}
set {
_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessorsAndAccessorOpenBraceOnSameLine, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task StaticProperty()
{
var text = @"
class foo
{
public static int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private static int s_foo;
public static int Foo
{
get
{
return s_foo;
}
set
{
s_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task PropertyWithAttributes()
{
var text = @"
class foo
{
[A]
public int F[||]oo { get; set; }
}
";
var expected = @"
class foo
{
private int _foo;
[A]
public int Foo
{
get
{
return _foo;
}
set
{
_foo = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task CommentsInAccessors()
{
var text = @"
class foo
{
/// <summary>
/// test stuff here
/// </summary>
public int testf[||]oo { /* test1 */ get /* test2 */; /* test3 */ set /* test4 */; /* test5 */ } /* test6 */
}
";
var expected = @"
class foo
{
private int _testfoo;
/// <summary>
/// test stuff here
/// </summary>
public int testfoo
{ /* test1 */
get /* test2 */
{
return _testfoo;
} /* test3 */
set /* test4 */
{
_testfoo = value;
} /* test5 */
} /* test6 */
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task OverrideProperty()
{
var text = @"
class MyBaseClass
{
public virtual string Name { get; set; }
}
class MyDerivedClass : MyBaseClass
{
public override string N[||]ame {get; set;}
}
";
var expected = @"
class MyBaseClass
{
public virtual string Name { get; set; }
}
class MyDerivedClass : MyBaseClass
{
private string _name;
public override string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task SealedProperty()
{
var text = @"
class MyClass
{
public sealed string N[||]ame {get; set;}
}
";
var expected = @"
class MyClass
{
private string _name;
public sealed string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task VirtualProperty()
{
var text = @"
class MyBaseClass
{
public virtual string N[||]ame { get; set; }
}
class MyDerivedClass : MyBaseClass
{
public override string Name {get; set;}
}
";
var expected = @"
class MyBaseClass
{
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
class MyDerivedClass : MyBaseClass
{
public override string Name {get; set;}
}
";
await TestInRegularAndScriptAsync(text, expected, options: DoNotPreferExpressionBodiedAccessors, ignoreTrivia: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task AbstractProperty()
{
var text = @"
class MyBaseClass
{
public abstract string N[||]ame { get; set; }
}
class MyDerivedClass : MyBaseClass
{
public override string Name {get; set;}
}
";
await TestMissingAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task GetterOnly()
{
var text = @"
class foo
{
public int F[||]oo { get;}
}
";
await TestMissingAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task SetterOnly()
{
var text = @"
class foo
{
public int F[||]oo
````{
set {}
}
}
";
await TestMissingAsync(text);
}
[Fact, Trait(Traits.Feature, Traits.Features.ConvertAutoPropertyToFullProperty)]
public async Task ExpressionBodiedAccessors()
{
var text = @"
class foo
{
private int _testfoo;
public int testf[||]oo {get => _testfoo; set => _testfoo = value; }
}
";
await TestMissingAsync(text);
}
}
}
......@@ -123,6 +123,7 @@ public static class Features
public const string CodeModelMethodXml = "CodeModel.MethodXml";
public const string CommentSelection = nameof(CommentSelection);
public const string Completion = nameof(Completion);
public const string ConvertAutoPropertyToFullProperty = nameof(ConvertAutoPropertyToFullProperty);
public const string DebuggingBreakpoints = "Debugging.Breakpoints";
public const string DebuggingDataTips = "Debugging.DataTips";
public const string DebuggingIntelliSense = "Debugging.IntelliSense";
......
// 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.Composition;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.ConvertAutoPropertyToFullProperty;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.ConvertAutoPropertyToFullProperty
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider)), Shared]
internal class CSharpConvertAutoPropertyToFullPropertyCodeRefactoringProvider : AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider
{
internal async override Task<SyntaxNode> ConvertToExpressionBodyIfDesiredAsync(
Document document,
SyntaxNode accessor,
CancellationToken cancellationToken)
{
var accessorDeclarationSyntax = (AccessorDeclarationSyntax)accessor;
var preference = await GetExpressionBodyPreferenceAsync(document, cancellationToken).ConfigureAwait(false);
if (preference == ExpressionBodyPreference.Never)
{
return accessorDeclarationSyntax.WithSemicolonToken(default);
}
// Should always be able to convert to expression body since we are creating the accessor and know that it only has one line
Debug.Assert(accessorDeclarationSyntax.Body.TryConvertToExpressionBody(
accessorDeclarationSyntax.Kind(),
accessor.SyntaxTree.Options,
preference,
out var arrowExpression,
out var semicolonToken));
return accessorDeclarationSyntax
.WithExpressionBody(arrowExpression)
.WithBody(null)
.WithSemicolonToken(semicolonToken);
}
internal async Task<ExpressionBodyPreference> GetExpressionBodyPreferenceAsync(
Document document,
CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value;
}
internal override SyntaxNode GetPropertyDeclaration(SyntaxToken token)
{
var containingProperty = token.Parent.FirstAncestorOrSelf<PropertyDeclarationSyntax>();
if (containingProperty == null)
{
return null;
}
var start = containingProperty.AttributeLists.Count > 0
? containingProperty.AttributeLists.Last().GetLastToken().GetNextToken().SpanStart
: containingProperty.SpanStart;
// Offer this refactoring anywhere in the signature of the property
var position = token.SpanStart;
if (position < start || position > containingProperty.Identifier.Span.End)
{
return null;
}
return containingProperty;
}
internal override bool isAbstract(SyntaxNode property)
{
var propertyDeclarationSyntax = (PropertyDeclarationSyntax)property;
var modifiers = propertyDeclarationSyntax.GetModifiers();
foreach (var modifier in modifiers)
{
if (modifier.IsKind(SyntaxKind.AbstractKeyword))
{
return true;
}
}
return false;
}
internal override bool TryGetEmptyAccessors(
SyntaxNode propertyDeclarationSyntax,
out SyntaxNode emptyGetAccessor,
out SyntaxNode emptySetAccessor)
{
emptyGetAccessor = null;
emptySetAccessor = null;
var accessorListSyntax = ((PropertyDeclarationSyntax)propertyDeclarationSyntax).AccessorList;
if (accessorListSyntax == null)
{
return false;
}
foreach (var accessor in accessorListSyntax.Accessors)
{
if (accessor.Kind() == SyntaxKind.GetAccessorDeclaration && isEmpty(accessor))
{
emptyGetAccessor = accessor;
}
else if (accessor.Kind() == SyntaxKind.SetAccessorDeclaration && isEmpty(accessor))
{
emptySetAccessor = accessor;
}
}
// both getter and setter have to be empty
return (emptyGetAccessor != null && emptySetAccessor != null);
}
private bool isEmpty(AccessorDeclarationSyntax accessor)
=> (accessor.Body == null && accessor.ExpressionBody == null);
internal override SyntaxNode UpdateAccessor(SyntaxNode accessor, SyntaxNode[] statements)
{
var blockSyntax = SyntaxFactory.Block(
SyntaxFactory.Token(SyntaxKind.OpenBraceToken),
new SyntaxList<StatementSyntax>(statements.Cast<StatementSyntax>()),
SyntaxFactory.Token(SyntaxKind.CloseBraceToken)
.WithTrailingTrivia(((AccessorDeclarationSyntax)accessor).SemicolonToken.TrailingTrivia));
return ((AccessorDeclarationSyntax)accessor).WithBody(blockSyntax);
}
}
}
// 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;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles.SymbolSpecification;
namespace Microsoft.CodeAnalysis.ConvertAutoPropertyToFullProperty
{
internal abstract class AbstractConvertAutoPropertyToFullPropertyCodeRefactoringProvider
: CodeRefactoringProvider
{
internal abstract SyntaxNode GetPropertyDeclaration(SyntaxToken token);
internal abstract bool isAbstract(SyntaxNode property);
internal abstract bool TryGetEmptyAccessors(SyntaxNode propertyDeclarationSyntax,
out SyntaxNode emptyGetAccessor, out SyntaxNode emptySetAccessor);
internal abstract SyntaxNode UpdateAccessor(SyntaxNode accessor, SyntaxNode[] statements);
internal abstract Task<SyntaxNode> ConvertToExpressionBodyIfDesiredAsync(Document document,
SyntaxNode getAccessor, CancellationToken cancellationToken);
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(context.Span.Start);
var property = GetPropertyDeclaration(token);
if (property == null)
{
return;
}
if (isAbstract(property))
{
return;
}
// check to see if both property accessors exist and are empty
if (!TryGetEmptyAccessors(property, out var emptyGetAccessor, out var emptySetAccessor))
{
return;
}
context.RegisterRefactoring(
new ConvertAutoPropertyToFullPropertyCodeAction(
FeaturesResources.Convert_to_full_property,
c => ExpandToFullPropertyAsync(
document,
property,
emptyGetAccessor,
emptySetAccessor,
root,
context.CancellationToken)));
}
private async Task<Document> ExpandToFullPropertyAsync(
Document document,
SyntaxNode property,
SyntaxNode emptyGetAccessor,
SyntaxNode emptySetAccessor,
SyntaxNode root,
CancellationToken cancellationToken)
{
// Get the symbol representing the property
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var propertySymbol = semanticModel.GetDeclaredSymbol(property) as IPropertySymbol;
// generate a name for the new field based on naming preferences
var rules = await GetNamingRulesAsync(
document,
cancellationToken).ConfigureAwait(false);
var fieldName = GenerateFieldName(propertySymbol, rules);
// expand the property and add the field
var generator = SyntaxGenerator.GetGenerator(document);
var newRoot = await ExpandPropertyAndAddFieldAsync(
document,
property,
emptyGetAccessor,
emptySetAccessor,
root,
propertySymbol,
fieldName,
generator,
cancellationToken).ConfigureAwait(false);
return document.WithSyntaxRoot(newRoot);
}
private static async Task<ImmutableArray<NamingRule>> GetNamingRulesAsync(
Document document,
CancellationToken cancellationToken)
{
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
var rules = namingStyleOptions.CreateRules().NamingRules
.AddRange(GetDefaultRule(ImmutableArray.Create(new ModifierKind(ModifierKindEnum.IsStatic)), "s_"))
.AddRange(GetDefaultRule(ImmutableArray.Create<ModifierKind>(), "_"));
return rules;
}
private static string GenerateFieldName(
IPropertySymbol property,
ImmutableArray<NamingRule> rules)
{
var propertyName = property.Name;
var fieldName = "";
var isStatic = property.IsStatic;
foreach (var rule in rules)
{
if (rule.SymbolSpecification.AppliesTo(
new SymbolKindOrTypeKind(SymbolKind.Field),
isStatic ? DeclarationModifiers.Static : DeclarationModifiers.None,
Accessibility.Private))
{
fieldName = rule.NamingStyle.MakeCompliant(propertyName).Single();
break;
}
}
var uniqueName = NameGenerator.GenerateUniqueName(
fieldName, n => property.ContainingType.GetMembers(n).IsEmpty);
return uniqueName;
}
private async Task<SyntaxNode> ExpandPropertyAndAddFieldAsync(
Document document,
SyntaxNode property,
SyntaxNode getAccessor,
SyntaxNode setAccessor,
SyntaxNode root,
IPropertySymbol propertySymbol,
string fieldName,
SyntaxGenerator generator,
CancellationToken cancellationToken)
{
var workspace = document.Project.Solution.Workspace;
// add statements to existing accessors
var getAccessorStatements = new SyntaxNode[] {
generator.ReturnStatement(
generator.IdentifierName(fieldName)) };
var newGetAccessor = await AddStatementsToAccessorAsync(
document,
getAccessor,
getAccessorStatements,
generator,
cancellationToken).ConfigureAwait(false);
var setAccessorStatements = new SyntaxNode[] {
generator.ExpressionStatement(generator.AssignmentStatement(
generator.IdentifierName(fieldName),
generator.IdentifierName("value"))) };
var newSetAccessor = await AddStatementsToAccessorAsync(
document,
setAccessor,
setAccessorStatements,
generator,
cancellationToken).ConfigureAwait(false);
var newProperty = generator
.WithAccessorDeclarations(property, new SyntaxNode[] { newGetAccessor, newSetAccessor})
.WithAdditionalAnnotations(Formatter.Annotation)
.WithAdditionalAnnotations(new SyntaxAnnotation("property"));
newProperty = await Formatter.FormatAsync(newProperty, workspace).ConfigureAwait(false);
var newRoot = root.ReplaceNode(property, newProperty);
var newField = generator.FieldDeclaration(
fieldName,
generator.TypeExpression(propertySymbol.Type),
Accessibility.Private,
DeclarationModifiers.From(propertySymbol)).
WithAdditionalAnnotations(Formatter.Annotation);
var newFieldNodes = SpecializedCollections.SingletonEnumerable(newField);
newProperty = newRoot.GetAnnotatedNodes("property").Single();
newRoot = newRoot.InsertNodesBefore(newProperty, newFieldNodes);
return newRoot;
}
private async Task<SyntaxNode> AddStatementsToAccessorAsync(
Document document,
SyntaxNode accessor,
SyntaxNode[] statements,
SyntaxGenerator generator,
CancellationToken cancellationToken)
{
// shell to lang specific to update the accessor.
var newAccessor = UpdateAccessor(accessor, statements);
// then conver to expression bod
newAccessor= await ConvertToExpressionBodyIfDesiredAsync(
document,
newAccessor,
cancellationToken).ConfigureAwait(false);
return await Formatter.FormatAsync(newAccessor, document.Project.Solution.Workspace).ConfigureAwait(false);
}
private static ImmutableArray<NamingRule> GetDefaultRule(
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),
DiagnosticSeverity.Hidden));
}
private class ConvertAutoPropertyToFullPropertyCodeAction : CodeAction.DocumentChangeAction
{
public ConvertAutoPropertyToFullPropertyCodeAction(
string Title,
Func<CancellationToken,
Task<Document>> createChangedDocument) : base(Title, createChangedDocument)
{
}
}
}
}
......@@ -834,6 +834,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Convert to full property.
/// </summary>
internal static string Convert_to_full_property {
get {
return ResourceManager.GetString("Convert_to_full_property", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Convert to hex.
/// </summary>
......
......@@ -1292,6 +1292,9 @@ This version used in: {2}</value>
<data name="Move_declaration_near_reference" xml:space="preserve">
<value>Move declaration near reference</value>
</data>
<data name="Convert_to_full_property" xml:space="preserve">
<value>Convert to full property</value>
</data>
<data name="Generate_constructor_in_0_without_fields" xml:space="preserve">
<value>Generate constructor in '{0}' (without fields)</value>
</data>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册