diff --git a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs index e1a0e64321532319364022c562e259bd70379e3d..32c461e60c7088372139fa9fec0253899759c5d9 100644 --- a/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs +++ b/src/Features/Core/Portable/ExtractInterface/AbstractExtractInterfaceService.cs @@ -24,6 +24,26 @@ namespace Microsoft.CodeAnalysis.ExtractInterface { internal abstract class AbstractExtractInterfaceService : ILanguageService { + private struct SymbolMapping + { + public SymbolMapping( + Dictionary symbolToDeclarationAnnotationMap, + Solution annotatedSolution, + List documentIds, + SyntaxAnnotation typeNodeAnnotation) + { + SymbolToDeclarationAnnotationMap = symbolToDeclarationAnnotationMap; + AnnotatedSolution = annotatedSolution; + DocumentIds = documentIds; + TypeNodeAnnotation = typeNodeAnnotation; + } + + public Dictionary SymbolToDeclarationAnnotationMap { get; } + public Solution AnnotatedSolution { get; } + public List DocumentIds { get; } + public SyntaxAnnotation TypeNodeAnnotation { get; } + } + internal abstract Task GetTypeDeclarationAsync( Document document, int position, @@ -45,7 +65,7 @@ internal abstract class AbstractExtractInterfaceService : ILanguageService internal abstract bool ShouldIncludeAccessibilityModifier(SyntaxNode typeNode); - public async Task> GetExtractInterfaceCodeAction(Document document, TextSpan span, CancellationToken cancellationToken) + public async Task> GetExtractInterfaceCodeActionAsync(Document document, TextSpan span, CancellationToken cancellationToken) { var typeAnalysisResult = await AnalyzeTypeAtPositionAsync(document, span.Start, TypeDiscoveryRule.TypeNameOnly, cancellationToken).ConfigureAwait(false); @@ -175,16 +195,18 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT Solution solution, string containingNamespaceDisplay, INamedTypeSymbol extractedInterfaceSymbol, ExtractInterfaceTypeAnalysisResult refactoringResult, ExtractInterfaceOptionsResult extractInterfaceOptions, CancellationToken cancellationToken) { - var (symbolToDeclarationAnnotationMap, annotatedSolution, documentIds, typeNodeSyntaxAnnotation) = CreateSymbolToDeclarationAnnotationMap( + var symbolMapping = CreateSymbolToDeclarationAnnotationMap( extractInterfaceOptions.IncludedMembers, solution, refactoringResult.TypeNode, cancellationToken); + + var interfaceDocumentId = DocumentId.CreateNewId(refactoringResult.DocumentToExtractFrom.Project.Id, debugName: extractInterfaceOptions.FileName); var unformattedInterfaceDocument = GetUnformattedInterfaceDocument( - annotatedSolution, + symbolMapping.AnnotatedSolution, containingNamespaceDisplay, extractInterfaceOptions.FileName, refactoringResult.DocumentToExtractFrom.Folders, @@ -199,13 +221,13 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT var completedSolution = GetSolutionWithOriginalTypeUpdated( solutionWithFormattedInterfaceDocument, - documentIds, + symbolMapping.DocumentIds, refactoringResult.DocumentToExtractFrom.Id, - typeNodeSyntaxAnnotation, + symbolMapping.TypeNodeAnnotation, refactoringResult.TypeToExtractFrom, extractedInterfaceSymbol, extractInterfaceOptions.IncludedMembers, - symbolToDeclarationAnnotationMap, + symbolMapping.SymbolToDeclarationAnnotationMap, cancellationToken); return new ExtractInterfaceResult( @@ -219,20 +241,20 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT ExtractInterfaceOptionsResult extractInterfaceOptions, CancellationToken cancellationToken) { // Track all of the symbols we need to modify, which includes the original type declaration being modified - var (symbolToDeclarationAnnotationMap, annotatedSolution, documentIds, typeNodeSyntaxAnnotation) = CreateSymbolToDeclarationAnnotationMap( + var symbolMapping = CreateSymbolToDeclarationAnnotationMap( extractInterfaceOptions.IncludedMembers, solution, refactoringResult.TypeNode, cancellationToken); - var document = annotatedSolution.GetDocument(refactoringResult.DocumentToExtractFrom.Id); + var document = symbolMapping.AnnotatedSolution.GetDocument(refactoringResult.DocumentToExtractFrom.Id); var originalRoot = document.GetSyntaxRootSynchronously(cancellationToken); - var typeDeclaration = originalRoot.GetAnnotatedNodes(typeNodeSyntaxAnnotation).Single(); + var typeDeclaration = originalRoot.GetAnnotatedNodes(symbolMapping.TypeNodeAnnotation).Single(); var trackedDocument = document.WithSyntaxRoot(originalRoot.TrackNodes(typeDeclaration)); var currentRoot = trackedDocument.GetSyntaxRootSynchronously(cancellationToken); - var editor = new SyntaxEditor(currentRoot, annotatedSolution.Workspace); + 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(); @@ -245,10 +267,10 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT // After the interface is inserted, update the original type to show it implements the new interface var completedSolution = GetSolutionWithOriginalTypeUpdated( - unformattedSolution, documentIds, - refactoringResult.DocumentToExtractFrom.Id, typeNodeSyntaxAnnotation, + unformattedSolution, symbolMapping.DocumentIds, + refactoringResult.DocumentToExtractFrom.Id, symbolMapping.TypeNodeAnnotation, refactoringResult.TypeToExtractFrom, extractedInterfaceSymbol, - extractInterfaceOptions.IncludedMembers, symbolToDeclarationAnnotationMap, cancellationToken); + extractInterfaceOptions.IncludedMembers, symbolMapping.SymbolToDeclarationAnnotationMap, cancellationToken); return new ExtractInterfaceResult( succeeded: true, @@ -256,12 +278,7 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT navigationDocumentId: refactoringResult.DocumentToExtractFrom.Id); } - private - (Dictionary symbolToDeclarationAnnotationMap, - Solution annotatedSolution, - List documentIds, - SyntaxAnnotation typeNodeAnnotation) - CreateSymbolToDeclarationAnnotationMap( + private SymbolMapping CreateSymbolToDeclarationAnnotationMap( IEnumerable includedMembers, Solution solution, SyntaxNode typeNode, @@ -300,7 +317,7 @@ public ExtractInterfaceResult ExtractInterfaceFromAnalyzedType(ExtractInterfaceT annotatedSolution = document.WithSyntaxRoot(root.Value).Project.Solution; } - return (symbolToDeclarationAnnotationMap, annotatedSolution, documentIds, typeNodeAnnotation); + return new SymbolMapping(symbolToDeclarationAnnotationMap, annotatedSolution, documentIds, typeNodeAnnotation); } internal ExtractInterfaceOptionsResult GetExtractInterfaceOptions( diff --git a/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceCodeRefactoringProvider.cs b/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceCodeRefactoringProvider.cs index fdd55ef8a435a72f61bc6f837526a11eba8fdf14..624fcdc3d77c6a354b20d72fce571a13664b01dd 100644 --- a/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/ExtractInterface/ExtractInterfaceCodeRefactoringProvider.cs @@ -14,7 +14,7 @@ internal class ExtractInterfaceCodeRefactoringProvider : CodeRefactoringProvider public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var service = context.Document.GetLanguageService(); - var actions = await service.GetExtractInterfaceCodeAction(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false); + var actions = await service.GetExtractInterfaceCodeActionAsync(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false); context.RegisterRefactorings(actions); } }