Ejemplo n.º 1
0
 internal ReferencedSymbol(
     SymbolAndProjectId definitionAndProjectId,
     IEnumerable<ReferenceLocation> locations)
 {
     this.DefinitionAndProjectId = definitionAndProjectId;
     this.Locations = (locations ?? SpecializedCollections.EmptyEnumerable<ReferenceLocation>()).ToReadOnlyCollection();
 }
Ejemplo n.º 2
0
        private static Task<ImmutableArray<SymbolAndProjectId<INamedTypeSymbol>>> FindDerivedClassesAsync(
            SymbolAndProjectId<INamedTypeSymbol> type,
            Solution solution,
            IImmutableSet<Project> projects, 
            bool transitive,
            CancellationToken cancellationToken)
        {
            if (s_isNonSealedClass(type.Symbol))
            {
                Func<SymbolAndProjectIdSet, INamedTypeSymbol, bool> metadataTypeMatches =
                    (set, metadataType) => TypeDerivesFrom(set, metadataType, transitive);

                Func<SymbolAndProjectIdSet, INamedTypeSymbol, bool> sourceTypeImmediatelyMatches =
                    (set, metadataType) => set.Contains(SymbolAndProjectId.Create(metadataType.BaseType?.OriginalDefinition, projectId: null));

                return FindTypesAsync(type, solution, projects,
                    metadataTypeMatches: metadataTypeMatches,
                    sourceTypeImmediatelyMatches: sourceTypeImmediatelyMatches,
                    shouldContinueSearching: s_isNonSealedClass,
                    transitive: transitive,
                    cancellationToken: cancellationToken);
            }

            return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId<INamedTypeSymbol>>();
        }
 public Task OnReferenceFoundAsync(
     SymbolAndProjectId definition, ReferenceLocation reference)
 {
     return _service.Rpc.InvokeAsync(nameof(OnReferenceFoundAsync),
         SerializableSymbolAndProjectId.Dehydrate(definition),
         SerializableReferenceLocation.Dehydrate(reference));
 }
Ejemplo n.º 4
0
        private static async Task FindReferencesInServiceProcessAsync(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            IStreamingFindReferencesProgress progress,
            IImmutableSet<Document> documents,
            CancellationToken cancellationToken)
        {
            var client = await solution.Workspace.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
            if (client == null)
            {
                await FindReferencesInCurrentProcessAsync(
                    symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
                return;
            }

            // Create a callback that we can pass to the server process to hear about the 
            // results as it finds them.  When we hear about results we'll forward them to
            // the 'progress' parameter which will then upate the UI.
            var serverCallback = new ServerCallback(solution, progress, cancellationToken);

            using (var session = await client.CreateCodeAnalysisServiceSessionAsync(
                solution, serverCallback, cancellationToken).ConfigureAwait(false))
            {
                await session.InvokeAsync(
                    nameof(IRemoteSymbolFinder.FindReferencesAsync),
                    SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId),
                    documents?.Select(SerializableDocumentId.Dehydrate).ToArray()).ConfigureAwait(false);
            }
        }
        public Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location)
        {
            lock (_gate)
            {
                _symbolToLocations[definition].Add(location);
            }

            return _underlyingProgress.OnReferenceFoundAsync(definition, location);
        }
        public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
        {
            lock (_gate)
            {
                _symbolToLocations[definition] = new List<ReferenceLocation>();
            }

            return _underlyingProgress.OnDefinitionFoundAsync(definition);
        }
 internal static Task FindReferencesAsync(
     SymbolAndProjectId symbolAndProjectId,
     Solution solution,
     IStreamingFindReferencesProgress progress,
     IImmutableSet<Document> documents,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     var engineService = solution.Workspace.Services.GetService<ISymbolFinderEngineService>();
     return engineService.FindReferencesAsync(symbolAndProjectId, solution, progress, documents, cancellationToken);
 }
Ejemplo n.º 8
0
 internal static Task FindReferencesInCurrentProcessAsync(
     SymbolAndProjectId symbolAndProjectId, Solution solution,
     IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents,
     CancellationToken cancellationToken)
 {
     var finders = ReferenceFinders.DefaultReferenceFinders;
     progress = progress ?? StreamingFindReferencesProgress.Instance;
     var engine = new FindReferencesSearchEngine(
         solution, documents, finders, progress, cancellationToken);
     return engine.FindReferencesAsync(symbolAndProjectId);
 }
 public async Task FindReferencesAsync(
     SymbolAndProjectId symbolAndProjectId, Solution solution, 
     IStreamingFindReferencesProgress progress, IImmutableSet<Document> documents, 
     CancellationToken cancellationToken)
 {
     using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
     {
         await FindReferencesInCurrentProcessAsync(
             symbolAndProjectId, solution, progress, 
             documents, cancellationToken).ConfigureAwait(false);
     }
 }
Ejemplo n.º 10
0
 internal RenameLocations(
     ISet<RenameLocation> locations, 
     SymbolAndProjectId symbolAndProjectId, 
     Solution solution, 
     IEnumerable<SymbolAndProjectId> referencedSymbols, 
     IEnumerable<ReferenceLocation> implicitLocations, 
     OptionSet options)
 {
     _symbolAndProjectId = symbolAndProjectId;
     _solution = solution;
     _mergedResult = new SearchResult(locations, implicitLocations, referencedSymbols);
     Options = options;
 }
Ejemplo n.º 11
0
        public async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
            SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var linkedSymbols = new HashSet<SymbolAndProjectId>();

            var symbol = symbolAndProjectId.Symbol;
            foreach (var location in symbol.DeclaringSyntaxReferences)
            {
                var originalDocument = solution.GetDocument(location.SyntaxTree);

                // GetDocument will return null for locations in #load'ed trees.
                // TODO:  Remove this check and add logic to fetch the #load'ed tree's
                // Document once https://github.com/dotnet/roslyn/issues/5260 is fixed.
                if (originalDocument == null)
                {
                    Debug.Assert(solution.Workspace.Kind == "Interactive");
                    continue;
                }

                foreach (var linkedDocumentId in originalDocument.GetLinkedDocumentIds())
                {
                    var linkedDocument = solution.GetDocument(linkedDocumentId);
                    var linkedSyntaxRoot = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                    // Defend against constructed solutions with inconsistent linked documents
                    if (!linkedSyntaxRoot.FullSpan.Contains(location.Span))
                    {
                        continue;
                    }

                    var linkedNode = linkedSyntaxRoot.FindNode(location.Span, getInnermostNodeForTie: true);

                    var semanticModel = await linkedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                    var linkedSymbol = semanticModel.GetDeclaredSymbol(linkedNode, cancellationToken);

                    if (linkedSymbol != null &&
                        linkedSymbol.Kind == symbol.Kind &&
                        linkedSymbol.Name == symbol.Name)
                    {
                        var linkedSymbolAndProjectId = SymbolAndProjectId.Create(linkedSymbol, linkedDocument.Project.Id);
                        if (!linkedSymbols.Contains(linkedSymbolAndProjectId))
                        {
                            linkedSymbols.Add(linkedSymbolAndProjectId);
                        }
                    }
                }
            }

            return linkedSymbols.ToImmutableArray();
        }
            public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location)
            {
                // Ignore duplicate locations.  We don't want to clutter the UI with them.
                if (location.IsDuplicateReferenceLocation)
                {
                    return;
                }

                var referenceItem = location.TryCreateSourceReferenceItem(
                    GetDefinitionItem(definition), includeHiddenLocations: false);

                if (referenceItem != null)
                {
                    await _context.OnReferenceFoundAsync(referenceItem).ConfigureAwait(false);
                }
            }
