コード例 #1
0
            /// <summary>
            /// Until we have a proper design for displaying cross-target dependencies, we show all
            /// in one list.
            /// </summary>
            /// <returns></returns>
            public HashSet <string> GetUniqueTopLevelDependencies()
            {
                HashSet <string> topLevelDependenciesNames     = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                HashSet <string> topLevelDependenciesItemSpecs = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                foreach (var target in Targets)
                {
                    if (!DependenciesWorld.TryGetValue(target.Key, out DependencyMetadata targetMetadata))
                    {
                        continue;
                    }

                    foreach (var dependencyItemSpec in targetMetadata.DependenciesItemSpecs)
                    {
                        if (!DependenciesWorld.TryGetValue(dependencyItemSpec, out DependencyMetadata dependencyMetadata))
                        {
                            continue;
                        }

                        if (topLevelDependenciesNames.Contains(dependencyMetadata.Name))
                        {
                            // we already have this dependency form other target
                            continue;
                        }

                        topLevelDependenciesNames.Add(dependencyMetadata.Name);
                        topLevelDependenciesItemSpecs.Add(dependencyItemSpec);
                    }
                }

                return(topLevelDependenciesItemSpecs);
            }
コード例 #2
0
        private bool TryToFindDependency(string id, out IDependency dependency)
        {
            if (DependenciesWorld.TryGetValue(id, out dependency))
            {
                return(true);
            }

            return(_topLevelDependenciesByPathMap.TryGetValue(id, out dependency));
        }
コード例 #3
0
            public DependencyMetadata RemoveDependency(string itemSpec)
            {
                DependencyMetadata removedMetadata = null;

                if (!DependenciesWorld.TryGetValue(itemSpec, out removedMetadata))
                {
                    return(null);
                }

                DependenciesWorld.Remove(itemSpec);

                RemoveNodeFromCache(itemSpec);

                return(removedMetadata);
            }
コード例 #4
0
        protected override void ExecuteCore()
        {
            ImplicitPackageReferences = GetImplicitPackageReferences(DefaultImplicitPackages);

            PopulateTargets();

            PopulatePackages();

            PopulateAssemblies();
            PopulateExistingReferenceItems();

            InputDiagnosticMessages = InputDiagnosticMessages ?? Array.Empty <ITaskItem>();
            PopulateDiagnosticsMap();

            AddDependenciesToTheWorld(Packages, PackageDependencies);

            AddDependenciesToTheWorld(Assemblies, FileDependencies, (item) =>
            {
                // We keep analyzers and assemblies with CompileTimeAssembly metadata; skip everything else.

                ItemMetadata itemMetadata = null;
                if (Assemblies.TryGetValue(item.ItemSpec, out itemMetadata) &&
                    itemMetadata.Type == DependencyType.AnalyzerAssembly)
                {
                    return(false);
                }

                var fileGroup = item.GetMetadata(MetadataKeys.FileGroup);
                return(string.IsNullOrEmpty(fileGroup) || !fileGroup.Equals(CompileTimeAssemblyMetadata));
            });

            AddDependenciesToTheWorld(Assemblies, ExistingReferenceItemDependencies);

            AddDependenciesToTheWorld(DiagnosticsMap, InputDiagnosticMessages);

            // prepare output collection: add corresponding metadata to ITaskItem based in item type
            DependenciesDesignTime = DependenciesWorld.Select(itemKvp =>
            {
                var newTaskItem = new TaskItem(itemKvp.Key);
                foreach (var metadataKvp in itemKvp.Value.ToDictionary())
                {
                    newTaskItem.SetMetadata(metadataKvp.Key, metadataKvp.Value);
                }

                return(newTaskItem);
            }).ToArray();
        }
コード例 #5
0
            public DependencyMetadata RemoveDependency(string itemSpec)
            {
                if (!DependenciesWorld.TryGetValue(itemSpec, out DependencyMetadata removedMetadata))
                {
                    return(null);
                }

                DependenciesWorld.Remove(itemSpec);

                RemoveNodeFromCache(itemSpec);

                if (!itemSpec.Contains("/") && Targets.ContainsKey(itemSpec))
                {
                    Targets.Remove(itemSpec);
                }

                return(removedMetadata);
            }
コード例 #6
0
            public DependencyMetadata UpdateDependency(string itemSpec, IImmutableDictionary <string, string> properties)
            {
                if (!DependenciesWorld.TryGetValue(itemSpec, out DependencyMetadata dependencyMetadata))
                {
                    return(null);
                }

                if (!itemSpec.Contains("/"))
                {
                    if (Targets.TryGetValue(itemSpec, out TargetMetadata targetMetadata))
                    {
                        targetMetadata.SetProperties(properties);
                    }
                }

                dependencyMetadata.SetProperties(properties);

                RemoveNodeFromCache(itemSpec);

                return(dependencyMetadata);
            }
コード例 #7
0
        /// <inheritdoc />
        public ImmutableArray <IDependency> GetDependencyChildren(IDependency dependency)
        {
            if (dependency.DependencyIDs.Length == 0)
            {
                return(ImmutableArray <IDependency> .Empty);
            }

            lock (SyncLock)
            {
                if (!_dependenciesChildrenMap.TryGetValue(dependency.Id, out ImmutableArray <IDependency> children))
                {
                    children = _dependenciesChildrenMap[dependency.Id] = BuildChildren();
                }

                return(children);
            }

            ImmutableArray <IDependency> BuildChildren()
            {
                ImmutableArray <IDependency> .Builder children =
                    ImmutableArray.CreateBuilder <IDependency>(dependency.DependencyIDs.Length);

                foreach (string id in dependency.DependencyIDs)
                {
                    if (DependenciesWorld.TryGetValue(id, out IDependency child) ||
                        _topLevelDependenciesByPathMap.TryGetValue(id, out child))
                    {
                        children.Add(child);
                    }
                }

                return(children.Count == children.Capacity
                    ? children.MoveToImmutable()
                    : children.ToImmutable());
            }
        }
