Skip to main content

KtFunSig

Struct KtFunSig 

Source
pub struct KtFunSig {
    pub name: String,
    pub vis: KtVis,
    pub annotations: Vec<String>,
    pub kdoc: Option<String>,
    pub generics: Vec<String>,
    pub receiver: Option<KtType>,
    pub params: Vec<KtParam>,
    pub ret: Option<KtType>,
}
Expand description

A function signature: everything a KtFun has except a body and modifiers.

This is what an abstract member is — a fun interface’s single method, an interface member, an abstract class member. Having no body field at all is what makes a bodied SAM method unrepresentable: a fun interface whose one method has a body has no abstract method, and does not compile.

Converts into KtFun (with KtBody::None) and so into KtDecl, for use as an interface member; KtFun::signature goes the other way.

Fields§

§name: String§vis: KtVis§annotations: Vec<String>§kdoc: Option<String>§generics: Vec<String>

Generic type-variable names: ["R"]fun <R> ….

§receiver: Option<KtType>

Extension receiver: Some(Foo)fun Foo.name(…). A separate field rather than part of name, so name stays a plain identifier that can be checked as one.

§params: Vec<KtParam>§ret: Option<KtType>

Implementations§

Source§

impl KtFunSig

Source

pub fn new(name: impl Into<String>) -> Self

