public override SolutionDocumentNode Clone(SolutionDocumentNode newParent) { var newNode = new SolutionGlobalSection(newParent, Category, Value); newNode.Children.AddRange(Children.Select(x => x.Clone(newNode))); foreach (var keyValue in Values) { newNode.Values.Add(keyValue.Key, keyValue.Value); } return(newNode); }
public static SolutionFile Parse(string path, string[] contentLines) { var solutionFile = new SolutionFile(path); SolutionDocumentNode current = solutionFile; var isProjectMarkerAdded = false; foreach (var line in contentLines) { var parsedLine = SolutionDocLine.ParseLine(line); switch (parsedLine.Type) { case SlnDocLineType.ProjectBegin: { if (!(current is SolutionFile)) { throw new InvalidOperationException("Project must be located under Solution"); } var sln = current as SolutionFile; var proj = new SolutionProject(current, parsedLine); current = proj; if (sln.Projects.ContainsKey(proj.Guid)) { // already exists continue; } sln.Projects.Add(proj.Guid, proj); // The project is first item of projects. if (sln.Projects.Count == 1) { sln.Children.Add(new ProjectsNodeMarker(sln)); isProjectMarkerAdded = true; } } break; case SlnDocLineType.ProjectSectionBegin: { if (!(current is SolutionProject)) { throw new InvalidOperationException("ProjectSection must be located under Project"); } var proj = current as SolutionProject; var projSection = new SolutionProjectSection(current, parsedLine); current = projSection; if (proj.Sections.ContainsKey((projSection.Category, projSection.Value))) { // already exists continue; } proj.Sections.Add((projSection.Category, projSection.Value), projSection); } break; case SlnDocLineType.GlobalBegin: { if (!(current is SolutionFile)) { throw new InvalidOperationException("Global must be located under Solution"); } var sln = current as SolutionFile; sln.Global = new SolutionGlobal(current); if (!isProjectMarkerAdded) { // `Project` is always puts before `Global`. sln.Children.Add(new ProjectsNodeMarker(sln)); isProjectMarkerAdded = true; } sln.Children.Add(new GlobalNodeMarker(sln)); current = sln.Global; } break; case SlnDocLineType.GlobalSectionBegin: { if (!(current is SolutionGlobal)) { throw new InvalidOperationException("GlobalSection must be located under Global"); } var global = current as SolutionGlobal; var globalSection = new SolutionGlobalSection(current, parsedLine); if (global.Sections.ContainsKey((globalSection.Category, globalSection.Value))) { // already exists continue; } global.Sections.Add((globalSection.Category, globalSection.Value), globalSection); current = globalSection; } break; case SlnDocLineType.GlobalEnd: case SlnDocLineType.ProjectEnd: case SlnDocLineType.ProjectSectionEnd: case SlnDocLineType.GlobalSectionEnd: current = current.Parent; break; default: current.AddChild(parsedLine); break; } } return(solutionFile); }
private static void ModifySolutionFolders(SlnMergeMergeContext ctx) { if (ctx.Settings.NestedProjects == null || ctx.Settings.NestedProjects.Length == 0) { return; } // Build a solution folder tree. var solutionTree = BuildSolutionFlatTree(ctx.MergedSolutionFile); // Create a NestedProject section in the solution if it does not exist. if (!ctx.MergedSolutionFile.Global.Sections.TryGetValue(("NestedProjects", "preSolution"), out var section)) { section = new SolutionGlobalSection(ctx.MergedSolutionFile.Global, "NestedProjects", "preSolution"); ctx.MergedSolutionFile.Global.Sections.Add((section.Category, section.Value), section); } // Prepare to add nested projects. var definedSolutionFolders = (ctx.Settings.SolutionFolders ?? Array.Empty <SlnMergeSettings.SolutionFolder>()) .ToDictionary(k => k.FolderPath.Replace('\\', '/'), v => v.Guid); var nestedProjects = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var nestedProject in ctx.Settings.NestedProjects) { IEnumerable <string> nestedProjectGuids; var nestedProjectFolderGuid = default(string); // Find a target project if (string.IsNullOrEmpty(nestedProject.ProjectName)) { // by GUID nestedProjectGuids = new[] { nestedProject.ProjectGuid }; } else { // by Name var nestedProjectNamePattern = new Regex( "^" + Regex.Escape(nestedProject.ProjectName) .Replace(@"\*", ".*").Replace(@"\?", ".") + "$"); nestedProjectGuids = ctx.MergedSolutionFile.Projects.Values .Where(x => nestedProjectNamePattern.IsMatch(x.Name)) .Select(x => x.Guid); } // Find a solution folder if (string.IsNullOrEmpty(nestedProject.FolderPath)) { // by GUID nestedProjectFolderGuid = nestedProject.FolderGuid; } else { // by Path if (solutionTree.TryGetValue(nestedProject.FolderPath, out var folderNode)) { if (!folderNode.IsFolder) { throw new Exception($"Path '{nestedProject.FolderPath}' is not a Solution Folder."); } nestedProjectFolderGuid = folderNode.Project.Guid; } else { // The target Solution Folder does not exist. make the Solution Folders. var pathParts = nestedProject.FolderPath.Split('/', '\\'); for (var i = 0; i < pathParts.Length; i++) { var path = string.Join("/", pathParts.Take(i + 1)); var parentPath = string.Join("/", pathParts.Take(i)); if (solutionTree.TryGetValue(path, out var folderNode2)) { // A solution tree node already exists. if (!folderNode2.IsFolder) { throw new Exception($"Path '{path}' is not a Solution Folder."); } } else { // Create a new solution folder. if (!definedSolutionFolders.TryGetValue(path, out var guid)) { throw new Exception($"Path '{path}' doesn't exist in the Solution or Solution Folder definitions. To create a new folder, you need to define SolutionFolder in .mergesettings."); } var newFolder = new SolutionProject(ctx.MergedSolutionFile, typeGuid: GuidProjectTypeFolder, guid: guid.ToUpper(), name: pathParts[i], path: pathParts[i] ); ctx.MergedSolutionFile.Projects.Add(newFolder.Guid, newFolder); // If the solution folder has a parent folder, add the created folder as a child immediately. if (!string.IsNullOrEmpty(parentPath)) { section.Values[newFolder.Guid] = solutionTree[parentPath].Project.Guid; } // Rebuild the solution tree. solutionTree = BuildSolutionFlatTree(ctx.MergedSolutionFile); nestedProjectFolderGuid = newFolder.Guid; } } } } // Verify GUIDs / Paths if (!nestedProjectGuids.Any()) { throw new Exception($"Project '{nestedProject.ProjectName}' does not exists in the solution."); } if (nestedProjectFolderGuid == null) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } if (!ctx.MergedSolutionFile.Projects.ContainsKey(nestedProjectFolderGuid)) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } foreach (var nestedProjectGuid in nestedProjectGuids) { if (!ctx.MergedSolutionFile.Projects.ContainsKey(nestedProjectGuid)) { throw new Exception($"Project '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } nestedProjects.Add(nestedProjectGuid, nestedProjectFolderGuid); } } // Add nested projects. foreach (var keyValue in nestedProjects) { section.Values[keyValue.Key] = keyValue.Value; } }
private static void ModifySolutionFolders(SolutionFile solutionFile, SlnMergeSettings settings, ISlnMergeLogger logger) { if (settings.NestedProjects == null || settings.NestedProjects.Length == 0) { return; } // Build a solution folder tree. var solutionTree = BuildSolutionFlatTree(solutionFile); // Create a NestedProject section in the solution if it does not exist. if (!solutionFile.Global.Sections.TryGetValue(("NestedProjects", "preSolution"), out var section)) { section = new SolutionGlobalSection(solutionFile.Global, "NestedProjects", "preSolution"); solutionFile.Global.Sections.Add((section.Category, section.Value), section); } // Prepare to add nested projects. var nestedProjects = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); foreach (var nestedProject in settings.NestedProjects) { var nestedProjectGuid = default(string); var nestedProjectFolderGuid = default(string); // Find a target project if (string.IsNullOrEmpty(nestedProject.ProjectName)) { // by GUID nestedProjectGuid = nestedProject.ProjectGuid; } else { // by Name var proj = solutionFile.Projects.Values.FirstOrDefault(x => x.Name == nestedProject.ProjectName); if (proj != null) { nestedProjectGuid = proj.Guid; } } // Find a solution folder if (string.IsNullOrEmpty(nestedProject.FolderPath)) { // by GUID nestedProjectFolderGuid = nestedProject.FolderGuid; } else { // by Path if (solutionTree.TryGetValue(nestedProject.FolderPath, out var folderNode)) { if (!folderNode.IsFolder) { throw new Exception($"Path '{nestedProject.FolderPath}' is not a Solution Folder."); } nestedProjectFolderGuid = folderNode.Project.Guid; } else { // The target Solution Folder does not exist. make the Solution Folders. var pathParts = nestedProject.FolderPath.Split('/', '\\'); for (var i = 0; i < pathParts.Length; i++) { var path = string.Join("/", pathParts.Take(i + 1)); var parentPath = string.Join("/", pathParts.Take(i)); if (solutionTree.TryGetValue(path, out var folderNode2)) { // A solution tree node already exists. if (!folderNode2.IsFolder) { throw new Exception($"Path '{path}' is not a Solution Folder."); } } else { // Create a new solution folder. var newFolder = new SolutionProject(solutionFile, typeGuid: GuidProjectTypeFolder, guid: Guid.NewGuid().ToString("B").ToUpper(), name: pathParts[i], path: pathParts[i] ); solutionFile.Projects.Add(newFolder.Guid, newFolder); // If the solution folder has a parent folder, add the created folder as a child immediately. if (!string.IsNullOrEmpty(parentPath)) { section.Values[newFolder.Guid] = solutionTree[parentPath].Project.Guid; } // Rebuild the solution tree. solutionTree = BuildSolutionFlatTree(solutionFile); nestedProjectFolderGuid = newFolder.Guid; } } } } // Verify GUIDs / Paths if (nestedProjectGuid == null) { throw new Exception($"Project '{nestedProject.ProjectName}' does not exists in the solution."); } if (nestedProjectFolderGuid == null) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } if (!solutionFile.Projects.ContainsKey(nestedProjectGuid)) { throw new Exception($"Project '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } if (!solutionFile.Projects.ContainsKey(nestedProjectFolderGuid)) { throw new Exception($"Solution Folder '{nestedProject.FolderGuid}' (GUID) does not exists in the solution."); } nestedProjects.Add(nestedProjectGuid, nestedProjectFolderGuid); } // Add nested projects. foreach (var keyValue in nestedProjects) { section.Values[keyValue.Key] = keyValue.Value; } }