Skip to content

Commit 03d8d77

Browse files
MVP POC
This is a working prototype.
1 parent 8978eef commit 03d8d77

File tree

6 files changed

+131
-60
lines changed

6 files changed

+131
-60
lines changed

MermaidGraph.NET.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
```mermaid
2+
graph TD
3+
MermaidGraph.NET --> mermaid-graph
4+
mermaid-graph -->|NuGet| Microsoft.Build
5+
mermaid-graph -->|NuGet| Microsoft.Build.Locator
6+
mermaid-graph -->|NuGet| Microsoft.Build.Utilities.Core
7+
mermaid-graph -->|NuGet| System.CommandLine.DragonFruit
8+
```

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
# MermaidGraph.NET
22
Create a mermaid graph of the dependency diagram for a project, or whole solution.
3+
4+
## Example
5+
{!MermaidGraph.NET.md!}
6+
7+
[MermaidGraph.NET.md](MermaidGraph.NET.md)

mermaid-graph/Commands.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System.Text;
2+
using Microsoft.Build.Construction;
3+
using Microsoft.Build.Evaluation;
4+
5+
namespace MermaidGraph;
6+
7+
/// <summary>
8+
/// The commands that can be run by `mermaid-graph`
9+
/// </summary>
10+
public static class Commands
11+
{
12+
private static readonly StringBuilder Graph = new();
13+
14+
private const string Fence = "```";
15+
16+
static Commands()
17+
{
18+
Graph.AppendLine(Fence + "mermaid");
19+
Graph.AppendLine("graph TD");
20+
}
21+
22+
/// <summary>
23+
/// Generate the dependency graph of a Visual Studio Project.
24+
/// </summary>
25+
/// <param name="path">Full path to `.csproj` file.</param>
26+
public static void Project(string path)
27+
{
28+
GraphProject(path);
29+
Graph.AppendLine(Fence);
30+
Console.WriteLine(Graph.ToString());
31+
}
32+
33+
private static void GraphProject(string path)
34+
{
35+
// Load project
36+
var project = new Project(path);
37+
var projectName = Path.GetFileNameWithoutExtension(path);
38+
39+
foreach (var item in project.GetItems("ProjectReference"))
40+
{
41+
string refPath = item.EvaluatedInclude;
42+
string refName = Path.GetFileNameWithoutExtension(refPath);
43+
Graph.AppendLine($" {projectName} --> {refName}");
44+
}
45+
46+
foreach (var item in project.GetItems("PackageReference"))
47+
{
48+
string packageName = item.EvaluatedInclude;
49+
Graph.AppendLine($" {projectName} -->|NuGet| {packageName}");
50+
}
51+
}
52+
53+
/// <summary>
54+
/// Generate the dependency graph of a Visual Studio Solution.
55+
/// </summary>
56+
/// <param name="path">Full path to `.sln` file.</param>
57+
public static void Solution(string path)
58+
{
59+
var solutionFile = SolutionFile.Parse(path);
60+
var solutionName = Path.GetFileNameWithoutExtension(path);
61+
foreach (var project in solutionFile.ProjectsInOrder)
62+
{
63+
if (project.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)
64+
{
65+
var projectPath = project.AbsolutePath;
66+
var projectName = Path.GetFileNameWithoutExtension(projectPath);
67+
Graph.AppendLine($" {solutionName} --> {projectName}");
68+
if (File.Exists(projectPath))
69+
{
70+
GraphProject(projectPath);
71+
}
72+
}
73+
}
74+
75+
Graph.AppendLine(Fence);
76+
Console.WriteLine(Graph.ToString());
77+
}
78+
}

mermaid-graph/Program.cs

Lines changed: 32 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,55 @@
1-
using System.Text;
2-
using Microsoft.Build.Evaluation;
3-
using Microsoft.Build.Locator;
1+
using Microsoft.Build.Locator;
42

5-
namespace mermaid_graph;
3+
namespace MermaidGraph;
64

