Skip to content

Commit

Permalink
Inline property decorators everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
dfed committed Jan 1, 2025
1 parent 2f238c5 commit 919bcb7
Show file tree
Hide file tree
Showing 7 changed files with 424 additions and 812 deletions.
3 changes: 1 addition & 2 deletions Sources/SafeDI/Decorators/Instantiated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
///
/// An example of the macro in use:
///
/// @Instantiated
/// private let dependency: DependencyType
/// @Instantiated private let dependency: DependencyType
///
/// Note that the access level of the dependency in the above example does not affect the dependency tree – a `private` dependency can still be `@Received` by `@Instantiable`-decorated types further down the dependency tree.
@attached(peer)
Expand Down
12 changes: 4 additions & 8 deletions Tests/SafeDICoreTests/FileVisitorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ final class FileVisitorTests: XCTestCase {
fatalError("SafeDI doesn't inspect the initializer body")
}
@Forwarded
private let user: User
@Forwarded private let user: User
@Received
let networkService: NetworkService
@Received let networkService: NetworkService
}
"""))
XCTAssertEqual(
Expand Down Expand Up @@ -95,11 +93,9 @@ final class FileVisitorTests: XCTestCase {
fatalError("SafeDI doesn't inspect the initializer body")
}
@Forwarded
private let user: User
@Forwarded private let user: User
@Received
let networkService: NetworkService
@Received let networkService: NetworkService
}
@Instantiable
Expand Down
93 changes: 31 additions & 62 deletions Tests/SafeDIMacrosTests/InjectableMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ import SafeDICore
assertMacro {
"""
public struct ExampleService {
@Instantiated(fulfilledByType: "SomethingElse")
let something: Something
@Instantiated(fulfilledByType: "SomethingElse") let something: Something
}
"""
} expansion: {
Expand All @@ -74,8 +73,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated(fulfilledByType: "Module.ConcreteType")
let instantiatedA: InstantiatedA
@Instantiated(fulfilledByType: "Module.ConcreteType") let instantiatedA: InstantiatedA
}
"""
} expansion: {
Expand All @@ -84,6 +82,7 @@ import SafeDICore
init(instantiatedA: InstantiatedA) {
self.instantiatedA = instantiatedA
}
let instantiatedA: InstantiatedA
}
"""
Expand All @@ -100,8 +99,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated
var instantiatedA: InstantiatedA
@Instantiated var instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -111,11 +109,10 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated
var instantiatedA: InstantiatedA
┬──
╰─ 🛑 Dependency can not be mutable unless it is decorated with a property wrapper. Mutations to a dependency are not propagated through the dependency tree.
✏️ Replace `var` with `let`
@Instantiated var instantiatedA: InstantiatedA
┬──
╰─ 🛑 Dependency can not be mutable unless it is decorated with a property wrapper. Mutations to a dependency are not propagated through the dependency tree.
✏️ Replace `var` with `let`
}
"""
} fixes: {
Expand All @@ -125,7 +122,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated let instantiatedA: InstantiatedA
@Instantiated let instantiatedA: InstantiatedA
}
"""
} expansion: {
Expand All @@ -152,8 +149,7 @@ import SafeDICore
}
@ObservedObject
@Instantiated
var instantiatedA: InstantiatedA
@Instantiated var instantiatedA: InstantiatedA
var body: some View {
Text("\\(ObjectIdentifier(instantiatedA))")
Expand Down Expand Up @@ -186,17 +182,15 @@ import SafeDICore
assertMacro {
"""
public struct ExampleService {
@Instantiated(fulfilledByType: "LoginViewController")
let loginViewControllerBuilder: Instantiator<UIViewController>
@Instantiated(fulfilledByType: "LoginViewController") let loginViewControllerBuilder: Instantiator<UIViewController>
}
"""
} diagnostics: {
"""
public struct ExampleService {
@Instantiated(fulfilledByType: "LoginViewController")
@Instantiated(fulfilledByType: "LoginViewController") let loginViewControllerBuilder: Instantiator<UIViewController>
┬────────────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByType` can not be used on an `Instantiator` or `SendableInstantiator`. Use an `ErasedInstantiator` or `SendableErasedInstantiator` instead
let loginViewControllerBuilder: Instantiator<UIViewController>
}
"""
}
Expand All @@ -206,17 +200,15 @@ import SafeDICore
assertMacro {
"""
public struct ExampleService {
@Instantiated
let loginViewControllerBuilder: ErasedInstantiator<UIViewController>
@Instantiated let loginViewControllerBuilder: ErasedInstantiator<UIViewController>
}
"""
} diagnostics: {
"""
public struct ExampleService {
@Instantiated
@Instantiated let loginViewControllerBuilder: ErasedInstantiator<UIViewController>
┬────────────
╰─ 🛑 `ErasedInstantiator` and `SendableErasedInstantiator` require use of the argument `fulfilledByType`
let loginViewControllerBuilder: ErasedInstantiator<UIViewController>
}
"""
}
Expand All @@ -230,8 +222,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Received
static let instantiatedA: InstantiatedA
@Received static let instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -241,10 +232,9 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Received
@Received static let instantiatedA: InstantiatedA
┬────────
╰─ 🛑 This macro can not decorate `static` variables
static let instantiatedA: InstantiatedA
}
"""
}
Expand Down Expand Up @@ -275,8 +265,7 @@ import SafeDICore
}
static let fulfilledByType = "ConcreteType"
@Instantiated(fulfilledByType: fulfilledByType)
let instantiatedA: InstantiatedA
@Instantiated(fulfilledByType: fulfilledByType) let instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -287,10 +276,9 @@ import SafeDICore
}
static let fulfilledByType = "ConcreteType"
@Instantiated(fulfilledByType: fulfilledByType)
@Instantiated(fulfilledByType: fulfilledByType) let instantiatedA: InstantiatedA
┬──────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByType` must be a string literal
let instantiatedA: InstantiatedA
}
"""
}
Expand All @@ -305,8 +293,7 @@ import SafeDICore
}
static let fulfilledByType = "ConcreteType"
@Instantiated(fulfilledByType: "\\(Self.fulfilledByType)")
let instantiatedA: InstantiatedA
@Instantiated(fulfilledByType: "\\(Self.fulfilledByType)") let instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -317,10 +304,9 @@ import SafeDICore
}
static let fulfilledByType = "ConcreteType"
@Instantiated(fulfilledByType: "\(Self.fulfilledByType)")
@Instantiated(fulfilledByType: "\(Self.fulfilledByType)") let instantiatedA: InstantiatedA
┬────────────────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByType` must be a string literal
let instantiatedA: InstantiatedA
}
"""#
}
Expand All @@ -334,8 +320,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated(fulfilledByType: "ConcreteType?")
let instantiatedA: InstantiatedA
@Instantiated(fulfilledByType: "ConcreteType?") let instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -345,10 +330,9 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated(fulfilledByType: "ConcreteType?")
@Instantiated(fulfilledByType: "ConcreteType?") let instantiatedA: InstantiatedA
┬──────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByType` must refer to a simple type
let instantiatedA: InstantiatedA
}
"""
}
Expand All @@ -362,8 +346,7 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated(fulfilledByType: "ConcreteType!")
let instantiatedA: InstantiatedA
@Instantiated(fulfilledByType: "ConcreteType!") let instantiatedA: InstantiatedA
}
"""
} diagnostics: {
Expand All @@ -373,10 +356,9 @@ import SafeDICore
self.instantiatedA = instantiatedA
}
@Instantiated(fulfilledByType: "ConcreteType!")
@Instantiated(fulfilledByType: "ConcreteType!") let instantiatedA: InstantiatedA
┬──────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByType` must refer to a simple type
let instantiatedA: InstantiatedA
}
"""
}
Expand All @@ -388,19 +370,17 @@ import SafeDICore
@Instantiable
public struct ExampleService {
static let instantiatedAName: StaticString = "instantiatedA"
@Received(fulfilledByDependencyNamed: instantiatedAName, ofType: InstantiatedA.self)
let receivedA: ReceivedA
@Received(fulfilledByDependencyNamed: instantiatedAName, ofType: InstantiatedA.self) let receivedA: ReceivedA
}
"""
} diagnostics: {
"""
@Instantiable
public struct ExampleService {
static let instantiatedAName: StaticString = "instantiatedA"
@Received(fulfilledByDependencyNamed: instantiatedAName, ofType: InstantiatedA.self)
@Received(fulfilledByDependencyNamed: instantiatedAName, ofType: InstantiatedA.self) let receivedA: ReceivedA
┬───────────────────────────────────────────────────────────────────────────────────
╰─ 🛑 The argument `fulfilledByDependencyNamed` must be a string literal
let receivedA: ReceivedA
}
"""
}
Expand All @@ -411,18 +391,16 @@ import SafeDICore
"""
@Instantiable
public struct ExampleService {
@Received(fulfilledByDependencyNamed: "instantiatedA", ofType: "InstantiatedA")
let receivedA: ReceivedA
@Received(fulfilledByDependencyNamed: "instantiatedA", ofType: "InstantiatedA") let receivedA: ReceivedA
}
"""
} diagnostics: {
"""
@Instantiable
public struct ExampleService {
@Received(fulfilledByDependencyNamed: "instantiatedA", ofType: "InstantiatedA")
@Received(fulfilledByDependencyNamed: "instantiatedA", ofType: "InstantiatedA") let receivedA: ReceivedA
┬──────────────────────────────────────────────────────────────────────────────
╰─ 🛑 The argument `ofType` must be a type literal
let receivedA: ReceivedA
}
"""
}
Expand All @@ -434,26 +412,17 @@ import SafeDICore
@Instantiable
public struct ExampleService {
static let erasedToConcreteExistential = true
@Received(
fulfilledByDependencyNamed: "receivedA",
ofType: ReceivedA.self,
erasedToConcreteExistential: erasedToConcreteExistential
)
let receivedA: AnyReceivedA
@Received(fulfilledByDependencyNamed: "receivedA", ofType: ReceivedA.self, erasedToConcreteExistential: erasedToConcreteExistential) let receivedA: AnyReceivedA
}
"""
} diagnostics: {
"""
@Instantiable
public struct ExampleService {
static let erasedToConcreteExistential = true
@Received(
@Received(fulfilledByDependencyNamed: "receivedA", ofType: ReceivedA.self, erasedToConcreteExistential: erasedToConcreteExistential) let receivedA: AnyReceivedA
┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
╰─ 🛑 The argument `erasedToConcreteExistential` must be a bool literal
fulfilledByDependencyNamed: "receivedA",
ofType: ReceivedA.self,
erasedToConcreteExistential: erasedToConcreteExistential
)
let receivedA: AnyReceivedA
}
"""
}
Expand Down
Loading

0 comments on commit 919bcb7

Please sign in to comment.