Skip to content

Commit

Permalink
Update inject macro to support containers (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncipollo authored Oct 16, 2024
1 parent efd1916 commit b511d50
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Sources/WhoopDIKit/Container/Container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public final class Container {
if let value = try definition?.get(params: params) as? T {
return value
} else if let injectable = T.self as? any Injectable.Type {
return try injectable.inject() as! T
return try injectable.inject(container: self) as! T
} else {
throw DependencyError.missingDependecy(ServiceKey(T.self, name: name))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/WhoopDIKit/Injectable/Injectable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import Foundation
/// This protocol is used to create a detached injectable component without needing a dependency module.
/// This is most likely used with the `@Injectable` macro, which will create the inject function and define it for you
public protocol Injectable {
static func inject() throws -> Self
static func inject(container: Container) throws -> Self
}
4 changes: 2 additions & 2 deletions Sources/WhoopDIKitMacros/InjectableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct InjectableMacro: ExtensionMacro, MemberMacro {

// Creates the whoopdi calls in the `inject` func
let injectingVariables: String = allVariables.map { variable in
"\(variable.name): WhoopDI.inject(\(variable.injectedName.map { "\"\($0)\"" } ?? "nil"))"
"\(variable.name): container.inject(\(variable.injectedName.map { "\"\($0)\"" } ?? "nil"))"
}.joined(separator: ", ")

let accessLevel = self.accessLevel(declaration: declaration) ?? "internal"
Expand All @@ -37,7 +37,7 @@ struct InjectableMacro: ExtensionMacro, MemberMacro {
/// }
"""
\(raw: accessLevel) static func inject() -> Self {
\(raw: accessLevel) static func inject(container: Container) -> Self {
Self.init(\(raw: injectingVariables))
}
""",
Expand Down
13 changes: 9 additions & 4 deletions Tests/WhoopDIKitTests/Container/ContainerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ class ContainerTests: XCTestCase {
}
XCTAssertTrue(dependency is DependencyB)
}

func test_injectableWithDependency() throws {
container.registerModules(modules: [FakeTestModuleForInjecting()])
let testInjecting: InjectableWithDependency = container.inject()
XCTAssertEqual(testInjecting, InjectableWithDependency(dependency: DependencyA()))
}

func test_injecting() throws {
throw XCTSkip("TODO: implement once WhoopDI uses a DI container")
func test_injectableWithNamedDependency() throws {
container.registerModules(modules: [FakeTestModuleForInjecting()])
let testInjecting: TestInjectingThing = container.inject()
XCTAssertEqual(testInjecting, TestInjectingThing(name: 1))
let testInjecting: InjectableWithNamedDependency = container.inject()
XCTAssertEqual(testInjecting, InjectableWithNamedDependency(name: 1))
}
}
16 changes: 8 additions & 8 deletions Tests/WhoopDIKitTests/Injectable/InjectableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
let bestThing: Int
internal static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject("Test"))
internal static func inject(container: Container) -> Self {
Self.init(bestThing: container.inject("Test"))
}
internal init(bestThing: Int) {
Expand Down Expand Up @@ -64,8 +64,8 @@ final class InjectableTests: XCTestCase {
lazy var lazyVar: Double = 100
let otherStringType: String.Type
public static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil), otherStringType: WhoopDI.inject(nil))
public static func inject(container: Container) -> Self {
Self.init(bestThing: container.inject(nil), otherStringType: container.inject(nil))
}
public init(bestThing: Int<String>, otherStringType: String.Type) {
Expand Down Expand Up @@ -95,8 +95,8 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
var bestThing: Int = 1
private static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil))
private static func inject(container: Container) -> Self {
Self.init(bestThing: container.inject(nil))
}
private init(bestThing: Int = 1) {
Expand All @@ -121,8 +121,8 @@ final class InjectableTests: XCTestCase {
struct ClosureHolder {
let closure: () -> String
internal static func inject() -> Self {
Self.init(closure: WhoopDI.inject(nil))
internal static func inject(container: Container) -> Self {
Self.init(closure: container.inject(nil))
}
internal init(closure: @escaping () -> String) {
Expand Down
11 changes: 9 additions & 2 deletions Tests/WhoopDIKitTests/Module/TestModules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class NilSingletonModule: DependencyModule {

protocol Dependency { }

class DependencyA: Dependency { }
struct DependencyA: Dependency, Equatable { }

class DependencyB: Dependency {
private let param: String
Expand Down Expand Up @@ -81,12 +81,19 @@ struct GenericDependency<T>: Dependency {

class FakeTestModuleForInjecting: DependencyModule {
override func defineDependencies() {
factory { DependencyA() }
factory(name: "FakeName", factory: { 1 })
}
}

@Injectable
struct TestInjectingThing: Equatable {
struct InjectableWithDependency: Equatable {
private let dependency: DependencyA
}

@Injectable
struct InjectableWithNamedDependency: Equatable {
@InjectableName(name: "FakeName")
let name: Int
}

4 changes: 2 additions & 2 deletions Tests/WhoopDIKitTests/WhoopDITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class WhoopDITests: XCTestCase {

func test_injecting() {
WhoopDI.registerModules(modules: [FakeTestModuleForInjecting()])
let testInjecting: TestInjectingThing = WhoopDI.inject()
XCTAssertEqual(testInjecting, TestInjectingThing(name: 1))
let testInjecting: InjectableWithNamedDependency = WhoopDI.inject()
XCTAssertEqual(testInjecting, InjectableWithNamedDependency(name: 1))
}
}

0 comments on commit b511d50

Please sign in to comment.