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