Exemplo n.º 1
0
        internal async Task BeginGetGraphDataAsync(IGraphContext context)
        {
            try
            {
                await EnsureInitializedAsync().ConfigureAwait(false);

                if (context.Direction == GraphContextDirection.Self &&
                    context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
                {
                    await CheckChildrenAsync(context).ConfigureAwait(false);
                }
                else if (context.Direction == GraphContextDirection.Contains)
                {
                    await GetChildrenAsync(context).ConfigureAwait(false);
                }
                else if (context.Direction == GraphContextDirection.Custom)
                {
                    await SearchAsync(context).ConfigureAwait(false);
                }
            }
            finally
            {
                // OnCompleted must be called to display changes
                context.OnCompleted();
            }
        }
        private void SearchNextItem(string term, IGraphContext context)
        {
            if (context.CancelToken.IsCancellationRequested || string.IsNullOrEmpty(term))
            {
                // stop right here, no more calls and empty the queue.
                this.searchItems = null;
                return;
            }

            IItemNode item;

            if (this.searchItems != null && this.searchItems.TryDequeue(out item))
            {
                var normalizedTerm    = term.ToLowerInvariant();
                var installedPackages = GetInstalledPackages(item.PhysicalPath)
                                        .Where(x => x.Id.ToLowerInvariant().Contains(normalizedTerm))
                                        .ToList();

                tracer.Info("Found {0} packages installed matching {1} on package file {2}",
                            installedPackages.Count, normalizedTerm, item.PhysicalPath);
                AddPackageNodes(context, () => this.GetOrCreateConfigNode(context, item), installedPackages, false);

                Application.Current.Dispatcher.BeginInvoke(new Action <string, IGraphContext>(SearchNextItem), term, context);
            }
            else
            {
                context.OnCompleted();
            }
        }
        public void BeginGetGraphData(IGraphContext context)
        {
            if (context.CancelToken.IsCancellationRequested)
            {
                return;
            }

            switch (context.Direction)
            {
            case GraphContextDirection.Self:
            {
                if (context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
                {
                    Prepare(context);
                }
                break;
            }

            case GraphContextDirection.Contains:
            {
                Prepare(context);
                TryPopulatePaketNode(context);
                break;
            }

            case GraphContextDirection.Custom:
                break;
            }

            context.OnCompleted();
        }
        internal async Task BeginGetGraphDataAsync(IGraphContext context)
        {
            try
            {
                await InitializeAsync();

                IEnumerable <Lazy <IDependenciesGraphActionHandler, IOrderPrecedenceMetadataView> > actionHandlers = GraphActionHandlers.Where(x => x.Value.CanHandleRequest(context));
                bool shouldTrackChanges = actionHandlers.Aggregate(
                    false, (previousTrackFlag, handler) => previousTrackFlag || handler.Value.HandleRequest(context));

                if (!shouldTrackChanges)
                {
                    return;
                }

                lock (_expandedGraphContextsLock)
                {
                    if (!ExpandedGraphContexts.Contains(context))
                    {
                        // Remember this graph context in order to track changes.
                        // When references change, we will adjust children of this graph as necessary
                        ExpandedGraphContexts.Add(context);
                    }
                }
            }
            finally
            {
                // OnCompleted must be called to display changes
                context.OnCompleted();
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Entry point for progression. Gets called every time when progression
        ///  - Needs to know if a node has children
        ///  - Wants to get children for a node
        ///  - During solution explorer search
        /// </summary>
        public void BeginGetGraphData(IGraphContext context)
        {
            JoinableFactory.RunAsync(async() =>
            {
                try
                {
                    await InitializeAsync();

                    foreach (Lazy <IDependenciesGraphActionHandler, IOrderPrecedenceMetadataView> handler in _graphActionHandlers)
                    {
                        if (handler.Value.TryHandleRequest(context))
                        {
                            _changeTracker.RegisterGraphContext(context);

                            // Only one handler should succeed
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    context.ReportError(ex);
                }
                finally
                {
                    // OnCompleted must be called to display changes
                    context.OnCompleted();
                }
            });
        }
Exemplo n.º 6
0
        private void CreateChildren(object state)
        {
            IGraphContext context = (IGraphContext)state;

            using (GraphTransactionScope scope = new GraphTransactionScope())
            {
                foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssAtDirectivesParent)))
                {
                    CreateChild <AtDirective>(context, node, CssGraphSchema.CssAtDirectives);
                    context.ReportProgress(1, 3, null);
                }

                foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssIdSelectorParent)))
                {
                    CreateChild <IdSelector>(context, node, CssGraphSchema.CssIdSelector);
                    context.ReportProgress(2, 3, null);
                }

                foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssClassSelectorParent)))
                {
                    CreateChild <ClassSelector>(context, node, CssGraphSchema.CssClassSelector);
                    context.ReportProgress(3, 3, null);
                }

                scope.Complete();
            }

            context.OnCompleted();
        }