Ejemplo n.º 13
0
        private RenameLocations(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            OptionSet options,
            SearchResult originalSymbolResult,
            List<SearchResult> overloadsResult,
            IEnumerable<RenameLocation> stringsResult,
            IEnumerable<RenameLocation> commentsResult)
        {
            _symbolAndProjectId = symbolAndProjectId;
            _solution = solution;
            Options = options;
            _originalSymbolResult = originalSymbolResult;
            _overloadsResult = overloadsResult;
            _stringsResult = stringsResult;
            _commentsResult = commentsResult;

            var mergedLocations = new HashSet<RenameLocation>();
            var mergedReferencedSymbols = new List<SymbolAndProjectId>();
            var mergedImplicitLocations = new List<ReferenceLocation>();

            if (options.GetOption(RenameOptions.RenameInStrings))
            {
                mergedLocations.AddRange(stringsResult);
            }

            if (options.GetOption(RenameOptions.RenameInComments))
            {
                mergedLocations.AddRange(commentsResult);
            }

            var renameMethodGroupReferences = 
                options.GetOption(RenameOptions.RenameOverloads) || !GetOverloadedSymbols(symbolAndProjectId).Any();
            var overloadsToMerge = (options.GetOption(RenameOptions.RenameOverloads) ? overloadsResult : null) ?? SpecializedCollections.EmptyEnumerable<SearchResult>();
            foreach (var result in overloadsToMerge.Concat(originalSymbolResult))
            {
                mergedLocations.AddRange(renameMethodGroupReferences
                    ? result.Locations
                    : result.Locations.Where(x => !x.IsMethodGroupReference));

                mergedImplicitLocations.AddRange(result.ImplicitLocations);
                mergedReferencedSymbols.AddRange(result.ReferencedSymbols);
            }

            _mergedResult = new SearchResult(mergedLocations, mergedImplicitLocations, mergedReferencedSymbols);
        }
Ejemplo n.º 14
0
        public async Task FindReferencesAsync(SymbolAndProjectId symbolAndProjectId)
        {
            await _progress.OnStartedAsync().ConfigureAwait(false);
            await _progressTracker.AddItemsAsync(1).ConfigureAwait(false);
            try
            {
                var symbols = await DetermineAllSymbolsAsync(symbolAndProjectId).ConfigureAwait(false);

                var projectMap = await CreateProjectMapAsync(symbols).ConfigureAwait(false);
                var documentMap = await CreateDocumentMapAsync(projectMap).ConfigureAwait(false);
                await ProcessAsync(documentMap).ConfigureAwait(false);
            }
            finally
            {
                await _progressTracker.ItemCompletedAsync().ConfigureAwait(false);
                await _progress.OnCompletedAsync().ConfigureAwait(false);
            }
        }
Ejemplo n.º 15
0
        internal static async Task<IEnumerable<SymbolAndProjectId>> FindOverridesAsync(
            SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Method can only have overrides if its a virtual, abstract or override and is not
            // sealed.
            var symbol = symbolAndProjectId.Symbol;
            if (symbol.IsOverridable())
            {
                // To find the overrides, we need to walk down the type hierarchy and check all
                // derived types.  TODO(cyrusn): This seems extremely costly.  Is there any way to
                // speed this up?
                var containingType = symbol.ContainingType.OriginalDefinition;
                var derivedTypes = await FindDerivedClassesAsync(
                    symbolAndProjectId.WithSymbol(containingType),
                    solution, projects, cancellationToken).ConfigureAwait(false);

                List<SymbolAndProjectId> results = null;
                foreach (var type in derivedTypes)
                {
                    foreach (var m in GetMembers(type, symbol.Name))
                    {
                        var sourceMember = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false);
                        var bestMember = sourceMember.Symbol != null ? sourceMember : m;
                        var member = bestMember.Symbol;
                        if (member != null &&
                            member.IsOverride &&
                            member.OverriddenMember() != null &&
                            OriginalSymbolsMatch(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition, solution, cancellationToken))
                        {
                            results = results ?? new List<SymbolAndProjectId>();
                            results.Add(bestMember);
                        }
                    }
                }

                if (results != null)
                {
                    return results;
                }
            }

            return SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
        }
 public async Task FindReferencesAsync(
     SymbolAndProjectId symbolAndProjectId, Solution solution, 
     IStreamingFindReferencesProgress progress,
     IImmutableSet<Document> documents, CancellationToken cancellationToken)
 {
     using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
     {
         if (symbolAndProjectId.ProjectId == null)
         {
             // This is a call through our old public API.  We don't have the necessary
             // data to effectively run the call out of proc.
             await DefaultSymbolFinderEngineService.FindReferencesInCurrentProcessAsync(
                 symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
         }
         else
         {
             await FindReferencesInServiceProcessAsync(
                 symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
         }
     }
 }
 private async Task ProcessDocumentAsync(
     Document document,
     SymbolAndProjectId symbolAndProjectId,
     IReferenceFinder finder)
 {
     using (Logger.LogBlock(FunctionId.FindReference_ProcessDocumentAsync, s_logDocument, document, symbolAndProjectId.Symbol, _cancellationToken))
     {
         try
         {
             var references = await finder.FindReferencesInDocumentAsync(symbolAndProjectId, document, _cancellationToken).ConfigureAwait(false);
             foreach (var location in references)
             {
                 await HandleLocationAsync(symbolAndProjectId, location).ConfigureAwait(false);
             }
         }
         finally
         {
             await _progressTracker.ItemCompletedAsync().ConfigureAwait(false);
         }
     }
 }
            public SymbolInlineRenameInfo(
                IEnumerable<IRefactorNotifyService> refactorNotifyServices,
                Document document,
                TextSpan triggerSpan,
                SymbolAndProjectId renameSymbolAndProjectId,
                bool forceRenameOverloads,
                CancellationToken cancellationToken)
            {
                this.CanRename = true;

                _refactorNotifyServices = refactorNotifyServices;
                _document = document;
                this.RenameSymbolAndProjectId = renameSymbolAndProjectId;

                this.HasOverloads = RenameLocations.GetOverloadedSymbols(this.RenameSymbolAndProjectId).Any();
                this.ForceRenameOverloads = forceRenameOverloads;

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

                _shortenedTriggerSpan = this.TriggerSpan != triggerSpan;
            }
Ejemplo n.º 19
0
        internal static async Task<ImmutableArray<ReferencedSymbol>> FindRenamableReferencesAsync(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.FindReference_Rename, cancellationToken))
            {
                var streamingProgress = new StreamingProgressCollector(
                    StreamingFindReferencesProgress.Instance);

                IImmutableSet<Document> documents = null;
                var engine = new FindReferencesSearchEngine(
                    solution,
                    documents,
                    ReferenceFinders.DefaultRenameReferenceFinders,
                    streamingProgress,
                    cancellationToken);

                await engine.FindReferencesAsync(symbolAndProjectId).ConfigureAwait(false);
                return streamingProgress.GetReferencedSymbols();
            }
        }
        private async Task<ImmutableArray<DocumentHighlights>> GetTagsForReferencedSymbolAsync(
            SymbolAndProjectId symbolAndProjectId,
            IImmutableSet<Document> documentsToSearch,
            Solution solution,
            CancellationToken cancellationToken)
        {
            var symbol = symbolAndProjectId.Symbol;
            Contract.ThrowIfNull(symbol);
            if (ShouldConsiderSymbol(symbol))
            {
                var progress = new StreamingProgressCollector(
                    StreamingFindReferencesProgress.Instance);
                await SymbolFinder.FindReferencesAsync(
                    symbolAndProjectId, solution, progress,
                    documentsToSearch, cancellationToken).ConfigureAwait(false);

                return await FilterAndCreateSpansAsync(
                    progress.GetReferencedSymbols(), solution, documentsToSearch, 
                    symbol, cancellationToken).ConfigureAwait(false);
            }

            return ImmutableArray<DocumentHighlights>.Empty;
        }
Ejemplo n.º 21
0
 private Task HandleLocationAsync(SymbolAndProjectId symbolAndProjectId, ReferenceLocation location)
 {
     return _progress.OnReferenceFoundAsync(symbolAndProjectId, location);
 }
