Skip to content

Commit 4f76356

Browse files
committed
[Macros] Implement a type wrapper transformation as a macro that conforms
to MemberDeclarationMacro, MemberAttributeMacro, and AccessorDeclarationMacro.
1 parent 8e9caa1 commit 4f76356

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,74 @@ public struct WrapStoredProperties: MemberAttributeMacro {
467467
}
468468
}
469469

470+
struct CustomTypeWrapperMacro {}
471+
472+
extension CustomTypeWrapperMacro: MemberDeclarationMacro {
473+
static func expansion(
474+
of node: CustomAttributeSyntax,
475+
attachedTo declaration: DeclSyntax,
476+
in context: inout MacroExpansionContext
477+
) throws -> [DeclSyntax] {
478+
return [
479+
"""
480+
481+
var _storage: Wrapper<Self>
482+
"""
483+
]
484+
}
485+
}
486+
487+
extension CustomTypeWrapperMacro: MemberAttributeMacro {
488+
static func expansion(
489+
of node: CustomAttributeSyntax,
490+
attachedTo declaration: DeclSyntax,
491+
annotating member: DeclSyntax,
492+
in context: inout MacroExpansionContext
493+
) throws -> [CustomAttributeSyntax] {
494+
return [
495+
CustomAttributeSyntax(
496+
attributeName: SimpleTypeIdentifierSyntax(
497+
name: .identifier("customTypeWrapper")
498+
)
499+
)
500+
.withLeadingTrivia([.newlines(1), .spaces(2)])
501+
]
502+
}
503+
}
504+
505+
extension CustomTypeWrapperMacro: AccessorDeclarationMacro {
506+
static func expansion(
507+
of node: CustomAttributeSyntax,
508+
attachedTo declaration: DeclSyntax,
509+
in context: inout MacroExpansionContext
510+
) throws -> [AccessorDeclSyntax] {
511+
guard let property = declaration.as(VariableDeclSyntax.self),
512+
let binding = property.bindings.first,
513+
let identifier = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier,
514+
binding.accessor == nil
515+
else {
516+
return []
517+
}
518+
519+
if identifier.text == "_storage" { return [] }
520+
521+
return [
522+
"""
523+
524+
get {
525+
_storage[wrappedKeyPath: \\.\(identifier)]
526+
}
527+
""",
528+
"""
529+
530+
set {
531+
_storage[wrappedKeyPath: \\.\(identifier)] = newValue
532+
}
533+
""",
534+
]
535+
}
536+
}
537+
470538
// MARK: Assertion helper functions
471539

472540
/// Assert that expanding the given macros in the original source produces
@@ -533,6 +601,7 @@ public let testMacros: [String: Macro.Type] = [
533601
"addBackingStorage": AddBackingStorage.self,
534602
"wrapAllProperties": WrapAllProperties.self,
535603
"wrapStoredProperties": WrapStoredProperties.self,
604+
"customTypeWrapper": CustomTypeWrapperMacro.self,
536605
]
537606

538607
final class MacroSystemTests: XCTestCase {
@@ -787,4 +856,41 @@ final class MacroSystemTests: XCTestCase {
787856
"""
788857
)
789858
}
859+
860+
func testTypeWrapperTransform() {
861+
AssertMacroExpansion(
862+
macros: testMacros,
863+
"""
864+
@customTypeWrapper
865+
struct Point {
866+
var x: Int
867+
var y: Int
868+
}
869+
""",
870+
// FIXME: Accessor brace indentation is off
871+
"""
872+
873+
struct Point {
874+
var x: Int {
875+
get {
876+
_storage[wrappedKeyPath: \\.x]
877+
}
878+
set {
879+
_storage[wrappedKeyPath: \\.x] = newValue
880+
}
881+
}
882+
var y: Int {
883+
get {
884+
_storage[wrappedKeyPath: \\.y]
885+
}
886+
set {
887+
_storage[wrappedKeyPath: \\.y] = newValue
888+
}
889+
}
890+
var _storage: Wrapper<Self>
891+
}
892+
"""
893+
)
894+
895+
}
790896
}

0 commit comments

Comments
 (0)