@@ -161,7 +161,7 @@ extension _DebugDescriptionPropertyMacro: PeerMacro {
161
161
// 2. The single item must be a return of a string literal
162
162
// 3. Later on, the interpolation in the string literal will be validated.
163
163
guard let codeBlock = onlyBinding. accessorBlock? . accessors. as ( CodeBlockItemListSyntax . self) ,
164
- let descriptionString = codeBlock. onlyReturnExpr ? . as ( StringLiteralExprSyntax . self) else {
164
+ let descriptionString = codeBlock. asSingleReturnExpr ? . as ( StringLiteralExprSyntax . self) else {
165
165
let message : ErrorMessage = " body must consist of a single string literal "
166
166
context. diagnose ( node: declaration, error: message)
167
167
return [ ]
@@ -184,25 +184,12 @@ extension _DebugDescriptionPropertyMacro: PeerMacro {
184
184
let expr = onlyLabeledExpr. expression
185
185
186
186
// "Parse" the expression into a flattened chain of property accesses.
187
- var propertyChain : [ DeclReferenceExprSyntax ] = [ ]
188
- var invalidExpr : ExprSyntax ? = nil
189
- if let declRef = expr. as ( DeclReferenceExprSyntax . self) {
190
- // A reference to a single property on self.
191
- propertyChain. append ( declRef)
192
- } else if let memberAccess = expr. as ( MemberAccessExprSyntax . self) {
193
- do {
194
- propertyChain = try memberAccess. propertyChain ( )
195
- } catch let error as UnexpectedExpr {
196
- invalidExpr = error. expr
197
- }
198
- } else {
199
- // The expression was neither a DeclReference nor a MemberAccess.
200
- invalidExpr = expr
201
- }
202
-
203
- if let invalidExpr {
187
+ var propertyChain : [ DeclReferenceExprSyntax ]
188
+ do {
189
+ propertyChain = try expr. propertyChain ( )
190
+ } catch let error as UnexpectedExpr {
204
191
let message : ErrorMessage = " only references to stored properties are allowed "
205
- context. diagnose ( node: invalidExpr , error: message)
192
+ context. diagnose ( node: error . expr , error: message)
206
193
return [ ]
207
194
}
208
195
@@ -397,10 +384,10 @@ extension PatternBindingSyntax {
397
384
case nil :
398
385
// No accessor block, not computed.
399
386
return false
400
- case . accessors( let accessors) ? :
387
+ case . accessors( let accessors) :
401
388
// A `get` accessor indicates a computed property.
402
389
return accessors. contains { $0. accessorSpecifier. tokenKind == . keyword( . get) }
403
- case . getter? :
390
+ case . getter:
404
391
// A property with an implementation block is a computed property.
405
392
return true
406
393
@unknown default :
@@ -411,7 +398,7 @@ extension PatternBindingSyntax {
411
398
412
399
extension CodeBlockItemListSyntax {
413
400
/// The return statement or expression for a code block consisting of only a single item.
414
- fileprivate var onlyReturnExpr : ExprSyntax ? {
401
+ fileprivate var asSingleReturnExpr : ExprSyntax ? {
415
402
guard let item = self . only? . item else {
416
403
return nil
417
404
}
@@ -423,35 +410,48 @@ fileprivate struct UnexpectedExpr: Error {
423
410
let expr : ExprSyntax
424
411
}
425
412
413
+ extension ExprSyntax {
414
+ /// Parse an expression consisting only of property references. Any other syntax throws an error.
415
+ fileprivate func propertyChain( ) throws -> [ DeclReferenceExprSyntax ] {
416
+ if let declRef = self . as ( DeclReferenceExprSyntax . self) {
417
+ // A reference to a single property on self.
418
+ return [ declRef]
419
+ } else if let memberAccess = self . as ( MemberAccessExprSyntax . self) {
420
+ return try memberAccess. propertyChain ( )
421
+ } else {
422
+ // This expression is neither a DeclReference nor a MemberAccess.
423
+ throw UnexpectedExpr ( expr: self )
424
+ }
425
+ }
426
+ }
427
+
426
428
extension MemberAccessExprSyntax {
427
- /// Parse a member access consisting only of property references. Any other syntax throws an error.
428
429
fileprivate func propertyChain( ) throws -> [ DeclReferenceExprSyntax ] {
429
430
// MemberAccess is left associative: a.b.c is ((a.b).c).
430
431
var propertyChain : [ DeclReferenceExprSyntax ] = [ ]
431
432
var current = self
432
- while let base = current. base {
433
+ while true {
434
+ guard let base = current. base else {
435
+ throw UnexpectedExpr ( expr: ExprSyntax ( current) )
436
+ }
437
+
433
438
propertyChain. append ( current. declName)
439
+
434
440
if let declRef = base. as ( DeclReferenceExprSyntax . self) {
435
- propertyChain. append ( declRef)
436
441
// Terminal case.
437
- break
438
- }
439
- if let next = base. as ( MemberAccessExprSyntax . self) {
440
- current = next
442
+ // Top-down traversal produces references in reverse order.
443
+ propertyChain. append ( declRef)
444
+ propertyChain. reverse ( )
445
+ return propertyChain
446
+ } else if let next = base. as ( MemberAccessExprSyntax . self) {
441
447
// Recursive case.
448
+ current = next
442
449
continue
450
+ } else {
451
+ // The expression was neither a DeclReference nor a MemberAccess.
452
+ throw UnexpectedExpr ( expr: base)
443
453
}
444
- // The expression was neither a DeclReference nor a MemberAccess.
445
- throw UnexpectedExpr ( expr: base)
446
- }
447
-
448
- guard current. base != nil else {
449
- throw UnexpectedExpr ( expr: ExprSyntax ( current) )
450
454
}
451
-
452
- // Top-down traversal produces references in reverse order.
453
- propertyChain. reverse ( )
454
- return propertyChain
455
455
}
456
456
}
457
457
0 commit comments