예제 #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);
        }