예제 #1
0
        private static async Task <IEnumerable <ReferencedSymbol> > FindReferencesAsync(
            ISymbol symbol,
            Solution solution,
            IFindReferencesProgress progress,
            IImmutableSet <Document> documents,
            FindReferencesSearchOptions options,
            CancellationToken cancellationToken)
        {
            progress = progress ?? FindReferencesProgress.Instance;
            var streamingProgress = new StreamingProgressCollector(
                new StreamingFindReferencesProgressAdapter(progress));

            await FindReferencesAsync(
                SymbolAndProjectId.Create(symbol, projectId: null),
                solution, streamingProgress, documents,
                options, cancellationToken).ConfigureAwait(false);

            return(streamingProgress.GetReferencedSymbols());
        }
예제 #2
0
        private static async Task FindImmediateMatchingMetadataTypesInMetadataReferenceAsync(
            SymbolAndProjectIdSet metadataTypes,
            Project project,
            Func <SymbolAndProjectIdSet, INamedTypeSymbol, bool> metadataTypeMatches,
            Compilation compilation,
            PortableExecutableReference reference,
            SymbolAndProjectIdSet result,
            CancellationToken cancellationToken)
        {
            // We store an index in SymbolTreeInfo of the *simple* metadata type name
            // to the names of the all the types that either immediately derive or
            // implement that type.  Because the mapping is from the simple name
            // we might get false positives.  But that's fine as we still use
            // 'metadataTypeMatches' to make sure the match is correct.
            var symbolTreeInfo = await SymbolTreeInfo.TryGetInfoForMetadataReferenceAsync(
                project.Solution, reference, loadOnly : false, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (symbolTreeInfo == null)
            {
                return;
            }

            // For each type we care about, see if we can find any derived types
            // in this index.
            foreach (var metadataType in metadataTypes)
            {
                var baseTypeName = metadataType.Symbol.Name;

                // For each derived type we find, see if we can map that back
                // to an actual symbol.  Then check if that symbol actually fits
                // our criteria.
                foreach (var derivedType in symbolTreeInfo.GetDerivedMetadataTypes(baseTypeName, compilation, cancellationToken))
                {
                    if (derivedType != null && derivedType.Locations.Any(s_isInMetadata))
                    {
                        if (metadataTypeMatches(metadataTypes, derivedType))
                        {
                            result.Add(SymbolAndProjectId.Create(derivedType, project.Id));
                        }
                    }
                }
            }
        }
예제 #3
0
        private static bool TypeDerivesFrom(
            SymbolAndProjectIdSet metadataTypes, INamedTypeSymbol type, bool transitive)
        {
            if (transitive)
            {
                for (var current = type.BaseType; current != null; current = current.BaseType)
                {
                    if (metadataTypes.Contains(
                            SymbolAndProjectId.Create(current.OriginalDefinition, projectId: null)))
                    {
                        return(true);
                    }
                }

                return(false);
            }
            else
            {
                return(metadataTypes.Contains(
                           SymbolAndProjectId.Create(type.BaseType?.OriginalDefinition, projectId: null)));
            }
        }
예제 #4
0
        private static async Task <SymbolAndProjectId> FindSourceDefinitionWorkerAsync(
            SymbolAndProjectId symbolAndProjectId,
            Solution solution,
            CancellationToken cancellationToken)
        {
            var symbol = symbolAndProjectId.Symbol;

            // If it's already in source, then we might already be done
            if (InSource(symbol))
            {
                // If our symbol doesn't have a containing assembly, there's nothing better we can do to map this
                // symbol somewhere else. The common case for this is a merged INamespaceSymbol that spans assemblies.
                if (symbol.ContainingAssembly == null)
                {
                    return(symbolAndProjectId);
                }

                // Just because it's a source symbol doesn't mean we have the final symbol we actually want. In retargeting cases,
                // the retargeted symbol is from "source" but isn't equal to the actual source definition in the other project. Thus,
                // we only want to return symbols from source here if it actually came from a project's compilation's assembly. If it isn't
                // then we have a retargeting scenario and want to take our usual path below as if it was a metadata reference
                foreach (var sourceProject in solution.Projects)
                {
                    // If our symbol is actually a "regular" source symbol, then we know the compilation is holding the symbol alive
                    // and thus TryGetCompilation is sufficient. For another example of this pattern, see Solution.GetProject(IAssemblySymbol)
                    // which we happen to call below.
                    if (sourceProject.TryGetCompilation(out var compilation))
                    {
                        if (symbol.ContainingAssembly.Equals(compilation.Assembly))
                        {
                            return(SymbolAndProjectId.Create(symbol, sourceProject.Id));
                        }
                    }
                }
            }
            else if (!symbol.Locations.Any(loc => loc.IsInMetadata))
            {
                // We have a symbol that's neither in source nor metadata
                return(default);