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()); }
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)); } } } } }
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))); } }
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);