/// <summary>
        /// Finds IProjectTree node in the top level children of a given parent IProjectTree node.
        /// Depending on the type of IDependencyNode search method is different:
        ///     - if dependency node has custom ItemSpec, we only can find it by caption.
        ///     - if dependency node has normal ItemSpec, we first try to find it by path and then
        ///       by caption if path was not found (since unresolved and resolved items can have
        ///       different items specs).
        /// </summary>
        private IProjectTree FindProjectTreeNode(IProjectTree parentNode,
                                                 IDependencyNode nodeInfo,
                                                 string projectFolder)
        {
            IProjectTree treeNode = null;

            if (nodeInfo.Flags.Contains(DependencyNode.CustomItemSpec))
            {
                treeNode = parentNode.FindNodeByCaption(nodeInfo.Caption);
            }
            else
            {
                var itemSpec = nodeInfo.Id.ItemSpec;
                if (!ManagedPathHelper.IsRooted(itemSpec))
                {
                    itemSpec = ManagedPathHelper.TryMakeRooted(projectFolder, itemSpec);
                }

                if (!string.IsNullOrEmpty(itemSpec))
                {
                    treeNode = parentNode.FindNodeByPath(itemSpec);
                }

                if (treeNode == null)
                {
                    treeNode = parentNode.FindNodeByCaption(nodeInfo.Caption);
                }
            }

            return(treeNode);
        }
Esempio n. 2
0
        /// <summary>
        /// Builds a sub tree under root: target framework or Dependencies node when there is only one target.
        /// </summary>
        private async Task <IProjectTree> BuildSubTreeAsync(
            IProjectTree rootNode,
            ITargetedDependenciesSnapshot targetedSnapshot,
            IEnumerable <IDependency> dependencies,
            IProjectCatalogSnapshot catalogs,
            bool isActiveTarget,
            bool shouldCleanup)
        {
            var currentNodes = new List <IProjectTree>();

            foreach (IDependency dependency in dependencies)
            {
                IProjectTree dependencyNode      = rootNode.FindNodeByCaption(dependency.Caption);
                bool         isNewDependencyNode = dependencyNode == null;

                if (!isNewDependencyNode &&
                    dependency.Flags.Contains(DependencyTreeFlags.SupportsHierarchy))
                {
                    if ((dependency.Resolved && dependencyNode.Flags.Contains(DependencyTreeFlags.UnresolvedFlags)) ||
                        (!dependency.Resolved && dependencyNode.Flags.Contains(DependencyTreeFlags.ResolvedFlags)))
                    {
                        // when transition from unresolved to resolved or vise versa - remove old node
                        // and re-add new  one to allow GraphProvider to recalculate children
                        isNewDependencyNode = true;
                        rootNode            = dependencyNode.Remove();
                        dependencyNode      = null;
                    }
                }

                dependencyNode = await CreateOrUpdateNodeAsync(dependencyNode, dependency, targetedSnapshot, catalogs, isActiveTarget);

                currentNodes.Add(dependencyNode);

                if (isNewDependencyNode)
                {
                    rootNode = rootNode.Add(dependencyNode).Parent;
                }
                else
                {
                    rootNode = dependencyNode.Parent;
                }
            }

            if (shouldCleanup)
            {
                rootNode = CleanupOldNodes(rootNode, currentNodes);
            }

            return(rootNode);
        }
