/// <summary>
 ///     Returns a value indicating whether the specified flags indicates that
 ///     the file or folder is missing on disk.
 /// </summary>
 public static bool IsMissingOnDisk(this ProjectTreeFlags flags)
 {
     return(!flags.HasFlag(ProjectTreeFlags.Common.FileSystemEntity));
 }
Ejemplo n.º 2
0
        public void Matches_MultipleFlags(string s, bool expected)
        {
            var detector = new FlagsStringMatcher(ProjectTreeFlags.Create("APPLE") + ProjectTreeFlags.Create("BANANA"));

            Assert.Equal(expected, detector.Matches(s));
        }
Ejemplo n.º 3
0
        private IProjectTree CreateOrUpdateNode(
            IProjectTree node,
            IDependencyViewModel viewModel,
            IRule rule,
            bool isProjectItem,
            ProjectTreeFlags?additionalFlags = null,
            ProjectTreeFlags?excludedFlags   = null)
        {
            if (node != null)
            {
                return(UpdateTreeNode());
            }

            string filePath = viewModel.OriginalModel != null &&
                              viewModel.OriginalModel.TopLevel &&
                              viewModel.OriginalModel.Resolved
                ? viewModel.OriginalModel.GetTopLevelId()
                : viewModel.FilePath;

            ProjectTreeFlags filteredFlags = FilterFlags(viewModel.Flags);

            return(isProjectItem
                ? CreateProjectItemTreeNode()
                : CreateProjectTreeNode());

            IProjectTree CreateProjectTreeNode()
            {
                // For IProjectTree remove ProjectTreeFlags.Common.Reference flag, otherwise CPS would fail to
                // map this node to graph node and GraphProvider would be never called.
                // Only IProjectItemTree can have this flag
                filteredFlags = filteredFlags.Except(DependencyTreeFlags.BaseReferenceFlags);

                return(_treeServices.CreateTree(
                           caption: viewModel.Caption,
                           filePath,
                           browseObjectProperties: rule,
                           icon: viewModel.Icon.ToProjectSystemType(),
                           expandedIcon: viewModel.ExpandedIcon.ToProjectSystemType(),
                           visible: true,
                           flags: filteredFlags));
            }

            IProjectTree CreateProjectItemTreeNode()
            {
                var itemContext = ProjectPropertiesContext.GetContext(
                    _commonServices.Project,
                    file: filePath,
                    itemType: viewModel.SchemaItemType,
                    itemName: filePath);

                return(_treeServices.CreateTree(
                           caption: viewModel.Caption,
                           itemContext: itemContext,
                           browseObjectProperties: rule,
                           icon: viewModel.Icon.ToProjectSystemType(),
                           expandedIcon: viewModel.ExpandedIcon.ToProjectSystemType(),
                           visible: true,
                           flags: filteredFlags));
            }

            IProjectTree UpdateTreeNode()
            {
                var updatedNodeParentContext = new ProjectTreeCustomizablePropertyContext
                {
                    ExistsOnDisk    = false,
                    ParentNodeFlags = node.Parent?.Flags ?? default
                };

                var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues
                {
                    Caption      = viewModel.Caption,
                    Flags        = viewModel.Flags,
                    Icon         = viewModel.Icon.ToProjectSystemType(),
                    ExpandedIcon = viewModel.ExpandedIcon.ToProjectSystemType()
                };

                foreach (Lazy <IProjectTreePropertiesProvider, IOrderPrecedenceMetadataView> provider in _projectTreePropertiesProviders)
                {
                    provider.Value.CalculatePropertyValues(updatedNodeParentContext, updatedValues);
                }

                return(node.SetProperties(
                           caption: updatedValues.Caption,
                           browseObjectProperties: rule,
                           icon: updatedValues.Icon,
                           expandedIcon: updatedValues.ExpandedIcon,
                           flags: updatedValues.Flags));
            }

            ProjectTreeFlags FilterFlags(ProjectTreeFlags flags)
            {
                if (additionalFlags.HasValue)
                {
                    flags = flags.Union(additionalFlags.Value);
                }

                if (excludedFlags.HasValue)
                {
                    flags = flags.Except(excludedFlags.Value);
                }

                return(flags);
            }
        }