Examples found in repository?
examples/showcase.rs (line 290)
164fn session_fragment() -> KtFile {
165    // `abstract class` with an `abstract` member (bodiless, and it says so),
166    // a `@Volatile` property, and an interface it implements.
167    let base = KtClass::class_with(KtClassModifier::Abstract, "NativeHandle")
168        .vis(KtVis::Public)
169        .kdoc("Owns a raw pointer into Rust and frees it exactly once.")
170        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
171        .implements(KtType::cls("AutoCloseable"))
172        .member(
173            KtProperty::var("ptr")
174                .ty(KtType::long())
175                .vis(KtVis::Internal)
176                .annotation("Volatile")
177                .kdoc("Zero once closed.")
178                .initializer("initialPtr"),
179        )
180        .member(
181            KtProperty::val("isClosed")
182                .ty(KtType::boolean())
183                .vis(KtVis::Public)
184                .accessors(KtCode::new().line("get() = ptr == 0L")),
185        )
186        .member(
187            KtFun::new("freePtr")
188                .vis(KtVis::Public)
189                .modifier("abstract")
190                .kdoc("Release the native allocation. Called once, under the lock.")
191                .param(KtParam::new("ptr", KtType::long())),
192        );
193
194    // `open class` extending the abstract base and constructing it.
195    let session = KtClass::class_with(KtClassModifier::Open, "Session")
196        .vis(KtVis::Public)
197        .annotation("Suppress(\"unused\")")
198        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
199        .extends(KtType::cls("NativeHandle"), Some("initialPtr"))
200        .implements(KtType::cls("io.example.api.Describable"))
201        .member(
202            KtFun::new("freePtr")
203                .vis(KtVis::Public)
204                .modifier("override")
205                .param(KtParam::new("ptr", KtType::long()))
206                .body(KtCode::new().line("JNINative.sessionFree(ptr)")),
207        )
208        .member(
209            KtFun::new("describe")
210                .vis(KtVis::Public)
211                .modifier("override")
212                .returns(KtType::string())
213                .expr_body(KtCode::new().line("\"Session(0x${ptr.toString(16)})\"")),
214        )
215        // A generic method whose body uses every `KtCode` block form.
216        .member(
217            KtFun::new("get")
218                .vis(KtVis::Public)
219                .generic("R")
220                .kdoc("Run a query, folding each reply into an accumulator.")
221                .param(KtParam::new("selector", KtType::string()))
222                .param(KtParam::new(
223                    "onReply",
224                    KtType::lambda(
225                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
226                        KtType::var_r(),
227                    ),
228                ))
229                .param(KtParam::new("timeoutMs", KtType::long()).default("10_000L"))
230                .returns(KtType::generic("List", [KtType::var_r()]))
231                .body(
232                    KtCode::new()
233                        .line("val acc = ArrayList<R>()")
234                        .line("val guard = Guard.acquire(this)")
235                        .import("io.example.internal.Guard")
236                        .try_finally(
237                            "",
238                            KtCode::new().blk("JNINative.sessionGet(ptr, selector, timeoutMs) { raw ->", |c| {
239                                c.line("acc.add(onReply(raw))")
240                            }),
241                            KtCode::new().line("guard.release()"),
242                        )
243                        .line("")
244                        // A long call that the renderer breaks by width at its
245                        // real nesting level.
246                        .wline("reportQueryOutcome(selector, timeoutMs, acc.size, acc.isNotEmpty(), \"query finished\", System.nanoTime())")
247                        .line("return acc"),
248                ),
249        )
250        // The interface's member extension, implemented.
251        .member(
252            KtFun::new("label")
253                .vis(KtVis::Public)
254                .modifier("override")
255                .receiver(KtType::cls("Sample"))
256                .returns(KtType::string())
257                .expr_body(KtCode::new().line("\"${keyExpr}@${describe()}\"")),
258        )
259        // A member extension of the class itself.
260        .member(
261            KtFun::new("toSample")
262                .vis(KtVis::Public)
263                .receiver(KtType::byte_array())
264                .returns(KtType::cls("Sample"))
265                .expr_body(KtCode::new().line("Sample(describe(), this)")),
266        )
267        // A nested class — its own scope, so its members may reuse names.
268        .member(
269            KtClass::class_("Config")
270                .vis(KtVis::Public)
271                .member(KtProperty::val("describe").initializer("\"config\"")),
272        )
273        .companion(
274            KtCompanion::new()
275                .vis(KtVis::Public)
276                .member(
277                    KtFun::new("open")
278                        .vis(KtVis::Public)
279                        .annotation("JvmStatic")
280                        .param(KtParam::new("config", KtType::string()).default("\"{}\""))
281                        .returns(KtType::cls("Session"))
282                        .expr_body(KtCode::new().line("Session(JNINative.sessionOpen(config))")),
283                ),
284        );
285
286    // A plain `interface`: bodiless members are abstract by position, and a
287    // `KtFunSig` is exactly that.
288    let describable = KtClass::interface_("Describable")
289        .vis(KtVis::Public)
290        .member(KtFunSig::new("describe").returns(KtType::string()))
291        // A member extension: abstract here, supplied by the implementor.
292        // `KtFunSig` carries a receiver too, so a signature does not quietly
293        // become a plain member.
294        .member(
295            KtFunSig::new("label")
296                .receiver(KtType::cls("Sample"))
297                .returns(KtType::string()),
298        );
299
300    // A `fun interface` (SAM) — its single method cannot carry a body.
301    let handler = KtFunInterface::new(
302        "ReplyHandler",
303        KtFunSig::new("onReply")
304            .param(KtParam::new("reply", KtType::cls("Reply")))
305            .returns(KtType::var_r()),
306    )
307    .vis(KtVis::Public)
308    .type_param("out R")
309    .kdoc("Invoked from the native thread for each reply.");
310
311    // Top-level extension functions. The receiver is a type, not part of the
312    // name, so it resolves through the import set and the name stays a plain
313    // identifier the validator can check as one.
314    let summary = KtFun::new("summary")
315        .vis(KtVis::Public)
316        .receiver(KtType::cls("Sample"))
317        .returns(KtType::string())
318        .expr_body(KtCode::new().line("\"$keyExpr (${payload.size} bytes)\""));
319
320    // Generics render before the receiver, which renders before the name.
321    let map_replies = KtFun::new("mapValues")
322        .vis(KtVis::Public)
323        .generic("R")
324        .receiver(KtType::generic("List", [KtType::cls("Reply")]))
325        .param(KtParam::new(
326            "transform",
327            KtType::lambda(
328                [("sample".to_string(), KtType::cls("Sample"))],
329                KtType::var_r(),
330            ),
331        ))
332        .returns(KtType::generic("List", [KtType::var_r()]))
333        .expr_body(
334            KtCode::new().line("filterIsInstance<Reply.Value>().map { transform(it.sample) }"),
335        );
336
337    // An extension on a *function type*. The receiver needs parentheses here
338    // or the `.` would bind to the return type instead.
339    let as_raw = KtFun::new("asRaw")
340        .vis(KtVis::Internal)
341        .receiver(KtType::lambda(
342            [("sample".to_string(), KtType::cls("Sample"))],
343            KtType::unit(),
344        ))
345        .returns(KtType::cls("io.example.api.internal.RawSink"))
346        // The proxy adapts a typed callback to the raw one the natives call,
347        // so it has to narrow `Reply` to the `Sample` the receiver takes.
348        .expr_body(
349            KtCode::new().line("RawSink { raw -> if (raw is Reply.Value) this(raw.sample) }"),
350        );
351
352    KtFile::new("io.example.api")
353        // FQNs named only from raw body text, which the model cannot see.
354        .imports(["io.example.api.internal.JNINative".to_string()])
355        .decl(base)
356        .decl(describable)
357        .decl(handler)
358        .decl(session)
359        .decl(summary)
360        .decl(map_replies)
361        .decl(as_raw)
362        .decl(KtDecl::TypeAlias {
363            vis: KtVis::Public,
364            name: "SampleList".to_string(),
365            target: KtType::generic("List", [KtType::cls("Sample")]),
366        })
367}
368
369/// The `external` surface — an object of natives, in its own subpackage.
370fn natives_fragment() -> KtFile {
371    let natives = KtClass::object_("JNINative")
372        .vis(KtVis::Internal)
373        .kdoc("One-to-one with the exported Rust symbols.")
374        .member(
375            KtFun::new("sessionOpen")
376                .vis(KtVis::Internal)
377                .param(KtParam::new("config", KtType::string()))
378                .returns(KtType::long())
379                .external(),
380        )
381        .member(
382            KtFun::new("sessionFree")
383                .vis(KtVis::Internal)
384                .param(KtParam::new("ptr", KtType::long()))
385                .external(),
386        )
387        .member(
388            KtFun::new("sessionGet")
389                .vis(KtVis::Internal)
390                .param(KtParam::new("ptr", KtType::long()))
391                .param(KtParam::new("selector", KtType::string()))
392                .param(KtParam::new("timeoutMs", KtType::long()))
393                .param(KtParam::new(
394                    "sink",
395                    KtType::lambda(
396                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
397                        KtType::unit(),
398                    ),
399                ))
400                .external(),
401        );
402
403    // A pre-rendered block, for text the model does not describe. Its name is
404    // a merge identity, never emitted.
405    let loader = KtDecl::Raw {
406        name: "__loadNative".to_string(),
407        code: KtCode::raw_reindent(
408            "internal val __loaded: Boolean = run {\n\
409             System.loadLibrary(\"example_jni\")\n\
410             true\n\
411             }",
412        ),
413    };
414
415    let raw_sink = KtFunInterface::new(
416        "RawSink",
417        KtFunSig::new("accept").param(KtParam::new("reply", KtType::cls("io.example.api.Reply"))),
418    )
419    .vis(KtVis::Internal);
420
421    KtFile::new("io.example.api.internal")
422        .decl(raw_sink)
423        .decl(natives)
424        .decl(loader)
425        // An FQN referenced only from raw text the model cannot see.
426        .import("io.example.api.Reply")
427}
Source

