/// <summary> /// Finds references using <see cref="SymbolFinder.FindReferencesAsync(ISymbol, Solution, CancellationToken)"/> /// </summary> private async Task AddSymbolReferencesAsync(Document document, int position, ArrayBuilder <INavigableItem> builder, IWaitContext waitContext) { var result = await this.FindReferencedSymbolsAsync(document, position, waitContext).ConfigureAwait(false); if (result != null) { var referencedSymbols = result.Item1; var searchSolution = result.Item2; var q = from r in referencedSymbols from loc in r.Locations select NavigableItemFactory.GetItemFromSymbolLocation(searchSolution, r.Definition, loc.Location); builder.AddRange(q); } }
private static bool TryPresentInNavigableItemsPresenter( Solution solution, ISymbol symbol, IEnumerable <Lazy <INavigableItemsPresenter> > presenters, string title, Location[] locations) { var presenter = presenters.FirstOrDefault(); if (presenter != null) { var navigableItems = locations.Select(location => NavigableItemFactory.GetItemFromSymbolLocation( solution, symbol, location, displayTaggedParts: null)).ToImmutableArray(); presenter.Value.DisplayResult(title, navigableItems); return(true); } return(false); }
public async Task <IEnumerable <INavigableItem> > FindReferencesAsync(Document document, int position, IWaitContext waitContext) { var cancellationToken = waitContext.CancellationToken; var result = await this.FindReferencedSymbolsAsync(document, position, waitContext).ConfigureAwait(false); if (result == null) { return(SpecializedCollections.EmptyEnumerable <INavigableItem>()); } var referencedSymbols = result.Item1; var searchSolution = result.Item2; var q = from r in referencedSymbols from loc in r.Locations select NavigableItemFactory.GetItemFromSymbolLocation(searchSolution, r.Definition, loc.Location); // realize the list here so that the consumer await'ing the result doesn't lazily cause // them to be created on an inapropriate thread. return(q.ToList()); }
public static bool TryGoToDefinition( ISymbol symbol, Project project, IEnumerable <Lazy <INavigableItemsPresenter> > presenters, IEnumerable <Lazy <IStreamingFindUsagesPresenter> > streamingPresenters, CancellationToken cancellationToken, bool thirdPartyNavigationAllowed = true, bool throwOnHiddenDefinition = false) { var alias = symbol as IAliasSymbol; if (alias != null) { var ns = alias.Target as INamespaceSymbol; if (ns != null && ns.IsGlobalNamespace) { return(false); } } // VB global import aliases have a synthesized SyntaxTree. // We can't go to the definition of the alias, so use the target type. var solution = project.Solution; if (symbol is IAliasSymbol && NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).All(l => project.Solution.GetDocument(l.SourceTree) == null)) { symbol = ((IAliasSymbol)symbol).Target; } var definition = SymbolFinder.FindSourceDefinitionAsync(symbol, solution, cancellationToken).WaitAndGetResult(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); symbol = definition ?? symbol; if (thirdPartyNavigationAllowed && TryThirdPartyNavigation(symbol, solution)) { return(true); } // If it is a partial method declaration with no body, choose to go to the implementation // that has a method body. if (symbol is IMethodSymbol) { symbol = ((IMethodSymbol)symbol).PartialImplementationPart ?? symbol; } var options = project.Solution.Options; var preferredSourceLocations = NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).ToArray(); var displayParts = NavigableItemFactory.GetSymbolDisplayTaggedParts(project, symbol); var title = displayParts.JoinText(); if (preferredSourceLocations.Length == 0) { // If there are no visible source locations, then tell the host about the symbol and // allow it to navigate to it. This will either navigate to any non-visible source // locations, or it can appropriately deal with metadata symbols for hosts that can go // to a metadata-as-source view. var symbolNavigationService = solution.Workspace.Services.GetService <ISymbolNavigationService>(); return(symbolNavigationService.TryNavigateToSymbol( symbol, project, options: options.WithChangedOption(NavigationOptions.PreferProvisionalTab, true), cancellationToken: cancellationToken)); } else if (preferredSourceLocations.Length == 1) { var item = NavigableItemFactory.GetItemFromSymbolLocation( solution, symbol, preferredSourceLocations[0], displayTaggedParts: null); return(TryGoToSingleLocation(item, options, throwOnHiddenDefinition)); } else { // We have multiple viable source locations, so ask the host what to do. Most hosts // will simply display the results to the user and allow them to choose where to // go. return(TryPresentInFindUsagesPresenter(solution, symbol, streamingPresenters, cancellationToken) || TryPresentInNavigableItemsPresenter(solution, symbol, presenters, title, preferredSourceLocations)); } }
public static bool TryGoToDefinition( ISymbol symbol, Project project, IEnumerable <Lazy <INavigableItemsPresenter> > presenters, CancellationToken cancellationToken, bool thirdPartyNavigationAllowed = true, bool throwOnHiddenDefinition = false) { var alias = symbol as IAliasSymbol; if (alias != null) { var ns = alias.Target as INamespaceSymbol; if (ns != null && ns.IsGlobalNamespace) { return(false); } } // VB global import aliases have a synthesized SyntaxTree. // We can't go to the definition of the alias, so use the target type. var solution = project.Solution; if (symbol is IAliasSymbol && NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).All(l => project.Solution.GetDocument(l.SourceTree) == null)) { symbol = ((IAliasSymbol)symbol).Target; } var definition = SymbolFinder.FindSourceDefinitionAsync(symbol, solution, cancellationToken).WaitAndGetResult(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); symbol = definition ?? symbol; if (thirdPartyNavigationAllowed && TryThirdPartyNavigation(symbol, solution)) { return(true); } // If it is a partial method declaration with no body, choose to go to the implementation // that has a method body. if (symbol is IMethodSymbol) { symbol = ((IMethodSymbol)symbol).PartialImplementationPart ?? symbol; } var preferredSourceLocations = NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).ToArray(); if (!preferredSourceLocations.Any()) { // If there are no visible source locations, then tell the host about the symbol and // allow it to navigate to it. THis will either navigate to any non-visible source // locations, or it can appropriately deal with metadata symbols for hosts that can go // to a metadata-as-source view. var symbolNavigationService = solution.Workspace.Services.GetService <ISymbolNavigationService>(); return(symbolNavigationService.TryNavigateToSymbol(symbol, project, cancellationToken: cancellationToken, usePreviewTab: true)); } // If we have a single location, then just navigate to it. if (preferredSourceLocations.Length == 1) { var firstItem = preferredSourceLocations[0]; var workspace = project.Solution.Workspace; var navigationService = workspace.Services.GetService <IDocumentNavigationService>(); if (navigationService.CanNavigateToSpan(workspace, solution.GetDocument(firstItem.SourceTree).Id, firstItem.SourceSpan)) { return(navigationService.TryNavigateToSpan(workspace, solution.GetDocument(firstItem.SourceTree).Id, firstItem.SourceSpan, usePreviewTab: true)); } else { if (throwOnHiddenDefinition) { const int E_FAIL = -2147467259; throw new COMException(EditorFeaturesResources.TheDefinitionOfTheObjectIsHidden, E_FAIL); } else { return(false); } } } else { // We have multiple viable source locations, so ask the host what to do. Most hosts // will simply display the results to the user and allow them to choose where to // go. if (presenters.Any()) { presenters.First().Value.DisplayResult(NavigableItemFactory.GetSymbolDisplayString(project, symbol), preferredSourceLocations.Select(location => NavigableItemFactory.GetItemFromSymbolLocation(solution, symbol, location)).ToList()); return(true); } return(false); } }
public static bool TryGoToDefinition( ISymbol symbol, Project project, IEnumerable <Lazy <INavigableDefinitionProvider> > externalDefinitionProviders, IEnumerable <Lazy <INavigableItemsPresenter> > presenters, CancellationToken cancellationToken, bool thirdPartyNavigationAllowed = true, bool throwOnHiddenDefinition = false) { var alias = symbol as IAliasSymbol; if (alias != null) { var ns = alias.Target as INamespaceSymbol; if (ns != null && ns.IsGlobalNamespace) { return(false); } } // VB global import aliases have a synthesized SyntaxTree. // We can't go to the definition of the alias, so use the target type. var solution = project.Solution; if (symbol is IAliasSymbol && NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).All(l => project.Solution.GetDocument(l.SourceTree) == null)) { symbol = ((IAliasSymbol)symbol).Target; } var definition = SymbolFinder.FindSourceDefinitionAsync(symbol, solution, cancellationToken).WaitAndGetResult(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); symbol = definition ?? symbol; if (thirdPartyNavigationAllowed && TryThirdPartyNavigation(symbol, solution)) { return(true); } // If it is a partial method declaration with no body, choose to go to the implementation // that has a method body. if (symbol is IMethodSymbol) { symbol = ((IMethodSymbol)symbol).PartialImplementationPart ?? symbol; } var options = project.Solution.Options; var preferredSourceLocations = NavigableItemFactory.GetPreferredSourceLocations(solution, symbol).ToArray(); var title = NavigableItemFactory.GetSymbolDisplayString(project, symbol); if (!preferredSourceLocations.Any()) { // Attempt to find source locations from external definition providers. if (thirdPartyNavigationAllowed && externalDefinitionProviders.Any()) { var externalSourceDefinitions = FindExternalDefinitionsAsync(symbol, project, externalDefinitionProviders, cancellationToken).WaitAndGetResult(cancellationToken).ToImmutableArray(); if (externalSourceDefinitions.Length > 0) { return(TryGoToDefinition(externalSourceDefinitions, title, options, presenters, throwOnHiddenDefinition)); } } // If there are no visible source locations, then tell the host about the symbol and // allow it to navigate to it. This will either navigate to any non-visible source // locations, or it can appropriately deal with metadata symbols for hosts that can go // to a metadata-as-source view. var symbolNavigationService = solution.Workspace.Services.GetService <ISymbolNavigationService>(); return(symbolNavigationService.TryNavigateToSymbol( symbol, project, options: options.WithChangedOption(NavigationOptions.PreferProvisionalTab, true), cancellationToken: cancellationToken)); } var navigableItems = preferredSourceLocations.Select(location => NavigableItemFactory.GetItemFromSymbolLocation(solution, symbol, location)).ToImmutableArray(); return(TryGoToDefinition(navigableItems, title, options, presenters, throwOnHiddenDefinition)); }