// The rename process and annotation for the bookkeeping is performed in one-step private async Task<Solution> AnnotateAndRename_WorkerAsync( Solution originalSolution, Solution partiallyRenamedSolution, HashSet<DocumentId> documentIdsToRename, IEnumerable<RenameLocation> renameLocations, RenamedSpansTracker renameSpansTracker, bool replacementTextValid) { try { foreach (var documentId in documentIdsToRename.ToList()) { _cancellationToken.ThrowIfCancellationRequested(); // We try to rewrite all locations that are not candidate locations. If there is only one location // it must be the correct one (the symbol is ambiguous to something else) and we always try to rewrite it. var document = originalSolution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false); var originalSyntaxRoot = await semanticModel.SyntaxTree.GetRootAsync(_cancellationToken).ConfigureAwait(false); // Get all rename locations for the current document. var allTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && !l.IsRenameInStringOrComment && (renameLocations.Count() == 1 || !l.IsCandidateLocation || l.IsMethodGroupReference)) .ToDictionary(l => l.Location.SourceSpan); // All textspan in the document documentId, that requires rename in String or Comment var stringAndCommentTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && l.IsRenameInStringOrComment) .GroupBy(l => l.ContainingLocationForStringOrComment) .Select(g => g.Key) .ToSet(); var conflictLocationSpans = _conflictLocations .Where(t => t.DocumentId == documentId) .Select(t => t.ComplexifiedSpan).ToSet(); // Annotate all nodes with a RenameLocation annotations to record old locations & old referenced symbols. // Also annotate nodes that should get complexified (nodes for rename locations + conflict locations) var parameters = new RenameRewriterParameters( _renamedSymbolDeclarationAnnotation, document, semanticModel, originalSyntaxRoot, _replacementText, _originalText, _possibleNameConflicts, allTextSpansInSingleSourceTree, stringAndCommentTextSpansInSingleSourceTree, conflictLocationSpans, originalSolution, _renameLocationSet.Symbol, replacementTextValid, renameSpansTracker, _optionSet, _renameAnnotations, _cancellationToken); var renameRewriterLanguageService = document.Project.LanguageServices.GetService<IRenameRewriterLanguageService>(); var newRoot = renameRewriterLanguageService.AnnotateAndRename(parameters); if (newRoot == originalSyntaxRoot) { // Update the list for the current phase, some files with strings containing the original or replacement // text may have been filtered out. documentIdsToRename.Remove(documentId); } else { partiallyRenamedSolution = partiallyRenamedSolution.WithDocumentSyntaxRoot(documentId, newRoot, PreservationMode.PreserveIdentity); } } return partiallyRenamedSolution; } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
// The rename process and annotation for the bookkeeping is performed in one-step private async Task <Solution> AnnotateAndRename_WorkerAsync( Solution originalSolution, Solution partiallyRenamedSolution, HashSet <DocumentId> documentIdsToRename, ISet <RenameLocation> renameLocations, RenamedSpansTracker renameSpansTracker, bool replacementTextValid) { try { foreach (var documentId in documentIdsToRename.ToList()) { _cancellationToken.ThrowIfCancellationRequested(); var document = originalSolution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync(_cancellationToken).ConfigureAwait(false); var originalSyntaxRoot = await semanticModel.SyntaxTree.GetRootAsync(_cancellationToken).ConfigureAwait(false); // Get all rename locations for the current document. var allTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && ShouldIncludeLocation(renameLocations, l)) .ToDictionary(l => l.Location.SourceSpan); // All textspan in the document documentId, that requires rename in String or Comment var stringAndCommentTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && l.IsRenameInStringOrComment) .GroupBy(l => l.ContainingLocationForStringOrComment) .Select(g => g.Key) .ToSet(); var conflictLocationSpans = _conflictLocations .Where(t => t.DocumentId == documentId) .Select(t => t.ComplexifiedSpan).ToSet(); // Annotate all nodes with a RenameLocation annotations to record old locations & old referenced symbols. // Also annotate nodes that should get complexified (nodes for rename locations + conflict locations) var parameters = new RenameRewriterParameters( _renamedSymbolDeclarationAnnotation, document, semanticModel, originalSyntaxRoot, _replacementText, _originalText, _possibleNameConflicts, allTextSpansInSingleSourceTree, stringAndCommentTextSpansInSingleSourceTree, conflictLocationSpans, originalSolution, _renameLocationSet.Symbol, replacementTextValid, renameSpansTracker, _optionSet, _renameAnnotations, _cancellationToken); var renameRewriterLanguageService = document.GetLanguageService <IRenameRewriterLanguageService>(); var newRoot = renameRewriterLanguageService.AnnotateAndRename(parameters); if (newRoot == originalSyntaxRoot) { // Update the list for the current phase, some files with strings containing the original or replacement // text may have been filtered out. documentIdsToRename.Remove(documentId); } else { partiallyRenamedSolution = partiallyRenamedSolution.WithDocumentSyntaxRoot(documentId, newRoot, PreservationMode.PreserveIdentity); } } return(partiallyRenamedSolution); } catch (Exception e) when(FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
// The rename process and annotation for the bookkeeping is performed in one-step private async Task <Solution> AnnotateAndRename_WorkerAsync( Solution originalSolution, Solution partiallyRenamedSolution, HashSet <DocumentId> documentIdsToRename, IEnumerable <RenameLocation> renameLocations, RenamedSpansTracker renameSpansTracker, bool replacementTextValid) { foreach (var documentId in documentIdsToRename.ToList()) { cancellationToken.ThrowIfCancellationRequested(); // We try to rewrite all locations that are not candidate locations. If there is only one location // it must be the correct one (the symbol is ambiguous to something else) and we always try to rewrite it. var document = originalSolution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var originalSyntaxRoot = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // Get all rename locations for the current document. var allTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && !l.IsRenameInStringOrComment && (renameLocations.Count() == 1 || !l.IsCandidateLocation)) .ToDictionary(l => l.Location.SourceSpan); // All textspan in the document documentId, that requires rename in String or Comment var stringAndCommentTextSpansInSingleSourceTree = renameLocations .Where(l => l.DocumentId == documentId && l.IsRenameInStringOrComment) .GroupBy(l => l.ContainingLocationForStringOrComment) .Select(g => g.Key) .ToSet(); var conflictLocationSpans = this.conflictLocations .Where(t => t.DocumentId == documentId) .Select(t => t.ComplexifiedSpan).ToSet(); // Annotate all nodes with a RenameLocation annotations to record old locations & old referenced symbols. // Also annotate nodes that should get complexified (nodes for rename locations + conflict locations) var parameters = new RenameRewriterParameters( this.renamedSymbolDeclarationAnnotation, document, semanticModel, originalSyntaxRoot, replacementText, originalText, possibleNameConflicts, allTextSpansInSingleSourceTree, stringAndCommentTextSpansInSingleSourceTree, conflictLocationSpans, originalSolution, renameLocationSet.Symbol, replacementTextValid, cancellationToken, renameSpansTracker, optionSet, this.renameAnnotations); var renameRewriterLanguageService = LanguageService.GetService <IRenameRewriterLanguageService>(document); var newRoot = renameRewriterLanguageService.AnnotateAndRename(parameters); if (newRoot == originalSyntaxRoot) { // Update the list for the current phase, some files with strings containing the original or replacement // text may have been filtered out. documentIdsToRename.Remove(documentId); } else { partiallyRenamedSolution = partiallyRenamedSolution.WithDocumentSyntaxRoot(documentId, newRoot, PreservationMode.PreserveIdentity); } } return(partiallyRenamedSolution); }