Skip to content

Commit 9544240

Browse files
Add name filtering
Improve tests
1 parent fae7751 commit 9544240

8 files changed

Lines changed: 95 additions & 37 deletions

File tree

mermaid-graph/Commands.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,20 @@ public class Commands
1010
/// <summary>
1111
/// Generate the dependency graph of a Visual Studio Project.
1212
/// </summary>
13-
/// <param name="file">`.csproj` file.</param>
14-
/// <param name="diagramType"></param>
15-
public static string Project(FileInfo file, DiagramType diagramType = DiagramType.Graph)
13+
public static string Project(FileInfo file, DiagramType diagramType = DiagramType.Graph, string? filter = null)
1614
{
1715
var graph = MermaidDiagram.GetDiagramType(diagramType);
1816

19-
return graph.Project(file);
17+
return graph.Project(file, filter);
2018
}
2119

2220
/// <summary>
2321
/// Generate the dependency graph of a Visual Studio Solution.
2422
/// </summary>
25-
/// <param name="file">`.sln` file.</param>
26-
/// <param name="diagramType"></param>
27-
public static string Solution(FileInfo file, DiagramType diagramType = DiagramType.Graph)
23+
public static string Solution(FileInfo file, DiagramType diagramType = DiagramType.Graph, string? filter = null)
2824
{
2925
var graph = MermaidDiagram.GetDiagramType(diagramType);
3026

31-
return graph.Solution(file);
27+
return graph.Solution(file, filter);
3228
}
3329
}

mermaid-graph/Diagrams/Base/IMermaidDiagram.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ public interface IMermaidDiagram
1111
/// Generate the diagram from a visual studio project file (*.csproj)
1212
/// </summary>
1313
/// <param name="file">The project file</param>
14+
/// <param name="filter">Exclude projects whose name matches the filter. (e.g., Test)</param>
1415
/// <returns>Mermaid Markdown</returns>
15-
public string Project(FileInfo file);
16+
public string Project(FileInfo file, string? filter = null);
1617

1718
/// <summary>
1819
/// Generate the diagram from a visual studio solution file (*.sln)
1920
/// </summary>
2021
/// <param name="file">The solution file.</param>
22+
/// <param name="filter">Exclude projects whose name matches the filter. (e.g., Test)</param>
2123
/// <returns>Mermaid Markdown</returns>
22-
public string Solution(FileInfo file);
24+
public string Solution(FileInfo file, string? filter = null);
2325
}

mermaid-graph/Diagrams/Base/MermaidDiagram.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public abstract class MermaidDiagram : IMermaidDiagram
2020
/// </summary>
2121
public const string MermaidBegin = Fence + "mermaid";
2222

23-
internal readonly StringBuilder Graph = new(256);
23+
internal StringBuilder Graph { get; } = new(256);
2424

2525
/// <summary>
2626
/// Initialize the MermaidDiagram class and ensure MSBuild is registered.
@@ -70,12 +70,12 @@ public virtual void Header(string title)
7070
public override string ToString() => Graph.ToString();
7171

7272
/// <inheritdoc />
73-
public virtual string Project(FileInfo file)
73+
public virtual string Project(FileInfo file, string? filter = null)
7474
{
7575
Header(file.Name);
7676
using var projectCollection = new ProjectCollection();
7777
var project = projectCollection.LoadProject(file.FullName);
78-
GraphProject(project);
78+
GraphProject(project, filter);
7979
Graph.AppendLine(Fence);
8080

8181
projectCollection.UnloadAllProjects();
@@ -84,11 +84,12 @@ public virtual string Project(FileInfo file)
8484
}
8585

8686
/// <inheritdoc />
87-
public abstract string Solution(FileInfo file);
87+
public abstract string Solution(FileInfo file, string? filter = null);
8888

8989
/// <summary>
9090
/// This method must be implemented in all derived classes to generate the graph for a project.
9191
/// </summary>
9292
/// <param name="project">A project to graph.</param>
93-
internal abstract void GraphProject(Project project);
93+
/// <param name="filter">Exclude projects whose name matches the filter. (e.g., Test)</param>
94+
internal abstract void GraphProject(Project project, string? filter = null);
9495
}

mermaid-graph/Diagrams/ClassDiagram.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@ public override void Header(string title)
1616
Graph.AppendLine("classDiagram");
1717
}
1818

