public async Task <IInlineRenameReplacementInfo> GetReplacementsAsync(string replacementText, OptionSet optionSet, CancellationToken cancellationToken) { var conflicts = await ConflictResolver.ResolveConflictsAsync( _renameLocationSet, _renameLocationSet.Symbol.Name, _renameInfo.GetFinalSymbolName(replacementText), optionSet, cancellationToken).ConfigureAwait(false); return(new InlineRenameReplacementInfo(conflicts)); }
/// <summary> /// Performs the renaming of the symbol in the solution, identifies renaming conflicts and automatically /// resolves them where possible. /// </summary> /// <param name="replacementText">The new name of the identifier</param> /// <param name="nonConflictSymbols">Used after renaming references. References that now bind to any of these /// symbols are not considered to be in conflict. Useful for features that want to rename existing references to /// point at some existing symbol. Normally this would be a conflict, but this can be used to override that /// behavior.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A conflict resolution containing the new solution.</returns> public Task <ConflictResolution> ResolveConflictsAsync( string replacementText, ImmutableHashSet <ISymbol>?nonConflictSymbols = null, CancellationToken cancellationToken = default ) => ConflictResolver.ResolveConflictsAsync( this, replacementText, nonConflictSymbols, cancellationToken );
internal static async Task <Solution> RenameAsync( RenameLocations locations, string newName, ImmutableHashSet <ISymbol> nonConflictSymbols = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(newName)) { throw new ArgumentException(nameof(newName)); } cancellationToken.ThrowIfCancellationRequested(); var conflictResolution = await ConflictResolver.ResolveConflictsAsync( locations, newName, nonConflictSymbols, cancellationToken).ConfigureAwait(false); return(conflictResolution.NewSolution); }
public Task <SerializableConflictResolution> ResolveConflictsAsync( PinnedSolutionInfo solutionInfo, SerializableRenameLocations renameLocationSet, string replacementText, SerializableSymbolAndProjectId[] nonConflictSymbolIds, CancellationToken cancellationToken) { return(RunServiceAsync <SerializableConflictResolution>(async() => { using (UserOperationBooster.Boost()) { var solution = await GetSolutionAsync(solutionInfo, cancellationToken).ConfigureAwait(false); var nonConflictSymbols = await GetNonConflictSymbolsAsync(solution, nonConflictSymbolIds, cancellationToken).ConfigureAwait(false); var result = await ConflictResolver.ResolveConflictsAsync( await RenameLocations.RehydrateAsync(solution, renameLocationSet, cancellationToken).ConfigureAwait(false), replacementText, nonConflictSymbols, cancellationToken).ConfigureAwait(false); return await result.DehydrateAsync(cancellationToken).ConfigureAwait(false); } }, cancellationToken)); }
private async Task <Result> EncapsulateFieldAsync(IFieldSymbol field, Document document, bool updateReferences, CancellationToken cancellationToken) { var originalField = field; var finalNames = GeneratePropertyAndFieldNames(field); var finalFieldName = finalNames.Item1; var generatedPropertyName = finalNames.Item2; // Annotate the field declarations so we can find it after rename. var fieldDeclaration = field.DeclaringSyntaxReferences.First(); var declarationAnnotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot(fieldDeclaration.SyntaxTree.GetRoot().ReplaceNode(fieldDeclaration.GetSyntax(), fieldDeclaration.GetSyntax().WithAdditionalAnnotations(declarationAnnotation))); var solution = document.Project.Solution; foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { var linkedDocument = solution.GetDocument(linkedDocumentId); var linkedRoot = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var linkedFieldNode = linkedRoot.FindNode(fieldDeclaration.Span); if (linkedFieldNode.Span != fieldDeclaration.Span) { continue; } var updatedRoot = linkedRoot.ReplaceNode(linkedFieldNode, linkedFieldNode.WithAdditionalAnnotations(declarationAnnotation)); solution = solution.WithDocumentSyntaxRoot(linkedDocumentId, updatedRoot); } document = solution.GetDocument(document.Id); // Resolve the annotated symbol and prepare for rename. var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var compilation = semanticModel.Compilation; field = field.GetSymbolKey().Resolve(compilation).Symbol as IFieldSymbol; Solution solutionNeedingProperty = null; // We couldn't resolve field after annotating its declaration. Bail if (field == null) { return(null); } if (updateReferences) { var locationsToIgnore = SpecializedCollections.EmptySet <TextSpan>(); var optionSet = document.Project.Solution.Workspace.Options; if (field.IsReadOnly) { var locationSet = await RenameLocationSet.FindAsync(field, document.Project.Solution, optionSet, cancellationToken).ConfigureAwait(false); var constructorSyntaxes = GetConstructorNodes(field.ContainingType); var locations = locationSet.Locations.Where(l => constructorSyntaxes.Any(c => c.Span.IntersectsWith(l.Location.SourceSpan))); if (locations.Any()) { locationsToIgnore = locations.Select(l => l.Location.SourceSpan).ToSet(); locationSet = new RenameLocationSet(locations.ToSet(), field, document.Project.Solution, locationSet.ReferencedSymbols, locationSet.ImplicitLocations); var resolution = await ConflictResolver.ResolveConflictsAsync(locationSet, field.Name, finalFieldName, optionSet, cancellationToken).ConfigureAwait(false); document = resolution.NewSolution.GetDocument(document.Id); semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); compilation = semanticModel.Compilation; field = field.GetSymbolKey().Resolve(compilation).Symbol as IFieldSymbol; } } var renameLocationSet = await RenameLocationSet.FindAsync(field, document.Project.Solution, optionSet, cancellationToken).ConfigureAwait(false); renameLocationSet = new RenameLocationSet(renameLocationSet.Locations.Where(l => !locationsToIgnore.Contains(l.Location.SourceSpan)).ToSet(), renameLocationSet.Symbol, renameLocationSet.Solution, renameLocationSet.ReferencedSymbols, renameLocationSet.ImplicitLocations); if (renameLocationSet.Locations.Any() || renameLocationSet.ImplicitLocations.Any()) { var conflictResolution = await ConflictResolver.ResolveConflictsAsync(renameLocationSet, field.Name, generatedPropertyName, optionSet, cancellationToken).ConfigureAwait(false); if (!conflictResolution.ReplacementTextValid) { return(null); } solutionNeedingProperty = conflictResolution.NewSolution; document = solutionNeedingProperty.GetDocument(document.Id); } } else { solutionNeedingProperty = document.Project.Solution; document = solutionNeedingProperty.GetDocument(document.Id); } var markFieldPrivate = field.DeclaredAccessibility != Accessibility.Private; var rewrittenFieldDeclaration = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, document, declarationAnnotation, cancellationToken).ConfigureAwait(false); document = await Formatter.FormatAsync(document.WithSyntaxRoot(rewrittenFieldDeclaration), Formatter.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); solution = document.Project.Solution; foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { var linkedDocument = solution.GetDocument(linkedDocumentId); var updatedLinkedRoot = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, linkedDocument, declarationAnnotation, cancellationToken).ConfigureAwait(false); var updatedLinkedDocument = await Formatter.FormatAsync(linkedDocument.WithSyntaxRoot(updatedLinkedRoot), Formatter.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); solution = updatedLinkedDocument.Project.Solution; } document = solution.GetDocument(document.Id); semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); compilation = semanticModel.Compilation; var newRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newDeclaration = newRoot.GetAnnotatedNodes <SyntaxNode>(declarationAnnotation).First(); field = semanticModel.GetDeclaredSymbol(newDeclaration, cancellationToken) as IFieldSymbol; var generatedProperty = GenerateProperty(generatedPropertyName, finalFieldName, originalField.DeclaredAccessibility, originalField, field.ContainingType, new SyntaxAnnotation(), document, cancellationToken); var codeGenerationService = document.GetLanguageService <ICodeGenerationService>(); var solutionWithProperty = await AddPropertyAsync(document, document.Project.Solution, field, generatedProperty, cancellationToken).ConfigureAwait(false); return(new Result(solutionWithProperty, originalField.ToDisplayString(), originalField.GetGlyph())); }