Ejemplo n.º 22
0
        private async Task <Solution> ProcessResultAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var locations          = diagnostic.AdditionalLocations;
            var propertyLocation   = locations[0];
            var declaratorLocation = locations[1];

            var declarator         = declaratorLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TVariableDeclarator>();
            var fieldDocument      = context.Document.Project.GetDocument(declarator.SyntaxTree);
            var fieldSemanticModel = await fieldDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var fieldSymbol = (IFieldSymbol)fieldSemanticModel.GetDeclaredSymbol(declarator);

            var property              = propertyLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TPropertyDeclaration>();
            var propertyDocument      = context.Document.Project.GetDocument(property.SyntaxTree);
            var propertySemanticModel = await propertyDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var propertySymbol = (IPropertySymbol)propertySemanticModel.GetDeclaredSymbol(property);

            Debug.Assert(fieldDocument.Project == propertyDocument.Project);
            var project     = fieldDocument.Project;
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            var solution       = context.Document.Project.Solution;
            var fieldLocations = await Renamer.GetRenameLocationsAsync(
                solution, SymbolAndProjectId.Create(fieldSymbol, fieldDocument.Project.Id),
                solution.Options, cancellationToken).ConfigureAwait(false);

            // First, create the updated property we want to replace the old property with
            var isWrittenToOutsideOfConstructor = IsWrittenToOutsideOfConstructorOrProperty(fieldSymbol, fieldLocations, property, cancellationToken);
            var updatedProperty = await UpdatePropertyAsync(
                propertyDocument, compilation, fieldSymbol, propertySymbol, property,
                isWrittenToOutsideOfConstructor, cancellationToken).ConfigureAwait(false);

            // Note: rename will try to update all the references in linked files as well.  However,
            // this can lead to some very bad behavior as we will change the references in linked files
            // but only remove the field and update the property in a single document.  So, you can
            // end in the state where you do this in one of the linked file:
            //
            //      int Prop { get { return this.field; } } => int Prop { get { return this.Prop } }
            //
            // But in the main file we'll replace:
            //
            //      int Prop { get { return this.field; } } => int Prop { get; }
            //
            // The workspace will see these as two irreconcilable edits.  To avoid this, we disallow
            // any edits to the other links for the files containing the field and property.  i.e.
            // rename will only be allowed to edit the exact same doc we're removing the field from
            // and the exact doc we're updating the property in.  It can't touch the other linked
            // files for those docs.  (It can of course touch any other documents unrelated to the
            // docs that the field and prop are declared in).
            var linkedFiles = new HashSet <DocumentId>();

            linkedFiles.AddRange(fieldDocument.GetLinkedDocumentIds());
            linkedFiles.AddRange(propertyDocument.GetLinkedDocumentIds());

            var canEdit = new Dictionary <SyntaxTree, bool>();

            // Now, rename all usages of the field to point at the property.  Except don't actually
            // rename the field itself.  We want to be able to find it again post rename.
            var updatedSolution = await Renamer.RenameAsync(fieldLocations, propertySymbol.Name,
                                                            location => !location.SourceSpan.IntersectsWith(declaratorLocation.SourceSpan) &&
                                                            CanEditDocument(solution, location.SourceTree, linkedFiles, canEdit),
                                                            symbols => HasConflict(symbols, propertySymbol, compilation, cancellationToken),
                                                            cancellationToken).ConfigureAwait(false);

            solution = updatedSolution;

            // Now find the field and property again post rename.
            fieldDocument    = solution.GetDocument(fieldDocument.Id);
            propertyDocument = solution.GetDocument(propertyDocument.Id);
            Debug.Assert(fieldDocument.Project == propertyDocument.Project);

            compilation = await fieldDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            fieldSymbol    = (IFieldSymbol)fieldSymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol;
            propertySymbol = (IPropertySymbol)propertySymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol;
            Debug.Assert(fieldSymbol != null && propertySymbol != null);

            declarator = (TVariableDeclarator)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
            var temp = await propertySymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);

            property = temp.FirstAncestorOrSelf <TPropertyDeclaration>();

            var nodeToRemove = GetNodeToRemove(declarator);

            // If we have a situation where the property is the second member in a type, and it
            // would become the first, then remove any leading blank lines from it so we don't have
            // random blanks above it that used to space it from the field that was there.
            //
            // The reason we do this special processing is that the first member of a type tends to
            // be special wrt leading trivia. i.e. users do not normally put blank lines before the
            // first member. And so, when a type now becomes the first member, we want to follow the
            // user's common pattern here.
            //
            // In all other code cases, i.e.when there are multiple fields above, or the field is
            // below the property, then the property isn't now becoming "the first member", and as
            // such, it doesn't want this special behavior about it's leading blank lines. i.e. if
            // the user has:
            //
            //  class C
            //  {
            //      int i;
            //      int j;
            //
            //      int Prop => j;
            //  }
            //
            // Then if we remove 'j' (or even 'i'), then 'Prop' would stay the non-first member, and
            // would definitely want to keep that blank line above it.
            //
            // In essence, the blank line above the property exists for separation from what's above
            // it. As long as something is above it, we keep the separation. However, if the
            // property becomes the first member in the type, the separation is now inappropriate
            // because there's nothing to actually separate it from.
            if (fieldDocument == propertyDocument)
            {
                var syntaxFacts = fieldDocument.GetLanguageService <ISyntaxFactsService>();
                if (WillRemoveFirstFieldInTypeDirectlyAboveProperty(syntaxFacts, property, nodeToRemove) &&
                    syntaxFacts.GetLeadingBlankLines(nodeToRemove).Length == 0)
                {
                    updatedProperty = syntaxFacts.GetNodeWithoutLeadingBlankLines(updatedProperty);
                }
            }

            var syntaxRemoveOptions = CreateSyntaxRemoveOptions(nodeToRemove);

            if (fieldDocument == propertyDocument)
            {
                // Same file.  Have to do this in a slightly complicated fashion.
                var declaratorTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var editor = new SyntaxEditor(declaratorTreeRoot, fieldDocument.Project.Solution.Workspace);
                editor.ReplaceNode(property, updatedProperty);
                editor.RemoveNode(nodeToRemove, syntaxRemoveOptions);

                var newRoot = editor.GetChangedRoot();
                newRoot = Format(newRoot, fieldDocument, cancellationToken);

                return(solution.WithDocumentSyntaxRoot(fieldDocument.Id, newRoot));
            }
            else
            {
                // In different files.  Just update both files.
                var fieldTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var propertyTreeRoot = await propertyDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var newFieldTreeRoot    = fieldTreeRoot.RemoveNode(nodeToRemove, syntaxRemoveOptions);
                var newPropertyTreeRoot = propertyTreeRoot.ReplaceNode(property, updatedProperty);

                newFieldTreeRoot    = Format(newFieldTreeRoot, fieldDocument, cancellationToken);
                newPropertyTreeRoot = Format(newPropertyTreeRoot, propertyDocument, cancellationToken);

                updatedSolution = solution.WithDocumentSyntaxRoot(fieldDocument.Id, newFieldTreeRoot);
                updatedSolution = updatedSolution.WithDocumentSyntaxRoot(propertyDocument.Id, newPropertyTreeRoot);

                return(updatedSolution);
            }
        }
        private async Task DetermineAllSymbolsCoreAsync(
            SymbolAndProjectId symbolAndProjectId, ConcurrentSet<SymbolAndProjectId> result)
        {
            _cancellationToken.ThrowIfCancellationRequested();

            var searchSymbolAndProjectId = MapToAppropriateSymbol(symbolAndProjectId);

            // 2) Try to map this back to source symbol if this was a metadata symbol.
            var sourceSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync(searchSymbolAndProjectId, _solution, _cancellationToken).ConfigureAwait(false);
            if (sourceSymbolAndProjectId.Symbol != null)
            {
                searchSymbolAndProjectId = sourceSymbolAndProjectId;
            }

            var searchSymbol = searchSymbolAndProjectId.Symbol;
            if (searchSymbol != null && result.Add(searchSymbolAndProjectId))
            {
                await _progress.OnDefinitionFoundAsync(searchSymbolAndProjectId).ConfigureAwait(false);

                // get project to search
                var projects = GetProjectScope();

                _cancellationToken.ThrowIfCancellationRequested();

                List<Task> finderTasks = new List<Task>();
                foreach (var f in _finders)
                {
                    finderTasks.Add(Task.Run(async () =>
                    {
                        var symbolTasks = new List<Task>();

                        var symbols = await f.DetermineCascadedSymbolsAsync(
                            searchSymbolAndProjectId, _solution, projects, _cancellationToken).ConfigureAwait(false);
                        AddSymbolTasks(result, symbols, symbolTasks);

                        // Defer to the language to see if it wants to cascade here in some special way.
                        var symbolProject = _solution.GetProject(searchSymbol.ContainingAssembly);
                        var service = symbolProject?.LanguageServices.GetService<ILanguageServiceReferenceFinder>();
                        if (service != null)
                        {
                            symbols = await service.DetermineCascadedSymbolsAsync(
                                searchSymbolAndProjectId, symbolProject, _cancellationToken).ConfigureAwait(false);
                            AddSymbolTasks(result, symbols, symbolTasks);
                        }

                        _cancellationToken.ThrowIfCancellationRequested();

                        await Task.WhenAll(symbolTasks).ConfigureAwait(false);
                    }, _cancellationToken));
                }

                await Task.WhenAll(finderTasks).ConfigureAwait(false);
            }
        }
            // More complicated forwarding functions.  These need to map from the symbols
            // used by the FAR engine to the INavigableItems used by the streaming FAR
            // feature.

            private DefinitionItem GetDefinitionItem(SymbolAndProjectId definition)
            {
                return(_definitionToItem.GetOrAdd(definition.Symbol, _definitionFactory));
            }
            /// <summary>
            /// Given a symbol, finds the symbol that actually defines the name that we're using.
            /// </summary>
            public static async Task<SymbolAndProjectId> FindDefinitionSymbolAsync(
                SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken)
            {
                var symbol = symbolAndProjectId.Symbol;
                Contract.ThrowIfNull(symbol);
                Contract.ThrowIfNull(solution);

                // Make sure we're on the original source definition if we can be
                var foundSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync(
                    symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

                var bestSymbolAndProjectId = foundSymbolAndProjectId.Symbol != null
                    ? foundSymbolAndProjectId
                    : symbolAndProjectId;
                symbol = bestSymbolAndProjectId.Symbol;

                // If we're renaming a property, it might be a synthesized property for a method
                // backing field.
                if (symbol.Kind == SymbolKind.Parameter)
                {
                    if (symbol.ContainingSymbol.Kind == SymbolKind.Method)
                    {
                        var containingMethod = (IMethodSymbol)symbol.ContainingSymbol;
                        if (containingMethod.AssociatedSymbol is IPropertySymbol)
                        {
                            var associatedPropertyOrEvent = (IPropertySymbol)containingMethod.AssociatedSymbol;
                            var ordinal = containingMethod.Parameters.IndexOf((IParameterSymbol)symbol);
                            if (ordinal < associatedPropertyOrEvent.Parameters.Length)
                            {
                                return bestSymbolAndProjectId.WithSymbol(
                                    associatedPropertyOrEvent.Parameters[ordinal]);
                            }
                        }
                    }
                }

                // if we are renaming a compiler generated delegate for an event, cascade to the event
                if (symbol.Kind == SymbolKind.NamedType)
                {
                    var typeSymbol = (INamedTypeSymbol)symbol;
                    if (typeSymbol.IsImplicitlyDeclared && typeSymbol.IsDelegateType() && typeSymbol.AssociatedSymbol != null)
                    {
                        return bestSymbolAndProjectId.WithSymbol(
                            typeSymbol.AssociatedSymbol);
                    }
                }

                // If we are renaming a constructor or destructor, we wish to rename the whole type
                if (symbol.Kind == SymbolKind.Method)
                {
                    var methodSymbol = (IMethodSymbol)symbol;
                    if (methodSymbol.MethodKind == MethodKind.Constructor ||
                        methodSymbol.MethodKind == MethodKind.StaticConstructor ||
                        methodSymbol.MethodKind == MethodKind.Destructor)
                    {
                        return bestSymbolAndProjectId.WithSymbol(
                            methodSymbol.ContainingType);
                    }
                }

                // If we are renaming a backing field for a property, cascade to the property
                if (symbol.Kind == SymbolKind.Field)
                {
                    var fieldSymbol = (IFieldSymbol)symbol;
                    if (fieldSymbol.IsImplicitlyDeclared &&
                        fieldSymbol.AssociatedSymbol.IsKind(SymbolKind.Property))
                    {
                        return bestSymbolAndProjectId.WithSymbol(
                            fieldSymbol.AssociatedSymbol);
                    }
                }

                // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol
                var propertyAndProjectId = await GetPropertyFromAccessorOrAnOverride(bestSymbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

                return propertyAndProjectId.Symbol != null
                    ? propertyAndProjectId
                    : bestSymbolAndProjectId;
            }
 public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
 => _service.Rpc.InvokeAsync(nameof(OnDefinitionFoundAsync),
                             SerializableSymbolAndProjectId.Dehydrate(definition));
Ejemplo n.º 27
0
            public async Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
            {
                var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false);

                await _context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
            }
        public async Task FindBasesAsync(Document document, int position, IFindUsagesContext context)
        {
            var cancellationToken = context.CancellationToken;
            var symbolAndProject  = await FindUsagesHelpers.GetRelevantSymbolAndProjectAtPositionAsync(
                document, position, cancellationToken).ConfigureAwait(false);

            if (symbolAndProject == null)
            {
                await context.ReportMessageAsync(
                    EditorFeaturesResources.Cannot_navigate_to_the_symbol_under_the_caret).ConfigureAwait(false);

                return;
            }

            var symbol = symbolAndProject.Value.symbol;
            var bases  = FindBaseHelpers.FindBases(
                symbol, symbolAndProject.Value.project, cancellationToken);

            await context.SetSearchTitleAsync(
                string.Format(EditorFeaturesResources._0_bases,
                              FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false);

            var project   = document.Project;
            var solution  = project.Solution;
            var projectId = project.Id;

            var found = false;

            // For each potential base, try to find its definition in sources.
            // If found, add it's definitionItem to the context.
            // If not found but the symbol is from metadata, create it's definition item from metadata and add to the context.
            foreach (var baseSymbol in bases)
            {
                var sourceDefinition = await SymbolFinder.FindSourceDefinitionAsync(
                    SymbolAndProjectId.Create(baseSymbol, projectId), solution, cancellationToken).ConfigureAwait(false);

                if (sourceDefinition.Symbol != null)
                {
                    var definitionItem = await sourceDefinition.Symbol.ToClassifiedDefinitionItemAsync(
                        solution.GetProject(sourceDefinition.ProjectId), includeHiddenLocations : false,
                        FindReferencesSearchOptions.Default, cancellationToken : cancellationToken)
                                         .ConfigureAwait(false);

                    await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);

                    found = true;
                }
                else if (baseSymbol.Locations.Any(l => l.IsInMetadata))
                {
                    var definitionItem = baseSymbol.ToNonClassifiedDefinitionItem(
                        project, includeHiddenLocations: true);
                    await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);

                    found = true;
                }
            }

            if (!found)
            {
                await context.ReportMessageAsync(EditorFeaturesResources.The_symbol_has_no_base)
                .ConfigureAwait(false);
            }
        }
 public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
 => _endPoint.InvokeAsync(nameof(SymbolFinder.FindReferencesServerCallback.OnDefinitionFoundAsync), new object[] { SerializableSymbolAndProjectId.Dehydrate(definition) }, _cancellationToken);
