Skip to content

Commit 8dc5a0f

Browse files
authored
Document @generable macro visibility inside #Playground (#81)
1 parent 82374ed commit 8dc5a0f

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

Sources/AnyLanguageModel/Generable.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ public enum GeneratedContentConversionError: Error {
4242
// MARK: - Macros
4343

4444
/// Conforms a type to ``Generable`` protocol.
45+
///
46+
/// This macro synthesizes a memberwise initializer
47+
/// and an `init(_ generatedContent: GeneratedContent)` initializer
48+
/// for the annotated type.
49+
///
50+
/// - Note: The synthesized memberwise initializer isn't visible inside other macro bodies,
51+
/// such as `#Playground`.
52+
/// As a workaround, use the `init(_ generatedContent:)` initializer
53+
/// or define a factory method on the type.
4554
@attached(extension, conformances: Generable, names: named(init(_:)), named(generatedContent))
4655
@attached(member, names: arbitrary)
4756
public macro Generable(description: String? = nil) =

Tests/AnyLanguageModelTests/GenerableMacroTests.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,40 @@ struct GenerableMacroTests {
141141
#expect(args.asPartiallyGenerated().id == generationID)
142142
}
143143
}
144+
145+
// MARK: - #Playground Usage
146+
147+
// The `#Playground` macro doesn't see the memberwise initializer
148+
// that `@Generable` expands. This is a limitation of how macros compose:
149+
// one macro's expansion isn't visible within another macro's body.
150+
//
151+
// The following code demonstrates workarounds for this limitation.
152+
153+
#if canImport(Playgrounds)
154+
import Playgrounds
155+
156+
// Use the `GeneratedContent` initializer explicitly.
157+
#Playground {
158+
let content = GeneratedContent(properties: [
159+
"name": "Alice",
160+
"age": 30,
161+
])
162+
let _ = try TestArguments(content)
163+
}
164+
165+
// Define a factory method as an alternative to the memberwise initializer.
166+
extension TestArguments {
167+
static func create(name: String, age: Int) -> TestArguments {
168+
try! TestArguments(
169+
GeneratedContent(properties: [
170+
"name": name,
171+
"age": age,
172+
])
173+
)
174+
}
175+
}
176+
177+
#Playground {
178+
let _ = TestArguments.create(name: "Bob", age: 42)
179+
}
180+
#endif // canImport(Playgrounds)

0 commit comments

Comments
 (0)