Skip to content

Commit 444598e

Browse files
committed
Fix adding @escaping keyword for closures in explicit init
1 parent 782a984 commit 444598e

4 files changed

Lines changed: 80 additions & 5 deletions

File tree

Sources/BuildableClient/main.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Buildable
22
import Foundation
33

44
@Buildable
5-
struct MyObject {
5+
public struct MyObject {
66
let m01: String
77
let m02: Int
88
let m03: Int8
@@ -32,9 +32,12 @@ struct MyObject {
3232
let m27: [String: String]
3333
var m28: String
3434
let m29: () -> Void
35-
let m30: (String) -> Void
36-
let m31: (String, Int) -> Void
37-
let m32: (String, Int) -> String
35+
let m30: (() -> Void)?
36+
let m31: (() -> Void)!
37+
let m32: (String) -> Void
38+
let m33: ((String) -> Void)?
39+
let m34: (String, Int) -> Void
40+
let m35: (String, Int) -> String
3841
var myEnum: MyEnum
3942
}
4043

Sources/BuildableMacro/Utils/AccessLevel/InitParameter.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,17 @@ struct InitParameter: Identifiable {
1313
let identifier: TokenSyntax
1414
let type: TypeSyntax
1515
let value: TokenSyntax?
16+
17+
var typeForExplicitInit: any TypeSyntaxProtocol {
18+
if type.as(FunctionTypeSyntax.self) != nil {
19+
return AttributedTypeSyntax(
20+
specifiers: TypeSpecifierListSyntax {
21+
SimpleTypeSpecifierSyntax(specifier: .identifier("@escaping"))
22+
},
23+
baseType: type
24+
)
25+
} else {
26+
return type
27+
}
28+
}
1629
}

Sources/BuildableMacro/Utils/AccessLevel/MakeExplicitInit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func makeExplicitInit(parameters: [InitParameter], accessLevel: AccessLevel) ->
1818
FunctionParameterSyntax(
1919
leadingTrivia: .newline,
2020
firstName: parameter.identifier,
21-
type: parameter.type,
21+
type: parameter.typeForExplicitInit,
2222
defaultValue: InitializerClauseSyntax(value: getDefaultValue(from: parameter)),
2323
trailingTrivia: parameter.id == parameters.last?.id ? .newline : nil
2424
)

Tests/BuildableMacroTests/BuildableStructTests.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,4 +621,63 @@ class BuildableStructTests: XCTestCase {
621621
macros: testMacros
622622
)
623623
}
624+
625+
func test_should_add_escaping_keyword_for_closure_in_public_init() {
626+
assertMacroExpansion(
627+
"""
628+
@Buildable
629+
public struct MyObject {
630+
public let m1: () -> Void
631+
public let m2: (String) -> Int
632+
public let m3: (() -> Void)?
633+
public let m4: (() -> Void)!
634+
}
635+
""",
636+
expandedSource: """
637+
638+
public struct MyObject {
639+
public let m1: () -> Void
640+
public let m2: (String) -> Int
641+
public let m3: (() -> Void)?
642+
public let m4: (() -> Void)!
643+
}
644+
645+
public struct MyObjectBuilder {
646+
public var m1: () -> Void = {
647+
}
648+
public var m2: (String) -> Int = { _ in
649+
return 0
650+
}
651+
public var m3: (() -> Void)?
652+
public var m4: (() -> Void)!
653+
654+
public init(
655+
m1: @escaping () -> Void = {
656+
},
657+
m2: @escaping (String) -> Int = { _ in
658+
return 0
659+
},
660+
m3: (() -> Void)? = nil,
661+
m4: (() -> Void)! = nil
662+
) {
663+
self.m1 = m1
664+
self.m2 = m2
665+
self.m3 = m3
666+
self.m4 = m4
667+
}
668+
669+
public func build() -> MyObject {
670+
return MyObject(
671+
m1: m1,
672+
m2: m2,
673+
m3: m3,
674+
m4: m4
675+
)
676+
}
677+
}
678+
679+
""",
680+
macros: testMacros
681+
)
682+
}
624683
}

0 commit comments

Comments
 (0)