1212using System . Linq ;
1313using System . Text ;
1414using CoreBuilder . Helper ;
15+ using CoreBuilder . Interface ;
16+ using CoreBuilder . UI ;
1517using Microsoft . CodeAnalysis ;
1618using Microsoft . CodeAnalysis . CSharp ;
1719using Microsoft . CodeAnalysis . CSharp . Syntax ;
@@ -40,8 +42,26 @@ public sealed class ApiExplorerCommand : ICommand
4042 /// <inheritdoc />
4143 public CommandSignature Signature => new ( Namespace , Name , ParameterCount ) ;
4244
45+
4346 /// <inheritdoc />
44- public int ParameterCount => 1 ;
47+ /// <summary>
48+ /// folder + optional outputMode
49+ /// </summary>
50+ public int ParameterCount => 2 ;
51+
52+ /// <summary>
53+ /// The output
54+ /// </summary>
55+ private readonly IEventOutput _output ;
56+
57+ /// <summary>
58+ /// Initializes a new instance of the <see cref="ApiExplorerCommand"/> class.
59+ /// </summary>
60+ /// <param name="output">The output.</param>
61+ public ApiExplorerCommand ( IEventOutput ? output = null )
62+ {
63+ _output = output ?? new WpfEventOutput ( ) ;
64+ }
4565
4666 /// <inheritdoc />
4767 public CommandResult Execute ( params string [ ] args )
@@ -53,6 +73,8 @@ public CommandResult Execute(params string[] args)
5373 if ( ! Directory . Exists ( rootPath ) )
5474 return CommandResult . Fail ( $ "Folder not found: { rootPath } ") ;
5575
76+ bool useWindow = args . Length > 1 && args [ 1 ] . Equals ( "window" , StringComparison . OrdinalIgnoreCase ) ;
77+
5678 var sb = new StringBuilder ( ) ;
5779 var files = Directory
5880 . EnumerateFiles ( rootPath , CoreResources . ResourceCsExtension , SearchOption . AllDirectories )
@@ -66,22 +88,18 @@ public CommandResult Execute(params string[] args)
6688 var tree = CSharpSyntaxTree . ParseText ( code ) ;
6789 var root = tree . GetCompilationUnitRoot ( ) ;
6890
69- // handle both block-style and file-scoped namespaces
7091 var namespaces = root . DescendantNodes ( ) . OfType < BaseNamespaceDeclarationSyntax > ( ) ;
7192 if ( ! namespaces . Any ( ) )
72- {
73- // handle top-level types (no namespace)
74- DumpTypes ( root . Members . OfType < BaseTypeDeclarationSyntax > ( ) , sb , "(global)" ) ;
75- }
93+ DumpTypes ( root . Members . OfType < BaseTypeDeclarationSyntax > ( ) , sb , _output , "(global)" ) ;
7694 else
77- {
7895 foreach ( var ns in namespaces )
79- DumpTypes ( ns . Members . OfType < BaseTypeDeclarationSyntax > ( ) , sb , ns . Name . ToString ( ) ) ;
80- }
96+ DumpTypes ( ns . Members . OfType < BaseTypeDeclarationSyntax > ( ) , sb , _output , ns . Name . ToString ( ) ) ;
8197 }
8298 catch ( Exception ex )
8399 {
84- sb . AppendLine ( $ "// Error parsing { file } : { ex . Message } ") ;
100+ var line = $ "// Error parsing { file } : { ex . Message } ";
101+ sb . AppendLine ( line ) ;
102+ _output ? . Write ( line ) ;
85103 }
86104 }
87105
@@ -94,14 +112,15 @@ public CommandResult Execute(params string[] args)
94112 /// <param name="types">The types.</param>
95113 /// <param name="sb">The sb.</param>
96114 /// <param name="nsName">Name of the ns.</param>
97- private static void DumpTypes ( IEnumerable < BaseTypeDeclarationSyntax > types , StringBuilder sb , string nsName )
115+ private static void DumpTypes ( IEnumerable < BaseTypeDeclarationSyntax > types , StringBuilder sb , IEventOutput ? output , string nsName )
98116 {
99- // Filter to only public types
100117 var publicTypes = types . Where ( t => IsPublic ( t . Modifiers ) ) . ToList ( ) ;
101- if ( publicTypes . Count == 0 )
102- return ; // Nothing public => skip the whole namespace
118+ if ( publicTypes . Count == 0 ) return ;
119+
120+ var nsLine = $ "namespace { nsName } ";
121+ sb . AppendLine ( nsLine ) ;
122+ output ? . Write ( nsLine ) ;
103123
104- sb . AppendLine ( $ "namespace { nsName } ") ;
105124 foreach ( var type in publicTypes )
106125 {
107126 var modifiers = string . Join ( " " , type . Modifiers ) ;
@@ -119,40 +138,37 @@ private static void DumpTypes(IEnumerable<BaseTypeDeclarationSyntax> types, Stri
119138 ? $ " : { string . Join ( ", " , baseList . Types . Select ( b => b . Type . ToString ( ) ) ) } "
120139 : string . Empty ;
121140
122- sb . AppendLine ( $ " { modifiers } { typeKind } { type . Identifier } { bases } ") ;
141+ var typeLine = $ " { modifiers } { typeKind } { type . Identifier } { bases } ";
142+ sb . AppendLine ( typeLine ) ;
143+ output ? . Write ( typeLine ) ;
123144
124145 if ( type is TypeDeclarationSyntax typeDecl )
125146 {
126147 foreach ( var member in typeDecl . Members )
127148 {
128- switch ( member )
149+ string ? memberLine = member switch
150+ {
151+ MethodDeclarationSyntax m when IsPublic ( m . Modifiers ) =>
152+ $ " method: { m . Identifier } ({ string . Join ( ", " , m . ParameterList . Parameters . Select ( p => $ "{ p . Type } { p . Identifier } ") ) } )",
153+ PropertyDeclarationSyntax p when IsPublic ( p . Modifiers ) =>
154+ $ " property: { p . Identifier } : { p . Type } ",
155+ FieldDeclarationSyntax f when IsPublic ( f . Modifiers ) =>
156+ $ " field: { string . Join ( ", " , f . Declaration . Variables . Select ( v => v . Identifier . Text ) ) } : { f . Declaration . Type } ",
157+ EventDeclarationSyntax e when IsPublic ( e . Modifiers ) =>
158+ $ " event: { e . Identifier } : { e . Type } ",
159+ _ => null
160+ } ;
161+
162+ if ( memberLine != null )
129163 {
130- case MethodDeclarationSyntax m when IsPublic ( m . Modifiers ) :
131- var isExtension = m . ParameterList . Parameters . FirstOrDefault ( ) ?
132- . Modifiers . Any ( mod => mod . IsKind ( SyntaxKind . ThisKeyword ) ) == true ;
133-
134- var prefix = isExtension ? "extension method" : "method" ;
135- sb . AppendLine (
136- $ " { prefix } : { m . Identifier } ({ string . Join ( ", " , m . ParameterList . Parameters . Select ( p => $ "{ p . Type } { p . Identifier } ") ) } )") ;
137- break ;
138-
139- case PropertyDeclarationSyntax p when IsPublic ( p . Modifiers ) :
140- sb . AppendLine ( $ " property: { p . Identifier } : { p . Type } ") ;
141- break ;
142-
143- case FieldDeclarationSyntax f when IsPublic ( f . Modifiers ) :
144- sb . AppendLine (
145- $ " field: { string . Join ( ", " , f . Declaration . Variables . Select ( v => v . Identifier . Text ) ) } : { f . Declaration . Type } ") ;
146- break ;
147-
148- case EventDeclarationSyntax e when IsPublic ( e . Modifiers ) :
149- sb . AppendLine ( $ " event: { e . Identifier } : { e . Type } ") ;
150- break ;
164+ sb . AppendLine ( memberLine ) ;
165+ output ? . Write ( memberLine ) ;
151166 }
152167 }
153168 }
154169
155170 sb . AppendLine ( ) ;
171+ output ? . Write ( "" ) ;
156172 }
157173 }
158174
0 commit comments