diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b8d3fe..8ae8956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,14 @@ ## [未リリース] - +## [1.0.1] - 2026-01-01 + +### 変更 + +- **@Statable マクロ**: `public init()` の自動生成を削除 + - `@Observable` マクロとの相互作用問題を回避するため + - ユーザーが明示的に `public init() {}` を定義する必要あり + - 依存性注入などカスタム初期化が可能に ## [1.0.0] - 2025-01-01 @@ -43,5 +50,8 @@ - README.md(日本語・英語) - RELEASE_PROCESS.md -[未リリース]: https://github.com/no-problem-dev/swift-statable/compare/v1.0.0...HEAD +[未リリース]: https://github.com/no-problem-dev/swift-statable/compare/v1.0.1...HEAD +[1.0.1]: https://github.com/no-problem-dev/swift-statable/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/no-problem-dev/swift-statable/releases/tag/v1.0.0 + + diff --git a/Package.swift b/Package.swift index 1e12ffe..8333339 100644 --- a/Package.swift +++ b/Package.swift @@ -18,6 +18,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/swiftlang/swift-syntax.git", from: "600.0.0"), + .package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.4.0"), ], targets: [ // MARK: - Macro Implementation diff --git a/README.md b/README.md index fe4aac6..f205f31 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ import Statable @Statable(MetabolicProfile.self) @MainActor @Observable final class ProfileStore { - // マクロが value, state, isLoading などを自動生成 + public init() {} // カスタムcomputed properties var currentAge: Int { value?.age() ?? 0 } @@ -41,7 +41,7 @@ enum WorkoutOperation: String, CaseIterable, Sendable { @Statable([WorkoutActivity].self, operations: WorkoutOperation.self) @MainActor @Observable final class WorkoutStore { - // value, state, operations などが自動生成 + public init() {} var isRecording: Bool { operations.isActive(.recordStrength) || operations.isActive(.recordCardio) diff --git a/README_EN.md b/README_EN.md index eb94a63..a741449 100644 --- a/README_EN.md +++ b/README_EN.md @@ -27,9 +27,8 @@ import Statable @Statable(MetabolicProfile.self) @MainActor @Observable final class ProfileStore { - // Macro auto-generates value, state, isLoading, etc. + public init() {} - // Custom computed properties var currentAge: Int { value?.age() ?? 0 } } @@ -41,7 +40,7 @@ enum WorkoutOperation: String, CaseIterable, Sendable { @Statable([WorkoutActivity].self, operations: WorkoutOperation.self) @MainActor @Observable final class WorkoutStore { - // Auto-generates value, state, operations, etc. + public init() {} var isRecording: Bool { operations.isActive(.recordStrength) || operations.isActive(.recordCardio) diff --git a/Sources/Statable/Macros.swift b/Sources/Statable/Macros.swift index fb8cd1c..b4a3049 100644 --- a/Sources/Statable/Macros.swift +++ b/Sources/Statable/Macros.swift @@ -77,14 +77,14 @@ /// try await api.record(workout) /// } /// ``` -@attached(member, names: named(_asyncValue), named(_operations), named(init), named(value), named(state), named(isLoading), named(isIdle), named(isFailed), named(hasValue), named(error), named(operations), named(set), named(setError), named(startLoading), named(reset), named(load), named(loadIfNeeded), named(reload)) +@attached(member, names: named(_asyncValue), named(_operations), named(value), named(state), named(isLoading), named(isIdle), named(isFailed), named(hasValue), named(error), named(operations), named(set), named(setError), named(startLoading), named(reset), named(load), named(loadIfNeeded), named(reload)) @attached(extension, conformances: Statable, Sendable) public macro Statable( _ valueType: T.Type ) = #externalMacro(module: "StatableMacros", type: "StatableMacro") /// 操作トラッキング付きの@Statable -@attached(member, names: named(_asyncValue), named(_operations), named(init), named(value), named(state), named(isLoading), named(isIdle), named(isFailed), named(hasValue), named(error), named(operations), named(set), named(setError), named(startLoading), named(reset), named(load), named(loadIfNeeded), named(reload)) +@attached(member, names: named(_asyncValue), named(_operations), named(value), named(state), named(isLoading), named(isIdle), named(isFailed), named(hasValue), named(error), named(operations), named(set), named(setError), named(startLoading), named(reset), named(load), named(loadIfNeeded), named(reload)) @attached(extension, conformances: Statable, Sendable) public macro Statable( _ valueType: T.Type, diff --git a/Sources/StatableMacros/StatableMacro.swift b/Sources/StatableMacros/StatableMacro.swift index d7e6f3c..80da648 100644 --- a/Sources/StatableMacros/StatableMacro.swift +++ b/Sources/StatableMacros/StatableMacro.swift @@ -33,14 +33,6 @@ public struct StatableMacro: MemberMacro, ExtensionMacro { let valueType = args.valueType let operationType = args.operationType - // 既存のinitがあるか確認 - let hasExistingInit = declaration.memberBlock.members.contains { member in - if let initDecl = member.decl.as(InitializerDeclSyntax.self) { - return initDecl.signature.parameterClause.parameters.isEmpty - } - return false - } - var members: [DeclSyntax] = [] // 1. 内部 AsyncValue ストレージ @@ -61,17 +53,7 @@ public struct StatableMacro: MemberMacro, ExtensionMacro { ) } - // 3. init(既存がなければ生成) - if !hasExistingInit { - members.append( - """ - public init() { - } - """ - ) - } - - // 4. Computed Properties (パススルー) + // 3. Computed Properties (パススルー) members.append(contentsOf: [ """ /// 現在の値 @@ -117,7 +99,7 @@ public struct StatableMacro: MemberMacro, ExtensionMacro { """, ]) - // 5. Operations プロパティ(operationType指定時のみ) + // 4. Operations プロパティ(operationType指定時のみ) if let opType = operationType { members.append( """ @@ -129,7 +111,7 @@ public struct StatableMacro: MemberMacro, ExtensionMacro { ) } - // 6. Methods (パススルー) + // 5. Methods (パススルー) members.append(contentsOf: [ """ /// 値を設定(loaded状態に遷移) diff --git a/Tests/StatableMacrosTests/StatableMacroTests.swift b/Tests/StatableMacrosTests/StatableMacroTests.swift index e55c17b..cf0322c 100644 --- a/Tests/StatableMacrosTests/StatableMacroTests.swift +++ b/Tests/StatableMacrosTests/StatableMacroTests.swift @@ -26,9 +26,6 @@ final class StatableMacroTests: XCTestCase { @ObservationIgnored private let _asyncValue = AsyncValue() - public init() { - } - /// 現在の値 public var value: Profile? { _asyncValue.value @@ -107,22 +104,18 @@ final class StatableMacroTests: XCTestCase { ) } - func testStatableDoesNotGenerateInitIfExists() throws { + func testStatablePreservesUserDefinedInit() throws { assertMacroExpansion( """ @Statable(Profile.self) final class ProfileStore { - init() { - print("custom init") - } + public init() {} } """, expandedSource: """ final class ProfileStore { - init() { - print("custom init") - } + public init() {} @ObservationIgnored private let _asyncValue = AsyncValue() @@ -219,9 +212,6 @@ final class StatableMacroTests: XCTestCase { @ObservationIgnored private let _asyncValue = AsyncValue() - public init() { - } - /// 現在の値 public var value: Module.Profile? { _asyncValue.value @@ -317,9 +307,6 @@ final class StatableMacroTests: XCTestCase { @ObservationIgnored private let _operations = OperationTracker() - public init() { - } - /// 現在の値 public var value: [Activity]? { _asyncValue.value diff --git a/Tests/StatableMacrosTests/TrackMacroTests.swift b/Tests/StatableMacrosTests/TrackMacroTests.swift index c1bffad..c525e5c 100644 --- a/Tests/StatableMacrosTests/TrackMacroTests.swift +++ b/Tests/StatableMacrosTests/TrackMacroTests.swift @@ -24,6 +24,7 @@ final class TrackMacroTests: XCTestCase { } } + @ObservationIgnored private let _operations = OperationTracker() """, macros: trackMacros @@ -42,6 +43,7 @@ final class TrackMacroTests: XCTestCase { } } + @ObservationIgnored private let _ops = OperationTracker() """, macros: trackMacros