7-
internal class Program
5+
// ReSharper disable UnusedMember.Global
6+
7+
/// <summary>
8+
/// mermaid-graph.exe
9+
/// </summary>
10+
internal sealed class Program
811
{
912
/// <summary>
1013
/// Outputs a mermaid graph of the dependency diagram for a project, or whole solution.
1114
/// </summary>
1215
/// <param name="path">Full path to the solution (*.sln) or project (*.csproj) file that will be mapped.</param>
1316
/// <returns>HResult</returns>
14-
static int Main(string path)
17+
internal static int Main(string path)
1518
{
16-
if (!File.Exists(path))
19+
var file = new FileInfo(path);
20+
if (!file.Exists)
1721
{
1822
Console.WriteLine($"Error: File not found - {path}");
1923
return 1;
2024
}
2125

22-
// Register the MSBuild instance (needed for Microsoft.Build.Evaluation)
23-
MSBuildLocator.RegisterDefaults();
24-
25-
if (path.EndsWith(".csproj"))
26+
try
2627
{
27-
return Commands.Project(path);
28+
// Ensure MSBuild is registered
29+
if (!MSBuildLocator.IsRegistered)
30+
{
31+
MSBuildLocator.RegisterDefaults();
32+
}
33+
34+
if (path.EndsWith(".csproj"))
35+
{
36+
Commands.Project(file.FullName);
37+
return 0;
38+
}
39+
40+
if (path.EndsWith(".sln"))
41+
{
42+
Commands.Solution(file.FullName);
43+
return 0;
44+
}
2845
}
29-
30-
if (path.EndsWith(".sln"))
46+
catch (Exception ex)
3147
{
32-
return Commands.Solution(path);
48+
Console.WriteLine(ex);
49+
return ex.HResult;
3350
}
3451

3552
Console.WriteLine($"Error: Unsupported file type - {path}");
3653
return 2;
3754
}
38-
}
39-
40-
public static class Commands
41-
{
42-
/// <summary>
43-
/// Generate
44-
/// </summary>
45-
46-
public static int Project(string path)
47-
{
48-
// Load project
49-
var project = new Project(path);
50-
51-
var sb = new StringBuilder("```");
52-
sb.AppendLine("graph TD;");
53-
54-
string projectName = Path.GetFileNameWithoutExtension(path);
55-
56-
// Add ProjectReferences
57-
foreach (var item in project.GetItems("ProjectReference"))
58-
{
59-
string refPath = item.EvaluatedInclude;
60-
string refName = Path.GetFileNameWithoutExtension(refPath);
61-
sb.AppendLine($" {projectName} --> {refName}");
62-
}
63-
64-
// Add PackageReferences
65-
foreach (var item in project.GetItems("PackageReference"))
66-
{
67-
string packageName = item.EvaluatedInclude;
68-
sb.AppendLine($" {projectName} -->|NuGet| {packageName}");
69-
}
70-
71-
// Output Mermaid.js graph
72-
Console.WriteLine(sb.ToString());
73-
74-
return 0;
75-
}
76-
77-
internal static int Solution(string path)
78-
{
79-
throw new NotImplementedException();
80-
}
8155
}

mermaid-graph/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"mermaid-graph": {
44
"commandName": "Project",
5-
"commandLineArgs": "--path \"..\\..\\..\\mermaid-graph.csproj\""
5+
"commandLineArgs": "--path \"..\\..\\..\\..\\MermaidGraph.NET.sln\""
66
}
77
}
88
}

mermaid-graph/mermaid-graph.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@
33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
55
<TargetFramework>net9.0</TargetFramework>
6-
<RootNamespace>mermaid_graph</RootNamespace>
6+
<RootNamespace>MermaidGraph</RootNamespace>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>
99
<InvariantGlobalization>true</InvariantGlobalization>
10+
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
11+
<AnalysisLevel>latest-recommended</AnalysisLevel>
12+
<PackAsTool>True</PackAsTool>
13+
<StartupObject>MermaidGraph.Program</StartupObject>
1014
</PropertyGroup>
1115

1216
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
1317
<WarningLevel>8</WarningLevel>
18+
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
1419
</PropertyGroup>
1520

1621
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
1722
<WarningLevel>8</WarningLevel>
23+
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
1824
</PropertyGroup>
1925

2026
<ItemGroup>

0 commit comments

Comments
 (0)