Skip to content

Commit 290b28d

Browse files
authored
Cleanup error paths (#39)
Updates `MacroContext.error(at:message:highlights:notes:fixIts:)` to return an `ExpansionError` which can be immediately thrown by the caller to simplify the early exit path. After this change `ExpansionError` should no longer be directly created.
1 parent 8288ef3 commit 290b28d

15 files changed

+42
-78
lines changed

Sources/MMIOMacros/Macros/Arguments/BitFieldTypeProjection.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@ extension BitFieldTypeProjection: ExpressibleByExprSyntax {
3030
let base = memberAccess.base,
3131
memberAccess.declName.baseName.tokenKind == .keyword(.`self`)
3232
else {
33-
context.error(
33+
throw context.error(
3434
at: expression,
3535
message: .expectedTypeReferenceLiteral(),
3636
fixIts: .replaceExpressionWithTypeReference(node: expression))
37-
throw ExpansionError()
3837
}
3938
self.expression = base
4039
}

Sources/MMIOMacros/Macros/Arguments/BitWidth.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ extension BitWidth: ExpressibleByExprSyntax {
2626
let value = try Int(expression: expression, in: context)
2727
let validBitWidths = [8, 16, 32, 64]
2828
guard validBitWidths.contains(value) else {
29-
context.error(
29+
throw context.error(
3030
at: expression,
3131
message: .expectedLiteralValue(in: validBitWidths))
32-
throw ExpansionError()
3332
}
3433
self.value = value
3534
}

Sources/MMIOMacros/Macros/Arguments/Int+ExpressibleByExprSyntax.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ extension Int: ExpressibleByExprSyntax {
2121
let intLiteral = expression.as(IntegerLiteralExprSyntax.self),
2222
let int = intLiteral.value
2323
else {
24-
context.error(
24+
throw context.error(
2525
at: expression,
2626
message: .expectedIntegerLiteral())
27-
throw ExpansionError()
2827
}
2928
self = int
3029
}

Sources/MMIOMacros/Macros/Arguments/Range+ExpressibleByExprSyntax.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ extension Range: ExpressibleByExprSyntax where Bound: ExpressibleByExprSyntax {
2727
} else if let sequence = expression.as(SequenceExprSyntax.self) {
2828
let elements = sequence.elements
2929
guard elements.count == 3 else {
30-
context.error(
30+
throw context.error(
3131
at: sequence,
3232
message: .expectedRangeLiteral())
33-
throw ExpansionError()
3433
}
3534

3635
let index0 = elements.startIndex
@@ -44,10 +43,9 @@ extension Range: ExpressibleByExprSyntax where Bound: ExpressibleByExprSyntax {
4443
right: elements[index2],
4544
in: context)
4645
} else {
47-
context.error(
46+
throw context.error(
4847
at: expression,
4948
message: .expectedRangeLiteral())
50-
throw ExpansionError()
5149
}
5250
}
5351

@@ -62,19 +60,17 @@ extension Range: ExpressibleByExprSyntax where Bound: ExpressibleByExprSyntax {
6260
let op = op.as(BinaryOperatorExprSyntax.self),
6361
op.operator.text == "..<"
6462
else {
65-
context.error(
63+
throw context.error(
6664
at: overall,
6765
message: .expectedRangeLiteral())
68-
throw ExpansionError()
6966
}
7067

7168
let left = try Bound(expression: left, in: context)
7269
let right = try Bound(expression: right, in: context)
7370
guard left < right else {
74-
context.error(
71+
throw context.error(
7572
at: overall,
7673
message: .expectedRangeLiteral())
77-
throw ExpansionError()
7874
}
7975
return Self(uncheckedBounds: (left, right))
8076
}

Sources/MMIOMacros/Macros/BitFieldMacro.swift

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ extension BitFieldMacro {
3535
) throws -> [AccessorDeclSyntax] {
3636
// Can only applied to variables.
3737
guard let variableDecl = declaration.as(VariableDeclSyntax.self) else {
38-
context.error(
38+
throw context.error(
3939
at: declaration,
4040
message: .expectedVarDecl())
41-
return []
4241
}
4342

4443
// Must be `var` binding.
@@ -51,32 +50,28 @@ extension BitFieldMacro {
5150
guard let identifierPattern = binding.pattern.as(IdentifierPatternSyntax.self) else {
5251
if binding.pattern.is(TuplePatternSyntax.self) {
5352
// Binding identifier must not be a tuple.
54-
context.error(
53+
throw context.error(
5554
at: binding.pattern,
5655
message: .unexpectedTupleBindingIdentifier())
57-
return []
5856
} else if binding.pattern.is(WildcardPatternSyntax.self) {
59-
context.error(
57+
throw context.error(
6058
at: binding.pattern,
6159
message: .expectedBindingIdentifier(),
6260
fixIts: .insertBindingIdentifier(node: binding.pattern))
63-
return []
6461
} else {
65-
context.error(
62+
throw context.error(
6663
at: binding.pattern,
6764
message: .internalError())
68-
return []
6965
}
7066
}
7167

7268
// Binding identifier must not be "_" (implicitly named).
7369
guard identifierPattern.identifier.tokenKind != .wildcard else {
7470
// FIXME: never reached
75-
context.error(
71+
throw context.error(
7672
at: binding.pattern,
7773
message: .expectedBindingIdentifier(),
7874
fixIts: .insertBindingIdentifier(node: binding.pattern))
79-
return []
8075
}
8176

8277
// Binding must have a type annotation.
@@ -87,19 +82,17 @@ extension BitFieldMacro {
8782
if let typeIdentifier = type.as(IdentifierTypeSyntax.self) {
8883
// Binding type must not be "_" (implicitly typed).
8984
guard typeIdentifier.name.tokenKind != .wildcard else {
90-
context.error(
85+
throw context.error(
9186
at: type,
9287
message: .unexpectedInferredType(),
9388
fixIts: .insertBindingType(node: binding))
94-
return []
9589
}
9690
} else if type.is(MemberTypeSyntax.self) {
9791
// Ok
9892
} else {
99-
context.error(
93+
throw context.error(
10094
at: type,
10195
message: .unexpectedBindingType())
102-
return []
10396
}
10497

10598
// Binding must not have any accessors.

Sources/MMIOMacros/Macros/RegisterBankOffsetMacro.swift

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ extension RegisterBankOffsetMacro: MMIOAccessorMacro {
4949
) throws -> [AccessorDeclSyntax] {
5050
// Can only applied to variables.
5151
guard let variableDecl = declaration.as(VariableDeclSyntax.self) else {
52-
context.error(
53-
at: declaration,
54-
message: .expectedVarDecl())
55-
return []
52+
throw context.error(at: declaration, message: .expectedVarDecl())
5653
}
5754

5855
// Must be `var` binding.
@@ -65,32 +62,28 @@ extension RegisterBankOffsetMacro: MMIOAccessorMacro {
6562
guard let identifierPattern = binding.pattern.as(IdentifierPatternSyntax.self) else {
6663
if binding.pattern.is(TuplePatternSyntax.self) {
6764
// Binding identifier must not be a tuple.
68-
context.error(
65+
throw context.error(
6966
at: binding.pattern,
7067
message: .unexpectedTupleBindingIdentifier())
71-
return []
7268
} else if binding.pattern.is(WildcardPatternSyntax.self) {
73-
context.error(
69+
throw context.error(
7470
at: binding.pattern,
7571
message: .expectedBindingIdentifier(),
7672
fixIts: .insertBindingIdentifier(node: binding.pattern))
77-
return []
7873
} else {
79-
context.error(
74+
throw context.error(
8075
at: binding.pattern,
8176
message: .internalError())
82-
return []
8377
}
8478
}
8579

8680
// Binding identifier must not be "_" (implicitly named).
8781
guard identifierPattern.identifier.tokenKind != .wildcard else {
8882
// FIXME: never reached
89-
context.error(
83+
throw context.error(
9084
at: binding.pattern,
9185
message: .expectedBindingIdentifier(),
9286
fixIts: .insertBindingIdentifier(node: binding.pattern))
93-
return []
9487
}
9588

9689
// Binding must have a type annotation.
@@ -101,19 +94,17 @@ extension RegisterBankOffsetMacro: MMIOAccessorMacro {
10194
if let typeIdentifier = type.as(IdentifierTypeSyntax.self) {
10295
// Binding type must not be "_" (implicitly typed).
10396
guard typeIdentifier.name.tokenKind != .wildcard else {
104-
context.error(
97+
throw context.error(
10598
at: type,
10699
message: .unexpectedInferredType(),
107100
fixIts: .insertBindingType(node: binding))
108-
return []
109101
}
110102
} else if type.is(MemberTypeSyntax.self) {
111103
// Ok
112104
} else {
113-
context.error(
105+
throw context.error(
114106
at: type,
115107
message: .unexpectedBindingType())
116-
return []
117108
}
118109

119110
// Binding must not have any accessors.

Sources/MMIOMacros/Macros/RegisterMacro.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ extension RegisterMacro: MMIOMemberMacro {
5757
for member in structDecl.memberBlock.members {
5858
// Each member must be a variable declaration.
5959
guard let variableDecl = member.decl.as(VariableDeclSyntax.self) else {
60-
context.error(
60+
_ = context.error(
6161
at: member.decl,
6262
message: .onlyMemberVarDecls())
6363
error = true
@@ -151,10 +151,7 @@ extension RegisterMacro: MMIOExtensionMacro {
151151
let `extension`: DeclSyntax = "extension \(type.trimmed): RegisterValue {}"
152152

153153
guard let extensionDecl = `extension`.as(ExtensionDeclSyntax.self) else {
154-
context.error(
155-
at: `extension`,
156-
message: .internalError())
157-
return []
154+
throw context.error(at: `extension`, message: .internalError())
158155
}
159156

160157
return [extensionDecl]

Sources/MMIOMacros/SwiftSyntaxExtensions/ArgumentParsing/ArgumentContainer.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,9 @@ extension ExactlyOne: ArgumentContainer {
4949
in context: MacroContext<some ParsableMacro, some MacroExpansionContext>
5050
) throws {
5151
guard initial == nil else {
52-
context.error(
52+
throw context.error(
5353
at: expression,
5454
message: .expectedExactlyOneArgumentValue(label: label))
55-
throw ExpansionError()
5655
}
5756
let value = try Value(expression: expression, in: context)
5857
self.init(parsed: .init(value: value, expression: expression))
@@ -76,10 +75,9 @@ extension ZeroOrOne: ArgumentContainer {
7675
in context: MacroContext<some ParsableMacro, some MacroExpansionContext>
7776
) throws {
7877
if let initial = initial, initial.parsed != nil {
79-
context.error(
78+
throw context.error(
8079
at: expression,
8180
message: .expectedZeroOrOneArgumentValues(label: label))
82-
throw ExpansionError()
8381
}
8482
let value = try Value(expression: expression, in: context)
8583
self.init(parsed: .init(value: value, expression: expression))

Sources/MMIOMacros/SwiftSyntaxExtensions/ArgumentParsing/ParsableMacro.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,11 @@ extension ParsableMacro {
154154
previousLabelMatched = false
155155
children.formIndex(after: &childIndex)
156156
} else {
157-
context.error(
157+
throw context.error(
158158
at: expression,
159159
message: .unexpectedArgumentLabel(
160160
expected: child.label,
161161
actual: expression.label?.text ?? "_"))
162-
throw ExpansionError()
163162
}
164163
}
165164

@@ -171,10 +170,9 @@ extension ParsableMacro {
171170
// Check that all expressions have been consumed.
172171
if expressionIndex != expressions.endIndex {
173172
let expression = expressions[expressionIndex]
174-
context.error(
173+
throw context.error(
175174
at: expression,
176175
message: .unexpectedExtraArgument(label: expression.label?.text ?? "_"))
177-
throw ExpansionError()
178176
}
179177

180178
// Check that all children have been parsed.
@@ -187,10 +185,9 @@ extension ParsableMacro {
187185
children.formIndex(after: &childIndex)
188186
continue
189187
}
190-
context.error(
188+
throw context.error(
191189
at: expressions.isEmpty ? Syntax(node) : Syntax(expressions),
192190
message: .unexpectedMissingArgument(label: child.label))
193-
throw ExpansionError()
194191
}
195192
}
196193
}

Sources/MMIOMacros/SwiftSyntaxExtensions/DeclGroupSyntax.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@ extension DeclGroupSyntax {
5252
let node: any SyntaxProtocol =
5353
(self as? DiagnosableDeclGroupSyntax)?.introducerKeyword ?? self
5454

55-
context.error(
55+
throw context.error(
5656
at: node,
5757
message: .expectedDecl(Other.self))
58-
59-
throw ExpansionError()
6058
}
6159
}

Sources/MMIOMacros/SwiftSyntaxExtensions/Diagnostics/ExpansionError.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
/// A marker error used as an early exit for a failed macro expansion.
13+
///
14+
/// Expansion errors should not be directly created, instead calls to
15+
/// ``MacroContext.error`` will return an expansion error which can be thrown
16+
/// to early exit.
1317
struct ExpansionError: Error {}

Sources/MMIOMacros/SwiftSyntaxExtensions/Diagnostics/MacroContext.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ where Macro: ParsableMacro, Context: MacroExpansionContext {
2727
highlights: [Syntax]? = nil,
2828
notes: [Note] = [],
2929
fixIts: FixIt...
30-
) {
30+
) -> ExpansionError {
3131
self.context.diagnose(
3232
.init(
3333
node: node,
@@ -36,6 +36,7 @@ where Macro: ParsableMacro, Context: MacroExpansionContext {
3636
highlights: highlights,
3737
notes: notes,
3838
fixIts: fixIts))
39+
return ExpansionError()
3940
}
4041
}
4142

Sources/MMIOMacros/SwiftSyntaxExtensions/PatternBindingSyntax.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@ extension PatternBindingSyntax {
1717
_ context: MacroContext<some ParsableMacro, some MacroExpansionContext>
1818
) throws -> TypeSyntax {
1919
guard let type = self.typeAnnotation?.type else {
20-
context.error(
20+
throw context.error(
2121
at: self,
2222
message: .expectedTypeAnnotation(),
2323
fixIts: .insertBindingType(node: self))
24-
throw ExpansionError()
2524
}
2625
return type
2726
}
@@ -30,11 +29,10 @@ extension PatternBindingSyntax {
3029
_ context: MacroContext<some ParsableMacro, some MacroExpansionContext>
3130
) throws {
3231
if let accessorBlock = self.accessorBlock {
33-
context.error(
32+
throw context.error(
3433
at: accessorBlock,
3534
message: .expectedStoredProperty(),
3635
fixIts: .removeAccessorBlock(node: self))
37-
throw ExpansionError()
3836
}
3937
}
4038
}

Sources/MMIOMacros/SwiftSyntaxExtensions/VariableDeclSyntax.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ extension VariableDeclSyntax {
3131
_ context: MacroContext<some ParsableMacro, some MacroExpansionContext>
3232
) throws {
3333
guard self.bindingKind == bindingKind else {
34-
context.error(
34+
throw context.error(
3535
at: self.bindingSpecifier,
3636
message: .expectedBindingKind(bindingKind),
37-
fixIts: .replaceWithVar(node: self.bindingSpecifier)
38-
)
39-
throw ExpansionError()
37+
fixIts: .replaceWithVar(node: self.bindingSpecifier))
4038
}
4139
}
4240
}
@@ -51,10 +49,9 @@ extension VariableDeclSyntax {
5149
_ context: MacroContext<some ParsableMacro, some MacroExpansionContext>
5250
) throws -> PatternBindingSyntax {
5351
guard let binding = self.singleBinding else {
54-
context.error(
52+
throw context.error(
5553
at: self.bindings,
5654
message: .expectedSingleBinding())
57-
throw ExpansionError()
5855
}
5956
return binding
6057
}

0 commit comments

Comments
 (0)