Ejemplo n.º 30
0
        private bool TryCreateUpdatedSolution(
            ChangeSignatureAnalyzedContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken, out Solution updatedSolution)
        {
            updatedSolution = context.Solution;
            var declaredSymbol = context.Symbol;

            var nodesToUpdate   = new Dictionary <DocumentId, List <SyntaxNode> >();
            var definitionToUse = new Dictionary <SyntaxNode, ISymbol>();

            bool hasLocationsInMetadata = false;

            var symbols = FindChangeSignatureReferencesAsync(
                SymbolAndProjectId.Create(declaredSymbol, context.Project.Id),
                context.Solution, cancellationToken).WaitAndGetResult(cancellationToken);

            foreach (var symbol in symbols)
            {
                if (symbol.Definition.Kind == SymbolKind.Method &&
                    ((symbol.Definition as IMethodSymbol).MethodKind == MethodKind.PropertyGet || (symbol.Definition as IMethodSymbol).MethodKind == MethodKind.PropertySet))
                {
                    continue;
                }

                if (symbol.Definition.Kind == SymbolKind.NamedType)
                {
                    continue;
                }

                if (symbol.Definition.Locations.Any(loc => loc.IsInMetadata))
                {
                    hasLocationsInMetadata = true;
                    continue;
                }

                var symbolWithSyntacticParameters = symbol.Definition;
                var symbolWithSemanticParameters  = symbol.Definition;

                var includeDefinitionLocations = true;

                if (symbol.Definition.Kind == SymbolKind.Field)
                {
                    includeDefinitionLocations = false;
                }

                if (symbolWithSyntacticParameters.Kind == SymbolKind.Event)
                {
                    var eventSymbol = symbolWithSyntacticParameters as IEventSymbol;
                    var type        = eventSymbol.Type as INamedTypeSymbol;
                    if (type != null && type.DelegateInvokeMethod != null)
                    {
                        symbolWithSemanticParameters = type.DelegateInvokeMethod;
                    }
                    else
                    {
                        continue;
                    }
                }

                if (symbolWithSyntacticParameters.Kind == SymbolKind.Method)
                {
                    var methodSymbol = symbolWithSyntacticParameters as IMethodSymbol;
                    if (methodSymbol.MethodKind == MethodKind.DelegateInvoke)
                    {
                        symbolWithSyntacticParameters = methodSymbol.ContainingType;
                    }

                    if (methodSymbol.Name == WellKnownMemberNames.DelegateBeginInvokeName &&
                        methodSymbol.ContainingType != null &&
                        methodSymbol.ContainingType.IsDelegateType())
                    {
                        includeDefinitionLocations = false;
                    }
                }

                // Find and annotate all the relevant definitions

                if (includeDefinitionLocations)
                {
                    foreach (var def in symbolWithSyntacticParameters.Locations)
                    {
                        if (!TryGetNodeWithEditableSignatureOrAttributes(def, updatedSolution, out var nodeToUpdate, out var documentId))
                        {
                            continue;
                        }

                        if (!nodesToUpdate.ContainsKey(documentId))
                        {
                            nodesToUpdate.Add(documentId, new List <SyntaxNode>());
                        }

                        AddUpdatableNodeToDictionaries(nodesToUpdate, documentId, nodeToUpdate, definitionToUse, symbolWithSemanticParameters);
                    }
                }

                // Find and annotate all the relevant references

                foreach (var location in symbol.Locations)
                {
                    if (location.Location.IsInMetadata)
                    {
                        hasLocationsInMetadata = true;
                        continue;
                    }

                    if (!TryGetNodeWithEditableSignatureOrAttributes(location.Location, updatedSolution, out var nodeToUpdate2, out var documentId2))
                    {
                        continue;
                    }

                    if (!nodesToUpdate.ContainsKey(documentId2))
                    {
                        nodesToUpdate.Add(documentId2, new List <SyntaxNode>());
                    }

                    AddUpdatableNodeToDictionaries(nodesToUpdate, documentId2, nodeToUpdate2, definitionToUse, symbolWithSemanticParameters);
                }
            }

            if (hasLocationsInMetadata)
            {
                var notificationService = context.Solution.Workspace.Services.GetService <INotificationService>();
                if (!notificationService.ConfirmMessageBox(FeaturesResources.This_symbol_has_related_definitions_or_references_in_metadata_Changing_its_signature_may_result_in_build_errors_Do_you_want_to_continue, severity: NotificationSeverity.Warning))
                {
                    return(false);
                }
            }

            // Construct all the relevant syntax trees from the base solution

            var updatedRoots = new Dictionary <DocumentId, SyntaxNode>();

            foreach (var docId in nodesToUpdate.Keys)
            {
                var doc     = updatedSolution.GetDocument(docId);
                var updater = doc.Project.LanguageServices.GetService <AbstractChangeSignatureService>();
                var root    = doc.GetSyntaxRootSynchronously(CancellationToken.None);

                var nodes = nodesToUpdate[docId];

                var newRoot = root.ReplaceNodes(nodes, (originalNode, potentiallyUpdatedNode) =>
                {
                    return(updater.ChangeSignature(doc, definitionToUse[originalNode], potentiallyUpdatedNode, originalNode, CreateCompensatingSignatureChange(definitionToUse[originalNode], options.UpdatedSignature), cancellationToken));
                });

                var annotatedNodes = newRoot.GetAnnotatedNodes <SyntaxNode>(syntaxAnnotation: changeSignatureFormattingAnnotation);

                var formattedRoot = Formatter.FormatAsync(
                    newRoot,
                    changeSignatureFormattingAnnotation,
                    doc.Project.Solution.Workspace,
                    options: null,
                    rules: GetFormattingRules(doc),
                    cancellationToken: CancellationToken.None).WaitAndGetResult(CancellationToken.None);

                updatedRoots[docId] = formattedRoot;
            }

            // Update the documents using the updated syntax trees

            foreach (var docId in nodesToUpdate.Keys)
            {
                updatedSolution = updatedSolution.WithDocumentSyntaxRoot(docId, updatedRoots[docId]);
            }

            return(true);
        }
