public Task <IInlineRenameLocationSet> FindRenameLocationsAsync(OptionSet optionSet, CancellationToken cancellationToken)
            {
                Task <RenameLocationSet> renameTask;

                lock (_gate)
                {
                    if (_underlyingFindRenameLocationsTask == null)
                    {
                        // If this is the first call, then just start finding the initial set of rename
                        // locations.
                        _underlyingFindRenameLocationsTask = RenameLocationSet.FindAsync(
                            this.RenameSymbol, _document.Project.Solution, optionSet, cancellationToken);
                        renameTask = _underlyingFindRenameLocationsTask;

                        // null out the option set.  We don't need it anymore, and this will ensure
                        // we don't call FindWithUpdatedOptionsAsync below.
                        optionSet = null;
                    }
                    else
                    {
                        // We already have a task to figure out the set of rename locations.  Let it
                        // finish, then ask it to get the rename locations with the updated options.
                        renameTask = _underlyingFindRenameLocationsTask;
                    }
                }

                return(GetLocationSet(renameTask, optionSet, cancellationToken));
            }
Beispiel #2
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()));
        }