1
+ using System . ComponentModel ;
2
+ using H . Generators ;
3
+ using Microsoft . CodeAnalysis ;
4
+
5
+ namespace Anthropic . Generators . Core . Conversion ;
6
+
7
+ public static class ToModels
8
+ {
9
+ public static InterfaceData PrepareData (
10
+ this INamedTypeSymbol interfaceSymbol )
11
+ {
12
+ interfaceSymbol = interfaceSymbol ?? throw new ArgumentNullException ( nameof ( interfaceSymbol ) ) ;
13
+
14
+ var methods = interfaceSymbol
15
+ . GetMembers ( )
16
+ . OfType < IMethodSymbol > ( )
17
+ . Where ( static x => x . MethodKind == MethodKind . Ordinary )
18
+ . Select ( static x => new MethodData (
19
+ Name : x . Name ,
20
+ Description : GetDescription ( x ) ,
21
+ IsAsync : x . IsAsync || x . ReturnType . Name == "Task" ,
22
+ IsVoid : x . ReturnsVoid ,
23
+ Parameters : new OpenApiSchema (
24
+ Name : x . Name ,
25
+ Description : GetDescription ( x ) ,
26
+ Type : "object" ,
27
+ SchemaType : "object" ,
28
+ Properties :
29
+ x . Parameters
30
+ . Where ( static x => x . Type . MetadataName != "CancellationToken" )
31
+ . Select ( static x => ToParameterData (
32
+ typeSymbol : x . Type ,
33
+ name : x . Name ,
34
+ description : GetDescription ( x ) ,
35
+ isRequired : ! x . IsOptional ) )
36
+ . ToArray ( ) ,
37
+ EnumValues : Array . Empty < string > ( ) ,
38
+ IsNullable : false ,
39
+ IsRequired : true ,
40
+ Format : null ,
41
+ ArrayItem : Array . Empty < OpenApiSchema > ( ) ,
42
+ DefaultValue : string . Empty ) ) )
43
+ . ToArray ( ) ;
44
+
45
+ return new InterfaceData (
46
+ Namespace : interfaceSymbol . ContainingNamespace . ToDisplayString ( ) ,
47
+ Name : interfaceSymbol . ToDisplayString ( SymbolDisplayFormat . MinimallyQualifiedFormat ) ,
48
+ Methods : methods ) ;
49
+ }
50
+
51
+ private static OpenApiSchema ToParameterData ( ITypeSymbol typeSymbol , string ? name = null , string ? description = null , bool isRequired = true )
52
+ {
53
+ string schemaType ;
54
+ string ? format = null ;
55
+ var properties = Array . Empty < OpenApiSchema > ( ) ;
56
+ OpenApiSchema ? arrayItem = null ;
57
+ switch ( typeSymbol . TypeKind )
58
+ {
59
+ case TypeKind . Enum :
60
+ schemaType = "string" ;
61
+ break ;
62
+
63
+ case TypeKind . Structure :
64
+ switch ( typeSymbol . SpecialType )
65
+ {
66
+ case SpecialType . System_Int32 :
67
+ schemaType = "integer" ;
68
+ format = "int32" ;
69
+ break ;
70
+
71
+ case SpecialType . System_Int64 :
72
+ schemaType = "integer" ;
73
+ format = "int64" ;
74
+ break ;
75
+
76
+ case SpecialType . System_Single :
77
+ schemaType = "number" ;
78
+ format = "double" ;
79
+ break ;
80
+
81
+ case SpecialType . System_Double :
82
+ schemaType = "number" ;
83
+ format = "float" ;
84
+ break ;
85
+
86
+ case SpecialType . System_DateTime :
87
+ schemaType = "string" ;
88
+ format = "date-time" ;
89
+ break ;
90
+
91
+ case SpecialType . System_Boolean :
92
+ schemaType = "boolean" ;
93
+ break ;
94
+
95
+ case SpecialType . None :
96
+ switch ( typeSymbol . Name )
97
+ {
98
+ case "DateOnly" :
99
+ schemaType = "string" ;
100
+ format = "date" ;
101
+ break ;
102
+
103
+ default :
104
+ throw new NotImplementedException ( $ "{ typeSymbol . Name } is not implemented.") ;
105
+ }
106
+ break ;
107
+
108
+ default :
109
+ throw new NotImplementedException ( $ "{ typeSymbol . SpecialType } is not implemented.") ;
110
+ }
111
+ break ;
112
+
113
+ case TypeKind . Class :
114
+ switch ( typeSymbol . SpecialType )
115
+ {
116
+ case SpecialType . System_String :
117
+ schemaType = "string" ;
118
+ break ;
119
+
120
+
121
+ case SpecialType . None :
122
+ schemaType = "object" ;
123
+ properties = typeSymbol . GetMembers ( )
124
+ . OfType < IPropertySymbol > ( )
125
+ . Select ( static y => ToParameterData (
126
+ typeSymbol : y . Type ,
127
+ name : y . Name ,
128
+ description : GetDescription ( y ) ,
129
+ isRequired : true ) )
130
+ . ToArray ( ) ;
131
+ break ;
132
+
133
+ default :
134
+ throw new NotImplementedException ( $ "{ typeSymbol . SpecialType } is not implemented.") ;
135
+ }
136
+ break ;
137
+
138
+ case TypeKind . Interface when typeSymbol . MetadataName == "IReadOnlyCollection`1" :
139
+ schemaType = "array" ;
140
+ arrayItem = ( typeSymbol as INamedTypeSymbol ) ? . TypeArguments
141
+ . Select ( static y => ToParameterData ( y ) )
142
+ . FirstOrDefault ( ) ;
143
+ break ;
144
+
145
+ case TypeKind . Array :
146
+ schemaType = "array" ;
147
+ arrayItem = ToParameterData ( ( typeSymbol as IArrayTypeSymbol ) ? . ElementType ! ) ;
148
+ break ;
149
+
150
+ default :
151
+ throw new NotImplementedException ( $ "{ typeSymbol . TypeKind } is not implemented.") ;
152
+ }
153
+
154
+ return new OpenApiSchema (
155
+ Name : ! string . IsNullOrWhiteSpace ( name )
156
+ ? name !
157
+ : typeSymbol . Name ,
158
+ Description : ! string . IsNullOrWhiteSpace ( description )
159
+ ? description !
160
+ : GetDescription ( typeSymbol ) ,
161
+ Type : typeSymbol . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ,
162
+ DefaultValue : GetDefaultValue ( typeSymbol ) ,
163
+ SchemaType : schemaType ,
164
+ Format : format ,
165
+ Properties : properties ,
166
+ ArrayItem : arrayItem != null ? [ arrayItem . Value ] : Array . Empty < OpenApiSchema > ( ) ,
167
+ EnumValues : typeSymbol . TypeKind == TypeKind . Enum
168
+ ? typeSymbol
169
+ . GetMembers ( )
170
+ . OfType < IFieldSymbol > ( )
171
+ . Select ( static x => x . Name . ToLowerInvariant ( ) )
172
+ . ToArray ( )
173
+ : [ ] ,
174
+ IsNullable : IsNullable ( typeSymbol ) ,
175
+ IsRequired : isRequired ) ;
176
+ }
177
+
178
+ private static bool IsNullable ( ITypeSymbol typeSymbol )
179
+ {
180
+ if ( typeSymbol . TypeKind == TypeKind . Enum )
181
+ {
182
+ return false ;
183
+ }
184
+ if ( typeSymbol . TypeKind == TypeKind . Structure )
185
+ {
186
+ return false ;
187
+ }
188
+
189
+ return typeSymbol . SpecialType switch
190
+ {
191
+ SpecialType . System_String => false ,
192
+ _ => true ,
193
+ } ;
194
+ }
195
+
196
+ private static string GetDefaultValue ( ITypeSymbol typeSymbol )
197
+ {
198
+ switch ( typeSymbol . SpecialType )
199
+ {
200
+ case SpecialType . System_String :
201
+ return "string.Empty" ;
202
+
203
+ default :
204
+ return string . Empty ;
205
+ }
206
+ }
207
+
208
+ private static string GetDescription ( ISymbol symbol )
209
+ {
210
+ return symbol . GetAttributes ( )
211
+ . FirstOrDefault ( static x => x . AttributeClass ? . Name == nameof ( DescriptionAttribute ) ) ?
212
+ . ConstructorArguments . First ( ) . Value ? . ToString ( ) ?? string . Empty ;
213
+ }
214
+ }
0 commit comments