19-
/// <summary>
20-
/// Generate the dependency graph of a Visual Studio Solution.
21-
/// </summary>
22-
/// <param name="file">`.sln` file.</param>
23-
public override string Solution(FileInfo file)
19+
/// <inheritdoc />
20+
public override string Solution(FileInfo file, string? filter = null)
2421
{
2522
Header(file.Name);
2623
var solutionFile = SolutionFile.Parse(file.FullName);
@@ -37,15 +34,19 @@ type solution
3734
foreach (var project in solutionFile.ProjectsInOrder)
3835
{
3936
if (project.ProjectType != SolutionProjectType.KnownToBeMSBuildFormat) continue;
40-
37+
4138
var projectPath = project.AbsolutePath;
4239
var projectName = Path.GetFileNameWithoutExtension(projectPath);
40+
if (!string.IsNullOrEmpty(filter) &&
41+
projectName.Contains(filter, StringComparison.Ordinal))
42+
continue;
43+
4344
Graph.AppendLine($" {solutionId} --> {projectName}");
4445
var projectFile = new FileInfo(projectPath);
4546
if (projectFile.Exists)
4647
{
4748
var referenceProject = projectCollection.LoadProject(projectFile.FullName);
48-
GraphProject(referenceProject);
49+
GraphProject(referenceProject, filter);
4950
}
5051
}
5152

@@ -56,11 +57,13 @@ type solution
5657
return Graph.ToString();
5758
}
5859

