private void StartSearch(IGraphContext context) { var searchParameter = context.GetValue <ISolutionSearchParameters>(typeof(ISolutionSearchParameters).GUID.ToString()); if (searchParameter != null) { var term = searchParameter.SearchQuery.SearchString; var items = package.DevEnv.SolutionExplorer().Solution .Traverse() .OfType <IItemNode>() .Where(item => item.DisplayName == "packages.config"); searchItems = new ConcurrentQueue <IItemNode>(); foreach (var item in items) { searchItems.Enqueue(item); } TrackChanges(context); Application.Current.Dispatcher.BeginInvoke(new Action <string, IGraphContext>(SearchNextItem), term, context); } }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private void Search(IGraphContext graphContext) { var searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); var searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); if (searchParameters == null) { return; } var searchTerm = searchParameters.SearchQuery.SearchString?.ToLowerInvariant(); if (searchTerm == null) { return; } var cachedDependencyToMatchingResultsMap = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var searchResultsPerContext = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var snapshotProviders = AggregateSnapshotProvider.GetSnapshotProviders(); foreach (var snapshotProvider in snapshotProviders) { var snapshot = snapshotProvider.CurrentSnapshot; if (snapshot == null) { continue; } searchResultsPerContext[snapshotProvider.ProjectFilePath] = SearchFlat(snapshotProvider.ProjectFilePath, searchTerm.ToLowerInvariant(), graphContext, snapshot); } foreach (var snapshotProvider in snapshotProviders) { var snapshot = snapshotProvider.CurrentSnapshot; if (snapshot == null) { continue; } var allTopLevelDependencies = snapshot.GetFlatTopLevelDependencies(); var matchedDependencies = searchResultsPerContext[snapshotProvider.ProjectFilePath]; using (var scope = new GraphTransactionScope()) { foreach (var topLevelDependency in allTopLevelDependencies) { var targetedSnapshot = snapshot.Targets[topLevelDependency.TargetFramework]; if (!cachedDependencyToMatchingResultsMap .TryGetValue(topLevelDependency.Id, out HashSet <IDependency> topLevelDependencyMatches)) { var viewProvider = ViewProviders.FirstOrDefault(x => x.Value.SupportsDependency(topLevelDependency)); if (viewProvider == null) { continue; } var processed = viewProvider.Value.MatchSearchResults( snapshotProvider.ProjectFilePath, topLevelDependency, searchResultsPerContext, out topLevelDependencyMatches); if (!processed) { if (matchedDependencies.Count == 0) { continue; } topLevelDependencyMatches = GetMatchingResultsForDependency( topLevelDependency, targetedSnapshot, matchedDependencies, cachedDependencyToMatchingResultsMap); } cachedDependencyToMatchingResultsMap[topLevelDependency.Id] = topLevelDependencyMatches; } if (topLevelDependencyMatches.Count == 0) { continue; } var topLevelNode = Builder.AddTopLevelGraphNode(graphContext, snapshotProvider.ProjectFilePath, topLevelDependency.ToViewModel(targetedSnapshot)); foreach (var matchedDependency in topLevelDependencyMatches) { var matchedDependencyNode = Builder.AddGraphNode(graphContext, snapshotProvider.ProjectFilePath, topLevelNode, matchedDependency.ToViewModel(targetedSnapshot)); graphContext.Graph.Links.GetOrCreate(topLevelNode, matchedDependencyNode, null /*label*/, GraphCommonSchema.Contains); } if (topLevelNode != null) { // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelNode.AddCategory(CodeNodeCategories.ProjectItem); } } scope.Complete(); } } graphContext.OnCompleted(); }
internal static List <IGraphQuery> GetGraphQueries(IGraphContext context) { var graphQueries = new List <IGraphQuery>(); if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren)) { graphQueries.Add(new ContainsChildrenGraphQuery()); } if (context.Direction == GraphContextDirection.Contains || (context.Direction == GraphContextDirection.Target && context.LinkCategories.Contains(CodeLinkCategories.Contains))) { graphQueries.Add(new ContainsGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.InheritsFrom)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new InheritsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new InheritedByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.SourceReferences)) { graphQueries.Add(new IsUsedByGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.Calls)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new CallsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new IsCalledByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.Implements)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new ImplementsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new ImplementedByGraphQuery()); } } if (context.LinkCategories.Contains(RoslynGraphCategories.Overrides)) { if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new OverridesGraphQuery()); } else if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new OverriddenByGraphQuery()); } } if (context.Direction == GraphContextDirection.Custom) { var searchParameters = context.GetValue <ISolutionSearchParameters>(typeof(ISolutionSearchParameters).GUID.ToString()); if (searchParameters != null) { // WARNING: searchParameters.SearchQuery returns an IVsSearchQuery object, which // is a COM type. Therefore, it's probably best to grab the values we want now // rather than get surprised by COM marshalling later. graphQueries.Add(new SearchGraphQuery(searchParameters.SearchQuery.SearchString)); } } return(graphQueries); }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private void Search(IGraphContext graphContext) { string searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); ISolutionSearchParameters searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); string?searchTerm = searchParameters?.SearchQuery.SearchString; if (searchTerm == null) { return; } var cachedDependencyToMatchingResultsMap = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var searchResultsPerContext = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); System.Collections.Generic.IReadOnlyCollection <IDependenciesSnapshot> snapshots = AggregateSnapshotProvider.GetSnapshots(); foreach (IDependenciesSnapshot snapshot in snapshots) { searchResultsPerContext[snapshot.ProjectPath] = SearchFlat( searchTerm, snapshot); } foreach (IDependenciesSnapshot snapshot in snapshots) { IEnumerable <IDependency> allTopLevelDependencies = snapshot.GetFlatTopLevelDependencies(); HashSet <IDependency> matchedDependencies = searchResultsPerContext[snapshot.ProjectPath]; using var scope = new GraphTransactionScope(); foreach (IDependency topLevelDependency in allTopLevelDependencies) { ITargetedDependenciesSnapshot targetedSnapshot = snapshot.DependenciesByTargetFramework[topLevelDependency.TargetFramework]; if (!cachedDependencyToMatchingResultsMap .TryGetValue(topLevelDependency.Id, out HashSet <IDependency>?topLevelDependencyMatches)) { IDependenciesGraphViewProvider?viewProvider = FindViewProvider(topLevelDependency); if (viewProvider == null) { continue; } if (!viewProvider.MatchSearchResults( topLevelDependency, searchResultsPerContext, out topLevelDependencyMatches)) { if (matchedDependencies.Count == 0) { continue; } topLevelDependencyMatches = GetMatchingResultsForDependency( topLevelDependency, targetedSnapshot, matchedDependencies, cachedDependencyToMatchingResultsMap); } cachedDependencyToMatchingResultsMap[topLevelDependency.Id] = topLevelDependencyMatches; } if (topLevelDependencyMatches.Count == 0) { continue; } GraphNode topLevelNode = _builder.AddTopLevelGraphNode(graphContext, snapshot.ProjectPath, topLevelDependency.ToViewModel(targetedSnapshot)); foreach (IDependency matchedDependency in topLevelDependencyMatches) { GraphNode matchedDependencyNode = _builder.AddGraphNode(graphContext, snapshot.ProjectPath, topLevelNode, matchedDependency.ToViewModel(targetedSnapshot)); graphContext.Graph.Links.GetOrCreate(topLevelNode, matchedDependencyNode, label: null, GraphCommonSchema.Contains); } if (topLevelNode != null) { // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelNode.AddCategory(CodeNodeCategories.ProjectItem); } } scope.Complete(); } graphContext.OnCompleted(); }
internal static List <IGraphQuery> GetGraphQueries( IGraphContext context, IThreadingContext threadingContext, IAsynchronousOperationListener asyncListener) { var graphQueries = new List <IGraphQuery>(); if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren)) { graphQueries.Add(new ContainsChildrenGraphQuery()); } if (context.Direction == GraphContextDirection.Contains || (context.Direction == GraphContextDirection.Target && context.LinkCategories.Contains(CodeLinkCategories.Contains))) { graphQueries.Add(new ContainsGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.InheritsFrom)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new InheritsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new InheritedByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.SourceReferences)) { graphQueries.Add(new IsUsedByGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.Calls)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new CallsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new IsCalledByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.Implements)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new ImplementsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new ImplementedByGraphQuery()); } } if (context.LinkCategories.Contains(RoslynGraphCategories.Overrides)) { if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new OverridesGraphQuery()); } else if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new OverriddenByGraphQuery()); } } if (context.Direction == GraphContextDirection.Custom) { var searchParameters = context.GetValue <ISolutionSearchParameters>(typeof(ISolutionSearchParameters).GUID.ToString()); if (searchParameters != null) { // WARNING: searchParameters.SearchQuery returns an IVsSearchQuery object, which is a COM type. // Therefore, it's probably best to grab the values we want now rather than get surprised by COM // marshalling later. // // Create two queries. One to find results in normal docs, and one to find results in generated // docs. That way if the generated docs take a long time we can still report the regular doc // results immediately. graphQueries.Add(new SearchGraphQuery(searchParameters.SearchQuery.SearchString, NavigateToSearchScope.RegularDocuments, threadingContext, asyncListener)); graphQueries.Add(new SearchGraphQuery(searchParameters.SearchQuery.SearchString, NavigateToSearchScope.GeneratedDocuments, threadingContext, asyncListener)); } } return(graphQueries); }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private async Task SearchAsync(IGraphContext graphContext) { var searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); var searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); if (searchParameters == null) { return; } var searchTerm = searchParameters.SearchQuery.SearchString?.ToLowerInvariant(); if (searchTerm == null) { return; } var projectContexts = ProjectContextProvider.GetProjectContexts(); foreach (var projectContext in projectContexts) { var subTreeProviders = projectContext.GetProviders(); foreach (var subTreeProvider in subTreeProviders) { await RegisterSubTreeProviderAsync(subTreeProvider, graphContext).ConfigureAwait(false); foreach (var topLevelNode in subTreeProvider.RootNode.Children) { var refreshedTopLevelNode = subTreeProvider.GetDependencyNode(topLevelNode.Id); if (refreshedTopLevelNode == null) { continue; } var matchingNodes = await subTreeProvider.SearchAsync(refreshedTopLevelNode, searchTerm).ConfigureAwait(true); if (matchingNodes == null || matchingNodes.Count() <= 0) { continue; } // Note: scope should start and complete on the same thread, so we have to do it for each provider. using (var scope = new GraphTransactionScope()) { // add provider's root node to display matching nodes var topLevelGraphNode = AddTopLevelGraphNode(graphContext, projectContext.ProjectFilePath, subTreeProvider, nodeInfo: refreshedTopLevelNode); // now recursively add graph nodes for provider nodes that match search criteria under // provider's root node AddNodesToGraphRecursive(graphContext, projectContext.ProjectFilePath, subTreeProvider, topLevelGraphNode, matchingNodes); // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelGraphNode.AddCategory(CodeNodeCategories.ProjectItem); scope.Complete(); } } } } graphContext.OnCompleted(); }
public void BeginGetGraphData(IGraphContext context) { EnsureInitialized(); var graphQueries = new List <IGraphQuery>(); if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren)) { graphQueries.Add(new ContainsChildrenGraphQuery()); } if (context.Direction == GraphContextDirection.Contains) { graphQueries.Add(new ContainsGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.InheritsFrom)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new InheritsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new InheritedByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.SourceReferences)) { graphQueries.Add(new IsUsedByGraphQuery()); } if (context.LinkCategories.Contains(CodeLinkCategories.Calls)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new CallsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new IsCalledByGraphQuery()); } } if (context.LinkCategories.Contains(CodeLinkCategories.Implements)) { if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new ImplementsGraphQuery()); } else if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new ImplementedByGraphQuery()); } } if (context.LinkCategories.Contains(RoslynGraphCategories.Overrides)) { if (context.Direction == GraphContextDirection.Source) { graphQueries.Add(new OverridesGraphQuery()); } else if (context.Direction == GraphContextDirection.Target) { graphQueries.Add(new OverriddenByGraphQuery()); } } if (context.Direction == GraphContextDirection.Custom) { var searchParameters = context.GetValue <ISolutionSearchParameters>(typeof(ISolutionSearchParameters).GUID.ToString()); if (searchParameters != null) { // WARNING: searchParameters.SearchQuery returns an IVsSearchQuery object, which // is a COM type. Therefore, it's probably best to grab the values we want now // rather than get surprised by COM marshalling later. graphQueries.Add(new SearchGraphQuery(searchParameters.SearchQuery.SearchString)); } } if (graphQueries.Count > 0) { _graphQueryManager.AddQueries(context, graphQueries); } else { // It's an unknown query type, so we're done context.OnCompleted(); } }