提交 549a46d7 编写于 作者: J Julien Couvreur

Factor common code out

上级 839e7fe4
......@@ -38,7 +38,6 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithNone),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithNone));
[Fact]
public async Task TestIntLocalDeclaration()
{
......
......@@ -8,17 +8,39 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseExplicitType
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.UseExplicitType), Shared]
internal partial class UseExplicitTypeCodeRefactoringProvider : CodeRefactoringProvider
internal class UseExplicitTypeCodeRefactoringProvider : AbstractUseTypeCodeRefactoringProvider
{
protected override string Title
=> CSharpFeaturesResources.Use_explicit_type;
protected override TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken)
=> CSharpUseExplicitTypeHelper.Instance.FindAnalyzableType(node, semanticModel, cancellationToken);
protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken)
=> CSharpUseExplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, optionSet, cancellationToken);
protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, SyntaxNode node, CancellationToken cancellationToken)
=> UseExplicitTypeCodeFixProvider.HandleDeclarationAsync(document, editor, node, cancellationToken);
}
internal abstract class AbstractUseTypeCodeRefactoringProvider : CodeRefactoringProvider
{
protected abstract Task HandleDeclarationAsync(Document document, SyntaxEditor editor, SyntaxNode node, CancellationToken cancellationToken);
protected abstract TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken);
protected abstract TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken);
protected abstract string Title { get; }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var document = context.Document;
......@@ -47,7 +69,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
Debug.Assert(declaration.IsKind(SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement, SyntaxKind.DeclarationExpression));
var declaredType = CSharpUseExplicitTypeHelper.Instance.FindAnalyzableType(declaration, semanticModel, cancellationToken);
var declaredType = FindAnalyzableType(declaration, semanticModel, cancellationToken);
if (declaredType == null)
{
return;
......@@ -63,8 +85,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
return;
}
var typeStyle = CSharpUseExplicitTypeHelper.Instance.AnalyzeTypeName(
declaredType, semanticModel, optionSet, cancellationToken);
var typeStyle = AnalyzeTypeName(declaredType, semanticModel, optionSet, cancellationToken);
if (typeStyle.IsStylePreferred && typeStyle.Severity != DiagnosticSeverity.Hidden)
{
// the analyzer would handle this. So we do not.
......@@ -78,7 +99,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
context.RegisterRefactoring(
new MyCodeAction(
CSharpFeaturesResources.Use_explicit_type,
Title,
c => UpdateDocumentAsync(document, declaredType, c)));
}
......@@ -89,12 +110,12 @@ private static SyntaxNode GetDeclaration(SyntaxNode root, TextSpan textSpan)
a => a.IsKind(SyntaxKind.DeclarationExpression, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement));
}
private static async Task<Document> UpdateDocumentAsync(Document document, SyntaxNode node, CancellationToken cancellationToken)
private async Task<Document> UpdateDocumentAsync(Document document, SyntaxNode node, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
await UseExplicitTypeCodeFixProvider.HandleDeclarationAsync(document, editor, node, cancellationToken).ConfigureAwait(false);
await HandleDeclarationAsync(document, editor, node, cancellationToken).ConfigureAwait(false);
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
......
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.UseImplicitType
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.UseImplicitType), Shared]
internal partial class UseImplicitTypeCodeRefactoringProvider : CodeRefactoringProvider
internal partial class UseImplicitTypeCodeRefactoringProvider : UseExplicitType.AbstractUseTypeCodeRefactoringProvider
{
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
var document = context.Document;
var textSpan = context.Span;
var cancellationToken = context.CancellationToken;
if (!textSpan.IsEmpty)
{
return;
}
if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
{
return;
}
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var declaration = GetDeclaration(root, textSpan);
if (declaration == null)
{
return;
}
Debug.Assert(declaration.IsKind(SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement, SyntaxKind.DeclarationExpression));
var declaredType = CSharpUseImplicitTypeHelper.Instance.FindAnalyzableType(declaration, semanticModel, cancellationToken);
if (declaredType == null)
{
return;
}
if (declaredType.OverlapsHiddenPosition(cancellationToken))
{
return;
}
if (!declaredType.Span.IntersectsWith(textSpan.Start))
{
return;
}
var typeStyle = CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(
declaredType, semanticModel, optionSet, cancellationToken);
if (typeStyle.IsStylePreferred && typeStyle.Severity != DiagnosticSeverity.Hidden)
{
// the analyzer would handle this. So we do not.
return;
}
protected override string Title
=> CSharpFeaturesResources.Use_implicit_type;
if (!typeStyle.CanConvert())
{
return;
}
protected override TypeSyntax FindAnalyzableType(SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken)
=> CSharpUseImplicitTypeHelper.Instance.FindAnalyzableType(node, semanticModel, cancellationToken);
context.RegisterRefactoring(
new MyCodeAction(
CSharpFeaturesResources.Use_implicit_type,
c => UpdateDocumentAsync(document, declaredType, c)));
}
private static SyntaxNode GetDeclaration(SyntaxNode root, TextSpan textSpan)
{
var token = root.FindToken(textSpan.Start);
return token.Parent?.FirstAncestorOrSelf<SyntaxNode>(
a => a.IsKind(SyntaxKind.DeclarationExpression, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement));
}
private static async Task<Document> UpdateDocumentAsync(Document document, SyntaxNode node, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
UseImplicitTypeCodeFixProvider.HandleDeclaration( editor, node);
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
}
protected override TypeStyleResult AnalyzeTypeName(TypeSyntax typeName, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken)
=> CSharpUseImplicitTypeHelper.Instance.AnalyzeTypeName(typeName, semanticModel, optionSet, cancellationToken);
private class MyCodeAction : CodeAction.DocumentChangeAction
protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, SyntaxNode node, CancellationToken cancellationToken)
{
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument) :
base(title, createChangedDocument)
{
}
UseImplicitTypeCodeFixProvider.HandleDeclaration(editor, node);
return Task.CompletedTask;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册