Ejemplo n.º 4
0
 public IProjectTree SetFlags(ProjectTreeFlags flags)
 {
     throw new NotImplementedException();
 }
        public async Task WhenMultipleTargetSnapshotsWithExistingDependencies_ShouldApplyChanges()
        {
            var dependencyModelRootXxx = new TestDependencyModel
            {
                ProviderType = "Xxx",
                Id           = "XxxDependencyRoot",
                Name         = "XxxDependencyRoot",
                Caption      = "XxxDependencyRoot",
                Resolved     = true
            };

            var dependencyXxx1 = new TestDependency
            {
                ProviderType    = "Xxx",
                Id              = "xxx\\dependency1",
                Path            = "dependencyxxxpath",
                Name            = "dependency1",
                Caption         = "Dependency1",
                SchemaItemType  = "Xxx",
                Resolved        = true,
                TargetFramework = _tfm1
            };

            var dependencyModelRootYyy = new TestDependencyModel
            {
                ProviderType = "Yyy",
                Id           = "YyyDependencyRoot",
                Name         = "YyyDependencyRoot",
                Caption      = "YyyDependencyRoot"
            };

            var dependencyYyy1 = new TestDependency
            {
                ProviderType    = "Yyy",
                Id              = "yyy\\dependency1",
                Path            = "dependencyyyypath",
                Name            = "dependency1",
                Caption         = "Dependency1",
                SchemaItemType  = "Yyy",
                Resolved        = true,
                TargetFramework = _tfm1
            };

            var dependencyYyyExisting = new TestDependency
            {
                ProviderType    = "Yyy",
                Id              = "yyy\\dependencyExisting",
                Path            = "dependencyyyyExistingpath",
                Name            = "dependencyExisting",
                Caption         = "DependencyExisting",
                SchemaItemType  = "Yyy",
                Resolved        = true,
                TargetFramework = _tfm1
            };

            var dependencyModelRootZzz = new TestDependencyModel
            {
                ProviderType = "Zzz",
                Id           = "ZzzDependencyRoot",
                Name         = "ZzzDependencyRoot",
                Caption      = "ZzzDependencyRoot",
                Resolved     = true,
                Flags        = ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp)
            };

            var dependencyAny1 = new TestDependency
            {
                ProviderType    = "Zzz",
                Id              = "ZzzDependencyAny1",
                Path            = "ZzzDependencyAny1path",
                Name            = "ZzzDependencyAny1",
                Caption         = "ZzzDependencyAny1",
                TargetFramework = TargetFramework.Any
            };

            var dependenciesRoot = new TestProjectTree
            {
                Caption  = "MyDependencies",
                Children =
                {
                    new TestProjectTree
                    {
                        Caption = "OldRootChildToBeRemoved"
                    },
                    new TestProjectTree
                    {
                        Caption  = "YyyDependencyRoot",
                        FilePath = "YyyDependencyRoot",
                        Children =
                        {
                            new TestProjectTree
                            {
                                Caption  = "DependencyExisting",
                                FilePath = "yyy\\dependencyExisting"
                            }
                        }
                    }
                }
            };

            var targetModel1 = new TestDependencyModel
            {
                Id      = "tfm1",
                Name    = "tfm1",
                Caption = "tfm1"
            };

            var targetModel2 = new TestDependencyModel
            {
                Id      = "tfm2",
                Name    = "tfm2",
                Caption = "tfm2"
            };

            var provider = CreateProvider(
                rootModels: new[] { dependencyModelRootXxx, dependencyModelRootYyy, dependencyModelRootZzz },
                targetModels: new[] { targetModel1, targetModel2 });

            var snapshot = GetSnapshot(
                (_tfm1, new[] { dependencyXxx1, dependencyYyy1, dependencyYyyExisting }),
                (_tfm2, new[] { dependencyXxx1, dependencyYyy1, dependencyYyyExisting }),
                (TargetFramework.Any, new[] { dependencyAny1 }));

            // Act
            var resultTree = await provider.BuildTreeAsync(dependenciesRoot, snapshot);

            // Assert
            var expectedFlatHierarchy =
                @"Caption=MyDependencies, FilePath=, IconHash=325248080, ExpandedIconHash=325248080, Rule=, IsProjectItem=False, CustomTag=
    Caption=ZzzDependencyRoot, FilePath=ZzzDependencyRoot, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=
        Caption=ZzzDependencyAny1, FilePath=ZzzDependencyAny1, IconHash=325248665, ExpandedIconHash=325248817, Rule=, IsProjectItem=False, CustomTag=
    Caption=tfm2, FilePath=tfm2, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=, BubbleUpFlag=True
        Caption=XxxDependencyRoot, FilePath=XxxDependencyRoot, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=
            Caption=Dependency1, FilePath=tfm1\Xxx\dependencyxxxpath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=False, CustomTag=
        Caption=YyyDependencyRoot, FilePath=YyyDependencyRoot, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=
            Caption=Dependency1, FilePath=tfm1\Yyy\dependencyyyypath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=False, CustomTag=
            Caption=DependencyExisting, FilePath=tfm1\Yyy\dependencyyyyExistingpath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=False, CustomTag=
    Caption=tfm1, FilePath=tfm1, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=, BubbleUpFlag=True
        Caption=XxxDependencyRoot, FilePath=XxxDependencyRoot, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=
            Caption=Dependency1, FilePath=tfm1\Xxx\dependencyxxxpath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=True, CustomTag=
        Caption=YyyDependencyRoot, FilePath=YyyDependencyRoot, IconHash=0, ExpandedIconHash=0, Rule=, IsProjectItem=False, CustomTag=
            Caption=Dependency1, FilePath=tfm1\Yyy\dependencyyyypath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=True, CustomTag=
            Caption=DependencyExisting, FilePath=tfm1\Yyy\dependencyyyyExistingpath, IconHash=325248088, ExpandedIconHash=325248260, Rule=, IsProjectItem=True, CustomTag=";

            Assert.Equal(expectedFlatHierarchy, ToTestDataString((TestProjectTree)resultTree));
        }
