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));
            }
예제 #2
0
 /// <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
     );
예제 #3
0
        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));
        }
예제 #5
0
        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()));
        }