From 549a46d74332f379a7cada49c4460d42afa4c8ec Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 19 Apr 2018 21:20:43 -0700 Subject: [PATCH] Factor common code out --- .../UseExplicitType/UseExplicitTypeTests.cs | 1 - .../UseExplicitTypeCodeRefactoringProvider.cs | 35 ++++-- .../UseImplicitTypeCodeRefactoringProvider.cs | 102 +++--------------- 3 files changed, 40 insertions(+), 98 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/CodeActions/UseExplicitType/UseExplicitTypeTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/UseExplicitType/UseExplicitTypeTests.cs index eddf4464367..277193e2b7c 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/UseExplicitType/UseExplicitTypeTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/UseExplicitType/UseExplicitTypeTests.cs @@ -38,7 +38,6 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithNone), SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithNone)); - [Fact] public async Task TestIntLocalDeclaration() { diff --git a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitType/UseExplicitTypeCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitType/UseExplicitTypeCodeRefactoringProvider.cs index 2a6f8d60c11..dcd9a73925f 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitType/UseExplicitTypeCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/UseExplicitType/UseExplicitTypeCodeRefactoringProvider.cs @@ -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 UpdateDocumentAsync(Document document, SyntaxNode node, CancellationToken cancellationToken) + private async Task 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); diff --git a/src/Features/CSharp/Portable/CodeRefactorings/UseImplicitType/UseImplicitTypeCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/CodeRefactorings/UseImplicitType/UseImplicitTypeCodeRefactoringProvider.cs index 898573b8321..d6fc02ad6e5 100644 --- a/src/Features/CSharp/Portable/CodeRefactorings/UseImplicitType/UseImplicitTypeCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/CodeRefactorings/UseImplicitType/UseImplicitTypeCodeRefactoringProvider.cs @@ -1,111 +1,33 @@ // 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( - a => a.IsKind(SyntaxKind.DeclarationExpression, SyntaxKind.VariableDeclaration, SyntaxKind.ForEachStatement)); - } - - private static async Task 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> createChangedDocument) : - base(title, createChangedDocument) - { - } + UseImplicitTypeCodeFixProvider.HandleDeclaration(editor, node); + return Task.CompletedTask; } } } -- GitLab