/// <summary>
 /// Specifies if there is unresolved child somewhere in the dependency graph
 /// </summary>
 public static bool HasUnresolvedDependency(this IDependency self, ITargetedDependenciesSnapshot snapshot)
 {
     return(snapshot.CheckForUnresolvedDependencies(self));
 }
        private async Task <IProjectTree> BuildSubTreesAsync(
            IProjectTree rootNode,
            ITargetFramework activeTarget,
            ITargetedDependenciesSnapshot targetedSnapshot,
            Func <IProjectTree, IEnumerable <IProjectTree>, IProjectTree> syncFunc)
        {
            var groupedByProviderType = new Dictionary <string, List <IDependency> >(StringComparers.DependencyProviderTypes);

            foreach (IDependency dependency in targetedSnapshot.TopLevelDependencies)
            {
                if (!dependency.Visible)
                {
                    // If a dependency is not visible we will still register a top-level group if it
                    // has the ShowEmptyProviderRootNode flag.
                    if (!dependency.Flags.Contains(DependencyTreeFlags.ShowEmptyProviderRootNode))
                    {
                        // No such flag, so skip it completely.
                        continue;
                    }
                }

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

                // Only add visible dependencies. See note above.
                if (dependency.Visible)
                {
                    dependencies.Add(dependency);
                }
            }

            var currentNodes = new List <IProjectTree>(capacity: groupedByProviderType.Count);

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

            foreach ((string providerType, List <IDependency> dependencies) in groupedByProviderType)
            {
                IDependencyViewModel?subTreeViewModel = _viewModelFactory.CreateRootViewModel(
                    providerType,
                    targetedSnapshot.CheckForUnresolvedDependencies(providerType));

                if (subTreeViewModel == null)
                {
                    // In theory this should never happen, as it means we have a dependency model of a type
                    // that no provider claims. https://github.com/dotnet/project-system/issues/3653
                    continue;
                }

                IProjectTree subTreeNode      = rootNode.FindChildWithCaption(subTreeViewModel.Caption);
                bool         isNewSubTreeNode = subTreeNode == null;

                ProjectTreeFlags excludedFlags = targetedSnapshot.TargetFramework.Equals(TargetFramework.Any)
                    ? ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp)
                    : ProjectTreeFlags.Empty;

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

                subTreeNode = await BuildSubTreeAsync(
                    subTreeNode,
                    targetedSnapshot,
                    dependencies,
                    isActiveTarget,
                    shouldCleanup : !isNewSubTreeNode);

                currentNodes.Add(subTreeNode);

                rootNode = isNewSubTreeNode
                    ? rootNode.Add(subTreeNode).Parent
                    : subTreeNode.Parent;
            }

            return(syncFunc(rootNode, currentNodes));
        }
        /// <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,
            Func <IProjectTree, IEnumerable <IProjectTree>, IProjectTree> syncFunc)
        {
            var groupedByProviderType = new Dictionary <string, List <IDependency> >(StringComparers.DependencyProviderTypes);

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

            var currentNodes = new List <IProjectTree>(capacity: groupedByProviderType.Count);

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

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

                ProjectTreeFlags excludedFlags = targetedSnapshot.TargetFramework.Equals(TargetFramework.Any)
                    ? ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp)
                    : ProjectTreeFlags.Empty;

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

                subTreeNode = await BuildSubTreeAsync(
                    subTreeNode,
                    targetedSnapshot,
                    dependencies,
                    isActiveTarget,
                    shouldCleanup : !isNewSubTreeNode);

                currentNodes.Add(subTreeNode);

                rootNode = isNewSubTreeNode
                    ? rootNode.Add(subTreeNode).Parent
                    : subTreeNode.Parent;
            }

            return(syncFunc(rootNode, currentNodes));
        }
Beispiel #4
0
        /// <summary>
        /// Builds all available sub trees under root: target framework or Dependencies node
        /// when there is only one target.
        /// </summary>
        private IProjectTree BuildSubTrees(
            IProjectTree rootNode,
            ITargetFramework activeTarget,
            ITargetedDependenciesSnapshot targetedSnapshot,
            IProjectCatalogSnapshot catalogs,
            Func <IProjectTree, IEnumerable <IProjectTree>, IProjectTree> syncFunc)
        {
            var currentNodes           = new List <IProjectTree>();
            var grouppedByProviderType = new Dictionary <string, List <IDependency> >(StringComparer.OrdinalIgnoreCase);

            foreach (var 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.
                        grouppedByProviderType.Add(dependency.ProviderType, new List <IDependency>());
                    }

                    continue;
                }

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

                dependencies.Add(dependency);
            }

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

            foreach (var dependencyGroup in grouppedByProviderType)
            {
                var subTreeViewModel = ViewModelFactory.CreateRootViewModel(
                    dependencyGroup.Key, targetedSnapshot.CheckForUnresolvedDependencies(dependencyGroup.Key));
                var subTreeNode      = rootNode.FindNodeByCaption(subTreeViewModel.Caption);
                var isNewSubTreeNode = subTreeNode == null;

                var 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 = BuildSubTree(
                    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));
        }