提交 bd72b5cf 编写于 作者: A Andrew Hall (METAL)

PR feedback, cleanup, and move SymbolMapping to it's own file

上级 39eb8f8b
......@@ -14,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.ExtractInterface
internal class ExtractInterfaceCommandHandler : AbstractExtractInterfaceCommandHandler
{
[ImportingConstructor]
public ExtractInterfaceCommandHandler(IThreadingContext threadingContext) :
base(threadingContext)
public ExtractInterfaceCommandHandler(IThreadingContext threadingContext)
: base(threadingContext)
{
}
}
......

// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// 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.Threading;
using Microsoft.CodeAnalysis.Editor.Shared;
......
......@@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp.ExtractInterface
[ExportLanguageService(typeof(AbstractExtractInterfaceService), LanguageNames.CSharp), Shared]
internal sealed class CSharpExtractInterfaceService : AbstractExtractInterfaceService
{
internal override async Task<SyntaxNode> GetTypeDeclarationAsync(Document document, int position, TypeDiscoveryRule typeDiscoveryRule, CancellationToken cancellationToken)
protected override async Task<SyntaxNode> GetTypeDeclarationAsync(Document document, int position, TypeDiscoveryRule typeDiscoveryRule, CancellationToken cancellationToken)
{
var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);
......@@ -69,7 +69,7 @@ internal override bool ShouldIncludeAccessibilityModifier(SyntaxNode typeNode)
return typeDeclaration.Modifiers.Any(m => SyntaxFacts.IsAccessibilityModifier(m.Kind()));
}
internal override Task<Solution> UpdateMembersWithExplicitImplementationsAsync(
protected override Task<Solution> UpdateMembersWithExplicitImplementationsAsync(
Solution unformattedSolution, IReadOnlyList<DocumentId> documentIds,
INamedTypeSymbol extractedInterface, INamedTypeSymbol typeToExtractFrom,
IEnumerable<ISymbol> includedMembers, Dictionary<ISymbol, SyntaxAnnotation> symbolToDeclarationMap,
......
// 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;
namespace Microsoft.CodeAnalysis.ExtractInterface
{
internal abstract partial class AbstractExtractInterfaceService
{
private readonly struct SymbolMapping
{
public SymbolMapping(
Dictionary<ISymbol, SyntaxAnnotation> symbolToDeclarationAnnotationMap,
Solution annotatedSolution,
List<DocumentId> documentIds,
SyntaxAnnotation typeNodeAnnotation)
{
SymbolToDeclarationAnnotationMap = symbolToDeclarationAnnotationMap;
AnnotatedSolution = annotatedSolution;
DocumentIds = documentIds;
TypeNodeAnnotation = typeNodeAnnotation;
}
public Dictionary<ISymbol, SyntaxAnnotation> SymbolToDeclarationAnnotationMap { get; }
public Solution AnnotatedSolution { get; }
public List<DocumentId> DocumentIds { get; }
public SyntaxAnnotation TypeNodeAnnotation { get; }
}
}
}
......@@ -22,35 +22,15 @@
namespace Microsoft.CodeAnalysis.ExtractInterface
{
internal abstract class AbstractExtractInterfaceService : ILanguageService
internal abstract partial class AbstractExtractInterfaceService : ILanguageService
{
private readonly struct SymbolMapping
{
public SymbolMapping(
Dictionary<ISymbol, SyntaxAnnotation> symbolToDeclarationAnnotationMap,
Solution annotatedSolution,
List<DocumentId> documentIds,
SyntaxAnnotation typeNodeAnnotation)
{
SymbolToDeclarationAnnotationMap = symbolToDeclarationAnnotationMap;
AnnotatedSolution = annotatedSolution;
DocumentIds = documentIds;
TypeNodeAnnotation = typeNodeAnnotation;
}
public Dictionary<ISymbol, SyntaxAnnotation> SymbolToDeclarationAnnotationMap { get; }
public Solution AnnotatedSolution { get; }
public List<DocumentId> DocumentIds { get; }
public SyntaxAnnotation TypeNodeAnnotation { get; }
}
internal abstract Task<SyntaxNode> GetTypeDeclarationAsync(
protected abstract Task<SyntaxNode> GetTypeDeclarationAsync(
Document document,
int position,
TypeDiscoveryRule typeDiscoveryRule,
CancellationToken cancellationToken);
internal abstract Task<Solution> UpdateMembersWithExplicitImplementationsAsync(
protected abstract Task<Solution> UpdateMembersWithExplicitImplementationsAsync(
Solution unformattedSolution,
IReadOnlyList<DocumentId> documentId,
INamedTypeSymbol extractedInterfaceSymbol,
......@@ -169,20 +149,20 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
case ExtractInterfaceOptionsResult.ExtractLocation.NewFile:
var containingNamespaceDisplay = GetContainingNamespaceDisplay(refactoringResult.TypeToExtractFrom, refactoringResult.DocumentToExtractFrom.Project.CompilationOptions);
return await ExtractInterfaceToNewFileAsync(
solution: solution,
containingNamespaceDisplay: containingNamespaceDisplay,
extractedInterfaceSymbol: extractedInterfaceSymbol,
refactoringResult: refactoringResult,
extractInterfaceOptions: extractInterfaceOptions,
cancellationToken: cancellationToken).ConfigureAwait(false);
solution,
containingNamespaceDisplay,
extractedInterfaceSymbol,
refactoringResult,
extractInterfaceOptions,
cancellationToken).ConfigureAwait(false);
case ExtractInterfaceOptionsResult.ExtractLocation.SameFile:
return await ExtractInterfaceToSameFileAsync(
solution: solution,
extractedInterfaceSymbol: extractedInterfaceSymbol,
refactoringResult: refactoringResult,
extractInterfaceOptions: extractInterfaceOptions,
cancellationToken: cancellationToken).ConfigureAwait(false);
solution,
refactoringResult,
extractedInterfaceSymbol,
extractInterfaceOptions,
cancellationToken).ConfigureAwait(false);
default: throw new InvalidOperationException($"Unable to extract interface for operation of type {extractInterfaceOptions.GetType()}");
}
......@@ -192,14 +172,12 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
Solution solution, string containingNamespaceDisplay, INamedTypeSymbol extractedInterfaceSymbol,
ExtractInterfaceTypeAnalysisResult refactoringResult, ExtractInterfaceOptionsResult extractInterfaceOptions, CancellationToken cancellationToken)
{
var symbolMapping = await CreateSymbolToDeclarationAnnotationMapAsync(
var symbolMapping = await CreateSymbolMappingAsync(
extractInterfaceOptions.IncludedMembers,
solution,
refactoringResult.TypeNode,
cancellationToken).ConfigureAwait(false);
var interfaceDocumentId = DocumentId.CreateNewId(refactoringResult.DocumentToExtractFrom.Project.Id, debugName: extractInterfaceOptions.FileName);
var unformattedInterfaceDocument = await GetUnformattedInterfaceDocumentAsync(
......@@ -211,13 +189,8 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
interfaceDocumentId,
cancellationToken).ConfigureAwait(false);
var solutionWithFormattedInterfaceDocument = await GetFormattedSolutionAsync(
var completedUnformattedSolution = await GetSolutionWithOriginalTypeUpdatedAsync(
unformattedInterfaceDocument.Project.Solution,
SpecializedCollections.SingletonList(unformattedInterfaceDocument.Id),
cancellationToken).ConfigureAwait(false);
var completedSolution = await GetSolutionWithOriginalTypeUpdatedAsync(
solutionWithFormattedInterfaceDocument,
symbolMapping.DocumentIds,
refactoringResult.DocumentToExtractFrom.Id,
symbolMapping.TypeNodeAnnotation,
......@@ -227,6 +200,11 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
symbolMapping.SymbolToDeclarationAnnotationMap,
cancellationToken).ConfigureAwait(false);
var completedSolution = await GetFormattedSolutionAsync(
completedUnformattedSolution,
symbolMapping.DocumentIds.Concat(unformattedInterfaceDocument.Id),
cancellationToken).ConfigureAwait(false);
return new ExtractInterfaceResult(
succeeded: true,
updatedSolution: completedSolution,
......@@ -238,24 +216,25 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
ExtractInterfaceOptionsResult extractInterfaceOptions, CancellationToken cancellationToken)
{
// Track all of the symbols we need to modify, which includes the original type declaration being modified
var symbolMapping = await CreateSymbolToDeclarationAnnotationMapAsync(
var symbolMapping = await CreateSymbolMappingAsync(
extractInterfaceOptions.IncludedMembers,
solution,
refactoringResult.TypeNode,
cancellationToken).ConfigureAwait(false);
var document = symbolMapping.AnnotatedSolution.GetDocument(refactoringResult.DocumentToExtractFrom.Id);
var originalRoot = document.GetSyntaxRootSynchronously(cancellationToken);
var originalRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var typeDeclaration = originalRoot.GetAnnotatedNodes(symbolMapping.TypeNodeAnnotation).Single();
var trackedDocument = document.WithSyntaxRoot(originalRoot.TrackNodes(typeDeclaration));
var currentRoot = trackedDocument.GetSyntaxRootSynchronously(cancellationToken);
var currentRoot = await trackedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(currentRoot, symbolMapping.AnnotatedSolution.Workspace);
// Generate the interface syntax node, which will be inserted above the type it's extracted from
var codeGenService = trackedDocument.GetLanguageService<ICodeGenerationService>();
var interfaceNode = codeGenService.CreateNamedTypeDeclaration(extractedInterfaceSymbol).WithAdditionalAnnotations(SimplificationHelpers.SimplifyModuleNameAnnotation);
var interfaceNode = codeGenService.CreateNamedTypeDeclaration(extractedInterfaceSymbol)
.WithAdditionalAnnotations(SimplificationHelpers.SimplifyModuleNameAnnotation);
typeDeclaration = currentRoot.GetCurrentNode(typeDeclaration);
editor.InsertBefore(typeDeclaration, interfaceNode);
......@@ -275,7 +254,7 @@ public async Task<ExtractInterfaceResult> ExtractInterfaceFromAnalyzedTypeAsync(
navigationDocumentId: refactoringResult.DocumentToExtractFrom.Id);
}
private async Task<SymbolMapping> CreateSymbolToDeclarationAnnotationMapAsync(
private async Task<SymbolMapping> CreateSymbolMappingAsync(
IEnumerable<ISymbol> includedMembers,
Solution solution,
SyntaxNode typeNode,
......@@ -449,7 +428,7 @@ private async Task<Solution> GetFormattedSolutionAsync(Solution unformattedSolut
symbolToDeclarationAnnotationMap,
cancellationToken).ConfigureAwait(false);
return await GetFormattedSolutionAsync(updatedUnformattedSolution, documentIds, cancellationToken).ConfigureAwait(false);
return updatedUnformattedSolution;
}
private ImmutableArray<ISymbol> CreateInterfaceMembers(IEnumerable<ISymbol> includedMembers)
......
// 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.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.ExtractInterface
......
......@@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractInterface
Friend Class VisualBasicExtractInterfaceService
Inherits AbstractExtractInterfaceService
Friend Overrides Async Function GetTypeDeclarationAsync(
Protected Overrides Async Function GetTypeDeclarationAsync(
document As Document, position As Integer,
typeDiscoveryRule As TypeDiscoveryRule,
cancellationToken As CancellationToken) As Task(Of SyntaxNode)
......@@ -94,7 +94,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExtractInterface
Return typeDeclaration.GetModifiers().Any(Function(m) SyntaxFacts.IsAccessibilityModifier(m.Kind()))
End Function
Friend Overrides Async Function UpdateMembersWithExplicitImplementationsAsync(
Protected Overrides Async Function UpdateMembersWithExplicitImplementationsAsync(
unformattedSolution As Solution, documentIds As IReadOnlyList(Of DocumentId), extractedInterfaceSymbol As INamedTypeSymbol,
typeToExtractFrom As INamedTypeSymbol, includedMembers As IEnumerable(Of ISymbol),
symbolToDeclarationAnnotationMap As Dictionary(Of ISymbol, SyntaxAnnotation), cancellationToken As CancellationToken) As Task(Of Solution)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册