1+ using Microsoft . Build . Construction ;
2+ using Microsoft . Build . Evaluation ;
3+
4+ namespace MermaidGraph . Diagrams ;
5+
6+ internal class GraphDiagram : Diagram
7+ {
8+ /// <inheritdoc />
9+ public override void Header ( string title )
10+ {
11+ base . Header ( title ) ;
12+ Graph . AppendLine ( "graph TD" ) ;
13+ }
14+
15+ /// <summary>
16+ /// Generate the dependency graph of a Visual Studio Project.
17+ /// </summary>
18+ /// <param name="file">`.csproj` file.</param>
19+ public override string Project ( FileInfo file )
20+ {
21+ Header ( file . Name ) ;
22+ using var projectCollection = new ProjectCollection ( ) ;
23+ var project = projectCollection . LoadProject ( file . FullName ) ;
24+ GraphProject ( project ) ;
25+ Graph . AppendLine ( Fence ) ;
26+ var graph = Graph . ToString ( ) ;
27+
28+ // Cleanup
29+ Graph . Clear ( ) ;
30+ projectCollection . UnloadAllProjects ( ) ;
31+
32+ return graph ;
33+ }
34+
35+ /// <summary>
36+ /// Generate the dependency graph of a Visual Studio Solution.
37+ /// </summary>
38+ /// <param name="file">`.sln` file.</param>
39+ public override string Solution ( FileInfo file )
40+ {
41+ Header ( file . Name ) ;
42+ var solutionFile = SolutionFile . Parse ( file . FullName ) ;
43+ var solutionName = Path . GetFileNameWithoutExtension ( file . Name ) ;
44+ var solutionId = $ "{ solutionName } ";
45+ Graph . AppendLine ( $$ """
46+ class {{ solutionName }} {
47+ type solution
48+ }
49+ """ ) ;
50+
51+ using var projectCollection = new ProjectCollection ( ) ;
52+
53+ foreach ( var project in solutionFile . ProjectsInOrder )
54+ {
55+ if ( project . ProjectType != SolutionProjectType . KnownToBeMSBuildFormat ) continue ;
56+
57+ var projectPath = project . AbsolutePath ;
58+ var projectName = Path . GetFileNameWithoutExtension ( projectPath ) ;
59+ Graph . AppendLine ( $ " { solutionId } --> { projectName } ") ;
60+ var projectFile = new FileInfo ( projectPath ) ;
61+ if ( projectFile . Exists )
62+ {
63+ var referenceProject = projectCollection . LoadProject ( projectFile . FullName ) ;
64+ GraphProject ( referenceProject ) ;
65+ }
66+ }
67+
68+ Graph . AppendLine ( Fence ) ;
69+ var graph = Graph . ToString ( ) ;
70+
71+ // Cleanup
72+ Graph . Clear ( ) ;
73+ projectCollection . UnloadAllProjects ( ) ;
74+
75+ return graph ;
76+ }
77+
78+ private void GraphProject ( Project project )
79+ {
80+ var projectName = Path . GetFileNameWithoutExtension ( project . FullPath ) ;
81+ var type = project . GetPropertyValue ( "OutputType" ) ;
82+ var targetFramework = project . GetPropertyValue ( "TargetFramework" ) ?? project . GetPropertyValue ( "TargetFrameworks" ) ;
83+ Graph . AppendLine ( $$ """
84+ class {{ projectName }} {
85+ type {{ type }}
86+ target {{ targetFramework }}
87+ }
88+ """ ) ;
89+
90+ foreach ( var item in project . GetItems ( "ProjectReference" ) )
91+ {
92+ var refPath = item . EvaluatedInclude ;
93+ var refName = Path . GetFileNameWithoutExtension ( refPath ) ;
94+ Graph . AppendLine ( $ " { projectName } ..> { refName } ") ;
95+ }
96+
97+ foreach ( var item in project . GetItems ( "PackageReference" ) )
98+ {
99+ var packageName = item . EvaluatedInclude ;
100+ var version = item . GetMetadataValue ( "Version" ) ;
101+ Graph . AppendLine ( $$ """
102+ class {{ packageName }} {
103+ type NuGet
104+ version {{ version }}
105+ }
106+ """ ) ;
107+
108+ Graph . AppendLine ( $ " { projectName } ..> { packageName } ") ;
109+ }
110+ }
111+ }
0 commit comments