Skip to content

Commit 007ade5

Browse files
committed
Always generate computed getter if alias is specified
The getter with a computed name is always generated, the optional getter alias will produce a second getter. Allows for better support for the Resolvable macro.
1 parent 948b6b1 commit 007ade5

File tree

2 files changed

+118
-24
lines changed

2 files changed

+118
-24
lines changed

Sources/KnitCodeGen/TypeSafetySourceFile.swift

+46-10
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,21 @@ public enum TypeSafetySourceFile {
2424
""") {
2525

2626
for registration in unnamedRegistrations {
27-
try makeResolver(registration: registration, getterAlias: registration.getterAlias)
27+
let resolvers = try makeResolvers(registration: registration, getterAlias: registration.getterAlias)
28+
for resolver in resolvers {
29+
resolver
30+
}
2831
}
2932
for namedGroup in namedGroups {
3033
let firstGetterAlias = namedGroup.registrations[0].getterAlias
31-
try makeResolver(
34+
let resolvers = try makeResolvers(
3235
registration: namedGroup.registrations[0],
3336
enumName: "\(config.assemblyName).\(namedGroup.enumName)",
3437
getterAlias: firstGetterAlias
3538
)
39+
for resolver in resolvers {
40+
resolver
41+
}
3642
}
3743
}
3844
if !namedGroups.isEmpty {
@@ -48,11 +54,11 @@ public enum TypeSafetySourceFile {
4854
}
4955

5056
/// Create the type safe resolver function for this registration
51-
static func makeResolver(
57+
static func makeResolvers(
5258
registration: Registration,
5359
enumName: String? = nil,
5460
getterAlias: String? = nil
55-
) throws -> DeclSyntaxProtocol {
61+
) throws -> [DeclSyntaxProtocol] {
5662
var modifier = ""
5763
if let spi = registration.spi {
5864
modifier += "@_spi(\(spi)) "
@@ -71,23 +77,53 @@ public enum TypeSafetySourceFile {
7177
"file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line"
7278
].compactMap { $0 }.joined(separator: ", ")
7379
let usages = ["\(registration.service).self", nameUsage, argUsage].compactMap { $0 }.joined(separator: ", ")
74-
let funcName = getterAlias ?? TypeNamer.computedIdentifierName(type: registration.service)
7580

76-
let function = try FunctionDeclSyntax("\(raw: modifier)func \(raw: funcName)(\(raw: inputs)) -> \(raw: registration.service)") {
77-
"knitUnwrap(resolve(\(raw: usages)), callsiteFile: file, callsiteFunction: function, callsiteLine: line)"
81+
let function = try makeResolveFunction(
82+
modifier: modifier,
83+
registration: registration,
84+
functionName: TypeNamer.computedIdentifierName(type: registration.service),
85+
inputs: inputs,
86+
usages: usages
87+
)
88+
89+
let aliasFunction: FunctionDeclSyntax? = try getterAlias.map {
90+
try makeResolveFunction(
91+
modifier: modifier,
92+
registration: registration,
93+
functionName: $0,
94+
inputs: inputs,
95+
usages: usages
96+
)
7897
}
7998

8099
// Wrap the output in an #if where needed
81100
guard let ifConfigCondition = registration.ifConfigCondition else {
82-
return function
101+
return [function, aliasFunction].compactMap { $0 }
83102
}
84-
let codeBlock = CodeBlockItemListSyntax([.init(item: .init(function))])
103+
let codeBlock = CodeBlockItemListSyntax(
104+
[
105+
.init(item: .init(function)),
106+
aliasFunction.map { .init(item: .init($0)) }
107+
].compactMap { $0 }
108+
)
85109
let clause = IfConfigClauseSyntax(
86110
poundKeyword: .poundIfToken(),
87111
condition: ifConfigCondition,
88112
elements: .statements(codeBlock)
89113
)
90-
return IfConfigDeclSyntax(clauses: [clause])
114+
return [IfConfigDeclSyntax(clauses: [clause])]
115+
}
116+
117+
private static func makeResolveFunction(
118+
modifier: String,
119+
registration: Registration,
120+
functionName: String,
121+
inputs: String,
122+
usages: String
123+
) throws -> FunctionDeclSyntax {
124+
try FunctionDeclSyntax("\(raw: modifier)func \(raw: functionName)(\(raw: inputs)) -> \(raw: registration.service)") {
125+
"knitUnwrap(resolve(\(raw: usages)), callsiteFile: file, callsiteFunction: function, callsiteLine: line)"
126+
}
91127
}
92128

93129
private static func argumentString(registration: Registration) -> (input: String?, usage: String?) {

Tests/KnitCodeGenTests/TypeSafetySourceFileTests.swift

+72-14
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ final class TypeSafetySourceFileTests: XCTestCase {
3737
func serviceA(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> ServiceA {
3838
knitUnwrap(resolve(ServiceA.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
3939
}
40+
public func serviceD(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> ServiceD {
41+
knitUnwrap(resolve(ServiceD.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
42+
}
4043
public func serviceDAlias(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> ServiceD {
4144
knitUnwrap(resolve(ServiceD.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
4245
}
@@ -75,10 +78,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
7578
func testRegistrationMultipleArguments() {
7679
let registration = Registration(service: "A", accessLevel: .public, arguments: [.init(type: "String"), .init(type: "URL")])
7780
XCTAssertEqual(
78-
try TypeSafetySourceFile.makeResolver(
81+
try TypeSafetySourceFile.makeResolverString(
7982
registration: registration,
8083
enumName: nil
81-
).formatted().description,
84+
),
8285
"""
8386
public func a(string: String, url: URL, file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
8487
knitUnwrap(resolve(A.self, arguments: string, url), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -90,10 +93,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
9093
func testRegistrationSingleArgument() {
9194
let registration = Registration(service: "A", accessLevel: .public, arguments: [.init(type: "String")])
9295
XCTAssertEqual(
93-
try TypeSafetySourceFile.makeResolver(
96+
try TypeSafetySourceFile.makeResolverString(
9497
registration: registration,
9598
enumName: nil
96-
).formatted().description,
99+
),
97100
"""
98101
public func a(string: String, file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
99102
knitUnwrap(resolve(A.self, argument: string), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -105,10 +108,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
105108
func testRegistrationDuplicateParamType() {
106109
let registration = Registration(service: "A", accessLevel: .public, arguments: [.init(type: "String"), .init(type: "String")])
107110
XCTAssertEqual(
108-
try TypeSafetySourceFile.makeResolver(
111+
try TypeSafetySourceFile.makeResolverString(
109112
registration: registration,
110113
enumName: nil
111-
).formatted().description,
114+
),
112115
"""
113116
public func a(string1: String, string2: String, file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
114117
knitUnwrap(resolve(A.self, arguments: string1, string2), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -120,10 +123,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
120123
func testRegistrationArgumentAndName() {
121124
let registration = Registration(service: "A", name: "test", accessLevel: .public, arguments: [.init(type: "String")])
122125
XCTAssertEqual(
123-
try TypeSafetySourceFile.makeResolver(
126+
try TypeSafetySourceFile.makeResolverString(
124127
registration: registration,
125128
enumName: "MyAssembly.A_ResolutionKey"
126-
).formatted().description,
129+
),
127130
"""
128131
public func a(name: MyAssembly.A_ResolutionKey, string: String, file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
129132
knitUnwrap(resolve(A.self, name: name.rawValue, argument: string), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -135,10 +138,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
135138
func testRegistrationWithPrenamedArguments() {
136139
let registration = Registration(service: "A", accessLevel: .public, arguments: [.init(identifier: "arg", type: "String")])
137140
XCTAssertEqual(
138-
try TypeSafetySourceFile.makeResolver(
141+
try TypeSafetySourceFile.makeResolverString(
139142
registration: registration,
140143
enumName: nil
141-
).formatted().description,
144+
),
142145
"""
143146
public func a(arg: String, file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
144147
knitUnwrap(resolve(A.self, argument: arg), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -151,15 +154,36 @@ final class TypeSafetySourceFileTests: XCTestCase {
151154
var registration = Registration(service: "A", accessLevel: .public)
152155
registration.ifConfigCondition = ExprSyntax("SOME_FLAG")
153156
XCTAssertEqual(
154-
try TypeSafetySourceFile.makeResolver(
157+
try TypeSafetySourceFile.makeResolverString(
158+
registration: registration,
159+
enumName: nil
160+
),
161+
"""
162+
#if SOME_FLAG
163+
public func a(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
164+
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
165+
}
166+
#endif
167+
"""
168+
)
169+
}
170+
171+
func testRegistrationWithIfConfigAndAlias() {
172+
var registration = Registration(service: "A", accessLevel: .public, getterAlias: "fooAlias")
173+
registration.ifConfigCondition = ExprSyntax("SOME_FLAG")
174+
XCTAssertEqual(
175+
try TypeSafetySourceFile.makeResolverString(
155176
registration: registration,
156177
enumName: nil
157-
).formatted().description,
178+
),
158179
"""
159180
#if SOME_FLAG
160181
public func a(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
161182
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
162183
}
184+
public func fooAlias(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
185+
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
186+
}
163187
#endif
164188
"""
165189
)
@@ -168,10 +192,10 @@ final class TypeSafetySourceFileTests: XCTestCase {
168192
func testRegistrationWithSPI() {
169193
let registration = Registration(service: "A", accessLevel: .public, spi: "Testing")
170194
XCTAssertEqual(
171-
try TypeSafetySourceFile.makeResolver(
195+
try TypeSafetySourceFile.makeResolverString(
172196
registration: registration,
173197
enumName: nil
174-
).formatted().description,
198+
),
175199
"""
176200
@_spi(Testing) public func a(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
177201
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
@@ -180,6 +204,23 @@ final class TypeSafetySourceFileTests: XCTestCase {
180204
)
181205
}
182206

207+
func testRegisrationWithGetterAlias() {
208+
let registration = Registration(service: "A", accessLevel: .public, getterAlias: "fooAlias")
209+
XCTAssertEqual(
210+
try TypeSafetySourceFile.makeResolverString(
211+
registration: registration
212+
),
213+
"""
214+
public func a(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
215+
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
216+
}
217+
public func fooAlias(file: StaticString = #fileID, function: StaticString = #function, line: UInt = #line) -> A {
218+
knitUnwrap(resolve(A.self), callsiteFile: file, callsiteFunction: function, callsiteLine: line)
219+
}
220+
"""
221+
)
222+
}
223+
183224
func testArgumentIdentifiers() {
184225
let registration1 = Registration(service: "A", arguments: [.init(type: "String?")])
185226
XCTAssertEqual(
@@ -376,3 +417,20 @@ final class TypeSafetySourceFileTests: XCTestCase {
376417
}
377418

378419
}
420+
421+
private extension TypeSafetySourceFile {
422+
423+
static func makeResolverString(
424+
registration: Registration,
425+
enumName: String? = nil
426+
) throws -> String {
427+
try TypeSafetySourceFile.makeResolvers(
428+
registration: registration,
429+
enumName: enumName,
430+
getterAlias: registration.getterAlias
431+
)
432+
.map { $0.formatted().description }
433+
.joined(separator: "\n")
434+
}
435+
436+
}

0 commit comments

Comments
 (0)