using Microsoft.Build.Construction; namespace DotNetSolutionTools.Core; public static class SolutionProjectParity { public static List CompareSolutionAndCSharpProjects( string solutionFolderPath, string solutionFilePath ) { var csprojList = RetrieveAllCSharpProjectNamesFromFolder(solutionFolderPath); var solutionFile = ParseSolutionFileFromPath(solutionFilePath); ArgumentNullException.ThrowIfNull(solutionFile); var projectsMissingFromSolution = FindProjectsMissingFromSolution(csprojList, solutionFile); return projectsMissingFromSolution; } public static string[] RetrieveAllCSharpProjectNamesFromFolder(string solutionFolderPath) { var csprojList = RetrieveAllCSharpProjectFullPathsFromFolder(solutionFolderPath); csprojList = csprojList.Select(x => x.Replace(solutionFolderPath, "")).ToArray(); return csprojList; } public static string[] RetrieveAllCSharpProjectFullPathsFromFolder(string solutionFolderPath) { // if solutionFolderPath does not end with a slash, add one if (solutionFolderPath[^1] != Path.DirectorySeparatorChar) { solutionFolderPath += Path.DirectorySeparatorChar; } var csprojList = Directory.GetFiles( solutionFolderPath, "*.csproj", SearchOption.AllDirectories ); return csprojList; } public static SolutionFile? ParseSolutionFileFromPath(string solutionFilePath) { var solutionFile = SolutionFile.Parse(solutionFilePath); return solutionFile; } public static List FindProjectsMissingFromSolution( string[] csprojList, SolutionFile solutionFile ) { var projects = solutionFile.ProjectsInOrder; var projectsMissingFromSolution = new List(); foreach (var project in csprojList) { var projectInSolution = projects.FirstOrDefault(x => x.RelativePath == project); if (projectInSolution == null) { projectsMissingFromSolution.Add(project); } } return projectsMissingFromSolution; } public static List GetCSharpProjectObjectsFromSolutionFile( SolutionFile solutionFile ) { var projectList = solutionFile.ProjectsByGuid .Where(x => x.Value.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) .Select(s => ProjectRootElement.Open(s.Value.AbsolutePath)) .ToList(); return projectList; } }