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
37 changes: 37 additions & 0 deletions Sources/Cradle/DependencyGraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@
// final class `sources` source graph 저장 프로퍼티와 생성 initializer 추가
// `overrides: true` graph의 인스턴스별 Factory 선택 builder와 생성 경로 추가
// source·override가 없는 graph의 initializer·stored property 미변경
/**
`@Provide` Factory로 의존성을 등록하고 생성 접근자를 만드는 graph Macro입니다.

제네릭 매개변수와 `where` 절이 없는 `final class` 또는 `actor`에 적용합니다.
일반 `@Provide` Factory의 반환 타입을 기준으로 graph에 읽기 전용 생성 프로퍼티를 추가합니다.

- Parameters:
- lifetime: graph 인스턴스의 보유 범위입니다. 기본값은 `.instance`이며, `.shared`는 프로세스 동안
보유하는 `static let shared` graph를 만듭니다.
- sources: `final class` 조합 graph가 보관하고 Factory에서 읽을 source graph 타입 배열입니다.
기본값은 빈 배열입니다.
- overrides: graph 인스턴스별 Factory 교체를 위한 `override`와 `OverrideBuilder` 생성 여부입니다.
기본값은 `false`입니다.
- diagram: `CradlePlugin`의 Mermaid 개발 산출물에 해당 graph를 포함할지 정하는 값입니다.
기본값은 `true`입니다.
- Important: `actor` graph에는 `sources`를 사용할 수 없습니다. `sources` 또는 `overrides: true`를
사용한 graph에는 initializer를 직접 선언할 수 없습니다.
*/
@attached(member, names: arbitrary)
public macro DependencyGraph(
_ lifetime: DependencyGraphLifetime = .instance,
Expand All @@ -25,6 +43,14 @@ public macro DependencyGraph(
)

// `@DependencyGraph` 본체에서 생성 접근자가 호출할 private factory 표시
/**
기본 `.shared` 수명으로 의존성을 등록하는 Factory Macro입니다.

`@DependencyGraph` 본체에 직접 선언한 동기 `private` 인스턴스 메서드에 적용합니다.
Factory 결과는 graph를 만들 때 한 번 생성되고 해당 graph가 보관합니다.

- Important: 호출 시점 입력이 필요하면 `@Provide(.transient)`와 `@External`을 함께 사용합니다.
*/
@attached(peer, names: arbitrary)
@attached(body)
public macro Provide() = #externalMacro(
Expand All @@ -33,6 +59,17 @@ public macro Provide() = #externalMacro(
)

// Factory 결과를 graph 수명 정책에 맞게 소유하도록 표시
/**
지정한 수명 정책으로 의존성을 등록하는 Factory Macro입니다.

`@DependencyGraph` 본체에 직접 선언한 동기 `private` 인스턴스 메서드에 적용합니다.
외부 입력이 없는 Factory의 반환 타입이 등록 타입과 생성 접근자의 타입이 됩니다.

- Parameter lifetime: Factory 결과의 graph별 보유 정책입니다. `.shared`는 graph 생성 중 한 번,
`.lazy`는 생성 프로퍼티를 처음 읽을 때 한 번, `.transient`는 접근할 때마다 Factory를 평가합니다.
- Important: `@External` 입력은 명시적인 `.transient` Factory에서만 사용할 수 있으며, 이때 Macro는
호출 시점 생성 메서드를 만듭니다.
*/
@attached(peer, names: arbitrary)
@attached(body)
public macro Provide(_ lifetime: DependencyLifetime) = #externalMacro(
Expand Down
22 changes: 22 additions & 0 deletions Sources/Cradle/DependencyGraphLifetime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,31 @@
//

// graph 인스턴스의 생성·보유 범위 정책
/**
graph 인스턴스의 생성과 보유 범위를 정하는 정책입니다.

`DependencyLifetime`이 Factory 결과의 수명을 정하는 것과 달리 graph 자체의 보유 범위를 정합니다.

- Note: provider 결과의 평가 시점과 보유 방식은 `DependencyLifetime`로 따로 지정합니다.
*/
public enum DependencyGraphLifetime: Sendable {
// 호출자가 직접 만드는 graph 인스턴스 범위
/**
호출자가 직접 생성하고 보유하는 graph 인스턴스 범위입니다.

graph가 해제되면 graph가 보관하던 provider 결과의 참조도 놓습니다.

- Note: provider 결과의 보유 방식은 각 `@Provide`의 `DependencyLifetime`를 따릅니다.
*/
case instance
// 프로세스 동안 보유하는 정적 graph 범위
/**
프로세스 동안 보유하는 `static let shared` graph 범위입니다.

`actor`와 `@MainActor` graph는 기존 격리를 유지합니다. 비격리 `final class`는 직접 `Sendable`
준수를 선언해야 합니다.

- Warning: 이 graph는 프로세스 동안 보유되므로 해제 시점을 검증하는 대상이 아닙니다.
*/
case shared
}
28 changes: 28 additions & 0 deletions Sources/Cradle/DependencyLifetime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,39 @@
//

