/// <summary>
        ///     Given a Solution File; Identify the new Projects that would
        /// need to be added to reflect the current dependency tree.
        /// </summary>
        /// <param name="solution">The Solution file to examine.</param>
        /// <returns>The new projects for the given solution</returns>
        internal static string[] GetNewDependenciesInSolution(SolutionFile solution, bool filterConditionalReferences)
        {
            // Get a list of projects in the solution
            IEnumerable <string> existingProjects = SolutionUtilities.GetProjectsFromSolution(solution);

            // Get an updated list of dependencies
            IEnumerable <string> resolvedNOrderReferences = MSBuildUtilities.ProjectsIncludingNOrderDependencies(existingProjects, filterConditionalReferences);

            // Filter to only new projects
            string[] newReferences = resolvedNOrderReferences.Except(existingProjects, StringComparer.InvariantCultureIgnoreCase).ToArray();

            return(newReferences);
        }
        /// <summary>
        ///   Gets all Projects INCLUDING their N-Order Dependencies based off
        /// a project listing. Also Includes RuntimeReference Tags.
        /// </summary>
        /// <param name="projectList">A list of MSBuild Projects.</param>
        /// <returns>All Projects in the List INCLUDING their N-Order Dependencies AND Runtime References.</returns>
        public static IEnumerable <string> ProjectsIncludingNOrderDependencies(IEnumerable <string> projectList, bool filterConditionalReferences)
        {
            // Have our Resolved References
            SortedSet <string> resolvedReferences = new SortedSet <string>(StringComparer.InvariantCultureIgnoreCase);

            // Start Spinning for References
            Stack <string> projectsToResolve = new Stack <string>(projectList.Distinct());

            while (projectsToResolve.Count > 0)
            {
                // Start resolving the current project
                string currentProjectToResolve = projectsToResolve.Pop();

                // Don't attempt to resolve projects which have already been resolved
                if (!resolvedReferences.Contains(currentProjectToResolve))
                {
                    // Add the current project to the list of resolved projects
                    resolvedReferences.Add(currentProjectToResolve);

                    // Get a list of all MSBuild ProjectReferences
                    IEnumerable <string> projectReferences = GetMSBuildProjectReferencesFullPath(currentProjectToResolve, filterConditionalReferences);

                    // But only add those which have not already been resolved
                    foreach (string projectReference in projectReferences)
                    {
                        if (!resolvedReferences.Contains(projectReference))
                        {
                            projectsToResolve.Push(projectReference);
                        }
                    }

                    // Also get a list of all RuntimeReferences
                    IEnumerable <string> runtimeReferences = MSBuildUtilities.GetRuntimeReferences(currentProjectToResolve);

                    // But only add those which have not already been resolved
                    foreach (string runtimeReference in runtimeReferences)
                    {
                        if (!resolvedReferences.Contains(runtimeReference))
                        {
                            projectsToResolve.Push(runtimeReference);
                        }
                    }
                }
            }

            return(resolvedReferences);
        }
        /// <summary>
        /// Generates a "Solution Fragment" that contains the correct syntax
        /// for adding a Project to a Visual Studio Solution.
        /// </summary>
        /// <param name="solutionRoot">The Directory that contains the solution file. This is used to generate the relative path to the CSPROJ File.</param>
        /// <param name="pathToProjFile">The fully qualified path to the Project File.</param>
        /// <returns>A named Tuple where the first element is the projectFragment lines (in order) for a Visual Studio Solution and the second is the projectGuid.</returns>
        internal static (IEnumerable <string> ProjectFragment, string ProjectGuid) FragmentForProject(string solutionRoot, string pathToProjFile)
        {
            string relativePathToProject = PathUtilities.GetRelativePath(solutionRoot, pathToProjFile);
            string projectTypeGuid       = GetProjectTypeGuid(pathToProjFile);
            string projectName           = Path.GetFileNameWithoutExtension(pathToProjFile);
            string projectGuid           = MSBuildUtilities.GetMSBuildProjectGuid(pathToProjFile);

            // Fix up relative paths to use backslash instead of forward slash
            relativePathToProject = relativePathToProject.Replace('/', '\\');

            string[] fragment =
                new string[]
            {
                $"Project(\"{projectTypeGuid}\") = \"{projectName}\", \"{relativePathToProject}\", \"{projectGuid}\"",
                $"EndProject",
            };
            return(fragment, projectGuid);
        }