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