Skip to content

Commit 6aaa056

Browse files
Throw errors instead of using fatalError
1 parent 1847dc7 commit 6aaa056

File tree

3 files changed

+29
-30
lines changed

3 files changed

+29
-30
lines changed

SourceKitLSPDevUtils/Sources/ConfigSchemaGen/ConfigSchemaGen.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,16 @@ public struct ConfigSchemaGen {
118118
static func generateDocumentation(from schema: OptionTypeSchama, context: OptionSchemaContext) throws -> Data {
119119
let docBuilder = OptionDocumentBuilder(context: context)
120120
guard let data = try docBuilder.build(from: schema).data(using: .utf8) else {
121-
throw ConfigSchemaGenError.documentationEncodingFailed
121+
throw ConfigSchemaGenError("Failed to encode documentation as UTF-8")
122122
}
123123
return data
124124
}
125125
}
126126

127-
enum ConfigSchemaGenError: Error, CustomStringConvertible {
128-
case documentationEncodingFailed
127+
struct ConfigSchemaGenError: Error, CustomStringConvertible {
128+
let description: String
129129

130-
var description: String {
131-
switch self {
132-
case .documentationEncodingFailed:
133-
return "Failed to encode documentation as UTF-8"
134-
}
130+
init(_ description: String) {
131+
self.description = description
135132
}
136133
}

SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionDocument.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct OptionDocumentBuilder {
7979
}
8080
}
8181
guard case .struct(let schema) = schema.kind else {
82-
fatalError("Root schema must be a struct")
82+
throw ConfigSchemaGenError("Root schema must be a struct")
8383
}
8484
for property in schema.properties {
8585
try appendProperty(property, indentLevel: 0)

SourceKitLSPDevUtils/Sources/ConfigSchemaGen/OptionSchema.swift

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ struct OptionSchemaContext {
9696
let structInfo = try buildStructProperties(decl)
9797
return OptionTypeSchama(kind: .struct(structInfo))
9898
case .enumDecl(let decl):
99-
let enumInfo = buildEnumCases(decl)
99+
let enumInfo = try buildEnumCases(decl)
100100
return OptionTypeSchama(kind: .enum(enumInfo))
101101
default:
102-
fatalError("Unsupported type: \(typeDecl)")
102+
throw ConfigSchemaGenError("Unsupported type declaration: \(typeDecl)")
103103
}
104104
}
105105

@@ -108,15 +108,17 @@ struct OptionSchemaContext {
108108
switch type.as(TypeSyntaxEnum.self) {
109109
case .optionalType(let type):
110110
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+
}
112114
wrapped.isOptional = true
113115
return wrapped
114116
case .arrayType(let type):
115117
let value = try resolveType(type.element)
116118
return OptionTypeSchama(kind: .array(value: value))
117119
case .dictionaryType(let type):
118120
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)")
120122
}
121123
let value = try resolveType(type.value)
122124
return OptionTypeSchama(kind: .dictionary(value: value))
@@ -131,33 +133,33 @@ struct OptionSchemaContext {
131133
return OptionTypeSchama(kind: primitiveType)
132134
} else if type.name.trimmedDescription == "Set" {
133135
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)")
135137
}
136138
return OptionTypeSchama(kind: .array(value: try resolveType(elementType)))
137139
} else {
138140
let type = try typeNameResolver.lookupType(for: type)
139141
return try buildSchema(from: type)
140142
}
141143
default:
142-
fatalError("Unsupported type: \(type)")
144+
throw ConfigSchemaGenError("Unsupported type syntax: \(type)")
143145
}
144146
}
145147

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
148150
guard let caseDecl = member.decl.as(EnumCaseDeclSyntax.self) else {
149151
return []
150152
}
151-
return caseDecl.elements.map {
153+
return try caseDecl.elements.map {
152154
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)")
154156
}
155157
let name: String
156158
if let rawValue = $0.rawValue?.value {
157159
if let stringLiteral = rawValue.as(StringLiteralExprSyntax.self), stringLiteral.segments.count == 1 {
158160
name = stringLiteral.segments.first!.description
159161
} else {
160-
fatalError("Unsupported raw value type: \(rawValue)")
162+
throw ConfigSchemaGenError("Only string literals without interpolation are supported as enum case raw values: \(caseDecl)")
161163
}
162164
} else {
163165
name = $0.name.text
@@ -173,19 +175,19 @@ struct OptionSchemaContext {
173175
var properties: [OptionTypeSchama.Property] = []
174176
for member in node.memberBlock.members {
175177
// Skip computed properties
176-
if let variable = member.decl.as(VariableDeclSyntax.self),
178+
guard let variable = member.decl.as(VariableDeclSyntax.self),
177179
let binding = variable.bindings.first,
178180
let type = binding.typeAnnotation,
179181
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+
)
189191
}
190192
let typeName = node.name.text
191193
return .init(name: typeName, properties: properties)

0 commit comments

Comments
 (0)