Exemple #1
0
        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));
        }
Exemple #3
0
        private GraphNode AddTopLevelGraphNode(IGraphContext graphContext,
                                               string projectPath,
                                               IProjectDependenciesSubTreeProvider subTreeProvider,
                                               IDependencyNode nodeInfo)
        {
            var newNodeId = GetTopLevelGraphNodeId(projectPath, nodeInfo);

            return(DoAddGraphNode(newNodeId, graphContext, projectPath, subTreeProvider, null, nodeInfo));
        }
Exemple #4
0
 public DependenciesChangedEventArgs(
     IProjectDependenciesSubTreeProvider provider,
     string?targetShortOrFullName,
     IDependenciesChanges changes,
     IProjectCatalogSnapshot catalogs,
     IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions)
     : this(provider, targetShortOrFullName, changes, CancellationToken.None)
 {
 }
Exemple #5
0
        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));
        }
Exemple #6
0
 public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider,
                                     IDependenciesChangeDiff changes,
                                     IProjectCatalogSnapshot catalogs,
                                     IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions)
 {
     Provider           = provider;
     Changes            = changes;
     Catalogs           = catalogs;
     DataSourceVersions = dataSourceVersions;
 }
Exemple #7
0
 /// <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;
 }
Exemple #9
0
        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);
            }
        }
Exemple #10
0
        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);
        }
Exemple #14
0
 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);
 }
Exemple #17
0
        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);
        }
Exemple #18
0
 public virtual bool CanDependOnProvider(IProjectDependenciesSubTreeProvider otherProvider)
 {
     return(false);
 }