8
8
9
9
namespace SkiaSharpGenerator ;
10
10
11
- public sealed class DocumentationStore
11
+ public sealed class DocumentationStore ( string sourceFile )
12
12
{
13
- private string _source ;
14
- private readonly Dictionary < string , string > _docs = new Dictionary < string , string > ( StringComparer . Ordinal ) ;
13
+ private readonly string _source = File . ReadAllText ( sourceFile ) ;
14
+ private readonly Dictionary < string , string > _docs = new ( StringComparer . Ordinal ) ;
15
15
16
- public static string Type ( string name ) =>
16
+ public static string Type ( string name ) =>
17
17
$ "T:{ name } ";
18
18
public static string Field ( string typeName , string fieldName ) =>
19
19
$ "F:{ typeName } .{ fieldName } ";
20
20
public static string Property ( string typeName , string propertyName ) =>
21
21
$ "P:{ typeName } .{ propertyName } ";
22
- public static string Method ( string typeName , string methodName , params string [ ] paramTypes ) =>
22
+ public static string Method ( string typeName , string methodName , params string [ ] paramTypes ) =>
23
23
$ "M:{ typeName } .{ methodName } ({ string . Join ( "," , paramTypes ) } )";
24
24
25
- public DocumentationStore ( string sourceFile )
26
- {
27
- _source = File . ReadAllText ( sourceFile ) ;
28
- }
29
-
30
25
public void Load ( )
31
26
{
32
27
var options = new CSharpParseOptions ( kind : SourceCodeKind . Regular , documentationMode : DocumentationMode . Parse ) ;
@@ -66,96 +61,108 @@ private void ProcessMember(MemberDeclarationSyntax member, string? currentType)
66
61
ProcessMember ( m , typeName ) ;
67
62
}
68
63
}
64
+ else if ( member is EnumDeclarationSyntax ed )
65
+ {
66
+ var enumName = ed . Identifier . Text ;
67
+ foreach ( var em in ed . Members )
68
+ {
69
+ ProcessMember ( em , enumName ) ;
70
+ }
71
+ }
69
72
}
70
73
}
71
74
72
75
private void AddIfAny ( MemberDeclarationSyntax member , string ? currentType )
73
76
{
74
- var xml = Extract ( member ) ;
75
- if ( xml == null )
76
- return ;
77
+ if ( GetDocKey ( member , currentType ) is { } key && Extract ( member ) is { } xml )
78
+ {
79
+ _docs [ key ] = xml ;
80
+ }
81
+ }
77
82
78
- string ? key = null ;
83
+ private static string ? GetDocKey ( MemberDeclarationSyntax member , string ? currentType )
84
+ {
79
85
if ( member is ClassDeclarationSyntax c )
80
- key = Type ( c . Identifier . Text ) ;
86
+ return Type ( c . Identifier . Text ) ;
81
87
else if ( member is StructDeclarationSyntax s )
82
- key = Type ( s . Identifier . Text ) ;
88
+ return Type ( s . Identifier . Text ) ;
83
89
else if ( member is InterfaceDeclarationSyntax i )
84
- key = Type ( i . Identifier . Text ) ;
90
+ return Type ( i . Identifier . Text ) ;
85
91
else if ( member is EnumDeclarationSyntax e )
86
- key = Type ( e . Identifier . Text ) ;
92
+ return Type ( e . Identifier . Text ) ;
93
+ else if ( member is EnumMemberDeclarationSyntax em && em . Parent is EnumDeclarationSyntax ep )
94
+ return Field ( ep . Identifier . Text , em . Identifier . Text ) ;
87
95
else if ( member is DelegateDeclarationSyntax d )
88
- key = Type ( d . Identifier . Text ) ;
96
+ return Type ( d . Identifier . Text ) ;
89
97
else if ( currentType != null && member is FieldDeclarationSyntax f )
90
- key = Field ( currentType , f . Declaration . Variables . First ( ) . Identifier . Text ) ;
98
+ return Field ( currentType , f . Declaration . Variables . First ( ) . Identifier . Text ) ;
91
99
else if ( currentType != null && member is PropertyDeclarationSyntax p )
92
- key = Property ( currentType , p . Identifier . Text ) ;
100
+ return Property ( currentType , p . Identifier . Text ) ;
93
101
else if ( currentType != null && member is MethodDeclarationSyntax m )
94
102
{
95
103
var paramTypes = m . ParameterList . Parameters
96
104
. Select ( p => NormalizeType ( p . Type ) )
97
105
. ToArray ( ) ;
98
- key = Method ( currentType , m . Identifier . Text , paramTypes ) ;
106
+ return Method ( currentType , m . Identifier . Text , paramTypes ) ;
99
107
}
100
108
else if ( currentType != null && member is OperatorDeclarationSyntax op )
101
109
{
102
110
var paramTypes = op . ParameterList . Parameters
103
111
. Select ( p => NormalizeType ( p . Type ) )
104
112
. ToArray ( ) ;
105
- key = Method ( currentType , GetOperatorMetadataName ( op ) , paramTypes ) ;
113
+ return Method ( currentType , GetOperatorMetadataName ( op ) , paramTypes ) ;
106
114
}
107
115
else if ( currentType != null && member is ConversionOperatorDeclarationSyntax cop )
108
116
{
109
117
var paramTypes = cop . ParameterList . Parameters
110
118
. Select ( p => NormalizeType ( p . Type ) )
111
119
. ToArray ( ) ;
112
- key = Method ( currentType , cop . ImplicitOrExplicitKeyword . IsKind ( SyntaxKind . ImplicitKeyword ) ? "op_Implicit" : "op_Explicit" , paramTypes ) ;
120
+ return Method ( currentType , cop . ImplicitOrExplicitKeyword . IsKind ( SyntaxKind . ImplicitKeyword ) ? "op_Implicit" : "op_Explicit" , paramTypes ) ;
113
121
}
114
-
115
- if ( key != null )
116
- _docs [ key ] = xml ;
122
+ else
123
+ return null ;
117
124
}
118
125
119
- private static string GetOperatorMetadataName ( OperatorDeclarationSyntax op )
120
- {
121
- var paramCount = op . ParameterList . Parameters . Count ;
122
- switch ( op . OperatorToken . Kind ( ) )
126
+ private static string GetOperatorMetadataName ( OperatorDeclarationSyntax op ) =>
127
+ op . OperatorToken . Kind ( ) switch
123
128
{
124
- case SyntaxKind . PlusToken : return paramCount == 1 ? "op_UnaryPlus" : "op_Addition" ;
125
- case SyntaxKind . MinusToken : return paramCount == 1 ? "op_UnaryNegation" : "op_Subtraction" ;
126
- case SyntaxKind . AsteriskToken : return "op_Multiply" ;
127
- case SyntaxKind . SlashToken : return "op_Division" ;
128
- case SyntaxKind . PercentToken : return "op_Modulus" ;
129
- case SyntaxKind . AmpersandToken : return "op_BitwiseAnd" ;
130
- case SyntaxKind . BarToken : return "op_BitwiseOr" ;
131
- case SyntaxKind . CaretToken : return "op_ExclusiveOr" ;
132
- case SyntaxKind . LessThanLessThanToken : return "op_LeftShift" ;
133
- case SyntaxKind . GreaterThanGreaterThanToken : return "op_RightShift" ;
134
- case SyntaxKind . EqualsEqualsToken : return "op_Equality" ;
135
- case SyntaxKind . ExclamationEqualsToken : return "op_Inequality" ;
136
- case SyntaxKind . LessThanToken : return "op_LessThan" ;
137
- case SyntaxKind . GreaterThanToken : return "op_GreaterThan" ;
138
- case SyntaxKind . LessThanEqualsToken : return "op_LessThanOrEqual" ;
139
- case SyntaxKind . GreaterThanEqualsToken : return "op_GreaterThanOrEqual" ;
140
- case SyntaxKind . PlusPlusToken : return "op_Increment" ;
141
- case SyntaxKind . MinusMinusToken : return "op_Decrement" ;
142
- case SyntaxKind . ExclamationToken : return "op_LogicalNot" ;
143
- case SyntaxKind . TildeToken : return "op_OnesComplement" ;
144
- case SyntaxKind . TrueKeyword : return "op_True" ;
145
- case SyntaxKind . FalseKeyword : return "op_False" ;
146
- default : return "op_Unknown" ; // fallback; unlikely but ensures a key if docs exist
147
- }
148
- }
129
+ SyntaxKind . PlusToken => op . ParameterList . Parameters . Count == 1 ? "op_UnaryPlus" : "op_Addition" ,
130
+ SyntaxKind . MinusToken => op . ParameterList . Parameters . Count == 1 ? "op_UnaryNegation" : "op_Subtraction" ,
131
+ SyntaxKind . AsteriskToken => "op_Multiply" ,
132
+ SyntaxKind . SlashToken => "op_Division" ,
133
+ SyntaxKind . PercentToken => "op_Modulus" ,
134
+ SyntaxKind . AmpersandToken => "op_BitwiseAnd" ,
135
+ SyntaxKind . BarToken => "op_BitwiseOr" ,
136
+ SyntaxKind . CaretToken => "op_ExclusiveOr" ,
137
+ SyntaxKind . LessThanLessThanToken => "op_LeftShift" ,
138
+ SyntaxKind . GreaterThanGreaterThanToken => "op_RightShift" ,
139
+ SyntaxKind . EqualsEqualsToken => "op_Equality" ,
140
+ SyntaxKind . ExclamationEqualsToken => "op_Inequality" ,
141
+ SyntaxKind . LessThanToken => "op_LessThan" ,
142
+ SyntaxKind . GreaterThanToken => "op_GreaterThan" ,
143
+ SyntaxKind . LessThanEqualsToken => "op_LessThanOrEqual" ,
144
+ SyntaxKind . GreaterThanEqualsToken => "op_GreaterThanOrEqual" ,
145
+ SyntaxKind . PlusPlusToken => "op_Increment" ,
146
+ SyntaxKind . MinusMinusToken => "op_Decrement" ,
147
+ SyntaxKind . ExclamationToken => "op_LogicalNot" ,
148
+ SyntaxKind . TildeToken => "op_OnesComplement" ,
149
+ SyntaxKind . TrueKeyword => "op_True" ,
150
+ SyntaxKind . FalseKeyword => "op_False" ,
151
+ _ => "op_Unknown" , // fallback; unlikely but ensures a key if docs exist
152
+ } ;
149
153
150
154
private static string NormalizeType ( TypeSyntax ? typeSyntax )
151
155
{
152
156
if ( typeSyntax == null )
153
157
return "?" ;
158
+
154
159
// Strip trivia and normalize whitespace
155
160
var text = typeSyntax . ToString ( ) . Trim ( ) ;
161
+
156
162
// Collapse spaces
157
163
while ( text . Contains ( " " ) )
158
164
text = text . Replace ( " " , " " ) ;
165
+
159
166
return text ;
160
167
}
161
168
@@ -165,10 +172,14 @@ private static bool IsPublic(MemberDeclarationSyntax member, string? currentType
165
172
if ( member is NamespaceDeclarationSyntax )
166
173
return true ;
167
174
168
- // Enum members (EnumMemberDeclarationSyntax) are always effectively public in a public enum
175
+ // For enum declarations: require ' public'
169
176
if ( member is EnumDeclarationSyntax enumDecl )
170
177
return enumDecl . Modifiers . Any ( m => m . IsKind ( SyntaxKind . PublicKeyword ) ) ;
171
178
179
+ // Enum members (EnumMemberDeclarationSyntax) are always effectively public in a public enum
180
+ if ( member is EnumMemberDeclarationSyntax enumMemberDecl )
181
+ return enumMemberDecl . Parent is EnumDeclarationSyntax parentDecl && parentDecl . Modifiers . Any ( m => m . IsKind ( SyntaxKind . PublicKeyword ) ) ;
182
+
172
183
// For type declarations: require 'public'
173
184
if ( member is TypeDeclarationSyntax typeDecl )
174
185
return typeDecl . Modifiers . Any ( m => m . IsKind ( SyntaxKind . PublicKeyword ) ) ;
0 commit comments