Ejemplo n.º 6
0
 /// <summary>
 ///     Returns a value indicating whether the specified flags has the specified flag.
 /// </summary>
 public static bool HasFlag(this ProjectTreeFlags flags, ProjectTreeFlags.Common flag)
 {
     return(flags.Contains(flag));
 }
Ejemplo n.º 7
0
 /// <summary>
 ///     Returns a value indicating whether the specified flags indicates that
 ///     the node is a folder.
 /// </summary>
 public static bool IsFolder(this ProjectTreeFlags flags)
 {
     return(flags.HasFlag(ProjectTreeFlags.Common.Folder));
 }
 /// <summary>
 ///     Returns a value indicating whether the specified property context represents the candidate special folder.
 /// </summary>
 protected abstract bool IsCandidateSpecialFolder(IProjectTreeCustomizablePropertyContext propertyContext, ProjectTreeFlags flags);
        private bool IsCandidateSpecialFolderItem(IProjectTreeCustomizablePropertyContext propertyContext, ProjectTreeFlags flags)
        {
            // We're a special folder item if our parent is the special folder. We rely on
            // the fact that "VisibleOnlyInShowAllFiles" is transitive; that is, if a parent
            // is marked with it, its children are also implicitly marked with it.
            if (propertyContext.ParentNodeFlags.Contains(FolderFlags))
            {
                return(flags.IsIncludedInProject());
            }

            return(false);
        }
Ejemplo n.º 10
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,
            TargetedDependenciesSnapshot targetedSnapshot,
            Func <IProjectTree, HashSet <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 HashSet <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,
                    browseObjectProperties: 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 !;

                Assumes.NotNull(rootNode);
            }

            return(syncFunc(rootNode, currentNodes));
        }