Ejemplo n.º 31
0
 protected virtual Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsAsync(
     SymbolAndProjectId <TSymbol> symbolAndProject, Solution solution, IImmutableSet <Project> projects,
     FindReferencesSearchOptions options, CancellationToken cancellationToken)
 {
     return(SpecializedTasks.EmptyImmutableArray <SymbolAndProjectId>());
 }
Ejemplo n.º 32
0
 public abstract Task <ImmutableArray <FinderLocation> > FindReferencesInDocumentAsync(
     SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken);
Ejemplo n.º 33
0
 public abstract Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsAsync(
     SymbolAndProjectId symbolAndProject, Solution solution, IImmutableSet <Project> projects,
     FindReferencesSearchOptions options, CancellationToken cancellationToken);
Ejemplo n.º 34
0
        private static async Task<SearchResult> AddLocationsReferenceSymbolsAsync(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            CancellationToken cancellationToken)
        {
            var symbol = symbolAndProjectId.Symbol;
            var locations = new HashSet<RenameLocation>();
            var referenceSymbols = await SymbolFinder.FindRenamableReferencesAsync(
                symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

            foreach (var referencedSymbol in referenceSymbols)
            {
                locations.AddAll(
                    await ReferenceProcessing.GetRenamableDefinitionLocationsAsync(referencedSymbol.Definition, symbol, solution, cancellationToken).ConfigureAwait(false));

                locations.AddAll(
                    await referencedSymbol.Locations.SelectManyAsync<ReferenceLocation, RenameLocation>(
                        (l, c) => ReferenceProcessing.GetRenamableReferenceLocationsAsync(referencedSymbol.Definition, symbol, l, solution, c),
                        cancellationToken).ConfigureAwait(false));
            }

            var implicitLocations = referenceSymbols.SelectMany(refSym => refSym.Locations).Where(loc => loc.IsImplicit).ToList();
            var referencedSymbols = referenceSymbols.Select(r => r.DefinitionAndProjectId).Where(r => !r.Symbol.Equals(symbol)).ToList();

            return new SearchResult(locations, implicitLocations, referencedSymbols);
        }
Ejemplo n.º 35
0
        protected override async Task UpdateAsync(CommandArrayInfo ainfo, CancellationToken cancelToken)
        {
            var doc = IdeApp.Workbench.ActiveDocument;

            if (doc == null || doc.FileName == FilePath.Null || doc.AnalysisDocument == null)
            {
                return;
            }
            var semanticModel = await doc.AnalysisDocument.GetSemanticModelAsync(cancelToken);

            if (semanticModel == null)
            {
                return;
            }
            var info = await RefactoringSymbolInfo.GetSymbolInfoAsync(doc, doc.Editor);

            bool added = false;

            var ext = doc.GetContent <CodeActionEditorExtension> ();

            var ciset = new CommandInfoSet();

            ciset.Text = GettextCatalog.GetString("Refactor");

            bool canRename = RenameHandler.CanRename(info.Symbol ?? info.DeclaredSymbol);

            if (canRename)
            {
                ciset.CommandInfos.Add(IdeApp.CommandService.GetCommandInfo(MonoDevelop.Ide.Commands.EditCommands.Rename), new Action(async delegate {
                    await new MonoDevelop.Refactoring.Rename.RenameRefactoring().Rename(info.Symbol ?? info.DeclaredSymbol);
                }));
                added = true;
            }
            bool first = true;

            if (ciset.CommandInfos.Count > 0)
            {
                ainfo.Add(ciset, null);
                added = true;
            }

            var gotoDeclarationSymbol = info.Symbol;

            if (gotoDeclarationSymbol == null && info.DeclaredSymbol != null && info.DeclaredSymbol.Locations.Length > 1)
            {
                gotoDeclarationSymbol = info.DeclaredSymbol;
            }
            if (IdeApp.ProjectOperations.CanJumpToDeclaration(gotoDeclarationSymbol) || gotoDeclarationSymbol == null && IdeApp.ProjectOperations.CanJumpToDeclaration(info.CandidateSymbols.FirstOrDefault()))
            {
                var type = (gotoDeclarationSymbol ?? info.CandidateSymbols.FirstOrDefault()) as INamedTypeSymbol;
                if (type != null && type.Locations.Length > 1)
                {
                    var declSet = new CommandInfoSet();
                    declSet.Text = GettextCatalog.GetString("_Go to Declaration");
                    foreach (var part in type.Locations)
                    {
                        var loc = part.GetLineSpan();
                        declSet.CommandInfos.Add(string.Format(GettextCatalog.GetString("{0}, Line {1}"), FormatFileName(part.SourceTree.FilePath), loc.StartLinePosition.Line + 1), new Action(() => IdeApp.ProjectOperations.JumpTo(type, part, doc.Project)));
                    }
                    ainfo.Add(declSet);
                }
                else
                {
                    ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.GotoDeclaration), new Action(() => GotoDeclarationHandler.Run(doc)));
                }
                added = true;
            }


            if (info.DeclaredSymbol != null && GotoBaseDeclarationHandler.CanGotoBase(info.DeclaredSymbol))
            {
                ainfo.Add(GotoBaseDeclarationHandler.GetDescription(info.DeclaredSymbol), new Action(() => GotoBaseDeclarationHandler.GotoBase(doc, info.DeclaredSymbol).Ignore()));
                added = true;
            }

            var sym = info.Symbol ?? info.DeclaredSymbol;

            if (doc.HasProject && sym != null)
            {
                ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.FindReferences), new System.Action(() => {
                    if (sym.Kind == SymbolKind.Local || sym.Kind == SymbolKind.Parameter || sym.Kind == SymbolKind.TypeParameter)
                    {
                        FindReferencesHandler.FindRefs(new [] { SymbolAndProjectId.Create(sym, doc.AnalysisDocument.Project.Id) }, doc.AnalysisDocument.Project.Solution).Ignore();
                    }
                    else
                    {
                        RefactoringService.FindReferencesAsync(FindReferencesHandler.FilterSymbolForFindReferences(sym).GetDocumentationCommentId()).Ignore();
                    }
                }));
                try {
                    if (Microsoft.CodeAnalysis.FindSymbols.SymbolFinder.FindSimilarSymbols(sym, semanticModel.Compilation).Count() > 1)
                    {
                        ainfo.Add(IdeApp.CommandService.GetCommandInfo(RefactoryCommands.FindAllReferences), new System.Action(() => RefactoringService.FindAllReferencesAsync(FindReferencesHandler.FilterSymbolForFindReferences(sym).GetDocumentationCommentId())));
                    }
                } catch (Exception) {
                    // silently ignore roslyn bug.
                }
            }
            added = true;
        }