Esempio n. 3
0
        /// <summary>
        /// Builds Dependencies tree for given dependencies snapshot
        /// </summary>
        public override async Task <IProjectTree> BuildTreeAsync(
            IProjectTree dependenciesTree,
            IDependenciesSnapshot snapshot,
            CancellationToken cancellationToken = default)
        {
            IProjectTree originalTree         = dependenciesTree;
            var          currentTopLevelNodes = new List <IProjectTree>();

            IProjectTree rememberNewNodes(IProjectTree rootNode, IEnumerable <IProjectTree> currentNodes)
            {
                if (currentNodes != null)
                {
                    currentTopLevelNodes.AddRange(currentNodes);
                }

                return(rootNode);
            }

            if (snapshot.Targets.Where(x => !x.Key.Equals(TargetFramework.Any)).Count() == 1)
            {
                foreach (KeyValuePair <ITargetFramework, ITargetedDependenciesSnapshot> target in snapshot.Targets)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(originalTree);
                    }

                    dependenciesTree = await BuildSubTreesAsync(
                        dependenciesTree,
                        snapshot.ActiveTarget,
                        target.Value,
                        target.Value.Catalogs,
                        rememberNewNodes);
                }
            }
            else
            {
                foreach (KeyValuePair <ITargetFramework, ITargetedDependenciesSnapshot> target in snapshot.Targets)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(originalTree);
                    }

                    if (target.Key.Equals(TargetFramework.Any))
                    {
                        dependenciesTree = await BuildSubTreesAsync(dependenciesTree,
                                                                    snapshot.ActiveTarget,
                                                                    target.Value,
                                                                    target.Value.Catalogs,
                                                                    rememberNewNodes);
                    }
                    else
                    {
                        IProjectTree         node = dependenciesTree.FindNodeByCaption(target.Key.FriendlyName);
                        bool                 shouldAddTargetNode = node == null;
                        IDependencyViewModel targetViewModel     = ViewModelFactory.CreateTargetViewModel(target.Value);

                        node = CreateOrUpdateNode(node,
                                                  targetViewModel,
                                                  rule: null,
                                                  isProjectItem: false,
                                                  additionalFlags: ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp));
                        node = await BuildSubTreesAsync(node, snapshot.ActiveTarget, target.Value, target.Value.Catalogs, CleanupOldNodes);

                        if (shouldAddTargetNode)
                        {
                            dependenciesTree = dependenciesTree.Add(node).Parent;
                        }
                        else
                        {
                            dependenciesTree = node.Parent;
                        }

                        currentTopLevelNodes.Add(node);
                    }
                }
            }

            dependenciesTree = CleanupOldNodes(dependenciesTree, currentTopLevelNodes);

            // now update root Dependencies node status
            ProjectImageMoniker rootIcon = ViewModelFactory.GetDependenciesRootIcon(snapshot.HasUnresolvedDependency).ToProjectSystemType();

            return(dependenciesTree.SetProperties(icon: rootIcon, expandedIcon: rootIcon));
        }
Esempio n. 4
0
        /// <summary>
        /// Builds all available sub trees under root: target framework or Dependencies node
        /// when there is only one target.
        /// </summary>
        private async Task <IProjectTree> BuildSubTreesAsync(
            IProjectTree rootNode,
            ITargetFramework activeTarget,
            ITargetedDependenciesSnapshot targetedSnapshot,
            IProjectCatalogSnapshot catalogs,
            Func <IProjectTree, IEnumerable <IProjectTree>, IProjectTree> syncFunc)
        {
            var currentNodes          = new List <IProjectTree>();
            var groupedByProviderType = new Dictionary <string, List <IDependency> >(StringComparer.OrdinalIgnoreCase);

            foreach (IDependency dependency in targetedSnapshot.TopLevelDependencies)
            {
                if (!dependency.Visible)
                {
                    if (dependency.Flags.Contains(DependencyTreeFlags.ShowEmptyProviderRootNode))
                    {
                        // if provider sends special invisible node with flag ShowEmptyProviderRootNode, we
                        // need to show provider node even if it does not have any dependencies.
                        groupedByProviderType.Add(dependency.ProviderType, new List <IDependency>());
                    }

                    continue;
                }

                if (!groupedByProviderType.TryGetValue(dependency.ProviderType, out List <IDependency> dependencies))
                {
                    dependencies = new List <IDependency>();
                    groupedByProviderType.Add(dependency.ProviderType, dependencies);
                }

                dependencies.Add(dependency);
            }

            bool isActiveTarget = targetedSnapshot.TargetFramework.Equals(activeTarget);

            foreach (KeyValuePair <string, List <IDependency> > dependencyGroup in groupedByProviderType)
            {
                IDependencyViewModel subTreeViewModel = ViewModelFactory.CreateRootViewModel(
                    dependencyGroup.Key, targetedSnapshot.CheckForUnresolvedDependencies(dependencyGroup.Key));
                IProjectTree subTreeNode      = rootNode.FindNodeByCaption(subTreeViewModel.Caption);
                bool         isNewSubTreeNode = subTreeNode == null;

                ProjectTreeFlags excludedFlags = ProjectTreeFlags.Empty;
                if (targetedSnapshot.TargetFramework.Equals(TargetFramework.Any))
                {
                    excludedFlags = ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp);
                }

                subTreeNode = CreateOrUpdateNode(
                    subTreeNode,
                    subTreeViewModel,
                    rule: null,
                    isProjectItem: false,
                    excludedFlags: excludedFlags);

                subTreeNode = await BuildSubTreeAsync(
                    subTreeNode,
                    targetedSnapshot,
                    dependencyGroup.Value,
                    catalogs,
                    isActiveTarget,
                    shouldCleanup : !isNewSubTreeNode);

                currentNodes.Add(subTreeNode);

                if (isNewSubTreeNode)
                {
                    rootNode = rootNode.Add(subTreeNode).Parent;
                }
                else
                {
                    rootNode = subTreeNode.Parent;
                }
            }

            return(syncFunc(rootNode, currentNodes));
        }