Ejemplo n.º 11
0
        /// <inheritdoc />
        public async Task <IProjectTree> BuildTreeAsync(
            IProjectTree dependenciesTree,
            DependenciesSnapshot snapshot,
            CancellationToken cancellationToken = default)
        {
            // Keep a reference to the original tree to return in case we are cancelled.
            IProjectTree originalTree = dependenciesTree;

            bool hasSingleTarget = snapshot.DependenciesByTargetFramework.Count(x => !x.Key.Equals(TargetFramework.Any)) == 1;

            var currentTopLevelNodes = new HashSet <IProjectTree>();

            if (hasSingleTarget)
            {
                await BuildSingleTargetTreeAsync();
            }
            else
            {
                await BuildMultiTargetTreeAsync();
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(originalTree);
            }

            dependenciesTree = CleanupOldNodes(dependenciesTree, currentTopLevelNodes);

            ProjectImageMoniker rootIcon = _viewModelFactory.GetDependenciesRootIcon(snapshot.HasReachableVisibleUnresolvedDependency).ToProjectSystemType();

            return(dependenciesTree.SetProperties(icon: rootIcon, expandedIcon: rootIcon));

            async Task BuildSingleTargetTreeAsync()
            {
                foreach ((ITargetFramework _, TargetedDependenciesSnapshot targetedSnapshot) in snapshot.DependenciesByTargetFramework)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    dependenciesTree = await BuildSubTreesAsync(
                        rootNode : dependenciesTree,
                        snapshot.ActiveTargetFramework,
                        targetedSnapshot,
                        RememberNewNodes);
                }
            }

            async Task BuildMultiTargetTreeAsync()
            {
                foreach ((ITargetFramework targetFramework, TargetedDependenciesSnapshot targetedSnapshot) in snapshot.DependenciesByTargetFramework)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    if (targetFramework.Equals(TargetFramework.Any))
                    {
                        dependenciesTree = await BuildSubTreesAsync(
                            rootNode : dependenciesTree,
                            snapshot.ActiveTargetFramework,
                            targetedSnapshot,
                            RememberNewNodes);
                    }
                    else
                    {
                        IProjectTree?        node = dependenciesTree.FindChildWithCaption(targetFramework.FriendlyName);
                        bool                 shouldAddTargetNode = node == null;
                        IDependencyViewModel targetViewModel     = _viewModelFactory.CreateTargetViewModel(targetedSnapshot);

                        node = CreateOrUpdateNode(
                            node,
                            targetViewModel,
                            browseObjectProperties: null,
                            isProjectItem: false,
                            additionalFlags: ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp));

                        node = await BuildSubTreesAsync(
                            rootNode : node,
                            snapshot.ActiveTargetFramework,
                            targetedSnapshot,
                            CleanupOldNodes);

                        dependenciesTree = shouldAddTargetNode
                            ? dependenciesTree.Add(node).Parent !
                            : node.Parent !;

                        Assumes.NotNull(dependenciesTree);

                        currentTopLevelNodes.Add(node);
                    }
                }
            }

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

                return(rootNode);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Generates the original references directory tree.
        /// </summary>
        protected override void Initialize()
        {
#pragma warning disable RS0030 // symbol LoadedProject is banned
            using (UnconfiguredProjectAsynchronousTasksService.LoadedProject())
#pragma warning restore RS0030 // symbol LoadedProject is banned
            {
                base.Initialize();

                // this.IsApplicable may take a project lock, so we can't do it inline with this method
                // which is holding a private lock.  It turns out that doing it asynchronously isn't a problem anyway,
                // so long as we guard against races with the Dispose method.
#pragma warning disable RS0030 // symbol LoadedProjectAsync is banned
                UnconfiguredProjectAsynchronousTasksService.LoadedProjectAsync(
#pragma warning restore RS0030 // symbol LoadedProjectAsync is banned
                    async delegate
                {
                    await TaskScheduler.Default.SwitchTo(alwaysYield: true);
                    UnconfiguredProjectAsynchronousTasksService
                    .UnloadCancellationToken.ThrowIfCancellationRequested();

                    lock (SyncObject)
                    {
                        Verify.NotDisposed(this);

                        // Issue this token before hooking the SnapshotChanged event to prevent a race
                        // where a snapshot tree is replaced by the initial, empty tree created below.
                        // The handler will cancel this token before submitting its update.
                        CancellationToken initialTreeCancellationToken = _treeUpdateCancellationSeries.CreateNext();

                        _ = SubmitTreeUpdateAsync(
                            delegate
                        {
                            IProjectTree dependenciesNode = CreateDependenciesNode();

                            return(Task.FromResult(new TreeUpdateResult(dependenciesNode)));
                        },
                            initialTreeCancellationToken);

                        ITargetBlock <SnapshotChangedEventArgs> actionBlock = DataflowBlockFactory.CreateActionBlock <SnapshotChangedEventArgs>(
                            OnDependenciesSnapshotChangedAsync,
                            _project,
                            nameFormat: "DependenciesProjectTreeProviderSource {1}",
                            skipIntermediateInputData: true);
                        _snapshotEventListener = _dependenciesSnapshotProvider.SnapshotChangedSource.LinkTo(actionBlock, DataflowOption.PropagateCompletion);
                    }
                },
                    registerFaultHandler: true);
            }

            IProjectTree CreateDependenciesNode()
            {
                var values = new ReferencesProjectTreeCustomizablePropertyValues
                {
                    Caption      = Resources.DependenciesNodeName,
                    Icon         = ManagedImageMonikers.ReferenceGroup.ToProjectSystemType(),
                    ExpandedIcon = ManagedImageMonikers.ReferenceGroup.ToProjectSystemType(),
                    Flags        = ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp)
                                   + ProjectTreeFlags.Create(ProjectTreeFlags.Common.ReferencesFolder)
                                   + ProjectTreeFlags.Create(ProjectTreeFlags.Common.VirtualFolder)
                                   + DependencyTreeFlags.DependenciesRootNode
                };

                // Allow property providers to perform customization.
                // These are ordered from lowest priority to highest, allowing higher priority
                // providers to override lower priority providers.
                foreach (IProjectTreePropertiesProvider provider in _projectTreePropertiesProviders.ExtensionValues())
                {
                    provider.CalculatePropertyValues(ProjectTreeCustomizablePropertyContext.Instance, values);
                }

                // Note that all the parameters are specified so we can force this call to an
                // overload of NewTree available prior to 15.5 versions of CPS. Once a 15.5 build
                // is publicly available we can move this to an overload with default values for
                // most of the parameters, and we'll only need to pass the interesting ones.
                return(NewTree(
                           caption: values.Caption,
                           filePath: null,
                           browseObjectProperties: null,
                           icon: values.Icon,
                           expandedIcon: values.ExpandedIcon,
                           visible: true,
                           flags: values.Flags));
            }
        }
