Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 1 addition & 31 deletions Sources/KnitCodeGen/FunctionCallRegistrationParsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension FunctionCallExprSyntax {
let registrationIntoCollection = calledMethods
.first { method in
let name = method.calledExpression.declName.baseName.text
return name == "registerIntoCollection" || name == "autoregisterIntoCollection"
return name == "registerIntoCollection"
}
.flatMap { method in
makeRegistrationIntoCollection(arguments: method.arguments)
Expand Down Expand Up @@ -225,36 +225,6 @@ private func getArguments(
arguments: LabeledExprListSyntax,
trailingClosure: ClosureExprSyntax?
) throws -> [Registration.Argument] {
// `autoregister` parsing

// Check for a single argument param when using autoregister
if let argumentParam = arguments.first(where: {$0.label?.text == "argument"}),
let argumentType = getArgumentType(arg: argumentParam)
{
if TypeNamer.isClosure(type: argumentType) {
// Make all auto register closures @escaping
return [.init(type: "@escaping \(argumentType)")]
} else {
return [.init(type: argumentType)]
}
}

// Autoregister can provide multiple arguments.
// Everything between the `arguments` and `initializer` params is an argument
if let argumentsParamIndex = arguments.firstIndex(where: {$0.label?.text == "arguments"}),
let initIndex = arguments.firstIndex(where: {$0.label?.text == "initializer"}) {
return arguments[argumentsParamIndex..<initIndex].compactMap { element in
guard let type = getArgumentType(arg: element) else {
return nil
}
if TypeNamer.isClosure(type: type) {
return .init(type: "@escaping \(type)")
} else {
return .init(type: type)
}
}
}

// `register` parsing

// The factory closure if it exists, either as a named parameter or a trailing closure
Expand Down
9 changes: 4 additions & 5 deletions Sources/KnitCodeGen/Registration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ extension Registration {
if let identifier {
self.identifier = .fixed(identifier)
} else {
self.identifier = .computed
self.identifier = .wildcard
}
self.type = type
}
Expand All @@ -105,19 +105,18 @@ extension Registration {
/// Used for arguments defined in `.register` registrations.
case fixed(String)

/// Used for arguments provided to `.autoregister` registrations, as those do not receive explicit identifiers.
case computed
/// Unnamed parameters
case wildcard
}

}

public enum FunctionName: String, Codable, Sendable {
case register
case autoregister
case registerAbstract
case implements

static let standaloneFunctions: Set<FunctionName> = [.register, .autoregister, .registerAbstract]
static let standaloneFunctions: Set<FunctionName> = [.register, .registerAbstract]
static let standaloneNames: Set<String> = Set(standaloneFunctions.map { $0.rawValue })
}
}
2 changes: 1 addition & 1 deletion Sources/KnitCodeGen/TypeSafetySourceFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ extension Registration.Argument {
switch identifier {
case let .fixed(value):
return value
case .computed:
case .wildcard:
return TypeNamer.computedIdentifierName(type: type)
}
}
Expand Down
14 changes: 7 additions & 7 deletions Tests/KnitCodeGenTests/AssemblyParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,9 @@ final class AssemblyParsingTests: XCTestCase {
typealias TargetResolver = TestResolver
func assemble(container: Container) {
#if SOME_FLAG
container.autoregister(B.self, initializer: B.init)
container.register(B.self, factory: B.init)
#else
container.autoregister(C.self, initializer: C.init)
container.register(C.self, factory: C.init)
#endif
}
}
Expand All @@ -456,12 +456,12 @@ final class AssemblyParsingTests: XCTestCase {
typealias TargetResolver = TestResolver
func assemble(container: Container) {
#if SOME_FLAG
container.autoregister(A.self, initializer: A.init)
container.register(A.self, factory: A.init)
#endif

#if SOME_FLAG && !ANOTHER_FLAG
container.autoregister(B.self, initializer: B.init)
container.autoregister(C.self, initializer: C.init)
container.register(B.self, factory: B.init)
container.register(C.self, factory: C.init)
#endif
}
}
Expand All @@ -487,7 +487,7 @@ final class AssemblyParsingTests: XCTestCase {
typealias TargetResolver = TestResolver
func assemble(container: Container) {
#if targetEnvironment(simulator)
container.autoregister(A.self, initializer: A.init)
container.register(A.self, factory: A.init)
#endif
}
}
Expand All @@ -508,7 +508,7 @@ final class AssemblyParsingTests: XCTestCase {
func assemble(container: Container) {
#if DEBUG
#if FEATURE
container.autoregister(A.self, initializer: A.init)
container.register(A.self, factory: A.init)
#endif
#endif
}
Expand Down
151 changes: 18 additions & 133 deletions Tests/KnitCodeGenTests/RegistrationParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ final class RegistrationParsingTests: XCTestCase {
"container.register(AType.self)",
serviceName: "AType"
)
try assertRegistrationString(
"container.autoregister(BType.self)",
serviceName: "BType"
)
try assertMultipleRegistrationsString(
"""
container.register(AType.self) { _ in }
Expand All @@ -31,18 +27,18 @@ final class RegistrationParsingTests: XCTestCase {
)
try assertRegistrationString(
"""
container.autoregister(
container.register(
AnyPublisher<DataState, Never>.self,
initializer: DataStateProvider.adapter
factory: DataStateProvider.adapter
)
""",
serviceName: "AnyPublisher<DataState, Never>"
)
try assertRegistrationString(
"""
container.autoregister(
container.register(
((String) -> EntityGainLossDataArchiver).self,
initializer: FileClusterDataArchiver.makeArchiverProviderForEntityGainLoss
factory: FileClusterDataArchiver.makeArchiverProviderForEntityGainLoss
)
""",
serviceName: "((String) -> EntityGainLossDataArchiver)"
Expand Down Expand Up @@ -77,14 +73,6 @@ final class RegistrationParsingTests: XCTestCase {
serviceName: "A",
name: "service"
)

try assertRegistrationString(
"""
container.autoregister(A.self, name: "service2", initializer: A.init)
""",
serviceName: "A",
name: "service2"
)
}

func testGetterConfigRegistrations() throws {
Expand Down Expand Up @@ -140,14 +128,14 @@ final class RegistrationParsingTests: XCTestCase {

try assertMultipleRegistrationsString(
"""
container.autoregister(A.self, initializer: A.init)
container.register(A.self, factory: A.init)
.implements(B.self)
// @knit public
.implements(C.self, name: "foo")
.implements(D.self, name: "bar")
""",
registrations: [
Registration(service: "A", name: nil, accessLevel: .internal, functionName: .autoregister),
Registration(service: "A", name: nil, accessLevel: .internal, functionName: .register),
Registration(service: "B", name: nil, accessLevel: .internal, functionName: .implements),
Registration(service: "C", name: "foo", accessLevel: .public, functionName: .implements),
Registration(service: "D", name: "bar", accessLevel: .internal, functionName: .implements),
Expand Down Expand Up @@ -253,73 +241,6 @@ final class RegistrationParsingTests: XCTestCase {
)
}

func testAutoregisterWithArguments() throws {
// Single argument
try assertMultipleRegistrationsString(
"container.autoregister(A.self, argument: URL.self, initializer: A.init)",
registrations: [
Registration(service: "A", accessLevel: .internal, arguments: [.init(type: "URL")], functionName: .autoregister)
]
)

// Multiple arguments
try assertMultipleRegistrationsString(
"""
container.autoregister(
A.self,
arguments: URL.self,
Int.self,
String.self,
initializer: A.init
)
""",
registrations: [
Registration(
service: "A",
accessLevel: .internal,
arguments: [
.init(type: "URL"),
.init(type: "Int"),
.init(type: "String"),
],
functionName: .autoregister
)
]
)

// Single argument with name
try assertMultipleRegistrationsString(
"""
container.autoregister(A.self, name: "test", argument: URL.self, initializer: A.init)
""",
registrations: [
Registration(service: "A", name: "test", arguments: [.init(type: "URL")], functionName: .autoregister)
]
)

// Multiple arguments with name
try assertMultipleRegistrationsString(
"""
container.autoregister(
A.self,
name: "test",
arguments: URL.self,
Int.self,
initializer: A.init
)
""",
registrations: [
Registration(
service: "A",
name: "test",
accessLevel: .internal,
arguments: [.init(type: "URL"), .init(type: "Int")],
functionName: .autoregister
)
]
)
}

func testRegisterNonClosureFactoryType() throws {
// This is acceptable syntax but we will not be able to parse any arguments
try assertMultipleRegistrationsString(
Expand All @@ -334,15 +255,17 @@ final class RegistrationParsingTests: XCTestCase {

// Arguments on the main registration apply to implements also
func testForwardedWithArgument() throws {
// Single argument autoregister
// Single argument registration
try assertMultipleRegistrationsString(
"""
container.autoregister(A.self, argument: URL.self, initializer: A.init)
container.register(A.self) { (r: Resolver, url: URL) in
A(url: url)
}
.implements(B.self)
""",
registrations: [
Registration(service: "A", arguments: [.init(type: "URL")], functionName: .autoregister),
Registration(service: "B", arguments: [.init(type: "URL")], functionName: .implements)
Registration(service: "A", arguments: [.init(identifier: "url", type: "URL")], functionName: .register),
Registration(service: "B", arguments: [.init(identifier: "url", type: "URL")], functionName: .implements)
]
)

Expand Down Expand Up @@ -385,51 +308,22 @@ final class RegistrationParsingTests: XCTestCase {
)
}

func testAutoRegistrationWithComplexTypes() throws {
try assertMultipleRegistrationsString(
"""
container.autoregister(A.self, argument: String?.self, initializer: A.init)
""",
registrations: [
Registration(service: "A", arguments: [.init(type: "String?")], functionName: .autoregister),
]
)

func testClosureArgument() throws {
try assertMultipleRegistrationsString(
"""
container.autoregister(A.self, arguments: Result<Int, Error>.self, Optional<Int>.self, initializer: A.init)
container.register(A.self) { (r: Resolver, closure: () -> Void) in
A.init(closure: closure)
}
""",
registrations: [
Registration(
service: "A",
arguments: [
.init(type: "Result<Int, Error>"),
.init(type: "Optional<Int>"),
],
functionName: .autoregister
arguments: [.init(identifier: "closure", type: "() -> Void")],
functionName: .register
),
]
)

try assertMultipleRegistrationsString(
"""
// @knit
container.autoregister((String, Int?).self, initializer: Factory.make)
""",
registrations: [
.init(service: "(String, Int?)", functionName: .autoregister)
]
)
}

func testClosureArgument() throws {
try assertMultipleRegistrationsString(
"container.autoregister(A.self, argument: (() -> Void).self, initializer: A.init)",
registrations: [
Registration(service: "A", arguments: [.init(type: "@escaping (() -> Void)")], functionName: .autoregister),
]
)

try assertMultipleRegistrationsString(
"""
container.register(A.self) { (resolver, arg1: @escaping () -> Void) in
Expand Down Expand Up @@ -540,15 +434,6 @@ final class RegistrationParsingTests: XCTestCase {
.init(service: "AType"),
]
)
try assertMultipleRegistrationsString(
"""
container.autoregisterIntoCollection(AType.self, initializer: AType.init)
.inObjectScope(.container)
""",
registrationsIntoCollections: [
.init(service: "AType"),
]
)
}

func testMultiLineComments() throws {
Expand Down