pub fn vis(self, v: KtVis) -> Self

Source

pub fn receiver(self, ty: KtType) -> Self

Make this an extension function on ty: fun <R> Foo<R>.name(…).

Examples found in repository?
examples/showcase.rs (line 296)
164fn session_fragment() -> KtFile {
165    // `abstract class` with an `abstract` member (bodiless, and it says so),
166    // a `@Volatile` property, and an interface it implements.
167    let base = KtClass::class_with(KtClassModifier::Abstract, "NativeHandle")
168        .vis(KtVis::Public)
169        .kdoc("Owns a raw pointer into Rust and frees it exactly once.")
170        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
171        .implements(KtType::cls("AutoCloseable"))
172        .member(
173            KtProperty::var("ptr")
174                .ty(KtType::long())
175                .vis(KtVis::Internal)
176                .annotation("Volatile")
177                .kdoc("Zero once closed.")
178                .initializer("initialPtr"),
179        )
180        .member(
181            KtProperty::val("isClosed")
182                .ty(KtType::boolean())
183                .vis(KtVis::Public)
184                .accessors(KtCode::new().line("get() = ptr == 0L")),
185        )
186        .member(
187            KtFun::new("freePtr")
188                .vis(KtVis::Public)
189                .modifier("abstract")
190                .kdoc("Release the native allocation. Called once, under the lock.")
191                .param(KtParam::new("ptr", KtType::long())),
192        );
193
194    // `open class` extending the abstract base and constructing it.
195    let session = KtClass::class_with(KtClassModifier::Open, "Session")
196        .vis(KtVis::Public)
197        .annotation("Suppress(\"unused\")")
198        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
199        .extends(KtType::cls("NativeHandle"), Some("initialPtr"))
200        .implements(KtType::cls("io.example.api.Describable"))
201        .member(
202            KtFun::new("freePtr")
203                .vis(KtVis::Public)
204                .modifier("override")
205                .param(KtParam::new("ptr", KtType::long()))
206                .body(KtCode::new().line("JNINative.sessionFree(ptr)")),
207        )
208        .member(
209            KtFun::new("describe")
210                .vis(KtVis::Public)
211                .modifier("override")
212                .returns(KtType::string())
213                .expr_body(KtCode::new().line("\"Session(0x${ptr.toString(16)})\"")),
214        )
215        // A generic method whose body uses every `KtCode` block form.
216        .member(
217            KtFun::new("get")
218                .vis(KtVis::Public)
219                .generic("R")
220                .kdoc("Run a query, folding each reply into an accumulator.")
221                .param(KtParam::new("selector", KtType::string()))
222                .param(KtParam::new(
223                    "onReply",
224                    KtType::lambda(
225                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
226                        KtType::var_r(),
227                    ),
228                ))
229                .param(KtParam::new("timeoutMs", KtType::long()).default("10_000L"))
230                .returns(KtType::generic("List", [KtType::var_r()]))
231                .body(
232                    KtCode::new()
233                        .line("val acc = ArrayList<R>()")
234                        .line("val guard = Guard.acquire(this)")
235                        .import("io.example.internal.Guard")
236                        .try_finally(
237                            "",
238                            KtCode::new().blk("JNINative.sessionGet(ptr, selector, timeoutMs) { raw ->", |c| {
239                                c.line("acc.add(onReply(raw))")
240                            }),
241                            KtCode::new().line("guard.release()"),
242                        )
243                        .line("")
244                        // A long call that the renderer breaks by width at its
245                        // real nesting level.
246                        .wline("reportQueryOutcome(selector, timeoutMs, acc.size, acc.isNotEmpty(), \"query finished\", System.nanoTime())")
247                        .line("return acc"),
248                ),
249        )
250        // The interface's member extension, implemented.
251        .member(
252            KtFun::new("label")
253                .vis(KtVis::Public)
254                .modifier("override")
255                .receiver(KtType::cls("Sample"))
256                .returns(KtType::string())
257                .expr_body(KtCode::new().line("\"${keyExpr}@${describe()}\"")),
258        )
259        // A member extension of the class itself.
260        .member(
261            KtFun::new("toSample")
262                .vis(KtVis::Public)
263                .receiver(KtType::byte_array())
264                .returns(KtType::cls("Sample"))
265                .expr_body(KtCode::new().line("Sample(describe(), this)")),
266        )
267        // A nested class — its own scope, so its members may reuse names.
268        .member(
269            KtClass::class_("Config")
270                .vis(KtVis::Public)
271                .member(KtProperty::val("describe").initializer("\"config\"")),
272        )
273        .companion(
274            KtCompanion::new()
275                .vis(KtVis::Public)
276                .member(
277                    KtFun::new("open")
278                        .vis(KtVis::Public)
279                        .annotation("JvmStatic")
280                        .param(KtParam::new("config", KtType::string()).default("\"{}\""))
281                        .returns(KtType::cls("Session"))
282                        .expr_body(KtCode::new().line("Session(JNINative.sessionOpen(config))")),
283                ),
284        );
285
286    // A plain `interface`: bodiless members are abstract by position, and a
287    // `KtFunSig` is exactly that.
288    let describable = KtClass::interface_("Describable")
289        .vis(KtVis::Public)
290        .member(KtFunSig::new("describe").returns(KtType::string()))
291        // A member extension: abstract here, supplied by the implementor.
292        // `KtFunSig` carries a receiver too, so a signature does not quietly
293        // become a plain member.
294        .member(
295            KtFunSig::new("label")
296                .receiver(KtType::cls("Sample"))
297                .returns(KtType::string()),
298        );
299
300    // A `fun interface` (SAM) — its single method cannot carry a body.
301    let handler = KtFunInterface::new(
302        "ReplyHandler",
303        KtFunSig::new("onReply")
304            .param(KtParam::new("reply", KtType::cls("Reply")))
305            .returns(KtType::var_r()),
306    )
307    .vis(KtVis::Public)
308    .type_param("out R")
309    .kdoc("Invoked from the native thread for each reply.");
310
311    // Top-level extension functions. The receiver is a type, not part of the
312    // name, so it resolves through the import set and the name stays a plain
313    // identifier the validator can check as one.
314    let summary = KtFun::new("summary")
315        .vis(KtVis::Public)
316        .receiver(KtType::cls("Sample"))
317        .returns(KtType::string())
318        .expr_body(KtCode::new().line("\"$keyExpr (${payload.size} bytes)\""));
319
320    // Generics render before the receiver, which renders before the name.
321    let map_replies = KtFun::new("mapValues")
322        .vis(KtVis::Public)
323        .generic("R")
324        .receiver(KtType::generic("List", [KtType::cls("Reply")]))
325        .param(KtParam::new(
326            "transform",
327            KtType::lambda(
328                [("sample".to_string(), KtType::cls("Sample"))],
329                KtType::var_r(),
330            ),
331        ))
332        .returns(KtType::generic("List", [KtType::var_r()]))
333        .expr_body(
334            KtCode::new().line("filterIsInstance<Reply.Value>().map { transform(it.sample) }"),
335        );
336
337    // An extension on a *function type*. The receiver needs parentheses here
338    // or the `.` would bind to the return type instead.
339    let as_raw = KtFun::new("asRaw")
340        .vis(KtVis::Internal)
341        .receiver(KtType::lambda(
342            [("sample".to_string(), KtType::cls("Sample"))],
343            KtType::unit(),
344        ))
345        .returns(KtType::cls("io.example.api.internal.RawSink"))
346        // The proxy adapts a typed callback to the raw one the natives call,
347        // so it has to narrow `Reply` to the `Sample` the receiver takes.
348        .expr_body(
349            KtCode::new().line("RawSink { raw -> if (raw is Reply.Value) this(raw.sample) }"),
350        );
351
352    KtFile::new("io.example.api")
353        // FQNs named only from raw body text, which the model cannot see.
354        .imports(["io.example.api.internal.JNINative".to_string()])
355        .decl(base)
356        .decl(describable)
357        .decl(handler)
358        .decl(session)
359        .decl(summary)
360        .decl(map_replies)
361        .decl(as_raw)
362        .decl(KtDecl::TypeAlias {
363            vis: KtVis::Public,
364            name: "SampleList".to_string(),
365            target: KtType::generic("List", [KtType::cls("Sample")]),
366        })
367}
Source