コード例 #8
0
        private void AddDependenciesToTheWorld(Dictionary <string, ItemMetadata> items,
                                               ITaskItem[] itemDependencies,
                                               Func <ITaskItem, bool> shouldSkipItemCheck = null)
        {
            foreach (var dependency in itemDependencies)
            {
                var currentItemId = dependency.ItemSpec;
                if (!items.Keys.Contains(currentItemId))
                {
                    // if this package definition does not even exist - skip it
                    continue;
                }

                if (shouldSkipItemCheck != null && shouldSkipItemCheck(dependency))
                {
                    continue;
                }

                var parentTargetId = dependency.GetMetadata(MetadataKeys.ParentTarget) ?? string.Empty;
                if (parentTargetId.Contains("/") || !Targets.Keys.Contains(parentTargetId))
                {
                    // skip "target/rid"s and only consume actual targets and ignore non-existent parent targets
                    continue;
                }

                var parentPackageId = dependency.GetMetadata(MetadataKeys.ParentPackage) ?? string.Empty;
                if (!string.IsNullOrEmpty(parentPackageId) && !Packages.Keys.Contains(parentPackageId))
                {
                    // ignore non-existent parent packages
                    continue;
                }

                var currentPackageUniqueId = $"{parentTargetId}/{currentItemId}";
                // add current package to dependencies world
                var currentItem = items[currentItemId];
                DependenciesWorld[currentPackageUniqueId] = currentItem;

                // update parent
                var          parentDependencyId = $"{parentTargetId}/{parentPackageId}".Trim('/');
                ItemMetadata parentDependency   = null;
                if (DependenciesWorld.TryGetValue(parentDependencyId, out parentDependency))
                {
                    parentDependency.Dependencies.Add(currentItemId);
                    if (parentDependency.Type == DependencyType.Target)
                    {
                        currentItem.IsTopLevelDependency = true;
                    }
                }
                else
                {
                    // Update parent's Dependencies count and make sure parent is in the dependencies world
                    if (!string.IsNullOrEmpty(parentPackageId))
                    {
                        parentDependency = Packages[parentPackageId];
                    }
                    else
                    {
                        parentDependency = Targets[parentTargetId];
                        currentItem.IsTopLevelDependency = true;
                    }

                    parentDependency.Dependencies.Add(currentItemId);
                    DependenciesWorld[parentDependencyId] = parentDependency;
                }
            }
        }
コード例 #9
0
        private bool MergeChanges(
            IDependenciesChanges changes,
            IEnumerable <IDependenciesSnapshotFilter> snapshotFilters,
            IEnumerable <IProjectDependenciesSubTreeProvider> subTreeProviders,
            HashSet <string> projectItemSpecs)
        {
            var worldBuilder    = DependenciesWorld.ToBuilder();
            var topLevelBuilder = TopLevelDependencies.ToBuilder();

            var anyChanges = false;

            foreach (var removed in changes.RemovedNodes)
            {
                var targetedId = Dependency.GetID(TargetFramework, removed.ProviderType, removed.Id);
                if (!worldBuilder.TryGetValue(targetedId, out IDependency dependency))
                {
                    continue;
                }

                if (snapshotFilters != null)
                {
                    foreach (var filter in snapshotFilters)
                    {
                        dependency = filter.BeforeRemove(
                            ProjectPath, TargetFramework, dependency, worldBuilder, topLevelBuilder, out bool filterAnyChanges);

                        anyChanges |= filterAnyChanges;

                        if (dependency == null)
                        {
                            break;
                        }
                    }
                }

                if (dependency == null)
                {
                    continue;
                }

                anyChanges = true;

                worldBuilder.Remove(targetedId);
                topLevelBuilder.Remove(dependency);
            }

            var subTreeProvidersMap = GetSubTreeProviderMap(subTreeProviders);

            foreach (var added in changes.AddedNodes)
            {
                IDependency newDependency = new Dependency(added, TargetFramework, ProjectPath);

                if (snapshotFilters != null)
                {
                    foreach (var filter in snapshotFilters)
                    {
                        newDependency = filter.BeforeAdd(
                            ProjectPath,
                            TargetFramework,
                            newDependency,
                            worldBuilder,
                            topLevelBuilder,
                            subTreeProvidersMap,
                            projectItemSpecs,
                            out bool filterAnyChanges);

                        anyChanges |= filterAnyChanges;

                        if (newDependency == null)
                        {
                            break;
                        }
                    }
                }

                if (newDependency == null)
                {
                    continue;
                }

                anyChanges = true;

                worldBuilder.Remove(newDependency.Id);
                worldBuilder.Add(newDependency.Id, newDependency);
                if (newDependency.TopLevel)
                {
                    topLevelBuilder.Remove(newDependency);
                    topLevelBuilder.Add(newDependency);
                }
            }

            DependenciesWorld    = worldBuilder.ToImmutable();
            TopLevelDependencies = topLevelBuilder.ToImmutable();

            ConstructTopLevelDependenciesByPathMap();

            return(anyChanges);
        }