Пример #1
0
        private async Task <IProjectDependenciesSubTreeProvider> GetSubTreeProviderAsync(
            IGraphContext graphContext,
            GraphNode inputGraphNode,
            string projectPath,
            DependencyNodeId nodeId)
        {
            // Check if node has ProviderProperty set. It will be set for GraphNodes we created in
            // this class, but root nodes at first would have it set to null so e ould have to use
            // fallback File is part to get provider type for them.
            var subTreeProvider = inputGraphNode?.GetValue <IProjectDependenciesSubTreeProvider>(
                DependenciesGraphSchema.ProviderProperty);

            if (subTreeProvider == null)
            {
                var projectContext = ProjectContextProvider.GetProjectContext(projectPath);
                if (projectContext != null)
                {
                    subTreeProvider = projectContext.GetProvider(nodeId.ProviderType);
                }
            }

            if (subTreeProvider != null)
            {
                await RegisterSubTreeProviderAsync(subTreeProvider, graphContext).ConfigureAwait(false);
            }

            return(subTreeProvider);
        }
        /// <summary>
        /// Returns refreshed dependnecy node. There is a non trivial logic which is important:
        /// in order to find node at anypoint of time, we always fill live node instance children collection,
        /// which then could be found by recusrive search from RootNode. However we return always a new
        /// instance for requested node, to allow graph provider to compare old node instances to new ones
        /// when some thing changes in the dependent project and track changes. So in
        /// DependenciesGrpahProvider.TrackChangesOnGraphContextAsync we always remember old children
        /// collection for existing node, since for top level nodes (sent by CPS IProjectTree(s) we do update
        /// them here, which would make no difference between old and new nodes. For lower hierarchies below top
        /// nodes, new instances solve this problem.
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public override IDependencyNode GetDependencyNode(DependencyNodeId nodeId)
        {
            if (nodeId == null)
            {
                return(null);
            }

            // normalize id to have regular paths (graph provider replaces \ with /.
            nodeId = nodeId.ToNormalizedId();
            var node = RootNode.FindNode(nodeId, recursive: true);

            if (node == null)
            {
                return(null);
            }

            if (string.IsNullOrEmpty(nodeId.ContextProject))
            {
                return(node);
            }

            var projectPath    = nodeId.ContextProject;
            var projectContext = ProjectContextProvider.GetProjectContext(projectPath);

            if (projectContext == null)
            {
                return(node);
            }

            node.RemoveAllChildren();
            foreach (var subTreeProvider in projectContext.GetProviders())
            {
                if (subTreeProvider.RootNode == null || !subTreeProvider.RootNode.HasChildren)
                {
                    continue;
                }

                var rootNodeChildren = subTreeProvider.RootNode.Children;
                foreach (var child in rootNodeChildren)
                {
                    node.AddChild(DependencyNode.Clone(child));
                }
            }

            // create a new instance of the node to allow graph provider to compare changes
            var newNode = CreateDependencyNode(node.Id, node.Priority, node.Properties, node.Resolved);

            newNode.AddChildren(node.Children);

            return(newNode);
        }
Пример #3
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();
        }