59-
internal override void GraphProject(Project project)
60+
internal override void GraphProject(Project project, string? filter = null)
6061
{
6162
var projectName = Path.GetFileNameWithoutExtension(project.FullPath);
6263
var type = project.GetPropertyValue("OutputType");
63-
var targetFramework = project.GetPropertyValue("TargetFramework") ?? project.GetPropertyValue("TargetFrameworks");
64+
var targetFramework = project.GetPropertyValue("TargetFramework") ??
65+
project.GetPropertyValue("TargetFrameworks");
66+
6467
Graph.AppendLine($$"""
6568
class {{projectName}}{
6669
type {{type}}
@@ -72,6 +75,10 @@ class {{projectName}}{
7275
{
7376
var refPath = item.EvaluatedInclude;
7477
var refName = Path.GetFileNameWithoutExtension(refPath);
78+
if (!string.IsNullOrEmpty(filter) &&
79+
projectName.Contains(filter, StringComparison.Ordinal))
80+
continue;
81+
7582
Graph.AppendLine($" {projectName} ..> {refName}");
7683
}
7784

mermaid-graph/Diagrams/GraphDiagram.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@ public override void Header(string title)
1616
Graph.AppendLine("graph TD");
1717
}
1818

19-
/// <summary>
20-
/// Generate the dependency graph of a Visual Studio Solution.
21-
/// </summary>
22-
/// <param name="file">`.sln` file.</param>
23-
public override string Solution(FileInfo file)
19+
/// <inheritdoc />
20+
public override string Solution(FileInfo file, string? filter = null)
2421
{
2522
Header(file.Name);
2623
var solutionFile = SolutionFile.Parse(file.FullName);
@@ -35,12 +32,16 @@ public override string Solution(FileInfo file)
3532

3633
var projectPath = project.AbsolutePath;
3734
var projectName = Path.GetFileNameWithoutExtension(projectPath);
35+
if (!string.IsNullOrEmpty(filter) &&
36+
projectName.Contains(filter, StringComparison.Ordinal))
37+
continue;
38+
3839
Graph.AppendLine($" {solutionId} --> {projectName}");
3940
var projectFile = new FileInfo(projectPath);
4041
if (projectFile.Exists)
4142
{
4243
var referenceProject = projectCollection.LoadProject(projectFile.FullName);
43-
GraphProject(referenceProject);
44+
GraphProject(referenceProject, filter);
4445
}
4546
}
4647

@@ -51,14 +52,18 @@ public override string Solution(FileInfo file)
5152
return Graph.ToString();
5253
}
5354

54-
internal override void GraphProject(Project project)
55+
internal override void GraphProject(Project project, string? filter = null)
5556
{
5657
var projectName = Path.GetFileNameWithoutExtension(project.FullPath);
5758

5859
foreach (var item in project.GetItems("ProjectReference"))
5960
{
6061
var refPath = item.EvaluatedInclude;
6162
var refName = Path.GetFileNameWithoutExtension(refPath);
63+
if (!string.IsNullOrEmpty(filter) &&
64+
projectName.Contains(filter, StringComparison.Ordinal))
65+
continue;
66+
6267
Graph.AppendLine($" {projectName} --> {refName}");
6368
}
6469

mermaid-graph/Program.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ public sealed class Program
1212
/// </summary>
1313
/// <param name="path">Full path to the solution (*.sln) or project (*.csproj) file that will be mapped.</param>
1414
/// <param name="type">The type of diagram to generate (e.g., Graph or Class).</param>
15+
/// <param name="filter">Exclude projects whose name matches the filter. (e.g., Test)</param>
1516
/// <returns>HResult</returns>
16-
public static int Main(string? path, DiagramType type = DiagramType.Graph)
17+
public static int Main(string? path, DiagramType type = DiagramType.Graph, string? filter = null)
1718
{
1819
if (path is null)
1920
{
@@ -34,13 +35,13 @@ public static int Main(string? path, DiagramType type = DiagramType.Graph)
3435
{
3536
if (path.EndsWith(".csproj"))
3637
{
37-
Console.WriteLine(Commands.Project(file, type));
38+
Console.WriteLine(Commands.Project(file, type, filter));
3839
return 0;
3940
}
4041

4142
if (path.EndsWith(".sln"))
4243
{
43-
Console.WriteLine(Commands.Solution(file, type));
44+
Console.WriteLine(Commands.Solution(file, type, filter));
4445
return 0;
4546
}
4647
}

mermaid-graphTests/CommandsTests.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ private V8ScriptEngine Js {
2929
new object[] { DiagramType.Graph, "flowchart" }
3030
];
3131

32+
internal static readonly object[] FilterTestCases =
33+
[
34+
new object[] { DiagramType.Class, "Test" },
35+
new object[] { DiagramType.Graph, "Test" }
36+
];
37+
3238
[OneTimeTearDown]
3339
public void Disposal()
3440
{
@@ -46,10 +52,13 @@ public void DogFoodSolutionTest(DiagramType type, string typeName)
4652
var graph = Commands.Solution(info, type);
4753

4854
Console.WriteLine(graph);
49-
55+
Assert.That(graph, Is.Not.Null.Or.Empty, "Graph should not be null or empty.");
56+
Assert.That(graph, Does.Contain("mermaid-graph"));
57+
Assert.That(graph, Does.Contain("MermaidGraphTests"));
5058
var graphType = DetectType(ExtractMermaid(graph));
59+
Console.WriteLine($"Detected type: {graphType}");
60+
5161
Assert.That(graphType, Is.EqualTo(typeName));
52-
Console.WriteLine(graphType);
5362
}
5463

5564
[Test]
@@ -61,7 +70,9 @@ public void DogFoodProjectTest(DiagramType type, string typeName)
6170
var info = new FileInfo(filePath!);
6271
Assert.That(info.Exists);
6372
var graph = Commands.Project(info, type);
64-
73+
Assert.That(graph, Is.Not.Null.Or.Empty, "Graph should not be null or empty.");
74+
Assert.That(graph, Does.Contain("mermaid-graph"));
75+
Assert.That(graph, Does.Contain("MermaidGraphTests"));
6576
Console.WriteLine(graph);
6677

6778
var graphType = DetectType(ExtractMermaid(graph));
@@ -97,6 +108,24 @@ public void CommandLineFailTests(string? file, int hResult)
97108
Assert.That(Program.Main(file), Is.EqualTo(hResult));
98109
}
99110

111+
[Test]
112+
[TestCaseSource(nameof(FilterTestCases))]
113+
public void DiagramsShouldNotContainFilteredContent(DiagramType type, string filter)
114+
{
115+
var solutionPath = FindFileDownTree("*.sln");
116+
Assert.That(solutionPath, Is.Not.Null);
117+
var info = new FileInfo(solutionPath!);
118+
Assert.That(info.Exists);
119+
var graph = Commands.Solution(info, type);
120+
Assert.That(graph, Does.Contain(filter),
121+
$"Original Graph should contain filtered content: {filter}");
122+
123+
graph = Commands.Solution(info, type, filter);
124+
Console.WriteLine(graph);
125+
Assert.That(graph, Does.Not.Contain(filter),
126+
$"Graph should not contain filtered content: {filter}");
127+
}
128+
100129
private static string ExtractMermaid(string? markup)
101130
{
102131
Assert.That(markup, Does.StartWith(MermaidDiagram.MermaidBegin));

mermaid-graphTests/MermaidDiagramTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,22 @@ public void GetDiagramType_ShouldThrowForUnsupportedType()
2727
Assert.Throws<NotImplementedException>(()=>
2828
MermaidDiagram.GetDiagramType((DiagramType)999));
2929
}
30+
31+
[Test]
32+
[TestCase(DiagramType.Class)]
33+
[TestCase(DiagramType.Graph)]
34+
public void Header_ShouldInitializeGraphWithTitle(DiagramType type)
35+
{
36+
var diagram = (MermaidDiagram)MermaidDiagram.GetDiagramType(type);
37+
38+
// Arrange
39+
const string title = "Test Diagram";
40+
41+
// Act
42+
diagram.Header(title);
43+
44+
// Assert
45+
Assert.That(diagram.ToString(), Does.Contain($"title: {title}"));
46+
}
3047
}
3148

0 commit comments

Comments
 (0)