pub fn annotation(self, a: impl Into<String>) -> Self

Source

pub fn kdoc(self, d: impl Into<String>) -> Self

Source

pub fn generic(self, g: impl Into<String>) -> Self

Source

pub fn param(self, p: KtParam) -> Self

Examples found in repository?
examples/showcase.rs (line 304)
164fn session_fragment() -> KtFile {
165    // `abstract class` with an `abstract` member (bodiless, and it says so),
166    // a `@Volatile` property, and an interface it implements.
167    let base = KtClass::class_with(KtClassModifier::Abstract, "NativeHandle")
168        .vis(KtVis::Public)
169        .kdoc("Owns a raw pointer into Rust and frees it exactly once.")
170        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
171        .implements(KtType::cls("AutoCloseable"))
172        .member(
173            KtProperty::var("ptr")
174                .ty(KtType::long())
175                .vis(KtVis::Internal)
176                .annotation("Volatile")
177                .kdoc("Zero once closed.")
178                .initializer("initialPtr"),
179        )
180        .member(
181            KtProperty::val("isClosed")
182                .ty(KtType::boolean())
183                .vis(KtVis::Public)
184                .accessors(KtCode::new().line("get() = ptr == 0L")),
185        )
186        .member(
187            KtFun::new("freePtr")
188                .vis(KtVis::Public)
189                .modifier("abstract")
190                .kdoc("Release the native allocation. Called once, under the lock.")
191                .param(KtParam::new("ptr", KtType::long())),
192        );
193
194    // `open class` extending the abstract base and constructing it.
195    let session = KtClass::class_with(KtClassModifier::Open, "Session")
196        .vis(KtVis::Public)
197        .annotation("Suppress(\"unused\")")
198        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
199        .extends(KtType::cls("NativeHandle"), Some("initialPtr"))
200        .implements(KtType::cls("io.example.api.Describable"))
201        .member(
202            KtFun::new("freePtr")
203                .vis(KtVis::Public)
204                .modifier("override")
205                .param(KtParam::new("ptr", KtType::long()))
206                .body(KtCode::new().line("JNINative.sessionFree(ptr)")),
207        )
208        .member(
209            KtFun::new("describe")
210                .vis(KtVis::Public)
211                .modifier("override")
212                .returns(KtType::string())
213                .expr_body(KtCode::new().line("\"Session(0x${ptr.toString(16)})\"")),
214        )
215        // A generic method whose body uses every `KtCode` block form.
216        .member(
217            KtFun::new("get")
218                .vis(KtVis::Public)
219                .generic("R")
220                .kdoc("Run a query, folding each reply into an accumulator.")
221                .param(KtParam::new("selector", KtType::string()))
222                .param(KtParam::new(
223                    "onReply",
224                    KtType::lambda(
225                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
226                        KtType::var_r(),
227                    ),
228                ))
229                .param(KtParam::new("timeoutMs", KtType::long()).default("10_000L"))
230                .returns(KtType::generic("List", [KtType::var_r()]))
231                .body(
232                    KtCode::new()
233                        .line("val acc = ArrayList<R>()")
234                        .line("val guard = Guard.acquire(this)")
235                        .import("io.example.internal.Guard")
236                        .try_finally(
237                            "",
238                            KtCode::new().blk("JNINative.sessionGet(ptr, selector, timeoutMs) { raw ->", |c| {
239                                c.line("acc.add(onReply(raw))")
240                            }),
241                            KtCode::new().line("guard.release()"),
242                        )
243                        .line("")
244                        // A long call that the renderer breaks by width at its
245                        // real nesting level.
246                        .wline("reportQueryOutcome(selector, timeoutMs, acc.size, acc.isNotEmpty(), \"query finished\", System.nanoTime())")
247                        .line("return acc"),
248                ),
249        )
250        // The interface's member extension, implemented.
251        .member(
252            KtFun::new("label")
253                .vis(KtVis::Public)
254                .modifier("override")
255                .receiver(KtType::cls("Sample"))
256                .returns(KtType::string())
257                .expr_body(KtCode::new().line("\"${keyExpr}@${describe()}\"")),
258        )
259        // A member extension of the class itself.
260        .member(
261            KtFun::new("toSample")
262                .vis(KtVis::Public)
263                .receiver(KtType::byte_array())
264                .returns(KtType::cls("Sample"))
265                .expr_body(KtCode::new().line("Sample(describe(), this)")),
266        )
267        // A nested class — its own scope, so its members may reuse names.
268        .member(
269            KtClass::class_("Config")
270                .vis(KtVis::Public)
271                .member(KtProperty::val("describe").initializer("\"config\"")),
272        )
273        .companion(
274            KtCompanion::new()
275                .vis(KtVis::Public)
276                .member(
277                    KtFun::new("open")
278                        .vis(KtVis::Public)
279                        .annotation("JvmStatic")
280                        .param(KtParam::new("config", KtType::string()).default("\"{}\""))
281                        .returns(KtType::cls("Session"))
282                        .expr_body(KtCode::new().line("Session(JNINative.sessionOpen(config))")),
283                ),
284        );
285
286    // A plain `interface`: bodiless members are abstract by position, and a
287    // `KtFunSig` is exactly that.
288    let describable = KtClass::interface_("Describable")
289        .vis(KtVis::Public)
290        .member(KtFunSig::new("describe").returns(KtType::string()))
291        // A member extension: abstract here, supplied by the implementor.
292        // `KtFunSig` carries a receiver too, so a signature does not quietly
293        // become a plain member.
294        .member(
295            KtFunSig::new("label")
296                .receiver(KtType::cls("Sample"))
297                .returns(KtType::string()),
298        );
299
300    // A `fun interface` (SAM) — its single method cannot carry a body.
301    let handler = KtFunInterface::new(
302        "ReplyHandler",
303        KtFunSig::new("onReply")
304            .param(KtParam::new("reply", KtType::cls("Reply")))
305            .returns(KtType::var_r()),
306    )
307    .vis(KtVis::Public)
308    .type_param("out R")
309    .kdoc("Invoked from the native thread for each reply.");
310
311    // Top-level extension functions. The receiver is a type, not part of the
312    // name, so it resolves through the import set and the name stays a plain
313    // identifier the validator can check as one.
314    let summary = KtFun::new("summary")
315        .vis(KtVis::Public)
316        .receiver(KtType::cls("Sample"))
317        .returns(KtType::string())
318        .expr_body(KtCode::new().line("\"$keyExpr (${payload.size} bytes)\""));
319
320    // Generics render before the receiver, which renders before the name.
321    let map_replies = KtFun::new("mapValues")
322        .vis(KtVis::Public)
323        .generic("R")
324        .receiver(KtType::generic("List", [KtType::cls("Reply")]))
325        .param(KtParam::new(
326            "transform",
327            KtType::lambda(
328                [("sample".to_string(), KtType::cls("Sample"))],
329                KtType::var_r(),
330            ),
331        ))
332        .returns(KtType::generic("List", [KtType::var_r()]))
333        .expr_body(
334            KtCode::new().line("filterIsInstance<Reply.Value>().map { transform(it.sample) }"),
335        );
336
337    // An extension on a *function type*. The receiver needs parentheses here
338    // or the `.` would bind to the return type instead.
339    let as_raw = KtFun::new("asRaw")
340        .vis(KtVis::Internal)
341        .receiver(KtType::lambda(
342            [("sample".to_string(), KtType::cls("Sample"))],
343            KtType::unit(),
344        ))
345        .returns(KtType::cls("io.example.api.internal.RawSink"))
346        // The proxy adapts a typed callback to the raw one the natives call,
347        // so it has to narrow `Reply` to the `Sample` the receiver takes.
348        .expr_body(
349            KtCode::new().line("RawSink { raw -> if (raw is Reply.Value) this(raw.sample) }"),
350        );
351
352    KtFile::new("io.example.api")
353        // FQNs named only from raw body text, which the model cannot see.
354        .imports(["io.example.api.internal.JNINative".to_string()])
355        .decl(base)
356        .decl(describable)
357        .decl(handler)
358        .decl(session)
359        .decl(summary)
360        .decl(map_replies)
361        .decl(as_raw)
362        .decl(KtDecl::TypeAlias {
363            vis: KtVis::Public,
364            name: "SampleList".to_string(),
365            target: KtType::generic("List", [KtType::cls("Sample")]),
366        })
367}
368
369/// The `external` surface — an object of natives, in its own subpackage.
370fn natives_fragment() -> KtFile {
371    let natives = KtClass::object_("JNINative")
372        .vis(KtVis::Internal)
373        .kdoc("One-to-one with the exported Rust symbols.")
374        .member(
375            KtFun::new("sessionOpen")
376                .vis(KtVis::Internal)
377                .param(KtParam::new("config", KtType::string()))
378                .returns(KtType::long())
379                .external(),
380        )
381        .member(
382            KtFun::new("sessionFree")
383                .vis(KtVis::Internal)
384                .param(KtParam::new("ptr", KtType::long()))
385                .external(),
386        )
387        .member(
388            KtFun::new("sessionGet")
389                .vis(KtVis::Internal)
390                .param(KtParam::new("ptr", KtType::long()))
391                .param(KtParam::new("selector", KtType::string()))
392                .param(KtParam::new("timeoutMs", KtType::long()))
393                .param(KtParam::new(
394                    "sink",
395                    KtType::lambda(
396                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
397                        KtType::unit(),
398                    ),
399                ))
400                .external(),
401        );
402
403    // A pre-rendered block, for text the model does not describe. Its name is
404    // a merge identity, never emitted.
405    let loader = KtDecl::Raw {
406        name: "__loadNative".to_string(),
407        code: KtCode::raw_reindent(
408            "internal val __loaded: Boolean = run {\n\
409             System.loadLibrary(\"example_jni\")\n\
410             true\n\
411             }",
412        ),
413    };
414
415    let raw_sink = KtFunInterface::new(
416        "RawSink",
417        KtFunSig::new("accept").param(KtParam::new("reply", KtType::cls("io.example.api.Reply"))),
418    )
419    .vis(KtVis::Internal);
420
421    KtFile::new("io.example.api.internal")
422        .decl(raw_sink)
423        .decl(natives)
424        .decl(loader)
425        // An FQN referenced only from raw text the model cannot see.
426        .import("io.example.api.Reply")
427}
Source

