提交 3f304e65 编写于 作者: C CyrusNajmabadi

Extract out common base type for the code fix provider.

上级 8e427719
......@@ -362,8 +362,10 @@
<Compile Include="Structure\Providers\SwitchStatementStructureProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationCodeFixProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForMethodsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForMethodsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\UseExpressionBodyForMethods.cs" />
<Compile Include="UseObjectInitializer\CSharpUseObjectInitializerCodeFixProvider.cs" />
<Compile Include="UseThrowExpression\CSharpUseThrowExpressionDiagnosticAnalyzer.cs" />
<Compile Include="Structure\CSharpBlockStructureProvider.cs" />
......
......@@ -2,57 +2,50 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class UseExpressionBodyForMethodsDiagnosticAnalyzer :
AbstractUseExpressionBodyDiagnosticAnalyzer<MethodDeclarationSyntax>, IBuiltInAnalyzer
internal abstract class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> : CodeFixProvider
where TDeclaration : SyntaxNode
{
public UseExpressionBodyForMethodsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.MethodDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedMethods)
{
}
private readonly Option<CodeStyleOption<bool>> _option;
private readonly string _useExpressionBodyTitle;
private readonly string _useBlockBodyTitle;
protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; }
protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForMethodsCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId);
protected AbstractUseExpressionBodyCodeFixProvider(
string diagnosticId,
Option<CodeStyleOption<bool>> option,
string useExpressionBodyTitle,
string useBlockBodyTitle)
{
FixableDiagnosticIds = ImmutableArray.Create(diagnosticId);
_option = option;
_useExpressionBodyTitle = useExpressionBodyTitle;
_useBlockBodyTitle = useBlockBodyTitle;
}
public override Task RegisterCodeFixesAsync(CodeFixContext context)
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
var option = context.Document.Project.Solution.Workspace.Options.GetOption(
CSharpCodeStyleOptions.PreferExpressionBodiedMethods);
var option = context.Document.Project.Solution.Workspace.Options.GetOption(_option);
var title = option.Value
? FeaturesResources.Use_expression_body_for_methods
: FeaturesResources.Use_block_body_for_methods;
? _useExpressionBodyTitle
: _useBlockBodyTitle;
context.RegisterCodeFix(
new MyCodeAction(title, c => FixAsync(context.Document, diagnostic, c)),
......@@ -73,8 +66,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var option = document.Project.Solution.Workspace.Options.GetOption(
CSharpCodeStyleOptions.PreferExpressionBodiedMethods);
var option = document.Project.Solution.Workspace.Options.GetOption(_option);
foreach (var diagnostic in diagnostics)
{
......@@ -90,34 +82,48 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
SyntaxNode root, SyntaxEditor editor, Diagnostic diagnostic,
bool preferExpressionBody, CancellationToken cancellationToken)
{
var methodLocation = diagnostic.AdditionalLocations[0];
var methodDeclaration = (MethodDeclarationSyntax)methodLocation.FindNode(cancellationToken);
var declarationLocation = diagnostic.AdditionalLocations[0];
var declaration = (TDeclaration)declarationLocation.FindNode(cancellationToken);
var updatedMethodDeclaration = Update(methodDeclaration, preferExpressionBody).WithAdditionalAnnotations(
var updatedDeclaration = Update(declaration, preferExpressionBody).WithAdditionalAnnotations(
Formatter.Annotation);
editor.ReplaceNode(methodDeclaration, updatedMethodDeclaration);
editor.ReplaceNode(declaration, updatedDeclaration);
}
private MethodDeclarationSyntax Update(MethodDeclarationSyntax methodDeclaration, bool preferExpressionBody)
private TDeclaration Update(TDeclaration declaration, bool preferExpressionBody)
{
if (preferExpressionBody)
{
return methodDeclaration.WithBody(null)
.WithExpressionBody(methodDeclaration.Body.TryConvertToExpressionBody())
.WithSemicolonToken(GetFirstStatementSemicolon(methodDeclaration.Body));
return WithSemicolonToken(
WithExpressionBody(
WithBody(declaration, null),
GetBody(declaration).TryConvertToExpressionBody()),
GetFirstStatementSemicolon(GetBody(declaration)));
}
else
{
var block = methodDeclaration.ExpressionBody.ConvertToBlock(
methodDeclaration.SemicolonToken,
createReturnStatementForExpression: !methodDeclaration.ReturnType.IsVoid());
return methodDeclaration.WithBody(block)
.WithExpressionBody(null)
.WithSemicolonToken(default(SyntaxToken));
var block = GetExpressionBody(declaration).ConvertToBlock(
GetSemicolonToken(declaration),
CreateReturnStatementForExpression(declaration));
return WithSemicolonToken(
WithExpressionBody(
WithBody(declaration, block),
null),
default(SyntaxToken));
}
}
protected abstract bool CreateReturnStatementForExpression(TDeclaration declaration);
protected abstract SyntaxToken GetSemicolonToken(TDeclaration declaration);
protected abstract ArrowExpressionClauseSyntax GetExpressionBody(TDeclaration declaration);
protected abstract BlockSyntax GetBody(TDeclaration declaration);
protected abstract TDeclaration WithSemicolonToken(TDeclaration declaration, SyntaxToken token);
protected abstract TDeclaration WithExpressionBody(TDeclaration declaration, ArrowExpressionClauseSyntax expressionBody);
protected abstract TDeclaration WithBody(TDeclaration declaration, BlockSyntax body);
private SyntaxToken GetFirstStatementSemicolon(BlockSyntax body)
{
var firstStatement = body.Statements[0];
......
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class UseExpressionBodyForMethodsCodeFixProvider : AbstractUseExpressionBodyCodeFixProvider<MethodDeclarationSyntax>
{
public UseExpressionBodyForMethodsCodeFixProvider()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
CSharpCodeStyleOptions.PreferExpressionBodiedMethods,
FeaturesResources.Use_expression_body_for_methods,
FeaturesResources.Use_block_body_for_methods)
{
}
protected override SyntaxToken GetSemicolonToken(MethodDeclarationSyntax declaration)
=> declaration.SemicolonToken;
protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
=> declaration.ExpressionBody;
protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
protected override MethodDeclarationSyntax WithSemicolonToken(MethodDeclarationSyntax declaration, SyntaxToken token)
=> declaration.WithSemicolonToken(token);
protected override MethodDeclarationSyntax WithExpressionBody(MethodDeclarationSyntax declaration, ArrowExpressionClauseSyntax expressionBody)
=> declaration.WithExpressionBody(expressionBody);
protected override MethodDeclarationSyntax WithBody(MethodDeclarationSyntax declaration, BlockSyntax body)
=> declaration.WithBody(body);
protected override bool CreateReturnStatementForExpression(MethodDeclarationSyntax declaration)
=> !declaration.ReturnType.IsVoid();
}
}
\ No newline at end of file
// 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.Immutable;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class UseExpressionBodyForMethodsDiagnosticAnalyzer :
AbstractUseExpressionBodyDiagnosticAnalyzer<MethodDeclarationSyntax>, IBuiltInAnalyzer
{
public UseExpressionBodyForMethodsDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseExpressionBodyForMethodsDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_expression_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_block_body_for_methods), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
ImmutableArray.Create(SyntaxKind.MethodDeclaration),
CSharpCodeStyleOptions.PreferExpressionBodiedMethods)
{
}
protected override BlockSyntax GetBody(MethodDeclarationSyntax declaration)
=> declaration.Body;
protected override ArrowExpressionClauseSyntax GetExpressionBody(MethodDeclarationSyntax declaration)
=> declaration.ExpressionBody;
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册