Exemplo n.º 7
0
        internal async Task BeginGetGraphDataAsync(IGraphContext context)
        {
            try
            {
                await InitializeAsync().ConfigureAwait(false);

                var actionHandlers     = GraphActionHandlers.Where(x => x.Value.CanHandleRequest(context));
                var shouldTrackChanges = actionHandlers.Aggregate(
                    false, (previousTrackFlag, handler) => previousTrackFlag || handler.Value.HandleRequest(context));

                lock (_expandedGraphContextsLock)
                {
                    if (shouldTrackChanges && !ExpandedGraphContexts.Contains(context))
                    {
                        // Remember this graph context in order to track changes.
                        // When references change, we will adjust children of this graph as necessary
                        ExpandedGraphContexts.Add(context);
                    }
                }
            }
            finally
            {
                // OnCompleted must be called to display changes
                context.OnCompleted();
            }
        }
Exemplo n.º 8
0
        public void BeginGetGraphData(IGraphContext context)
        {
            if (context.Direction == GraphContextDirection.Self &&
                context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
            {
                MarkThatNodesHaveChildren(context);
            }

            else if (context.Direction == GraphContextDirection.Self ||
                     (context.Direction == GraphContextDirection.Contains && context.NodeCategories.Any(c => c.IsBasedOn(MarkdownSchema.Heading))))
            {
                PopulateChildrenOfNodes(context);
            }

            context.OnCompleted();
        }
Exemplo n.º 9
0
        public void BeginGetGraphData(IGraphContext context)
        {
            EnsureInitialized();

            var graphQueries = GetGraphQueries(context);

            if (graphQueries.Count > 0)
            {
                _graphQueryManager.AddQueries(context, graphQueries);
            }
            else
            {
                // It's an unknown query type, so we're done
                context.OnCompleted();
            }
        }
Exemplo n.º 10
0
        private void BeginGetGraphData(IGraphContext context, bool queueUserWorkItem)
        {
            if (context.Direction == GraphContextDirection.Self &&
                context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
            {
                var configNode = context.InputNodes.FirstOrDefault(node => node.IsConfigNode());
                if (configNode != null)
                {
                    using (var scope = new GraphTransactionScope())
                    {
                        configNode.SetValue(DgmlNodeProperties.ContainsChildren, true);
                        scope.Complete();
                    }
                }
            }
            else if (context.Direction == GraphContextDirection.Contains)
            {
                var configNode = context.InputNodes.FirstOrDefault(node => node.IsConfigNode());
                if (configNode != null)
                {
                    if (queueUserWorkItem)
                    {
                        ThreadPool.QueueUserWorkItem(TryAddPackageNodes, context);
                    }
                    else
                    {
                        TryAddPackageNodes(context);
                    }

                    // Prevent OnCompleted since we're either doing it
                    // async or synchronously and completing in AddPackageNodes.
                    return;
                }
            }
            else if (context.Direction == GraphContextDirection.Custom)
            {
                StartSearch(context);
                return;
            }

            context.OnCompleted();
        }
Exemplo n.º 11
0
        internal void AddQueries(IGraphContext context, List<IGraphQuery> graphQueries)
        {
            var asyncToken = _asyncListener.BeginAsyncOperation("GraphQueryManager.AddQueries");

            var solution = _workspace.CurrentSolution;

            var populateTask = PopulateContextGraphAsync(solution, graphQueries, context);

            // We want to ensure that no matter what happens, this initial context is completed
            var task = populateTask.SafeContinueWith(
                _ => context.OnCompleted(), context.CancelToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            if (context.TrackChanges)
            {
                task = task.SafeContinueWith(
                    _ => TrackChangesAfterFirstPopulate(graphQueries, context, solution),
                    context.CancelToken, TaskContinuationOptions.None, TaskScheduler.Default);
            }

            task.CompletesAsyncOperation(asyncToken);
        }
Exemplo n.º 12
0
        internal void AddQueries(IGraphContext context, List <IGraphQuery> graphQueries)
        {
            var asyncToken = _asyncListener.BeginAsyncOperation("GraphQueryManager.AddQueries");

            var solution = _workspace.CurrentSolution;

            var populateTask = PopulateContextGraphAsync(solution, graphQueries, context);

            // We want to ensure that no matter what happens, this initial context is completed
            var task = populateTask.SafeContinueWith(
                _ => context.OnCompleted(), context.CancelToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            if (context.TrackChanges)
            {
                task = task.SafeContinueWith(
                    _ => TrackChangesAfterFirstPopulate(graphQueries, context, solution),
                    context.CancelToken, TaskContinuationOptions.None, TaskScheduler.Default);
            }

            task.CompletesAsyncOperation(asyncToken);
        }
Exemplo n.º 13
0
        public override void BeginGetGraphData(IGraphContext context)
        {
            RegisterImages();

            if (context.Direction == GraphContextDirection.Contains)
            {
                CreateOutline(context);

                if (context.TrackChanges)
                {
                    ThreadPool.QueueUserWorkItem(CreateChildren, context);
                }
                else
                {
                    CreateChildren(context);
                }

                return; // Don't call OnCompleted
            }
            else if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
            {
                foreach (GraphNode node in GetAllowedFiles(context.InputNodes))
                {
                    node.SetValue(DgmlNodeProperties.ContainsChildren, true);
                }

                foreach (var node in context.InputNodes.Where(n =>
                                                              n.HasCategory(CssGraphSchema.CssAtDirectivesParent) ||
                                                              n.HasCategory(CssGraphSchema.CssIdSelectorParent) ||
                                                              n.HasCategory(CssGraphSchema.CssClassSelectorParent)
                                                              ))
                {
                    node.SetValue(DgmlNodeProperties.ContainsChildren, true);
                }
            }

            // Signals that all results have been created.
            context.OnCompleted();
        }
Exemplo n.º 14
0
        internal async Task BeginGetGraphDataAsync(IGraphContext context)
        {
            try
            {
                await InitializeAsync();

                bool shouldTrackChanges = false;
                foreach (Lazy <IDependenciesGraphActionHandler, IOrderPrecedenceMetadataView> handler in _graphActionHandlers)
                {
                    if (handler.Value.CanHandleRequest(context) &&
                        handler.Value.HandleRequest(context))
                    {
                        shouldTrackChanges = true;
                        break;
                    }
                }

                if (!shouldTrackChanges)
                {
                    return;
                }

                lock (_expandedGraphContexts)
                {
                    if (!_expandedGraphContexts.Contains(context))
                    {
                        // Remember this graph context in order to track changes.
                        // When references change, we will adjust children of this graph as necessary
                        _expandedGraphContexts.Add(context);
                    }
                }
            }
            finally
            {
                // OnCompleted must be called to display changes
                context.OnCompleted();
            }
        }
Exemplo n.º 15
0
        private void CreateChildren(object state)
        {
            IGraphContext context = (IGraphContext)state;

            using (GraphTransactionScope scope = new GraphTransactionScope())
            {
                foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessMixinParent)))
                {
                    CreateChild <LessMixinDeclaration>(context, node, LessGraphSchema.LessMixin);
                    context.ReportProgress(1, 2, null);
                }

                foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessVariableParent)))
                {
                    CreateChild <LessVariableDeclaration>(context, node, LessGraphSchema.LessVariable);
                    context.ReportProgress(2, 2, null);
                }

                scope.Complete();
            }

            context.OnCompleted();
        }
        /// <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();
        }
Exemplo n.º 17
0
        /// <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();
        }
Exemplo n.º 18
0
        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();
            }
        }
        /// <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();
        }
        public override void BeginGetGraphData(IGraphContext context)
        {
            RegisterImages();

            if (context.Direction == GraphContextDirection.Contains)
            {
                CreateOutline(context);

                if (context.TrackChanges)
                {
                    ThreadPool.QueueUserWorkItem(CreateChildren, context);
                }
                else
                {
                    CreateChildren(context);
                }

                return;
            }
            else if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren))
            {
                foreach (GraphNode node in GetAllowedFiles(context.InputNodes))
                {
                    node.SetValue(DgmlNodeProperties.ContainsChildren, true);
                }

                foreach (var node in context.InputNodes.Where(n =>
                    n.HasCategory(LessGraphSchema.LessMixinParent) ||
                    n.HasCategory(LessGraphSchema.LessVariableParent)
                    ))
                {
                    node.SetValue(DgmlNodeProperties.ContainsChildren, true);
                }
            }

            // Signals that all results have been created.
            context.OnCompleted();
        }