pub fn returns(self, ty: KtType) -> Self

Examples found in repository?
examples/showcase.rs (line 290)
164fn session_fragment() -> KtFile {
165    // `abstract class` with an `abstract` member (bodiless, and it says so),
166    // a `@Volatile` property, and an interface it implements.
167    let base = KtClass::class_with(KtClassModifier::Abstract, "NativeHandle")
168        .vis(KtVis::Public)
169        .kdoc("Owns a raw pointer into Rust and frees it exactly once.")
170        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
171        .implements(KtType::cls("AutoCloseable"))
172        .member(
173            KtProperty::var("ptr")
174                .ty(KtType::long())
175                .vis(KtVis::Internal)
176                .annotation("Volatile")
177                .kdoc("Zero once closed.")
178                .initializer("initialPtr"),
179        )
180        .member(
181            KtProperty::val("isClosed")
182                .ty(KtType::boolean())
183                .vis(KtVis::Public)
184                .accessors(KtCode::new().line("get() = ptr == 0L")),
185        )
186        .member(
187            KtFun::new("freePtr")
188                .vis(KtVis::Public)
189                .modifier("abstract")
190                .kdoc("Release the native allocation. Called once, under the lock.")
191                .param(KtParam::new("ptr", KtType::long())),
192        );
193
194    // `open class` extending the abstract base and constructing it.
195    let session = KtClass::class_with(KtClassModifier::Open, "Session")
196        .vis(KtVis::Public)
197        .annotation("Suppress(\"unused\")")
198        .ctor_param(KtCtorParam::new("initialPtr", KtType::long()))
199        .extends(KtType::cls("NativeHandle"), Some("initialPtr"))
200        .implements(KtType::cls("io.example.api.Describable"))
201        .member(
202            KtFun::new("freePtr")
203                .vis(KtVis::Public)
204                .modifier("override")
205                .param(KtParam::new("ptr", KtType::long()))
206                .body(KtCode::new().line("JNINative.sessionFree(ptr)")),
207        )
208        .member(
209            KtFun::new("describe")
210                .vis(KtVis::Public)
211                .modifier("override")
212                .returns(KtType::string())
213                .expr_body(KtCode::new().line("\"Session(0x${ptr.toString(16)})\"")),
214        )
215        // A generic method whose body uses every `KtCode` block form.
216        .member(
217            KtFun::new("get")
218                .vis(KtVis::Public)
219                .generic("R")
220                .kdoc("Run a query, folding each reply into an accumulator.")
221                .param(KtParam::new("selector", KtType::string()))
222                .param(KtParam::new(
223                    "onReply",
224                    KtType::lambda(
225                        [("reply".to_string(), KtType::cls("io.example.api.Reply"))],
226                        KtType::var_r(),
227                    ),
228                ))
229                .param(KtParam::new("timeoutMs", KtType::long()).default("10_000L"))
230                .returns(KtType::generic("List", [KtType::var_r()]))
231                .body(
232                    KtCode::new()
233                        .line("val acc = ArrayList<R>()")
234                        .line("val guard = Guard.acquire(this)")
235                        .import("io.example.internal.Guard")
236                        .try_finally(
237                            "",
238                            KtCode::new().blk("JNINative.sessionGet(ptr, selector, timeoutMs) { raw ->", |c| {
239                                c.line("acc.add(onReply(raw))")
240                            }),
241                            KtCode::new().line("guard.release()"),
242                        )
243                        .line("")
244                        // A long call that the renderer breaks by width at its
245                        // real nesting level.
246                        .wline("reportQueryOutcome(selector, timeoutMs, acc.size, acc.isNotEmpty(), \"query finished\", System.nanoTime())")
247                        .line("return acc"),
248                ),
249        )
250        // The interface's member extension, implemented.
251        .member(
252            KtFun::new("label")
253                .vis(KtVis::Public)
254                .modifier("override")
255                .receiver(KtType::cls("Sample"))
256                .returns(KtType::string())
257                .expr_body(KtCode::new().line("\"${keyExpr}@${describe()}\"")),
258        )
259        // A member extension of the class itself.
260        .member(
261            KtFun::new("toSample")
262                .vis(KtVis::Public)
263                .receiver(KtType::byte_array())
264                .returns(KtType::cls("Sample"))
265                .expr_body(KtCode::new().line("Sample(describe(), this)")),
266        )
267        // A nested class — its own scope, so its members may reuse names.
268        .member(
269            KtClass::class_("Config")
270                .vis(KtVis::Public)
271                .member(KtProperty::val("describe").initializer("\"config\"")),
272        )
273        .companion(
274            KtCompanion::new()
275                .vis(KtVis::Public)
276                .member(
277                    KtFun::new("open")
278                        .vis(KtVis::Public)
279                        .annotation("JvmStatic")
280                        .param(KtParam::new("config", KtType::string()).default("\"{}\""))
281                        .returns(KtType::cls("Session"))
282                        .expr_body(KtCode::new().line("Session(JNINative.sessionOpen(config))")),
283                ),
284        );
285
286    // A plain `interface`: bodiless members are abstract by position, and a
287    // `KtFunSig` is exactly that.
288    let describable = KtClass::interface_("Describable")
289        .vis(KtVis::Public)
290        .member(KtFunSig::new("describe").returns(KtType::string()))
291        // A member extension: abstract here, supplied by the implementor.
292        // `KtFunSig` carries a receiver too, so a signature does not quietly
293        // become a plain member.
294        .member(
295            KtFunSig::new("label")
296                .receiver(KtType::cls("Sample"))
297                .returns(KtType::string()),
298        );
299
300    // A `fun interface` (SAM) — its single method cannot carry a body.
301    let handler = KtFunInterface::new(
302        "ReplyHandler",
303        KtFunSig::new("onReply")
304            .param(KtParam::new("reply", KtType::cls("Reply")))
305            .returns(KtType::var_r()),
306    )
307    .vis(KtVis::Public)
308    .type_param("out R")
309    .kdoc("Invoked from the native thread for each reply.");
310
311    // Top-level extension functions. The receiver is a type, not part of the
312    // name, so it resolves through the import set and the name stays a plain
313    // identifier the validator can check as one.
314    let summary = KtFun::new("summary")
315        .vis(KtVis::Public)
316        .receiver(KtType::cls("Sample"))
317        .returns(KtType::string())
318        .expr_body(KtCode::new().line("\"$keyExpr (${payload.size} bytes)\""));
319
320    // Generics render before the receiver, which renders before the name.
321    let map_replies = KtFun::new("mapValues")
322        .vis(KtVis::Public)
323        .generic("R")
324        .receiver(KtType::generic("List", [KtType::cls("Reply")]))
325        .param(KtParam::new(
326            "transform",
327            KtType::lambda(
328                [("sample".to_string(), KtType::cls("Sample"))],
329                KtType::var_r(),
330            ),
331        ))
332        .returns(KtType::generic("List", [KtType::var_r()]))
333        .expr_body(
334            KtCode::new().line("filterIsInstance<Reply.Value>().map { transform(it.sample) }"),
335        );
336
337    // An extension on a *function type*. The receiver needs parentheses here
338    // or the `.` would bind to the return type instead.
339    let as_raw = KtFun::new("asRaw")
340        .vis(KtVis::Internal)
341        .receiver(KtType::lambda(
342            [("sample".to_string(), KtType::cls("Sample"))],
343            KtType::unit(),
344        ))
345        .returns(KtType::cls("io.example.api.internal.RawSink"))
346        // The proxy adapts a typed callback to the raw one the natives call,
347        // so it has to narrow `Reply` to the `Sample` the receiver takes.
348        .expr_body(
349            KtCode::new().line("RawSink { raw -> if (raw is Reply.Value) this(raw.sample) }"),
350        );
351
352    KtFile::new("io.example.api")
353        // FQNs named only from raw body text, which the model cannot see.
354        .imports(["io.example.api.internal.JNINative".to_string()])
355        .decl(base)
356        .decl(describable)
357        .decl(handler)
358        .decl(session)
359        .decl(summary)
360        .decl(map_replies)
361        .decl(as_raw)
362        .decl(KtDecl::TypeAlias {
363            vis: KtVis::Public,
364            name: "SampleList".to_string(),
365            target: KtType::generic("List", [KtType::cls("Sample")]),
366        })
367}

Trait Implementations§

Source§

impl Clone for KtFunSig

Source§

fn clone(&self) -> KtFunSig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for KtFunSig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<KtFunSig> for KtFun

Source§

fn from(s: KtFunSig) -> Self

A signature as a body-less function — an abstract member.

Source§

impl From<KtFunSig> for KtDecl

Source§

fn from(s: KtFunSig) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.