Ejemplo n.º 13
0
 protected AssetsFileTopLevelDependenciesCollectionSourceProvider(ProjectTreeFlags flags)
     : base(flags)
 {
 }
        private IProjectTree CreateOrUpdateNode(
            IProjectTree?node,
            IDependencyViewModel viewModel,
            IRule?browseObjectProperties,
            bool isProjectItem,
            ProjectTreeFlags?additionalFlags = null,
            ProjectTreeFlags?excludedFlags   = null)
        {
            if (node != null)
            {
                return(UpdateTreeNode());
            }

            string?filePath = viewModel.Dependency != null &&
                              viewModel.Dependency.Resolved
                ? viewModel.Dependency.GetTopLevelId()
                : viewModel.FilePath;

            ProjectTreeFlags filteredFlags = FilterFlags(viewModel.Flags);

            return(isProjectItem
                ? CreateProjectItemTreeNode()
                : CreateProjectTreeNode());

            IProjectTree CreateProjectTreeNode()
            {
                return(_treeServices.CreateTree(
                           caption: viewModel.Caption,
                           filePath,
                           browseObjectProperties: browseObjectProperties,
                           icon: viewModel.Icon.ToProjectSystemType(),
                           expandedIcon: viewModel.ExpandedIcon.ToProjectSystemType(),
                           visible: true,
                           flags: filteredFlags));
            }

            IProjectTree CreateProjectItemTreeNode()
            {
                Assumes.NotNull(filePath);

                var itemContext = ProjectPropertiesContext.GetContext(
                    _commonServices.Project,
                    file: filePath,
                    itemType: viewModel.SchemaItemType,
                    itemName: filePath);

                return(_treeServices.CreateTree(
                           caption: viewModel.Caption,
                           itemContext: itemContext,
                           browseObjectProperties: browseObjectProperties,
                           icon: viewModel.Icon.ToProjectSystemType(),
                           expandedIcon: viewModel.ExpandedIcon.ToProjectSystemType(),
                           visible: true,
                           flags: filteredFlags));
            }

            IProjectTree UpdateTreeNode()
            {
                var updatedNodeParentContext = new ProjectTreeCustomizablePropertyContext
                {
                    ExistsOnDisk    = false,
                    ParentNodeFlags = node !.Parent?.Flags ?? default
                };

                var updatedValues = new ReferencesProjectTreeCustomizablePropertyValues
                {
                    Caption      = viewModel.Caption,
                    Flags        = viewModel.Flags,
                    Icon         = viewModel.Icon.ToProjectSystemType(),
                    ExpandedIcon = viewModel.ExpandedIcon.ToProjectSystemType()
                };

                foreach (Lazy <IProjectTreePropertiesProvider, IOrderPrecedenceMetadataView> provider in _projectTreePropertiesProviders)
                {
                    provider.Value.CalculatePropertyValues(updatedNodeParentContext, updatedValues);
                }

                return(node.SetProperties(
                           caption: updatedValues.Caption,
                           browseObjectProperties: browseObjectProperties,
                           icon: updatedValues.Icon,
                           expandedIcon: updatedValues.ExpandedIcon,
                           flags: updatedValues.Flags));
            }

            ProjectTreeFlags FilterFlags(ProjectTreeFlags flags)
            {
                if (additionalFlags.HasValue)
                {
                    flags = flags.Union(additionalFlags.Value);
                }

                if (excludedFlags.HasValue)
                {
                    flags = flags.Except(excludedFlags.Value);
                }

                return(flags);
            }
        }
        /// <summary>
        /// Builds Dependencies tree for given dependencies snapshot
        /// </summary>
        public override async Task <IProjectTree> BuildTreeAsync(
            IProjectTree dependenciesTree,
            IDependenciesSnapshot snapshot,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var originalTree         = dependenciesTree;
            var currentTopLevelNodes = new List <IProjectTree>();
            Func <IProjectTree, IEnumerable <IProjectTree>, IProjectTree> rememberNewNodes = (rootNode, currentNodes) =>
            {
                if (currentNodes != null)
                {
                    currentTopLevelNodes.AddRange(currentNodes);
                }

                return(rootNode);
            };

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

                    dependenciesTree = await BuildSubTreesAsync(
                        dependenciesTree,
                        snapshot.ActiveTarget,
                        target.Value,
                        target.Value.Catalogs,
                        rememberNewNodes).ConfigureAwait(false);
                }
            }
            else
            {
                foreach (var 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).ConfigureAwait(false);
                    }
                    else
                    {
                        var node = dependenciesTree.FindNodeByCaption(target.Key.FriendlyName);
                        var shouldAddTargetNode = node == null;
                        var 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).ConfigureAwait(false);

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

                        currentTopLevelNodes.Add(node);
                    }
                }
            }

            dependenciesTree = CleanupOldNodes(dependenciesTree, currentTopLevelNodes);

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

            return(dependenciesTree.SetProperties(icon: rootIcon, expandedIcon: rootIcon));
        }
