private static async Task FindSymbolMonikerReferencesAsync( IFindSymbolMonikerUsagesService monikerUsagesService, ISymbol definition, IFindUsagesContext context, CancellationToken cancellationToken) { var moniker = SymbolMoniker.TryCreate(definition); if (moniker == null) { return; } // Let the find-refs window know we have outstanding work await using var _ = await context.ProgressTracker.AddSingleItemAsync().ConfigureAwait(false); var displayParts = GetDisplayParts(definition).AddRange(new[] { new TaggedText(TextTags.Space, " "), new TaggedText(TextTags.Text, EditorFeaturesResources.external), }); var definitionItem = DefinitionItem.CreateNonNavigableItem( tags: GlyphTags.GetTags(definition.GetGlyph()), displayParts, originationParts: DefinitionItem.GetOriginationParts(definition)); var monikers = ImmutableArray.Create(moniker); var first = true; await foreach (var referenceItem in monikerUsagesService.FindReferencesByMoniker( definitionItem, monikers, context.ProgressTracker, cancellationToken)) { if (first) { // found some results. Add the definition item to the context. first = false; await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false); } await context.OnExternalReferenceFoundAsync(referenceItem).ConfigureAwait(false); } }
private static async Task <DefinitionItem> ToDefinitionItemAsync( this ISymbol definition, Project project, bool includeHiddenLocations, bool includeClassifiedSpans, CancellationToken cancellationToken) { // Ensure we're working with the original definition for the symbol. I.e. When we're // creating definition items, we want to create them for types like Dictionary<TKey,TValue> // not some random instantiation of that type. // // This ensures that the type will both display properly to the user, as well as ensuring // that we can accurately resolve the type later on when we try to navigate to it. definition = definition.OriginalDefinition; var displayParts = definition.ToDisplayParts(GetFormat(definition)).ToTaggedText(); var nameDisplayParts = definition.ToDisplayParts(s_namePartsFormat).ToTaggedText(); var tags = GlyphTags.GetTags(definition.GetGlyph()); var displayIfNoReferences = definition.ShouldShowWithNoReferenceLocations( showMetadataSymbolsWithoutReferences: false); var sourceLocations = ArrayBuilder <DocumentSpan> .GetInstance(); var properties = GetProperties(definition); // If it's a namespace, don't create any normal location. Namespaces // come from many different sources, but we'll only show a single // root definition node for it. That node won't be navigable. if (definition.Kind != SymbolKind.Namespace) { foreach (var location in definition.Locations) { if (location.IsInMetadata) { return(DefinitionItem.CreateMetadataDefinition( tags, displayParts, nameDisplayParts, project, definition, properties, displayIfNoReferences)); } else if (location.IsInSource) { if (!location.IsVisibleSourceLocation() && !includeHiddenLocations) { continue; } var document = project.Solution.GetDocument(location.SourceTree); if (document != null) { var documentLocation = !includeClassifiedSpans ? new DocumentSpan(document, location.SourceSpan) : await ClassifiedSpansAndHighlightSpanFactory.GetClassifiedDocumentSpanAsync( document, location.SourceSpan, cancellationToken).ConfigureAwait(false); sourceLocations.Add(documentLocation); } } } } if (sourceLocations.Count == 0) { // If we got no definition locations, then create a sentinel one // that we can display but which will not allow navigation. return(DefinitionItem.CreateNonNavigableItem( tags, displayParts, DefinitionItem.GetOriginationParts(definition), properties, displayIfNoReferences)); } return(DefinitionItem.Create( tags, displayParts, sourceLocations.ToImmutableAndFree(), nameDisplayParts, properties, displayIfNoReferences)); }
private static async Task <DefinitionItem> ToDefinitionItemAsync( this ISymbol definition, Solution solution, bool isPrimary, bool includeHiddenLocations, bool includeClassifiedSpans, FindReferencesSearchOptions options, CancellationToken cancellationToken) { // Ensure we're working with the original definition for the symbol. I.e. When we're // creating definition items, we want to create them for types like Dictionary<TKey,TValue> // not some random instantiation of that type. // // This ensures that the type will both display properly to the user, as well as ensuring // that we can accurately resolve the type later on when we try to navigate to it. if (!definition.IsTupleField()) { // In an earlier implementation of the compiler APIs, tuples and tuple fields symbols were definitions // We pretend this is still the case definition = definition.OriginalDefinition; } var displayParts = GetDisplayParts(definition); var nameDisplayParts = definition.ToDisplayParts(s_namePartsFormat).ToTaggedText(); var tags = GlyphTags.GetTags(definition.GetGlyph()); var displayIfNoReferences = definition.ShouldShowWithNoReferenceLocations( options, showMetadataSymbolsWithoutReferences: false); using var sourceLocationsDisposer = ArrayBuilder <DocumentSpan> .GetInstance(out var sourceLocations); var properties = GetProperties(definition, isPrimary); // If it's a namespace, don't create any normal location. Namespaces // come from many different sources, but we'll only show a single // root definition node for it. That node won't be navigable. if (definition.Kind != SymbolKind.Namespace) { foreach (var location in definition.Locations) { if (location.IsInMetadata) { return(DefinitionItem.CreateMetadataDefinition( tags, displayParts, nameDisplayParts, solution, definition, properties, displayIfNoReferences)); } else if (location.IsInSource) { if (!location.IsVisibleSourceLocation() && !includeHiddenLocations) { continue; } var document = solution.GetDocument(location.SourceTree); if (document != null) { var documentLocation = !includeClassifiedSpans ? new DocumentSpan(document, location.SourceSpan) : await ClassifiedSpansAndHighlightSpanFactory.GetClassifiedDocumentSpanAsync( document, location.SourceSpan, cancellationToken).ConfigureAwait(false); sourceLocations.Add(documentLocation); } else { // Was this a source generated tree? If so, we don't have a document representaion (yet) so // we'll create a metadata symbol which will later be handled by the symbol navigation service // that way. Once we represent generated source trees as propery documents, we'll update the code above // to correctly make this item. var project = solution.GetOriginatingProject(definition); var generatorRunResult = await project.GetGeneratorDriverRunResultAsync(cancellationToken).ConfigureAwait(false); if (generatorRunResult.TryGetGeneratorAndHint(location.SourceTree, out _, out _)) { return(DefinitionItem.CreateMetadataDefinition( tags, displayParts, nameDisplayParts, solution, definition, properties, displayIfNoReferences)); } } } } } if (sourceLocations.Count == 0) { // If we got no definition locations, then create a sentinel one // that we can display but which will not allow navigation. return(DefinitionItem.CreateNonNavigableItem( tags, displayParts, DefinitionItem.GetOriginationParts(definition), properties, displayIfNoReferences)); } var displayableProperties = AbstractReferenceFinder.GetAdditionalFindUsagesProperties(definition); return(DefinitionItem.Create( tags, displayParts, sourceLocations.ToImmutable(), nameDisplayParts, properties, displayableProperties, displayIfNoReferences)); }