DependencyAnalyzer( IActivityMonitor m, IReadOnlyCollection <ISolution> solutions, ISolutionContext solutionCtx, ProjectItem.Cache projects, List <PackageReference> externalRefs, bool traceGraphDetails) { _solutions = solutions; _solutionContext = solutionCtx; _version = _solutionContext?.Version ?? 0; _projects = projects; _externalRefs = externalRefs; _defaultDependencyContext = CreateDependencyContext(m, traceGraphDetails); }
/// <summary> /// /// </summary> /// <param name="m"></param> /// <param name="solutions"></param> /// <param name="traceGraphDetails"></param> /// <param name="solutionCtx">May be null, used to construct the <see cref="DependencyAnalyzer"/></param> /// <returns></returns> internal static DependencyAnalyzer Create(IActivityMonitor m, IReadOnlyCollection <ISolution> solutions, bool traceGraphDetails, ISolutionContext solutionCtx) { var packages = new Dictionary <Artifact, LocalPackageItem>(); var projectItems = new ProjectItem.Cache(); var externalRefs = new List <PackageReference>(); // Note: Project to project references are translated into Requirements directly // in the ProjectItem constructor. // After having built the ProjectItem, we handle here the Packages (and PackageReferences between // projects). using (m.OpenDebug("Creating all the ProjectItem for all projects in all solutions.")) { foreach (var s in solutions) { using (m.OpenDebug($"Solution {s.Name}.")) { foreach (var project in s.Projects) { projectItems.Create(project); } } } } using (m.OpenDebug("Creating Package for all installable Artifacts in all solutions.")) { foreach (var s in solutions) { using (m.OpenDebug($"Solution {s.Name}.")) { foreach (var project in s.Projects) { foreach (var package in project.GeneratedArtifacts.Where(a => a.Artifact.Type.IsInstallable)) { if (packages.TryGetValue(package.Artifact, out var alreadyPublished)) { m.Error($"'{package.Project.Solution+"->"+package}' is already published by {alreadyPublished.Project.Solution+"->"+alreadyPublished.Project}."); return(null); } packages.Add(package.Artifact, new LocalPackageItem(package.Artifact, project)); m.Debug($"Package '{package}' created."); } } } } } // 3 - Create the requirements between each project and Packages that are bound to a // Published project (the LocalPackageItem previuosly created). // When PackageReferences references external Packages, we add it to the ExternalRefs. foreach (var project in projectItems.AllProjectItems) { // Consider package references (Project to Project references are handled by ProjectItem constructors). foreach (var dep in project.Project.PackageReferences) { if (packages.TryGetValue(dep.Target.Artifact, out LocalPackageItem target)) { if (target.Project.Solution != project.Project.Solution) { project.AddRequires(target); } else { // A project is referencing a Package that is generated by // its own Solution. This can happen (even if it is strange): for instance to test packages // from the solution itself (the more correct way to do this is to use another // Repository/Solution to test the packages since here you always test the "previous" // package version). // // We transform the package reference into a project reference so that this edge // case does not create cycles. project.AddRequires(projectItems[target.Project]); } } else { // Dependency to an external Package. externalRefs.Add(dep); } } } return(new DependencyAnalyzer( m, solutions, solutionCtx, projectItems, externalRefs, traceGraphDetails)); }