Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds main actor annotations where needed #12

Merged
merged 1 commit into from
Jul 12, 2024
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
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyModule.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation

/// Provides dependencies to the object graph. Modules can be registered with WhoopDI via `WhoopDI.registerModules`.
@MainActor
open class DependencyModule {
private var dependencies: [DependencyDefinition] = []

Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyRegister.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@MainActor
public protocol DependencyRegister {
static func removeAllDependencies()
static func registerModules(modules: [DependencyModule])
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/DependencyTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

/// Performs a depth first, post ordered search of the given module's dependency tree and flattens the tree into a list of modules
/// in which the lowest level modules are ordered first.
@MainActor
public final class DependencyTree {

private let dependencyModule: [DependencyModule]
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/WhoopDI.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
@MainActor
public final class WhoopDI: DependencyRegister {
private static let serviceDict = ServiceDictionary<DependencyDefinition>()
private static var localServiceDict: ServiceDictionary<DependencyDefinition>? = nil
Expand Down
1 change: 1 addition & 0 deletions Sources/WhoopDIKit/WhoopDIValidator.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// Provides verification that the object graph is complete. This is intended to be called from within a test.
@MainActor
public final class WhoopDIValidator {
private let paramsDict = ServiceDictionary<Any>()

Expand Down
3 changes: 2 additions & 1 deletion Sources/WhoopDIKitMacros/InjectableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ struct InjectableMacro: ExtensionMacro, MemberMacro {

return [
/// Adds the static inject function, such as:
/// @MainActor
/// public static func inject() -> Self {
/// Self.init(myValue: WhoopDI.inject(nil))
/// }
"""

@MainActor
\(raw: accessLevel) static func inject() -> Self {
Self.init(\(raw: injectingVariables))
}
Expand Down
14 changes: 12 additions & 2 deletions Tests/WhoopDIKitTests/DependencyModuleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,53 @@ class DependencyModuleTests: XCTestCase {
private let serviceKey = ServiceKey(String.self, name: "name")
private let serviceDict = ServiceDictionary<DependencyDefinition>()

private let module = DependencyModule()

@MainActor
func test_factory() {
let module = DependencyModule()
module.factory(name: "name") { "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is FactoryDefinition)
}

@MainActor
func test_factoryWithParams() {
let module = DependencyModule()
module.factoryWithParams(name: "name") { (_: Any) in "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is FactoryDefinition)
}

@MainActor
func test_singleton() {
let module = DependencyModule()
module.singleton(name: "name") { "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is SingletonDefinition)
}

@MainActor
func test_singletonWithParams() {
let module = DependencyModule()
module.singletonWithParams(name: "name") { (_: Any) in "dependency" }
module.addToServiceDictionary(serviceDict: serviceDict)

let defintion = serviceDict[serviceKey]
XCTAssertTrue(defintion is SingletonDefinition)
}

@MainActor
func test_ServiceKey_Returns_Subclass_Type() {
let testModule = TestDependencyModule(testModuleDependencies: [])
XCTAssertEqual(testModule.serviceKey, ServiceKey(type(of: TestDependencyModule())))
}

@MainActor
func test_SetMultipleModuleDependencies() {
let moduleA = DependencyModule()
let moduleB = DependencyModule()
Expand All @@ -55,13 +63,15 @@ class DependencyModuleTests: XCTestCase {
XCTAssertEqual(module.moduleDependencies, [moduleD, moduleC, moduleB, moduleA])
}

@MainActor
func test_SetSingleModuleDependency() {
let moduleA = DependencyModule()

let module = TestDependencyModule(testModuleDependencies: [moduleA])
XCTAssertEqual(module.moduleDependencies, [moduleA])
}

@MainActor
func test_SetNoModuleDependencies() {
let module = TestDependencyModule()
XCTAssertEqual(module.moduleDependencies, [])
Expand Down
14 changes: 11 additions & 3 deletions Tests/WhoopDIKitTests/DependencyTreeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import XCTest
@testable import WhoopDIKit

final class DependencyTreeTests: XCTestCase {
override func tearDown() {
WhoopDI.removeAllDependencies()

override func tearDown() async throws {
await WhoopDI.removeAllDependencies()
}

@MainActor
func testDepthFirstSearch_SingleList() {
let moduleD = module("D")
let moduleC = module("C", dependentModules: [moduleD])
Expand All @@ -17,6 +18,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleD, moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_SingeList_FilterDuplicates() {
let moduleDuplicate = module("C")
let moduleC = module("C", dependentModules: [moduleDuplicate])
Expand All @@ -27,6 +29,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_NoDependencyLoop() {
var loopDependency: [DependencyModule] = []
let moduleC = KeyedModule(key: "C", keyedModuleDependencies: loopDependency)
Expand All @@ -38,6 +41,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual([moduleC, moduleB, moduleA], tree.modules)
}

@MainActor
func testDepthFirstSearch_OneTopLevelModule() {
let modules = generateTree(rootKey: "A")

Expand All @@ -58,6 +62,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual(keys, tree.modules.map { $0.serviceKey.name })
}

@MainActor
func testDepthFirstSearch_MultipleTopLevelModules() {
let modules = generateTree(rootKey: "A") + generateTree(rootKey: "B")

Expand All @@ -80,6 +85,7 @@ final class DependencyTreeTests: XCTestCase {
XCTAssertEqual(keys, tree.modules.map { $0.serviceKey.name })
}

@MainActor
func testDepthFirstSearch_DuplicateTopLevelModules() {
let modules = generateTree(rootKey: "A") + generateTree(rootKey: "A")

Expand All @@ -102,6 +108,7 @@ final class DependencyTreeTests: XCTestCase {
}

private extension DependencyTreeTests {
@MainActor
func generateTree(rootKey: String = "", depth: Int = 0) -> [KeyedModule] {
if depth == 3 { return [] }

Expand All @@ -112,6 +119,7 @@ private extension DependencyTreeTests {
}
}

@MainActor
func module(_ name: String, dependentModules: [DependencyModule] = []) -> KeyedModule {
KeyedModule(key: name, keyedModuleDependencies: dependentModules)
}
Expand Down
4 changes: 4 additions & 0 deletions Tests/WhoopDIKitTests/InjectableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
let bestThing: Int

@MainActor
internal static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject("Test"))
}
Expand Down Expand Up @@ -60,6 +61,7 @@ final class InjectableTests: XCTestCase {
lazy var lazyVar: Double = 100
let otherStringType: String.Type

@MainActor
public static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil), otherStringType: WhoopDI.inject(nil))
}
Expand Down Expand Up @@ -91,6 +93,7 @@ final class InjectableTests: XCTestCase {
var newerThing: String { "not again" }
var bestThing: Int = 1

@MainActor
private static func inject() -> Self {
Self.init(bestThing: WhoopDI.inject(nil))
}
Expand All @@ -117,6 +120,7 @@ final class InjectableTests: XCTestCase {
struct ClosureHolder {
let closure: () -> String

@MainActor
internal static func inject() -> Self {
Self.init(closure: WhoopDI.inject(nil))
}
Expand Down
16 changes: 14 additions & 2 deletions Tests/WhoopDIKitTests/WhoopDITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,32 @@ import XCTest

class WhoopDITests: XCTestCase {

override func tearDown() {
WhoopDI.removeAllDependencies()
override func tearDown() async throws {
await WhoopDI.removeAllDependencies()
}

@MainActor
func test_inject() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", "param")
XCTAssertTrue(dependency is DependencyC)
}

@MainActor
func test_inject_generic_integer() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: GenericDependency<Int> = WhoopDI.inject()
XCTAssertEqual(42, dependency.value)
}

@MainActor
func test_inject_generic_string() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: GenericDependency<String> = WhoopDI.inject()
XCTAssertEqual("string", dependency.value)
}

@MainActor
func test_inject_localDefinition() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory") { module in
Expand All @@ -35,12 +39,14 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(dependency is DependencyA)
}

@MainActor
func test_inject_localDefinition_noOverride() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", params: "params") { _ in }
XCTAssertTrue(dependency is DependencyC)
}

@MainActor
func test_inject_localDefinition_withParams() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let dependency: Dependency = WhoopDI.inject("C_Factory", params: "params") { module in
Expand All @@ -49,6 +55,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(dependency is DependencyB)
}

@MainActor
func test_validation_fails_barParams() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -57,6 +64,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_missingDependencies() {
WhoopDI.registerModules(modules: [BadTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -70,6 +78,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_nilFactoryDependency() {
WhoopDI.registerModules(modules: [NilFactoryModule()])
let validator = WhoopDIValidator()
Expand All @@ -83,6 +92,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_fails_nilSingletonDependency() {
WhoopDI.registerModules(modules: [NilSingletonModule()])
let validator = WhoopDIValidator()
Expand All @@ -96,6 +106,7 @@ class WhoopDITests: XCTestCase {
XCTAssertTrue(failed)
}

@MainActor
func test_validation_succeeds() {
WhoopDI.registerModules(modules: [GoodTestModule()])
let validator = WhoopDIValidator()
Expand All @@ -110,6 +121,7 @@ class WhoopDITests: XCTestCase {
}
}

@MainActor
func test_injecting() {
WhoopDI.registerModules(modules: [FakeTestModuleForInjecting()])
let testInjecting: TestInjectingThing = WhoopDI.inject()
Expand Down
Loading