Ejemplo n.º 16
0
        protected DependencyModel(
            string caption,
            string?path,
            string originalItemSpec,
            ProjectTreeFlags flags,
            bool isResolved,
            bool isImplicit,
            IImmutableDictionary <string, string>?properties,
            bool isVisible = true)
        {
            Requires.NotNullOrEmpty(caption, nameof(caption));

            // IDependencyModel allows original item spec to be null, but we can satisfy a
            // more strict requirement for the dependency types produced internally.
            // External providers may not have a meaningful value, but do not use this type.
            Requires.NotNullOrEmpty(originalItemSpec, nameof(originalItemSpec));

            Path             = path;
            OriginalItemSpec = originalItemSpec;
            Properties       = properties ?? ImmutableStringDictionary <string> .EmptyOrdinal;
            Caption          = caption;
            Flags            = flags;

            if (Properties.TryGetBoolProperty(ProjectItemMetadata.Visible, out bool visibleProperty))
            {
                isVisible = visibleProperty;
            }

            DiagnosticLevel diagnosticLevel = DiagnosticLevel.None;

            if (Properties.TryGetStringProperty(ProjectItemMetadata.DiagnosticLevel, out string?levelString))
            {
                diagnosticLevel = levelString switch
                {
                    "Warning" => DiagnosticLevel.Warning,
                    "Error" => DiagnosticLevel.Error,
                    _ => DiagnosticLevel.None
                };
            }

            if (diagnosticLevel == DiagnosticLevel.None && !isResolved)
            {
                // Treat unresolved state as a warning diagnostic
                diagnosticLevel = DiagnosticLevel.Warning;
            }

            DependencyFlags depFlags = 0;

            if (isResolved)
            {
                depFlags |= DependencyFlags.Resolved;
            }
            if (isVisible)
            {
                depFlags |= DependencyFlags.Visible;
            }
            if (isImplicit)
            {
                depFlags |= DependencyFlags.Implicit;
            }
            _flags = depFlags;

            DiagnosticLevel = diagnosticLevel;
        }
