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));
            }
            public SymbolInlineRenameInfo(
                IEnumerable <IRefactorNotifyService> refactorNotifyServices, Document document, TextSpan triggerSpan, ISymbol renameSymbol, CancellationToken cancellationToken)
            {
                this.CanRename = true;

                _refactorNotifyServices = refactorNotifyServices;
                _document         = document;
                this.RenameSymbol = renameSymbol;

                this.HasOverloads = RenameLocationSet.GetOverloadedSymbols(this.RenameSymbol).Any();

                _isRenamingAttributePrefix = CanRenameAttributePrefix(document, triggerSpan, cancellationToken);
                this.TriggerSpan           = GetReferenceEditSpan(new InlineRenameLocation(document, triggerSpan), cancellationToken);

                _shortenedTriggerSpan = this.TriggerSpan != triggerSpan;
            }
Ejemplo n.º 3
0
        /// <summary>
        /// Performs the renaming of the symbol in the solution, identifies renaming conflicts and automatically resolves them where possible.
        /// </summary>
        /// <param name="renameLocationSet">The locations to perform the renaming at.</param>
        /// <param name="originalText">The original name of the identifier.</param>
        /// <param name="replacementText">The new name of the identifier</param>
        /// <param name="optionSet">The option for rename</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A conflict resolution containing the new solution.</returns>
        public static Task<ConflictResolution> ResolveConflictsAsync(
            RenameLocationSet renameLocationSet,
            string originalText,
            string replacementText,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // when someone e.g. renames a symbol from metadata through the API (IDE blocks this), we need to return
            var renameSymbolDeclarationLocation = renameLocationSet.Symbol.Locations.Where(loc => loc.IsInSource).FirstOrDefault();
            if (renameSymbolDeclarationLocation == null)
            {
                // Symbol "{0}" is not from source.
                throw new ArgumentException(string.Format(WorkspacesResources.RenameSymbolIsNotFromSource, renameLocationSet.Symbol.Name));
            }

            var session = new Session(renameLocationSet, renameSymbolDeclarationLocation, originalText, replacementText, optionSet, cancellationToken);
            return session.ResolveConflictsAsync();
        }
Ejemplo n.º 4
0
            public Session(RenameLocationSet renameLocationSet, Location renameSymbolDeclarationLocation, string originalText, string replacementText, OptionSet optionSet, CancellationToken cancellationToken)
            {
                _renameLocationSet = renameLocationSet;
                _renameSymbolDeclarationLocation = renameSymbolDeclarationLocation;
                _originalText = originalText;
                _replacementText = replacementText;
                _optionSet = optionSet;
                _cancellationToken = cancellationToken;

                _renamedSymbolDeclarationAnnotation = new RenameAnnotation();

                _conflictLocations = SpecializedCollections.EmptySet<ConflictLocationInfo>();
                _replacementTextValid = true;
                _possibleNameConflicts = new List<string>();

                // only process documents which possibly contain the identifiers.
                _documentsIdsToBeCheckedForConflict = new HashSet<DocumentId>();
                _documentIdOfRenameSymbolDeclaration = renameLocationSet.Solution.GetDocument(renameSymbolDeclarationLocation.SourceTree).Id;

                _renameAnnotations = new AnnotationTable<RenameAnnotation>(RenameAnnotation.Kind);
            }
Ejemplo n.º 5
0
            public Session(RenameLocationSet renameLocationSet, Location renameSymbolDeclarationLocation, string originalText, string replacementText, OptionSet optionSet, CancellationToken cancellationToken)
            {
                _renameLocationSet = renameLocationSet;
                _renameSymbolDeclarationLocation = renameSymbolDeclarationLocation;
                _originalText      = originalText;
                _replacementText   = replacementText;
                _optionSet         = optionSet;
                _cancellationToken = cancellationToken;

                _renamedSymbolDeclarationAnnotation = new RenameAnnotation();

                _conflictLocations     = SpecializedCollections.EmptySet <ConflictLocationInfo>();
                _replacementTextValid  = true;
                _possibleNameConflicts = new List <string>();

                // only process documents which possibly contain the identifiers.
                _documentsIdsToBeCheckedForConflict  = new HashSet <DocumentId>();
                _documentIdOfRenameSymbolDeclaration = renameLocationSet.Solution.GetDocument(renameSymbolDeclarationLocation.SourceTree).Id;

                _renameAnnotations = new AnnotationTable <RenameAnnotation>(RenameAnnotation.Kind);
            }
Ejemplo n.º 6
0
        /// <summary>
        /// Performs the renaming of the symbol in the solution, identifies renaming conflicts and automatically resolves them where possible.
        /// </summary>
        /// <param name="renameLocationSet">The locations to perform the renaming at.</param>
        /// <param name="originalText">The original name of the identifier.</param>
        /// <param name="replacementText">The new name of the identifier</param>
        /// <param name="optionSet">The option for rename</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A conflict resolution containing the new solution.</returns>
        public static Task <ConflictResolution> ResolveConflictsAsync(
            RenameLocationSet renameLocationSet,
            string originalText,
            string replacementText,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // when someone e.g. renames a symbol from metadata through the API (IDE blocks this), we need to return
            var renameSymbolDeclarationLocation = renameLocationSet.Symbol.Locations.Where(loc => loc.IsInSource).FirstOrDefault();

            if (renameSymbolDeclarationLocation == null)
            {
                // Symbol "{0}" is not from source.
                throw new ArgumentException(string.Format(WorkspacesResources.RenameSymbolIsNotFromSource, renameLocationSet.Symbol.Name));
            }

            var session = new Session(renameLocationSet, renameSymbolDeclarationLocation, originalText, replacementText, optionSet, cancellationToken);

            return(session.ResolveConflictsAsync());
        }
Ejemplo n.º 7
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()));
        }
 public InlineRenameLocationSet(SymbolInlineRenameInfo renameInfo, RenameLocationSet renameLocationSet)
 {
     _renameInfo        = renameInfo;
     _renameLocationSet = renameLocationSet;
     this.Locations     = renameLocationSet.Locations.Where(l => !l.IsCandidateLocation).Select(ConvertLocation).ToList();
 }