private GraphNode DoAddGraphNode(GraphNodeId graphNodeId, IGraphContext graphContext, string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider, GraphNode parentNode, IDependencyNode nodeInfo) { var newNode = graphContext.Graph.Nodes.GetOrCreate(graphNodeId, nodeInfo.Caption, null); newNode.SetValue(DgmlNodeProperties.Icon, GetIconStringName(nodeInfo.Icon)); newNode.SetValue(DependenciesGraphSchema.DependencyNodeProperty, nodeInfo); // priority sets correct order among peers newNode.SetValue(CodeNodeProperties.SourceLocation, new SourceLocation(projectPath, new Position(nodeInfo.Priority, 0))); newNode.SetValue(DependenciesGraphSchema.ProviderProperty, subTreeProvider); newNode.AddCategory(DependenciesGraphSchema.CategoryDependency); graphContext.OutputNodes.Add(newNode); if (parentNode != null) { graphContext.Graph.Links.GetOrCreate(parentNode, newNode, /*label*/ null, CodeLinkCategories.Contains); } return(newNode); }
public IDependencyViewModel CreateRootViewModel(string providerType, bool hasUnresolvedDependency) { IProjectDependenciesSubTreeProvider provider = GetProvider(providerType); IDependencyModel dependencyModel = provider.CreateRootDependencyNode(); return(dependencyModel.ToViewModel(hasUnresolvedDependency)); }
private GraphNode AddTopLevelGraphNode(IGraphContext graphContext, string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider, IDependencyNode nodeInfo) { var newNodeId = GetTopLevelGraphNodeId(projectPath, nodeInfo); return(DoAddGraphNode(newNodeId, graphContext, projectPath, subTreeProvider, null, nodeInfo)); }
public DependenciesChangedEventArgs( IProjectDependenciesSubTreeProvider provider, string?targetShortOrFullName, IDependenciesChanges changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) : this(provider, targetShortOrFullName, changes, CancellationToken.None) { }
private GraphNode AddGraphNode(IGraphContext graphContext, string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider, GraphNode parentNode, IDependencyNode nodeInfo) { var newNodeId = GetGraphNodeId(projectPath, nodeInfo); return(DoAddGraphNode(newNodeId, graphContext, projectPath, subTreeProvider, parentNode, nodeInfo)); }
public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) { Provider = provider; Changes = changes; Catalogs = catalogs; DataSourceVersions = dataSourceVersions; }
/// <summary> /// Initializes a new instance of <see cref="DependenciesChangedEventArgs"/>. /// </summary> /// <param name="provider">The subtree provider whose dependencies changed.</param> /// <param name="targetShortOrFullName"> /// The short or full name of the target framework to which <paramref name="changes"/> apply. /// Optional if the project is not multi-targeting. /// </param> /// <param name="changes">The collection of dependency changes.</param> /// <param name="token">A cancellation token that allows cancelling the update.</param> public DependenciesChangedEventArgs( IProjectDependenciesSubTreeProvider provider, string?targetShortOrFullName, IDependenciesChanges changes, CancellationToken token) { Provider = provider; TargetShortOrFullName = targetShortOrFullName; Changes = changes; Token = token; }
public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider, string targetShortOrFullName, IDependenciesChanges changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) { Provider = provider; TargetShortOrFullName = targetShortOrFullName; Changes = changes; Catalogs = catalogs; DataSourceVersions = dataSourceVersions; }
private void AddNodesToGraphRecursive(IGraphContext graphContext, string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider, GraphNode parentNode, IEnumerable <IDependencyNode> nodes) { foreach (var nodeInfo in nodes) { var graphNode = AddGraphNode(graphContext, projectPath, subTreeProvider, parentNode, nodeInfo); graphContext.Graph.Links.GetOrCreate(parentNode, graphNode, null, GraphCommonSchema.Contains); AddNodesToGraphRecursive(graphContext, projectPath, subTreeProvider, graphNode, nodeInfo.Children); } }
private async Task RegisterSubTreeProviderAsync(IProjectDependenciesSubTreeProvider subTreeProvider, IGraphContext graphContext) { lock (_RegisteredSubTreeProvidersLock) { if (RegisteredSubTreeProviders.Contains(subTreeProvider.ProviderType)) { return; } RegisteredSubTreeProviders.Add(subTreeProvider.ProviderType); } var icons = subTreeProvider.Icons; if (icons == null) { return; } IVsImageService2 imageService = null; foreach (var icon in icons) { if (Images.Contains(icon)) { // already registered - next continue; } // register icon if (imageService == null) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); imageService = ServiceProvider.GetService <IVsImageService2, SVsImageService>(); } imageService.TryAssociateNameWithMoniker(GetIconStringName(icon), icon); Images.Add(icon); } }
public static IDependenciesGraphProjectContextProvider Implement( string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider = null, IEnumerable <IProjectDependenciesSubTreeProvider> subTreeProviders = null, MockBehavior?mockBehavior = null) { var behavior = mockBehavior ?? MockBehavior.Default; var mock = new Mock <IDependenciesGraphProjectContextProvider>(behavior); var mockProjectContext = new Mock <IDependenciesGraphProjectContext>(); mockProjectContext.Setup(x => x.GetProvider("MyProvider")).Returns(subTreeProvider); mock.Setup(x => x.GetProjectContext(projectPath)).Returns(mockProjectContext.Object); if (subTreeProviders != null) { mockProjectContext.Setup(x => x.ProjectFilePath).Returns(projectPath); mockProjectContext.Setup(x => x.GetProviders()).Returns(subTreeProviders); mock.Setup(x => x.GetProjectContexts()).Returns(new[] { mockProjectContext.Object }); } return(mock.Object); }
private void AddNodesToGraphRecursive(IGraphContext graphContext, string projectPath, IProjectDependenciesSubTreeProvider subTreeProvider, GraphNode parentNode, IEnumerable <IDependencyNode> nodes, string searchTerm, HashSet <string> flatSearchResults) { foreach (var nodeInfo in nodes) { if (nodeInfo.Caption.ToLowerInvariant().Contains(searchTerm) && !flatSearchResults.Contains(nodeInfo.Caption)) { flatSearchResults.Add(nodeInfo.Caption); var graphNode = AddGraphNode(graphContext, projectPath, subTreeProvider, parentNode, nodeInfo); graphContext.Graph.Links.GetOrCreate(parentNode, graphNode, null, GraphCommonSchema.Contains); } var nodeChildren = nodeInfo.Children; AddNodesToGraphRecursive(graphContext, projectPath, subTreeProvider, parentNode, nodeChildren, searchTerm, flatSearchResults); } }
/// <summary> /// Creates or updates a project tree for a given IProjectDependenciesSubTreeProvider /// </summary> /// <param name="dependenciesNode"></param> /// <param name="subTreeProvider"></param> /// <param name="changes"></param> /// <param name="catalogs">Can be null if sub tree provider does not use design time build</param> /// <param name="cancellationToken"></param> /// <returns>IProjectTree for root Dependencies node</returns> private IProjectTree CreateOrUpdateSubTreeProviderNode(IProjectTree dependenciesNode, IProjectDependenciesSubTreeProvider subTreeProvider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, CancellationToken cancellationToken) { Requires.NotNull(dependenciesNode, nameof(dependenciesNode)); Requires.NotNull(subTreeProvider, nameof(subTreeProvider)); Requires.NotNull(subTreeProvider.RootNode, nameof(subTreeProvider.RootNode)); Requires.NotNullOrEmpty(subTreeProvider.RootNode.Caption, nameof(subTreeProvider.RootNode.Caption)); Requires.NotNullOrEmpty(subTreeProvider.ProviderType, nameof(subTreeProvider.ProviderType)); var projectFolder = Path.GetDirectoryName(UnconfiguredProject.FullPath); var providerRootTreeNode = GetSubTreeRootNode(dependenciesNode, subTreeProvider.RootNode.Flags); if (subTreeProvider.RootNode.HasChildren || subTreeProvider.ShouldBeVisibleWhenEmpty) { bool newNode = false; if (providerRootTreeNode == null) { providerRootTreeNode = NewTree( caption: subTreeProvider.RootNode.Caption, visible: true, filePath: subTreeProvider.RootNode.Id.ToString(), browseObjectProperties: null, flags: subTreeProvider.RootNode.Flags, icon: subTreeProvider.RootNode.Icon.ToProjectSystemType(), expandedIcon: subTreeProvider.RootNode.ExpandedIcon.ToProjectSystemType()); newNode = true; } if (changes != null) { foreach (var removedItem in changes.RemovedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, removedItem, projectFolder); if (treeNode != null) { providerRootTreeNode = treeNode.Remove(); } } foreach (var updatedItem in changes.UpdatedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, updatedItem, projectFolder); if (treeNode != null) { var updatedNodeParentContext = GetCustomPropertyContext(treeNode.Parent); var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = updatedItem.Caption, Flags = updatedItem.Flags, Icon = updatedItem.Icon.ToProjectSystemType(), ExpandedIcon = updatedItem.ExpandedIcon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(updatedNodeParentContext, updatedValues); // update existing tree node properties treeNode = treeNode.SetProperties( caption: updatedItem.Caption, flags: updatedItem.Flags, icon: updatedItem.Icon.ToProjectSystemType(), expandedIcon: updatedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = treeNode.Parent; } } foreach (var addedItem in changes.AddedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = FindProjectTreeNode(providerRootTreeNode, addedItem, projectFolder); if (treeNode == null) { treeNode = CreateProjectItemTreeNode(providerRootTreeNode, addedItem, catalogs); providerRootTreeNode = providerRootTreeNode.Add(treeNode).Parent; } } } if (newNode) { dependenciesNode = dependenciesNode.Add(providerRootTreeNode).Parent; } else { dependenciesNode = providerRootTreeNode.Parent; } } else { if (providerRootTreeNode != null) { dependenciesNode = dependenciesNode.Remove(providerRootTreeNode); } } return(dependenciesNode); }
public override bool CanDependOnProvider(IProjectDependenciesSubTreeProvider otherProvider) { return(NuGetDependenciesSubTreeProvider.ProviderTypeString .Equals(otherProvider?.ProviderType, StringComparison.OrdinalIgnoreCase)); }
/// <summary> /// Creates or updates a project tree for a given IProjectDependenciesSubTreeProvider /// </summary> /// <param name="dependenciesNode"></param> /// <param name="subTreeProvider"></param> /// <param name="changes"></param> /// <param name="catalogs">Can be null if sub tree provider does not use design time build</param> /// <param name="cancellationToken"></param> /// <returns>IProjectTree for root Dependencies node</returns> private IProjectTree CreateOrUpdateSubTreeProviderNode(IProjectTree dependenciesNode, IProjectDependenciesSubTreeProvider subTreeProvider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, CancellationToken cancellationToken) { Requires.NotNull(dependenciesNode, nameof(dependenciesNode)); Requires.NotNull(subTreeProvider, nameof(subTreeProvider)); Requires.NotNull(subTreeProvider.RootNode, nameof(subTreeProvider.RootNode)); Requires.NotNullOrEmpty(subTreeProvider.RootNode.Caption, nameof(subTreeProvider.RootNode.Caption)); Requires.NotNullOrEmpty(subTreeProvider.ProviderType, nameof(subTreeProvider.ProviderType)); var providerRootTreeNode = GetSubTreeRootNode(dependenciesNode, subTreeProvider.RootNode.Flags); if (subTreeProvider.RootNode.HasChildren || subTreeProvider.ShouldBeVisibleWhenEmpty) { bool newNode = false; if (providerRootTreeNode == null) { providerRootTreeNode = NewTree( caption: subTreeProvider.RootNode.Caption, visible: true, filePath: subTreeProvider.RootNode.Id.ToString(), browseObjectProperties: null, flags: subTreeProvider.RootNode.Flags, icon: subTreeProvider.RootNode.Icon.ToProjectSystemType(), expandedIcon: subTreeProvider.RootNode.ExpandedIcon.ToProjectSystemType()); newNode = true; } if (changes != null) { foreach (var removedItem in changes.RemovedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(removedItem.Id.ToString()); if (treeNode != null) { providerRootTreeNode = treeNode.Remove(); } } foreach (var updatedItem in changes.UpdatedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(updatedItem.Id.ToString()); if (treeNode != null) { var updatedNodeParentContext = GetCustomPropertyContext(treeNode.Parent); var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = updatedItem.Caption, Flags = updatedItem.Flags, Icon = updatedItem.Icon.ToProjectSystemType(), ExpandedIcon = updatedItem.ExpandedIcon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(updatedNodeParentContext, updatedValues); // update existing tree node properties treeNode = treeNode.SetProperties( caption: updatedItem.Caption, flags: updatedItem.Flags, icon: updatedItem.Icon.ToProjectSystemType(), expandedIcon: updatedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = treeNode.Parent; } } var configuredProjectExports = GetActiveConfiguredProjectExports(ActiveConfiguredProject); foreach (var addedItem in changes.AddedNodes) { if (cancellationToken.IsCancellationRequested) { return(dependenciesNode); } var treeNode = providerRootTreeNode.FindNodeByPath(addedItem.Id.ToString()); if (treeNode == null) { IRule rule = null; if (addedItem.Properties != null) { // when itemSpec is not in valid absolute path format, property page does not show // item name correctly. var itemSpec = addedItem.Flags.Contains(DependencyNode.CustomItemSpec) ? addedItem.Caption : addedItem.Id.ItemSpec; var itemContext = ProjectPropertiesContext.GetContext(UnconfiguredProject, addedItem.Id.ItemType, itemSpec); if (addedItem.Resolved) { rule = GetRuleForResolvableReference( itemContext, new KeyValuePair <string, IImmutableDictionary <string, string> >( addedItem.Id.ItemSpec, addedItem.Properties), catalogs, configuredProjectExports); } else { rule = GetRuleForUnresolvableReference( itemContext, catalogs, configuredProjectExports); } } // Notify about tree changes to customization context var customTreePropertyContext = GetCustomPropertyContext(providerRootTreeNode); var customTreePropertyValues = new ReferencesProjectTreeCustomizablePropertyValues { Caption = addedItem.Caption, Flags = addedItem.Flags, Icon = addedItem.Icon.ToProjectSystemType() }; ApplyProjectTreePropertiesCustomization(customTreePropertyContext, customTreePropertyValues); treeNode = NewTree(caption: addedItem.Caption, visible: true, filePath: addedItem.Id.ToString(), browseObjectProperties: rule, flags: addedItem.Flags, icon: addedItem.Icon.ToProjectSystemType(), expandedIcon: addedItem.ExpandedIcon.ToProjectSystemType()); providerRootTreeNode = providerRootTreeNode.Add(treeNode).Parent; } } } if (newNode) { dependenciesNode = dependenciesNode.Add(providerRootTreeNode).Parent; } else { dependenciesNode = providerRootTreeNode.Parent; } } else { if (providerRootTreeNode != null) { dependenciesNode = dependenciesNode.Remove(providerRootTreeNode); } } return(dependenciesNode); }
public override bool CanDependOnProvider(IProjectDependenciesSubTreeProvider otherProvider) { // projects depend on all kinds of providers changes return(true); }
GetDependencyNodeInfoAsync(IGraphContext graphContext, GraphNode inputGraphNode, string projectPath) { IDependencyNode node = null; IProjectDependenciesSubTreeProvider subTreeProvider = null; // check if node is toplevel or lowerlevel hierarchy node = inputGraphNode.GetValue <IDependencyNode>(DependenciesGraphSchema.DependencyNodeProperty); if (node == null) { // this is a top level dependency node or unsupported node like some source file node var hierarchyItem = inputGraphNode.GetValue <IVsHierarchyItem>(HierarchyGraphNodeProperties.HierarchyItem); if (hierarchyItem == null) { // unknown node return(node, subTreeProvider); } // now check node file path if it is a DependencyNodeId var nodeFilePath = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.File); var nodeId = DependencyNodeId.FromString(nodeFilePath); if (nodeId == null) { // check parent node - it will be a IProjectTree node which can have file path to be // in our DependencyNodeId format. If it is a top level dependency, it's parent will // be provider root node: Dependencies\NuGet\<top level dependency>. In this sample // parent for <top level dependency> will be NuGet node, which will be not IProjectItemTree, // but IProjecTree and thus has FilePath containing actual DependencyNodeId. var parentFilePath = hierarchyItem.Parent.CanonicalName; nodeId = DependencyNodeId.FromString(parentFilePath); } if (nodeId == null) { // unknown node return(node, subTreeProvider); } subTreeProvider = await GetSubTreeProviderAsync(graphContext, inputGraphNode, projectPath, nodeId).ConfigureAwait(false); if (subTreeProvider == null) { return(node, subTreeProvider); } // now get real DependencyNodeId - find the actual node in the provider's top // level node. Note: nodeId above we need only to get correct sub tree provider, but // it would not contain our top level node's ItemSpec, ItemType etc. We need to get it here. var caption = hierarchyItem.Text; node = subTreeProvider.RootNode.Children.Where(x => x.Caption.Equals(caption, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (node == null) { // node is not ours or does node exist anymore return(node, subTreeProvider); } } else { // this is lower level graph node that is created by this provider, just get it's subTreeProvider subTreeProvider = await GetSubTreeProviderAsync(graphContext, inputGraphNode, projectPath, node.Id).ConfigureAwait(false); } return(node, subTreeProvider); }
public virtual bool CanDependOnProvider(IProjectDependenciesSubTreeProvider otherProvider) { return(false); }