Ejemplo n.º 17
0
 /// <summary>
 ///     Returns a value indicating whether the specified flags has the flag <see cref="ProjectTreeFlags.Common.ProjectRoot"/>.
 /// </summary>
 public static bool IsProjectRoot(this ProjectTreeFlags flags)
 {
     return(flags.HasFlag(ProjectTreeFlags.Common.ProjectRoot));
 }
Ejemplo n.º 18
0
 protected DependenciesAttachedCollectionSourceProviderBase(ProjectTreeFlags flags) => _flagsStringMatcher = new FlagsStringMatcher(flags);
Ejemplo n.º 19
0
 /// <summary>
 ///     Returns a value indicating whether the specified flags indicates that
 ///     the node is included as part of the project.
 /// </summary>
 public static bool IsIncludedInProject(this ProjectTreeFlags flags)
 {
     return(!flags.HasFlag(ProjectTreeFlags.Common.IncludeInProjectCandidate));
 }
Ejemplo n.º 20
0
 public IProjectTree SetFlags(ProjectTreeFlags flags)
 {
     return(null);
 }
Ejemplo n.º 21
0
        /// <summary>
        ///     Returns a value indicating whether the specified flags exist.
        /// </summary>
        public static bool Contains(this ProjectTreeFlags source, ProjectTreeFlags flags)
        {
            ProjectTreeFlags newFlags = source.Except(flags);

            return((source.Count - newFlags.Count) == flags.Count);
        }
 public static ProjectTreeFlags CreateNewProjectRoot() =>
 ProjectTreeFlags.Create(ProjectTreeFlags.Common.ProjectRoot);
        protected sealed override bool IsCandidateSpecialFolder(IProjectTreeCustomizablePropertyContext propertyContext, ProjectTreeFlags flags)
        {
            if (propertyContext.ParentNodeFlags.IsProjectRoot() && flags.IsFolder() && flags.IsIncludedInProject())
            {
                string folderName = propertyContext.ProjectTreeSettings[AppDesigner.FolderNameProperty];

                return(StringComparers.Paths.Equals(folderName, propertyContext.ItemName));
            }

            return(false);
        }
 IProjectItemTree IProjectItemTree.SetFlags(ProjectTreeFlags flags)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 25
