/// <summary>
        /// Gets a <see cref="PackageSpec" /> for the specified project.
        /// </summary>
        /// <param name="project">An <see cref="IMSBuildProject" /> object that represents the project.</param>
        /// <param name="allInnerNodes">An <see cref="IReadOnlyDictionary{String,IMSBuildProject}" /> that represents all inner projects by their target framework.</param>
        /// <returns></returns>
        private PackageSpec GetPackageSpec(IMSBuildProject project, IReadOnlyDictionary <string, IMSBuildProject> allInnerNodes)
        {
            var settings = RestoreSettingsUtils.ReadSettings(
                project.GetProperty("RestoreSolutionDirectory"),
                project.GetProperty("RestoreRootConfigDirectory") ?? project.Directory,
                UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestoreConfigFile")),
                MachineWideSettingsLazy,
                _settingsLoadContext);

            // Get the target frameworks for the project and the project instance for each framework
            var projectsByTargetFramework = GetProjectTargetFrameworks(project, allInnerNodes);

            var restoreMetadataAndTargetFrameworkInformation = GetProjectRestoreMetadataAndTargetFrameworkInformation(project, projectsByTargetFramework, settings);

            var packageSpec = new PackageSpec(restoreMetadataAndTargetFrameworkInformation.TargetFrameworkInfos)
            {
                FilePath        = project.FullPath,
                Name            = restoreMetadataAndTargetFrameworkInformation.RestoreMetadata.ProjectName,
                RestoreMetadata = restoreMetadataAndTargetFrameworkInformation.RestoreMetadata,
                RuntimeGraph    = new RuntimeGraph(
                    MSBuildStringUtility.Split($"{project.GetProperty("RuntimeIdentifiers")};{project.GetProperty("RuntimeIdentifier")}")
                    .Concat(projectsByTargetFramework.Values.SelectMany(i => MSBuildStringUtility.Split($"{i.GetProperty("RuntimeIdentifiers")};{i.GetProperty("RuntimeIdentifier")}")))
                    .Distinct(StringComparer.Ordinal)
                    .Select(rid => new RuntimeDescription(rid))
                    .ToList(),
                    MSBuildStringUtility.Split(project.GetProperty("RuntimeSupports"))
                    .Distinct(StringComparer.Ordinal)
                    .Select(s => new CompatibilityProfile(s))
                    .ToList()
                    ),
                Version = GetProjectVersion(project)
            };

            return(packageSpec);
        }
 /// <summary>
 /// Gets the packages path for the specified project.
 /// </summary>
 /// <param name="project">The <see cref="IMSBuildItem" /> representing the project.</param>
 /// <param name="settings">The <see cref="ISettings" /> of the project.</param>
 /// <returns>The full path to the packages directory for the specified project.</returns>
 internal static string GetPackagesPath(IMSBuildProject project, ISettings settings)
 {
     return(RestoreSettingsUtils.GetValue(
                () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestorePackagesPathOverride")),
                () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestorePackagesPath")),
                () => SettingsUtility.GetGlobalPackagesFolder(settings)));
 }
        /// <summary>
        /// Gets the repository path for the specified project.
        /// </summary>
        /// <param name="project">The <see cref="IMSBuildItem" /> representing the project.</param>
        /// <param name="settings">The <see cref="ISettings" /> of the specified project.</param>
        /// <returns>The repository path of the specified project.</returns>
        internal static string GetRepositoryPath(IMSBuildProject project, ISettings settings)
        {
            return(RestoreSettingsUtils.GetValue(
                       () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestoreRepositoryPathOverride")),
                       () => UriUtility.GetAbsolutePath(project.Directory, project.GetProperty("RestoreRepositoryPath")),
                       () => SettingsUtility.GetRepositoryPath(settings),
                       () =>
            {
                string solutionDir = project.GetProperty("SolutionPath");

                solutionDir = string.Equals(solutionDir, "*Undefined*", StringComparison.OrdinalIgnoreCase)
                        ? project.Directory
                        : Path.GetDirectoryName(solutionDir);

                return UriUtility.GetAbsolutePath(solutionDir, PackagesConfig.PackagesNodeName);
            }));
        }
        /// <summary>
        /// Gets the name of the specified project.
        /// </summary>
        /// <param name="project">The <see cref="IMSBuildItem" /> representing the project.</param>
        /// <returns>The name of the specified project.</returns>
        internal static string GetProjectName(IMSBuildProject project)
        {
            string packageId = project.GetProperty("PackageId");

            if (!string.IsNullOrWhiteSpace(packageId))
            {
                // If the PackageId property was specified, return that
                return(packageId);
            }

            string assemblyName = project.GetProperty("AssemblyName");

            if (!string.IsNullOrWhiteSpace(assemblyName))
            {
                // If the AssemblyName property was specified, return that
                return(assemblyName);
            }

            // By default return the MSBuildProjectName which is a built-in property that represents the name of the project file without the file extension
            return(project.GetProperty("MSBuildProjectName"));
        }
        /// <summary>
        /// Gets the target frameworks for the specified project.
        /// </summary>
        /// <param name="project">An <see cref="IMSBuildProject" /> representing the main project.</param>
        /// <param name="innerNodes">An <see cref="IReadOnlyDictionary{String,IMSBuildProject}" /> representing all inner projects by their target framework.</param>
        /// <returns></returns>
        internal static IReadOnlyDictionary <NuGetFramework, IMSBuildProject> GetProjectTargetFrameworks(IMSBuildProject project, IReadOnlyDictionary <string, IMSBuildProject> innerNodes)
        {
            // Get the raw list of target frameworks that the project specifies
            var projectFrameworkStrings = MSBuildProjectFrameworkUtility.GetProjectFrameworkStrings(
                projectFilePath: project.FullPath,
                targetFrameworks: project.GetProperty("TargetFrameworks"),
                targetFramework: project.GetProperty("TargetFramework"),
                targetFrameworkMoniker: project.GetProperty("TargetFrameworkMoniker"),
                targetPlatformIdentifier: project.GetProperty("TargetPlatformIdentifier"),
                targetPlatformVersion: project.GetProperty("TargetPlatformVersion"),
                targetPlatformMinVersion: project.GetProperty("TargetPlatformMinVersion")).ToList();

            var projectTargetFrameworks = new Dictionary <NuGetFramework, IMSBuildProject>();

            foreach (var projectTargetFramework in projectFrameworkStrings)
            {
                // Attempt to get the corresponding project instance for the target framework.  If one is not found, then the project must not target multiple frameworks
                // and the main project should be used
                if (!innerNodes.TryGetValue(projectTargetFramework, out IMSBuildProject innerNode))
                {
                    innerNode = project;
                }

                // Add the target framework and associate it with the project instance to be used for gathering details
                projectTargetFrameworks[NuGetFramework.Parse(projectTargetFramework)] = innerNode;
            }

            return(projectTargetFrameworks);
        }
        /// <summary>
        /// Gets the restore metadata and target framework information for the specified project.
        /// </summary>
        /// <param name="project">An <see cref="IMSBuildProject" /> representing the project.</param>
        /// <param name="projectsByTargetFramework">A <see cref="IReadOnlyDictionary{NuGetFramework,IMSBuildProject}" /> containing the inner nodes by target framework.</param>
        /// <param name="settings">The <see cref="ISettings" /> of the specified project.</param>
        /// <returns>A <see cref="Tuple" /> containing the <see cref="ProjectRestoreMetadata" /> and <see cref="List{TargetFrameworkInformation}" /> for the specified project.</returns>
        private (ProjectRestoreMetadata RestoreMetadata, List <TargetFrameworkInformation> TargetFrameworkInfos) GetProjectRestoreMetadataAndTargetFrameworkInformation(IMSBuildProject project, IReadOnlyDictionary <NuGetFramework, IMSBuildProject> projectsByTargetFramework, ISettings settings)
        {
            var projectName = GetProjectName(project);

            var outputPath = GetRestoreOutputPath(project);

            var targetFrameworkInfos = GetTargetFrameworkInfos(projectsByTargetFramework);

            var projectStyleResult = BuildTasksUtility.GetProjectRestoreStyle(
                restoreProjectStyle: project.GetProperty("RestoreProjectStyle"),
                hasPackageReferenceItems: targetFrameworkInfos.Any(i => i.Dependencies.Any()),
                projectJsonPath: project.GetProperty("_CurrentProjectJsonPath"),
                projectDirectory: project.Directory,
                projectName: project.GetProperty("MSBuildProjectName"),
                log: MSBuildLogger);

            var projectStyle = projectStyleResult.ProjectStyle;

            var innerNodes = projectsByTargetFramework.Values.ToList();

            ProjectRestoreMetadata restoreMetadata;

            if (projectStyle == ProjectStyle.PackagesConfig)
            {
                restoreMetadata = new PackagesConfigProjectRestoreMetadata
                {
                    PackagesConfigPath = projectStyleResult.PackagesConfigFilePath,
                    RepositoryPath     = GetRepositoryPath(project, settings)
                };
            }
            else
            {
                restoreMetadata = new ProjectRestoreMetadata
                {
                    CrossTargeting  = (projectStyle == ProjectStyle.PackageReference || projectStyle == ProjectStyle.DotnetToolReference) && projectsByTargetFramework.Count > 1,
                    FallbackFolders = BuildTasksUtility.GetFallbackFolders(
                        project.Directory,
                        project.SplitPropertyValueOrNull("RestoreFallbackFolders"),
                        project.SplitPropertyValueOrNull("RestoreFallbackFoldersOverride"),
                        innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFolders"))),
                        innerNodes.SelectMany(i => MSBuildStringUtility.Split(i.GetProperty("RestoreAdditionalProjectFallbackFoldersExcludes"))),
                        settings),
                    SkipContentFileWrite  = IsLegacyProject(project),
                    ValidateRuntimeAssets = project.IsPropertyTrue("ValidateRuntimeIdentifierCompatibility")
                };
            }

            restoreMetadata.CacheFilePath                = NoOpRestoreUtilities.GetProjectCacheFilePath(outputPath, project.FullPath);
            restoreMetadata.ConfigFilePaths              = settings.GetConfigFilePaths();
            restoreMetadata.OutputPath                   = outputPath;
            restoreMetadata.OriginalTargetFrameworks     = GetOriginalTargetFrameworks(project, projectsByTargetFramework.Keys.ToList());
            restoreMetadata.PackagesPath                 = GetPackagesPath(project, settings);
            restoreMetadata.ProjectName                  = projectName;
            restoreMetadata.ProjectPath                  = project.FullPath;
            restoreMetadata.ProjectStyle                 = projectStyle;
            restoreMetadata.ProjectUniqueName            = project.FullPath;
            restoreMetadata.ProjectWideWarningProperties = WarningProperties.GetWarningProperties(project.GetProperty("TreatWarningsAsErrors"), project.GetProperty("WarningsAsErrors"), project.GetProperty("NoWarn"));
            restoreMetadata.RestoreLockProperties        = new RestoreLockProperties(project.GetProperty("RestorePackagesWithLockFile"), project.GetProperty("NuGetLockFilePath"), project.IsPropertyTrue("RestoreLockedMode"));
            restoreMetadata.Sources          = GetSources(project, innerNodes, settings);
            restoreMetadata.TargetFrameworks = GetProjectRestoreMetadataFrameworkInfos(projectsByTargetFramework);

            return(restoreMetadata, targetFrameworkInfos);
        }
        /// <summary>
        /// Gets the restore output path for the specified project.
        /// </summary>
        /// <param name="project">The <see cref="IMSBuildItem" /> representing the project.</param>
        /// <returns>The full path to the restore output directory for the specified project.</returns>
        internal static string GetRestoreOutputPath(IMSBuildProject project)
        {
            string outputPath = project.GetProperty("RestoreOutputPath") ?? project.GetProperty("MSBuildProjectExtensionsPath");

            return(Path.GetFullPath(Path.Combine(project.Directory, outputPath)));
        }