// graph가 Factory 결과를 소유하는 수명 정책
/**
Factory 결과를 graph가 평가하고 보유하는 방식을 정하는 정책입니다.

`DependencyGraphLifetime`의 graph 인스턴스 보유 범위와 구분됩니다.

- Note: 이 정책은 graph 자체의 생성 방식이나 보유 기간을 변경하지 않습니다.
*/
public enum DependencyLifetime: Sendable {
// graph 생성 중 한 번 만들고 해당 graph에서 재사용
/**
graph를 생성할 때 Factory 결과를 한 번 만들고 해당 graph가 보관하는 정책입니다.

같은 graph 인스턴스의 생성 프로퍼티를 여러 번 읽어도 같은 결과를 반환합니다.

- Note: 전역 singleton이 아니라 graph 인스턴스별로 결과를 보관합니다.
*/
case shared
// 생성 프로퍼티를 처음 읽을 때 graph별로 한 번 생성
/**
생성 프로퍼티를 처음 읽을 때 Factory 결과를 graph별로 한 번 만드는 정책입니다.

Factory는 첫 접근 시점의 graph 상태를 읽고, 생성한 결과는 해당 graph가 보관합니다.

- Warning: `Sendable`을 준수하는 비격리 class의 `.shared` graph에는 사용할 수 없습니다.
*/
case lazy
// 생성 프로퍼티를 읽을 때마다 Factory를 호출
/**
생성 프로퍼티를 읽거나 외부 입력 생성 메서드를 호출할 때마다 Factory를 평가하는 정책입니다.

graph는 생성한 결과를 보관하지 않습니다.

- Important: 호출 시점 입력이 필요하면 Factory 매개변수에 `@External`을 함께 사용합니다.
*/
case transient
}
22 changes: 22 additions & 0 deletions Sources/Cradle/DependencyOverride.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,32 @@
//

// graph 생성 전에 기본 Factory 또는 교체 Factory를 선택하는 상태
/**
graph를 만들기 전에 원본 또는 교체 Factory를 선택하는 값입니다.

선택은 `Graph.override(...).build()`로 만드는 graph 인스턴스에만 적용합니다.

- Important: 선택 단계에서는 Factory를 실행하거나 `Graph.shared`를 변경하지 않습니다.
- Note: `Factory`가 `Sendable`이면 이 값도 `Sendable`을 준수합니다.
*/
public enum DependencyOverride<Factory> {
// graph 선언에 작성한 기본 Factory 선택
/**
graph 선언에 작성한 원본 Factory를 선택합니다.

`Graph.override(...)`에서 생략한 등록에도 이 선택을 적용합니다.

- Note: 원본 Factory의 평가 시점은 해당 등록의 `DependencyLifetime`를 따릅니다.
*/
case original
// graph 인스턴스에만 적용할 타입 지정 교체 Factory 선택
/**
생성할 graph 인스턴스에 적용할 타입 지정 교체 Factory를 선택합니다.

교체 Factory의 매개변수 타입과 순서, 반환 타입은 원본 `@Provide` Factory와 같습니다.

- Important: 교체 Factory의 평가 시점과 결과 보유 방식은 원본 등록의 `DependencyLifetime`를 따릅니다.
*/
case replace(Factory)
}

Expand Down
20 changes: 20 additions & 0 deletions Sources/Cradle/External.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,32 @@
//

// graph 생성 메서드 호출자가 전달할 `@Provide(.transient)` 입력
/**
`@Provide(.transient)` Factory에 호출 시점 외부 입력을 표시하는 property wrapper입니다.

Macro는 `@External` 매개변수만 호출자가 전달하는 생성 메서드를 만들고, 나머지 매개변수는 graph 등록으로
연결합니다.

- Important: graph는 이 값을 등록하거나 보관하지 않으며, 명시적인 `.transient` Factory에서만 사용할 수
있습니다.
*/
@propertyWrapper
public struct External<Value> {
// 원본 Factory가 사용할 외부 입력
/**
원본 Factory 매개변수에 전달할 외부 입력 값입니다.

- Note: 생성된 호출 시점 메서드의 서명이나 반환 결과에는 `External<Value>`가 노출되지 않습니다.
*/
public let wrappedValue: Value

// 생성 메서드에서 받은 값을 원본 Factory 매개변수로 전달
/**
원본 Factory 매개변수에 전달할 외부 입력 값을 저장합니다.

- Parameter wrappedValue: 생성된 호출 시점 메서드가 원본 Factory에 전달할 값입니다.
- Note: 이 initializer는 Macro가 생성한 Factory 호출 경로에서 wrapper 값을 구성합니다.
*/
public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
Expand Down