0
        public void Matches_SingleFlag_CaseInsensitive(string s, bool expected)
        {
            var detector = new FlagsStringMatcher(ProjectTreeFlags.Create("APPLE"), RegexOptions.IgnoreCase);

            Assert.Equal(expected, detector.Matches(s));
        }
Ejemplo n.º 26
0
            public IProjectTree SetFlags(ProjectTreeFlags flags)
            {
                Flags = flags;

                return(this);
            }
Ejemplo n.º 27
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,
            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));

                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,
            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 = await BuildSubTreeAsync(
                    subTreeNode,
                    targetedSnapshot,
                    dependencyGroup.Value,
                    catalogs,
                    isActiveTarget,
                    shouldCleanup : !isNewSubTreeNode).ConfigureAwait(false);

                currentNodes.Add(subTreeNode);

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

            return(syncFunc(rootNode, currentNodes));
        }
Ejemplo n.º 29
0
        /// <inheritdoc />
        public async Task <IProjectTree> BuildTreeAsync(
            IProjectTree dependenciesTree,
            IDependenciesSnapshot snapshot,
            CancellationToken cancellationToken = default)
        {
            IProjectTree originalTree = dependenciesTree;

            var currentTopLevelNodes = new List <IProjectTree>();

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

                    dependenciesTree = await BuildSubTreesAsync(
                        rootNode : dependenciesTree,
                        snapshot.ActiveTarget,
                        targetedSnapshot,
                        RememberNewNodes);
                }
            }
            else
            {
                foreach ((ITargetFramework targetFramework, ITargetedDependenciesSnapshot targetedSnapshot) in snapshot.Targets)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(originalTree);
                    }

                    if (targetFramework.Equals(TargetFramework.Any))
                    {
                        dependenciesTree = await BuildSubTreesAsync(
                            rootNode : dependenciesTree,
                            snapshot.ActiveTarget,
                            targetedSnapshot,
                            RememberNewNodes);
                    }
                    else
                    {
                        IProjectTree         node = dependenciesTree.FindChildWithCaption(targetFramework.FriendlyName);
                        bool                 shouldAddTargetNode = node == null;
                        IDependencyViewModel targetViewModel     = _viewModelFactory.CreateTargetViewModel(targetedSnapshot);

                        node = CreateOrUpdateNode(
                            node,
                            targetViewModel,
                            rule: null,
                            isProjectItem: false,
                            additionalFlags: ProjectTreeFlags.Create(ProjectTreeFlags.Common.BubbleUp));

                        node = await BuildSubTreesAsync(
                            rootNode : node,
                            snapshot.ActiveTarget,
                            targetedSnapshot,
                            CleanupOldNodes);

                        dependenciesTree = shouldAddTargetNode
                            ? dependenciesTree.Add(node).Parent
                            : 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));

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

                return(rootNode);
            }
        }
Ejemplo n.º 30
0
            public DependencyFlagCache(ProjectTreeFlags resolved, ProjectTreeFlags unresolved, ProjectTreeFlags remove = default)
            {
                // The 'isResolved' dimension determines whether we start with generic resolved or unresolved dependency flags.
                // We then add (union) and remove (except) any other flags as instructed.

                ProjectTreeFlags combinedResolved   = DependencyTreeFlags.ResolvedDependencyFlags.Union(resolved).Except(remove);
                ProjectTreeFlags combinedUnresolved = DependencyTreeFlags.UnresolvedDependencyFlags.Union(unresolved).Except(remove);

                // The 'isImplicit' dimension only enforces, when true, that the dependency cannot be removed.

                _lookup = new ProjectTreeFlags[4];
                _lookup[Index(isResolved: true, isImplicit: false)]  = combinedResolved;
                _lookup[Index(isResolved: true, isImplicit: true)]   = combinedResolved.Except(DependencyTreeFlags.SupportsRemove);
                _lookup[Index(isResolved: false, isImplicit: false)] = combinedUnresolved;
                _lookup[Index(isResolved: false, isImplicit: true)]  = combinedUnresolved.Except(DependencyTreeFlags.SupportsRemove);
            }