@@ -96,10 +96,10 @@ struct OptionSchemaContext {
96
96
let structInfo = try buildStructProperties ( decl)
97
97
return OptionTypeSchama ( kind: . struct( structInfo) )
98
98
case . enumDecl( let decl) :
99
- let enumInfo = buildEnumCases ( decl)
99
+ let enumInfo = try buildEnumCases ( decl)
100
100
return OptionTypeSchama ( kind: . enum( enumInfo) )
101
101
default :
102
- fatalError ( " Unsupported type: \( typeDecl) " )
102
+ throw ConfigSchemaGenError ( " Unsupported type declaration : \( typeDecl) " )
103
103
}
104
104
}
105
105
@@ -108,15 +108,17 @@ struct OptionSchemaContext {
108
108
switch type. as ( TypeSyntaxEnum . self) {
109
109
case . optionalType( let type) :
110
110
var wrapped = try resolveType ( type. wrappedType)
111
- assert ( !wrapped. isOptional, " Nested optional type is not supported " )
111
+ guard !wrapped. isOptional else {
112
+ throw ConfigSchemaGenError ( " Nested optional type is not supported " )
113
+ }
112
114
wrapped. isOptional = true
113
115
return wrapped
114
116
case . arrayType( let type) :
115
117
let value = try resolveType ( type. element)
116
118
return OptionTypeSchama ( kind: . array( value: value) )
117
119
case . dictionaryType( let type) :
118
120
guard type. key. trimmedDescription == " String " else {
119
- fatalError ( " Dictionary key type must be String: \( type. key) " )
121
+ throw ConfigSchemaGenError ( " Dictionary key type must be String: \( type. key) " )
120
122
}
121
123
let value = try resolveType ( type. value)
122
124
return OptionTypeSchama ( kind: . dictionary( value: value) )
@@ -131,33 +133,33 @@ struct OptionSchemaContext {
131
133
return OptionTypeSchama ( kind: primitiveType)
132
134
} else if type. name. trimmedDescription == " Set " {
133
135
guard let elementType = type. genericArgumentClause? . arguments. first? . argument else {
134
- fatalError ( " Set type must have one generic argument: \( type) " )
136
+ throw ConfigSchemaGenError ( " Set type must have one generic argument: \( type) " )
135
137
}
136
138
return OptionTypeSchama ( kind: . array( value: try resolveType ( elementType) ) )
137
139
} else {
138
140
let type = try typeNameResolver. lookupType ( for: type)
139
141
return try buildSchema ( from: type)
140
142
}
141
143
default :
142
- fatalError ( " Unsupported type: \( type) " )
144
+ throw ConfigSchemaGenError ( " Unsupported type syntax : \( type) " )
143
145
}
144
146
}
145
147
146
- private func buildEnumCases( _ node: EnumDeclSyntax ) -> OptionTypeSchama . Enum {
147
- let cases = node. memberBlock. members. flatMap { member -> [ OptionTypeSchama . Case ] in
148
+ private func buildEnumCases( _ node: EnumDeclSyntax ) throws -> OptionTypeSchama . Enum {
149
+ let cases = try node. memberBlock. members. flatMap { member -> [ OptionTypeSchama . Case ] in
148
150
guard let caseDecl = member. decl. as ( EnumCaseDeclSyntax . self) else {
149
151
return [ ]
150
152
}
151
- return caseDecl. elements. map {
153
+ return try caseDecl. elements. map {
152
154
guard $0. parameterClause == nil else {
153
- fatalError ( " Associated values are not supported: \( $0 ) " )
155
+ throw ConfigSchemaGenError ( " Associated values in enum cases are not supported: \( caseDecl ) " )
154
156
}
155
157
let name : String
156
158
if let rawValue = $0. rawValue? . value {
157
159
if let stringLiteral = rawValue. as ( StringLiteralExprSyntax . self) , stringLiteral. segments. count == 1 {
158
160
name = stringLiteral. segments. first!. description
159
161
} else {
160
- fatalError ( " Unsupported raw value type : \( rawValue ) " )
162
+ throw ConfigSchemaGenError ( " Only string literals without interpolation are supported as enum case raw values : \( caseDecl ) " )
161
163
}
162
164
} else {
163
165
name = $0. name. text
@@ -173,19 +175,19 @@ struct OptionSchemaContext {
173
175
var properties : [ OptionTypeSchama . Property ] = [ ]
174
176
for member in node. memberBlock. members {
175
177
// Skip computed properties
176
- if let variable = member. decl. as ( VariableDeclSyntax . self) ,
178
+ guard let variable = member. decl. as ( VariableDeclSyntax . self) ,
177
179
let binding = variable. bindings. first,
178
180
let type = binding. typeAnnotation,
179
181
binding. accessorBlock == nil
180
- {
181
- let name = binding . pattern . trimmed . description
182
- let defaultValue = binding. initializer ? . value . description
183
- let description = Self . extractDocComment ( variable . leadingTrivia )
184
- let typeInfo = try resolveType ( type . type )
185
- properties . append (
186
- . init ( name : name , type : typeInfo , description : description , defaultValue : defaultValue )
187
- )
188
- }
182
+ else { continue }
183
+
184
+ let name = binding. pattern . trimmed . description
185
+ let defaultValue = binding . initializer ? . value . description
186
+ let description = Self . extractDocComment ( variable . leadingTrivia )
187
+ let typeInfo = try resolveType ( type . type )
188
+ properties . append (
189
+ . init ( name : name , type : typeInfo , description : description , defaultValue : defaultValue )
190
+ )
189
191
}
190
192
let typeName = node. name. text
191
193
return . init( name: typeName, properties: properties)
0 commit comments