Ejemplo n.º 36
0
        private async Task <Solution> ProcessResult(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var locations          = diagnostic.AdditionalLocations;
            var propertyLocation   = locations[0];
            var declaratorLocation = locations[1];

            var declarator         = declaratorLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TVariableDeclarator>();
            var fieldDocument      = context.Document.Project.GetDocument(declarator.SyntaxTree);
            var fieldSemanticModel = await fieldDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var fieldSymbol = (IFieldSymbol)fieldSemanticModel.GetDeclaredSymbol(declarator);

            var property              = propertyLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TPropertyDeclaration>();
            var propertyDocument      = context.Document.Project.GetDocument(property.SyntaxTree);
            var propertySemanticModel = await propertyDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var propertySymbol = (IPropertySymbol)propertySemanticModel.GetDeclaredSymbol(property);

            Debug.Assert(fieldDocument.Project == propertyDocument.Project);
            var project     = fieldDocument.Project;
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            var solution       = context.Document.Project.Solution;
            var fieldLocations = await Renamer.GetRenameLocationsAsync(
                solution, SymbolAndProjectId.Create(fieldSymbol, fieldDocument.Project.Id),
                solution.Options, cancellationToken).ConfigureAwait(false);

            // First, create the updated property we want to replace the old property with
            var isWrittenToOutsideOfConstructor = IsWrittenToOutsideOfConstructorOrProperty(fieldSymbol, fieldLocations, property, cancellationToken);
            var updatedProperty = await UpdatePropertyAsync(propertyDocument, compilation, fieldSymbol, propertySymbol, property,
                                                            isWrittenToOutsideOfConstructor, cancellationToken).ConfigureAwait(false);

            // Now, rename all usages of the field to point at the property.  Except don't actually
            // rename the field itself.  We want to be able to find it again post rename.
            var updatedSolution = await Renamer.RenameAsync(fieldLocations, propertySymbol.Name,
                                                            location => !location.SourceSpan.IntersectsWith(declaratorLocation.SourceSpan),
                                                            symbols => HasConflict(symbols, propertySymbol, compilation, cancellationToken),
                                                            cancellationToken).ConfigureAwait(false);

            solution = updatedSolution;

            // Now find the field and property again post rename.
            fieldDocument    = solution.GetDocument(fieldDocument.Id);
            propertyDocument = solution.GetDocument(propertyDocument.Id);
            Debug.Assert(fieldDocument.Project == propertyDocument.Project);

            compilation = await fieldDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            fieldSymbol    = (IFieldSymbol)fieldSymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol;
            propertySymbol = (IPropertySymbol)propertySymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol;
            Debug.Assert(fieldSymbol != null && propertySymbol != null);

            declarator = (TVariableDeclarator)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
            var temp = await propertySymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false);

            property = temp.FirstAncestorOrSelf <TPropertyDeclaration>();

            var nodeToRemove = GetNodeToRemove(declarator);

            const SyntaxRemoveOptions options = SyntaxRemoveOptions.KeepUnbalancedDirectives | SyntaxRemoveOptions.AddElasticMarker;

            if (fieldDocument == propertyDocument)
            {
                // Same file.  Have to do this in a slightly complicated fashion.
                var declaratorTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var editor = new SyntaxEditor(declaratorTreeRoot, fieldDocument.Project.Solution.Workspace);
                editor.RemoveNode(nodeToRemove, options);
                editor.ReplaceNode(property, updatedProperty);

                var newRoot = editor.GetChangedRoot();
                newRoot = await FormatAsync(newRoot, fieldDocument, cancellationToken).ConfigureAwait(false);

                return(solution.WithDocumentSyntaxRoot(
                           fieldDocument.Id, newRoot));
            }
            else
            {
                // In different files.  Just update both files.
                var fieldTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var propertyTreeRoot = await propertyDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var newFieldTreeRoot    = fieldTreeRoot.RemoveNode(nodeToRemove, options);
                var newPropertyTreeRoot = propertyTreeRoot.ReplaceNode(property, updatedProperty);

                newFieldTreeRoot = await FormatAsync(newFieldTreeRoot, fieldDocument, cancellationToken).ConfigureAwait(false);

                newPropertyTreeRoot = await FormatAsync(newPropertyTreeRoot, propertyDocument, cancellationToken).ConfigureAwait(false);

                updatedSolution = solution.WithDocumentSyntaxRoot(fieldDocument.Id, newFieldTreeRoot);
                updatedSolution = updatedSolution.WithDocumentSyntaxRoot(propertyDocument.Id, newPropertyTreeRoot);

                return(updatedSolution);
            }
        }
Ejemplo n.º 37
0
 public abstract Task <ImmutableArray <ReferenceLocation> > FindReferencesInDocumentAsync(SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken);
            internal static async Task<SymbolAndProjectId> GetPropertyFromAccessorOrAnOverride(
                SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken)
            {
                var symbol = symbolAndProjectId.Symbol;
                if (symbol.IsPropertyAccessor())
                {
                    return symbolAndProjectId.WithSymbol(
                        ((IMethodSymbol)symbol).AssociatedSymbol);
                }

                if (symbol.IsOverride && symbol.OverriddenMember() != null)
                {
                    var originalSourceSymbol = await SymbolFinder.FindSourceDefinitionAsync(
                        symbolAndProjectId.WithSymbol(symbol.OverriddenMember()),
                        solution, cancellationToken).ConfigureAwait(false);

                    if (originalSourceSymbol.Symbol != null)
                    {
                        return await GetPropertyFromAccessorOrAnOverride(originalSourceSymbol, solution, cancellationToken).ConfigureAwait(false);
                    }
                }

                if (symbol.Kind == SymbolKind.Method &&
                    symbol.ContainingType.TypeKind == TypeKind.Interface)
                {
                    var methodImplementors = await SymbolFinder.FindImplementationsAsync(
                        symbolAndProjectId, solution, cancellationToken: cancellationToken).ConfigureAwait(false);

                    foreach (var methodImplementor in methodImplementors)
                    {
                        var propertyAccessorOrAnOverride = await GetPropertyFromAccessorOrAnOverride(methodImplementor, solution, cancellationToken).ConfigureAwait(false);
                        if (propertyAccessorOrAnOverride.Symbol != null)
                        {
                            return propertyAccessorOrAnOverride;
                        }
                    }
                }

                return default(SymbolAndProjectId);
            }
 public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
 => _service.InvokeAsync(nameof(OnDefinitionFoundAsync), new object[] { SerializableSymbolAndProjectId.Dehydrate(definition) }, _cancellationToken);
 public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
     => _service.Rpc.InvokeAsync(nameof(OnDefinitionFoundAsync),
         SerializableSymbolAndProjectId.Dehydrate(definition));
