Created
August 31, 2017 07:13
-
-
Save johannesegger/1c845a89aa59db89560633c2bc83ec83 to your computer and use it in GitHub Desktop.
Nuke .sln parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Xml; | |
using System.Xml.Linq; | |
using System.Xml.XPath; | |
namespace Nuke.Common.Tools.VisualStudio | |
{ | |
public class VSProject | |
{ | |
public VSProject(string outputType, string assemblyName) | |
{ | |
OutputType = outputType; | |
AssemblyName = assemblyName; | |
} | |
public string OutputType { get; } | |
public string AssemblyName { get; } | |
public static VSProject Parse(string path) | |
{ | |
// TODO support new csproj format | |
var doc = XDocument.Load(path); | |
var nsMgr = new XmlNamespaceManager(new NameTable()); | |
nsMgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003"); | |
var outputType = doc.XPathSelectElement("/x:Project/x:PropertyGroup/x:OutputType", nsMgr).Value; | |
var assemblyName = doc.XPathSelectElement("/x:Project/x:PropertyGroup/x:AssemblyName", nsMgr).Value; | |
return new VSProject(outputType, assemblyName); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
using Nuke.Core.Utilities; | |
namespace Nuke.Common.Tools.VisualStudio | |
{ | |
public class VSSolution | |
{ | |
public IReadOnlyCollection<Project> Projects { get; } | |
public VSSolution(IEnumerable<Project> projects) | |
{ | |
Projects = projects.ToList(); | |
} | |
public static VSSolution Parse(string path) | |
{ | |
string guidExpr(string name) => | |
$@"\{{(?<{Regex.Escape(name)}>[0-9a-fA-F]{{8}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{12}})\}}"; | |
string quotedGuidExpr(string name) => | |
$@"""{guidExpr(name)}"""; | |
string quotedTextExpr(string name) => | |
$@"""(?<{Regex.Escape(name)}>[^""]*)"""; | |
var lines = File.ReadAllLines(path); | |
var childToParentMap = lines | |
.SkipWhile(line => !Regex.IsMatch(line, @"^\s*GlobalSection\(NestedProjects\) = preSolution$")) | |
.Skip(1) | |
.TakeWhile(line => !Regex.IsMatch(line, @"^\s*EndGlobalSection$")) | |
.Select(line => Regex.Match(line, $@"^\s*{guidExpr("child")}\s*=\s*{guidExpr("parent")}$")) | |
.ToDictionary(m => Guid.Parse(m.Groups["child"].Value), m => Guid.Parse(m.Groups["parent"].Value)); | |
var projects = lines | |
.Select(line => Regex.Match(line, $@"^Project\({quotedGuidExpr("typeId")}\)\s*=\s*{quotedTextExpr("name")},\s*{quotedTextExpr("path")},\s*{quotedGuidExpr("id")}$")) | |
.Where(m => m.Success) | |
.Select(m => | |
{ | |
var id = Guid.Parse(m.Groups["id"].Value); | |
return new Project( | |
id, | |
m.Groups["name"].Value, | |
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), m.Groups["path"].Value)), | |
Guid.Parse(m.Groups["typeId"].Value), | |
childToParentMap.TryGetValue(id, out var parentId) ? (Guid?)parentId : null); | |
}) | |
.Where(p => p.Name != ".build"); | |
return new VSSolution(projects); | |
} | |
public class Project | |
{ | |
public Project( | |
Guid id, | |
string name, | |
string path, | |
Guid typeId, | |
Guid? parentId) | |
{ | |
Id = id; | |
Name = name; | |
Path = path; | |
Directory = System.IO.Path.GetDirectoryName(Path); | |
TypeId = typeId; | |
ParentId = parentId; | |
} | |
public Guid Id { get; } | |
public string Name { get; } | |
public string Path { get; } | |
public string Directory { get; } | |
public Guid TypeId { get; } | |
public Guid? ParentId { get; } | |
public IEnumerable<Project> GetParents(IEnumerable<Project> projects) | |
{ | |
var idToProjectMap = projects | |
.ToDictionary(p => p.Id, p => p); | |
var parentId = ParentId; | |
while (parentId != null) | |
{ | |
var parent = idToProjectMap[parentId.Value]; | |
yield return parent; | |
parentId = parent.ParentId; | |
} | |
} | |
public IEnumerable<Project> GetParentsAndSelf(IEnumerable<Project> projects) | |
{ | |
yield return this; | |
foreach (var parent in GetParents(projects)) | |
{ | |
yield return parent; | |
} | |
} | |
public string GetFullProjectName(IEnumerable<Project> projects) | |
{ | |
return GetParentsAndSelf(projects) | |
.Select(p => p.Name.Replace(".", "_")) | |
.Reverse() | |
.Join("\\"); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment