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); }