Ejemplo n.º 41
0
            /// <summary>
            /// Given a symbol, finds the symbol that actually defines the name that we're using.
            /// </summary>
            public static async Task <SymbolAndProjectId> FindDefinitionSymbolAsync(
                SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken)
            {
                var symbol = symbolAndProjectId.Symbol;

                Contract.ThrowIfNull(symbol);
                Contract.ThrowIfNull(solution);

                // Make sure we're on the original source definition if we can be
                var foundSymbolAndProjectId = await SymbolFinder.FindSourceDefinitionAsync(
                    symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

                var bestSymbolAndProjectId = foundSymbolAndProjectId.Symbol != null
                    ? foundSymbolAndProjectId
                    : symbolAndProjectId;

                symbol = bestSymbolAndProjectId.Symbol;

                // If we're renaming a property, it might be a synthesized property for a method
                // backing field.
                if (symbol.Kind == SymbolKind.Parameter)
                {
                    if (symbol.ContainingSymbol.Kind == SymbolKind.Method)
                    {
                        var containingMethod = (IMethodSymbol)symbol.ContainingSymbol;
                        if (containingMethod.AssociatedSymbol is IPropertySymbol)
                        {
                            var associatedPropertyOrEvent = (IPropertySymbol)containingMethod.AssociatedSymbol;
                            var ordinal = containingMethod.Parameters.IndexOf((IParameterSymbol)symbol);
                            if (ordinal < associatedPropertyOrEvent.Parameters.Length)
                            {
                                return(bestSymbolAndProjectId.WithSymbol(
                                           associatedPropertyOrEvent.Parameters[ordinal]));
                            }
                        }
                    }
                }

                // if we are renaming a compiler generated delegate for an event, cascade to the event
                if (symbol.Kind == SymbolKind.NamedType)
                {
                    var typeSymbol = (INamedTypeSymbol)symbol;
                    if (typeSymbol.IsImplicitlyDeclared && typeSymbol.IsDelegateType() && typeSymbol.AssociatedSymbol != null)
                    {
                        return(bestSymbolAndProjectId.WithSymbol(
                                   typeSymbol.AssociatedSymbol));
                    }
                }

                // If we are renaming a constructor or destructor, we wish to rename the whole type
                if (symbol.Kind == SymbolKind.Method)
                {
                    var methodSymbol = (IMethodSymbol)symbol;
                    if (methodSymbol.MethodKind == MethodKind.Constructor ||
                        methodSymbol.MethodKind == MethodKind.StaticConstructor ||
                        methodSymbol.MethodKind == MethodKind.Destructor)
                    {
                        return(bestSymbolAndProjectId.WithSymbol(
                                   methodSymbol.ContainingType));
                    }
                }

                // If we are renaming a backing field for a property, cascade to the property
                if (symbol.Kind == SymbolKind.Field)
                {
                    var fieldSymbol = (IFieldSymbol)symbol;
                    if (fieldSymbol.IsImplicitlyDeclared &&
                        fieldSymbol.AssociatedSymbol.IsKind(SymbolKind.Property))
                    {
                        return(bestSymbolAndProjectId.WithSymbol(
                                   fieldSymbol.AssociatedSymbol));
                    }
                }

                // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol
                var propertyAndProjectId = await GetPropertyFromAccessorOrAnOverride(bestSymbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

                return(propertyAndProjectId.Symbol != null
                    ? propertyAndProjectId
                    : bestSymbolAndProjectId);
            }
 private async Task<ConcurrentSet<SymbolAndProjectId>> DetermineAllSymbolsAsync(
     SymbolAndProjectId symbolAndProjectId)
 {
     using (Logger.LogBlock(FunctionId.FindReference_DetermineAllSymbolsAsync, _cancellationToken))
     {
         var result = new ConcurrentSet<SymbolAndProjectId>(
             new SymbolAndProjectIdComparer(MetadataUnifyingEquivalenceComparer.Instance));
         await DetermineAllSymbolsCoreAsync(symbolAndProjectId, result).ConfigureAwait(false);
         return result;
     }
 }
 public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
 {
     return(_context.OnDefinitionFoundAsync(GetDefinitionItem(definition)));
 }
        private static SymbolAndProjectId MapToAppropriateSymbol(
            SymbolAndProjectId symbolAndProjectId)
        {
            // Never search for an alias.  Always search for it's target.  Note: if the caller was
            // actually searching for an alias, they can always get that information out in the end
            // by checking the ReferenceLocations that are returned.
            var symbol = symbolAndProjectId.Symbol;
            var searchSymbol = symbol;

            if (searchSymbol is IAliasSymbol)
            {
                searchSymbol = ((IAliasSymbol)searchSymbol).Target;
            }

            searchSymbol = searchSymbol.GetOriginalUnreducedDefinition();

            // If they're searching for a delegate constructor, then just search for the delegate
            // itself.  They're practically interchangeable for consumers.
            if (searchSymbol.IsConstructor() && searchSymbol.ContainingType.TypeKind == TypeKind.Delegate)
            {
                searchSymbol = symbol.ContainingType;
            }

            return symbolAndProjectId.WithSymbol(searchSymbol);
        }
Ejemplo n.º 45
0
        /// <summary>
        /// Returns the corresponding symbol in this type or a base type that implements
        /// interfaceMember (either implicitly or explicitly), or null if no such symbol exists
        /// (which might be either because this type doesn't implement the container of
        /// interfaceMember, or this type doesn't supply a member that successfully implements
        /// interfaceMember).
        /// </summary>
        public static IEnumerable <SymbolAndProjectId> FindImplementationsForInterfaceMember(
            this SymbolAndProjectId <ITypeSymbol> typeSymbolAndProjectId,
            ISymbol interfaceMember,
            Workspace workspace,
            CancellationToken cancellationToken)
        {
            // This method can return multiple results.  Consider the case of:
            //
            // interface IFoo<X> { void Foo(X x); }
            //
            // class C : IFoo<int>, IFoo<string> { void Foo(int x); void Foo(string x); }
            //
            // If you're looking for the implementations of IFoo<X>.Foo then you want to find both
            // results in C.

            // TODO(cyrusn): Implement this using the actual code for
            // TypeSymbol.FindImplementationForInterfaceMember
            var typeSymbol = typeSymbolAndProjectId.Symbol;

            if (typeSymbol == null || interfaceMember == null)
            {
                yield break;
            }

            if (interfaceMember.Kind != SymbolKind.Event &&
                interfaceMember.Kind != SymbolKind.Method &&
                interfaceMember.Kind != SymbolKind.Property)
            {
                yield break;
            }

            // WorkItem(4843)
            //
            // 'typeSymbol' has to at least implement the interface containing the member.  note:
            // this just means that the interface shows up *somewhere* in the inheritance chain of
            // this type.  However, this type may not actually say that it implements it.  For
            // example:
            //
            // interface I { void Foo(); }
            //
            // class B { }
            //
            // class C : B, I { }
            //
            // class D : C { }
            //
            // D does implement I transitively through C.  However, even if D has a "Foo" method, it
            // won't be an implementation of I.Foo.  The implementation of I.Foo must be from a type
            // that actually has I in it's direct interface chain, or a type that's a base type of
            // that.  in this case, that means only classes C or B.
            var interfaceType = interfaceMember.ContainingType;

            if (!typeSymbol.ImplementsIgnoringConstruction(interfaceType))
            {
                yield break;
            }

            // We've ascertained that the type T implements some constructed type of the form I<X>.
            // However, we're not precisely sure which constructions of I<X> are being used.  For
            // example, a type C might implement I<int> and I<string>.  If we're searching for a
            // method from I<X> we might need to find several methods that implement different
            // instantiations of that method.
            var originalInterfaceType   = interfaceMember.ContainingType.OriginalDefinition;
            var originalInterfaceMember = interfaceMember.OriginalDefinition;
            var constructedInterfaces   = typeSymbol.AllInterfaces.Where(i =>
                                                                         SymbolEquivalenceComparer.Instance.Equals(i.OriginalDefinition, originalInterfaceType));

            foreach (var constructedInterface in constructedInterfaces)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var constructedInterfaceMember = constructedInterface.GetMembers().FirstOrDefault(m =>
                                                                                                  SymbolEquivalenceComparer.Instance.Equals(m.OriginalDefinition, originalInterfaceMember));

                if (constructedInterfaceMember == null)
                {
                    continue;
                }

                // Now we need to walk the base type chain, but we start at the first type that actually
                // has the interface directly in its interface hierarchy.
                var seenTypeDeclaringInterface = false;
                for (var currentType = typeSymbol; currentType != null; currentType = currentType.BaseType)
                {
                    seenTypeDeclaringInterface = seenTypeDeclaringInterface ||
                                                 currentType.GetOriginalInterfacesAndTheirBaseInterfaces().Contains(interfaceType.OriginalDefinition);

                    if (seenTypeDeclaringInterface)
                    {
                        var result = constructedInterfaceMember.TypeSwitch(
                            (IEventSymbol eventSymbol) => FindImplementations(currentType, eventSymbol, workspace, e => e.ExplicitInterfaceImplementations),
                            (IMethodSymbol methodSymbol) => FindImplementations(currentType, methodSymbol, workspace, m => m.ExplicitInterfaceImplementations),
                            (IPropertySymbol propertySymbol) => FindImplementations(currentType, propertySymbol, workspace, p => p.ExplicitInterfaceImplementations));

                        if (result != null)
                        {
                            yield return(typeSymbolAndProjectId.WithSymbol(result));

                            break;
                        }
                    }
                }
            }
        }
Ejemplo n.º 46
0
        public static async Task <ImmutableArray <SymbolAndProjectId> > FindImplementationsForInterfaceMemberAsync(
            this SymbolAndProjectId <ITypeSymbol> typeSymbolAndProjectId,
            SymbolAndProjectId interfaceMemberAndProjectId,
            Solution solution,
            CancellationToken cancellationToken)
        {
            // This method can return multiple results.  Consider the case of:
            //
            // interface IGoo<X> { void Goo(X x); }
            //
            // class C : IGoo<int>, IGoo<string> { void Goo(int x); void Goo(string x); }
            //
            // If you're looking for the implementations of IGoo<X>.Goo then you want to find both
            // results in C.

            var arrBuilder = ArrayBuilder <SymbolAndProjectId> .GetInstance();

            var interfaceMember = interfaceMemberAndProjectId.Symbol;

            // TODO(cyrusn): Implement this using the actual code for
            // TypeSymbol.FindImplementationForInterfaceMember
            var typeSymbol = typeSymbolAndProjectId.Symbol;

            if (typeSymbol == null || interfaceMember == null)
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            if (interfaceMember.Kind != SymbolKind.Event &&
                interfaceMember.Kind != SymbolKind.Method &&
                interfaceMember.Kind != SymbolKind.Property)
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            // WorkItem(4843)
            //
            // 'typeSymbol' has to at least implement the interface containing the member.  note:
            // this just means that the interface shows up *somewhere* in the inheritance chain of
            // this type.  However, this type may not actually say that it implements it.  For
            // example:
            //
            // interface I { void Goo(); }
            //
            // class B { }
            //
            // class C : B, I { }
            //
            // class D : C { }
            //
            // D does implement I transitively through C.  However, even if D has a "Goo" method, it
            // won't be an implementation of I.Goo.  The implementation of I.Goo must be from a type
            // that actually has I in it's direct interface chain, or a type that's a base type of
            // that.  in this case, that means only classes C or B.
            var interfaceType = interfaceMember.ContainingType;

            if (!typeSymbol.ImplementsIgnoringConstruction(interfaceType))
            {
                return(arrBuilder.ToImmutableAndFree());
            }

            // We've ascertained that the type T implements some constructed type of the form I<X>.
            // However, we're not precisely sure which constructions of I<X> are being used.  For
            // example, a type C might implement I<int> and I<string>.  If we're searching for a
            // method from I<X> we might need to find several methods that implement different
            // instantiations of that method.
            var originalInterfaceType   = interfaceMember.ContainingType.OriginalDefinition;
            var originalInterfaceMember = interfaceMember.OriginalDefinition;

            var constructedInterfaces = typeSymbol.AllInterfaces.Where(i =>
                                                                       SymbolEquivalenceComparer.Instance.Equals(i.OriginalDefinition, originalInterfaceType));

            // Try to get the compilation for the symbol we're searching for,
            // which can help identify matches with the call to SymbolFinder.OriginalSymbolsMatch.
            // OriginalSymbolMatch allows types to be matched across different assemblies
            // if they are considered to be the same type, which provides a more accurate
            // implementations list for interfaces.
            var typeSymbolProject      = solution.GetProject(typeSymbolAndProjectId.ProjectId);
            var interfaceMemberProject = solution.GetProject(interfaceMemberAndProjectId.ProjectId);

            var typeSymbolCompilation = await GetCompilationOrNullAsync(typeSymbolProject, cancellationToken).ConfigureAwait(false);

            var interfaceMemberCompilation = await GetCompilationOrNullAsync(interfaceMemberProject, cancellationToken).ConfigureAwait(false);

            foreach (var constructedInterface in constructedInterfaces)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var constructedInterfaceMember = constructedInterface.GetMembers().FirstOrDefault(typeSymbol =>
                                                                                                  SymbolFinder.OriginalSymbolsMatch(
                                                                                                      typeSymbol,
                                                                                                      interfaceMember,
                                                                                                      solution,
                                                                                                      typeSymbolCompilation,
                                                                                                      interfaceMemberCompilation,
                                                                                                      cancellationToken));

                if (constructedInterfaceMember == null)
                {
                    continue;
                }

                // Now we need to walk the base type chain, but we start at the first type that actually
                // has the interface directly in its interface hierarchy.
                var seenTypeDeclaringInterface = false;
                for (ITypeSymbol?currentType = typeSymbol; currentType != null; currentType = currentType.BaseType)
                {
                    seenTypeDeclaringInterface = seenTypeDeclaringInterface ||
                                                 currentType.GetOriginalInterfacesAndTheirBaseInterfaces().Contains(interfaceType.OriginalDefinition);

                    if (seenTypeDeclaringInterface)
                    {
                        var result = currentType.FindImplementations(constructedInterfaceMember, solution.Workspace);

                        if (result != null)
                        {
                            arrBuilder.Add(typeSymbolAndProjectId.WithSymbol(result));
                            break;
                        }
                    }
                }
            }

            return(arrBuilder.ToImmutableAndFree());
Ejemplo n.º 47
0
 internal static IEnumerable<SymbolAndProjectId> GetOverloadedSymbols(
     SymbolAndProjectId symbolAndProjectId)
 {
     var symbol = symbolAndProjectId.Symbol;
     if (symbol is IMethodSymbol)
     {
         var containingType = symbol.ContainingType;
         if (containingType.Kind == SymbolKind.NamedType)
         {
             foreach (var member in containingType.GetMembers())
             {
                 if (string.Equals(member.MetadataName, symbol.MetadataName, StringComparison.Ordinal) && member is IMethodSymbol && !member.Equals(symbol))
                 {
                     yield return symbolAndProjectId.WithSymbol(member);
                 }
             }
         }
     }
 }
Ejemplo n.º 48
0
 public abstract Task <ImmutableArray <SymbolAndProjectId> > DetermineCascadedSymbolsFromDelegateInvoke(
     SymbolAndProjectId <IMethodSymbol> symbolAndProjectId, Document document, CancellationToken cancellationToken);
Ejemplo n.º 49
0
 internal static Task <Solution> RenameSymbolAsync(
     Solution solution, SymbolAndProjectId symbolAndProjectId, string newName, OptionSet optionSet, CancellationToken cancellationToken = default)
 {
     return(RenameSymbolAsync(solution, symbolAndProjectId, newName, optionSet, nonConflictSymbols: null, cancellationToken));
 }
Ejemplo n.º 50
0
 public Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
     SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken = default(CancellationToken))
 {
     return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
 }
 private Task HandleLocationAsync(SymbolAndProjectId symbolAndProjectId, ReferenceLocation location)
 {
     return(_progress.OnReferenceFoundAsync(symbolAndProjectId, location));
 }