/// <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); }
private bool TryToFindDependency(string id, out IDependency dependency) { if (DependenciesWorld.TryGetValue(id, out dependency)) { return(true); } return(_topLevelDependenciesByPathMap.TryGetValue(id, out dependency)); }
public DependencyMetadata RemoveDependency(string itemSpec) { DependencyMetadata removedMetadata = null; if (!DependenciesWorld.TryGetValue(itemSpec, out removedMetadata)) { return(null); } DependenciesWorld.Remove(itemSpec); RemoveNodeFromCache(itemSpec); return(removedMetadata); }
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(); }
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); }
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); }
/// <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()); } }
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; } } }
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); }