Skip to content

Commit 8e7c7af

Browse files
committed
[Macros] Extend the property-wrapper example to also generate backing storage
The same use of the macro `@wrapProperty` expands in two ways, adding accessors and the storage declaration.
1 parent 0d1e0a2 commit 8e7c7af

File tree

1 file changed

+38
-9
lines changed

1 file changed

+38
-9
lines changed

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ struct DefineBitwidthNumberedStructsMacro: FreestandingDeclarationMacro {
208208
}
209209
}
210210

211-
public struct PropertyWrapper: AccessorDeclarationMacro {
211+
public struct PropertyWrapper { }
212+
213+
extension PropertyWrapper: AccessorDeclarationMacro {
212214
public static func expansion(
213215
of node: CustomAttributeSyntax,
214216
attachedTo declaration: DeclSyntax,
@@ -217,18 +219,10 @@ public struct PropertyWrapper: AccessorDeclarationMacro {
217219
guard let varDecl = declaration.as(VariableDeclSyntax.self),
218220
let binding = varDecl.bindings.first,
219221
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier,
220-
let type = binding.typeAnnotation?.type,
221222
binding.accessor == nil else {
222223
return []
223224
}
224225

225-
guard let wrapperTypeNameExpr = node.argumentList?.first?.expression,
226-
let stringLiteral = wrapperTypeNameExpr.as(StringLiteralExprSyntax.self),
227-
stringLiteral.segments.count == 1,
228-
case let .stringSegment(wrapperTypeNameSegment)? = stringLiteral.segments.first else {
229-
return []
230-
}
231-
232226
return [
233227
"""
234228
@@ -246,6 +240,40 @@ public struct PropertyWrapper: AccessorDeclarationMacro {
246240
}
247241
}
248242

243+
extension PropertyWrapper: PeerDeclarationMacro {
244+
public static func expansion(
245+
of node: CustomAttributeSyntax,
246+
attachedTo declaration: DeclSyntax,
247+
in context: inout MacroExpansionContext
248+
) throws -> [SwiftSyntax.DeclSyntax] {
249+
guard let varDecl = declaration.as(VariableDeclSyntax.self),
250+
let binding = varDecl.bindings.first,
251+
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier,
252+
let type = binding.typeAnnotation?.type,
253+
binding.accessor == nil else {
254+
return []
255+
}
256+
257+
guard let wrapperTypeNameExpr = node.argumentList?.first?.expression,
258+
let stringLiteral = wrapperTypeNameExpr.as(StringLiteralExprSyntax.self),
259+
stringLiteral.segments.count == 1,
260+
case let .stringSegment(wrapperTypeNameSegment)? = stringLiteral.segments.first else {
261+
return []
262+
}
263+
264+
let storageType: TypeSyntax = "\(wrapperTypeNameSegment.content)<\(type)>"
265+
let storageName = "_\(identifier)"
266+
267+
return [
268+
"""
269+
270+
private var \(raw: storageName): \(storageType)
271+
272+
"""
273+
]
274+
}
275+
}
276+
249277
public struct AddCompletionHandler: PeerDeclarationMacro {
250278
public static func expansion(
251279
of node: CustomAttributeSyntax,
@@ -571,6 +599,7 @@ final class MacroSystemTests: XCTestCase {
571599
_x.wrappedValue = newValue
572600
}
573601
}
602+
private var _x: MyWrapperType<Int>
574603
""")
575604
}
576605

0 commit comments

Comments
 (0)