From aa3cccb27ab7ca1dbc5d126f1df7ad44d7899e7c Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Wed, 3 Jun 2026 16:08:36 -0300 Subject: [PATCH] demonstrate and validate method doc comments (wrapping-c-library) Add /// doc comments to the calc module's methods and assert they surface via `lm methods` (human + --json) and `logoscore module-info`. Corrects the stale lm output (provider-path introspection lists only impl methods, not eventResponse/initLogos). Regenerated the tutorial markdown. Co-Authored-By: Claude Opus 4.8 (1M context) --- outputs/tutorial-wrapping-c-library.md | 87 ++++++++++++++++---- tests/tutorial-wrapping-c-library.test.yaml | 89 +++++++++++++++++---- 2 files changed, 145 insertions(+), 31 deletions(-) diff --git a/outputs/tutorial-wrapping-c-library.md b/outputs/tutorial-wrapping-c-library.md index 041bd70..99f7a08 100644 --- a/outputs/tutorial-wrapping-c-library.md +++ b/outputs/tutorial-wrapping-c-library.md @@ -370,14 +370,29 @@ public: // ── Public API — every method here is callable over IPC ────────── // The generator maps C++ types onto the wire automatically: // int64_t ↔ int std::string ↔ QString bool ↔ bool + // + // A `///` doc comment directly above a method becomes that method's + // `description` in getMethods() — surfaced by `lm`, `logoscore + // module-info`, and Basecamp's Methods list. (Plain `//` comments + // like this block are ignored, so they never leak into the API.) + + /// Adds two integers and returns the sum. int64_t add(int64_t a, int64_t b); + + /// Multiplies two integers and returns the product. int64_t multiply(int64_t a, int64_t b); + + /// Computes the factorial n! of a non-negative integer. int64_t factorial(int64_t n); + + /// Returns the nth Fibonacci number (0-indexed). int64_t fibonacci(int64_t n); + + /// Returns the version string of the wrapped libcalc C library. std::string libVersion(); - // Fire-and-forget: looks up the version, then emits it as an event - // instead of returning it. Used by the QML tutorial (Part 2). + /// Looks up the library version and emits it as a `versionReady` + /// event instead of returning it. Used by the QML tutorial (Part 2). void libVersionNotify(); // ── Events ─────────────────────────────────────────────────────── @@ -409,6 +424,7 @@ logos_events: | `StdLogosResult` | `LogosResult` (from ``) — `{ success, value, error }` | - Use `int64_t` for integers (not `int`) — that's the type the parser recognizes. +- **Document methods with `///`.** A doc comment (`///` or `/** … */`) directly above a method becomes its `description` in the module's introspection, surfaced by `lm`, `logoscore module-info`, and Basecamp. Plain `//` comments are ignored, so only intentional docs are exposed — you'll see this in action in Step 5. - Events are declared in a `logos_events:` section. The token is recognized by the generator before preprocessing; under a normal compile it just expands to `public`. ### 3.5 `src/calc_module_impl.cpp` — Implementation @@ -585,48 +601,48 @@ Dependencies: (none) ./lm/bin/lm methods result/lib/calc_module_plugin.dylib ``` -Output: +Output — each method you declared, with its `///` doc comment shown on a +`Description:` line: ``` Plugin Methods: =============== -void eventResponse(QString eventName, QVariantList args) - Signature: eventResponse(QString,QVariantList) - Invokable: no - -void initLogos(LogosAPI* api) - Signature: initLogos(LogosAPI*) - Invokable: yes - int add(int a, int b) Signature: add(int,int) Invokable: yes + Description: Adds two integers and returns the sum. int multiply(int a, int b) Signature: multiply(int,int) Invokable: yes + Description: Multiplies two integers and returns the product. int factorial(int n) Signature: factorial(int) Invokable: yes + Description: Computes the factorial n! of a non-negative integer. int fibonacci(int n) Signature: fibonacci(int) Invokable: yes + Description: Returns the nth Fibonacci number (0-indexed). QString libVersion() Signature: libVersion() Invokable: yes + Description: Returns the version string of the wrapped libcalc C library. void libVersionNotify() Signature: libVersionNotify() Invokable: yes + Description: Looks up the library version and emits it as a `versionReady` event instead of returning it. Used by the QML tutorial (Part 2). ``` -Notice the signatures are **Qt-typed** (`int`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue at work: `lm` is inspecting the synthesized Qt plugin, not your impl class. Your `int64_t add(int64_t, int64_t)` shows up on the wire as `add(int,int)`. +Two things to notice: -The `eventResponse` signal and `initLogos` method are also part of the generated wrapper — you didn't write them. `initLogos` is how the host hands the module its `LogosAPI`; `eventResponse` is the channel your `versionReady` event travels over. Both come for free with `interface: universal`. +- **Signatures are Qt-typed** (`int`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue: `lm` reports the wire types the synthesized Qt plugin exposes, so `int64_t add(int64_t, int64_t)` shows up as `add(int,int)`. +- **Each `Description:` line is your `///` doc comment**, carried through the module's `getMethods()` introspection. Plain `//` comments (like the type-mapping note in the header) are deliberately ignored, so only intentional docs surface; an undocumented method simply omits the line. The same descriptions appear in `logoscore module-info` and Basecamp's Methods list. ### 5.4 JSON output @@ -643,6 +659,7 @@ For scripting and CI, use `--json`: ```json [ { + "description": "Adds two integers and returns the sum.", "isInvokable": true, "name": "add", "parameters": [ @@ -656,6 +673,9 @@ For scripting and CI, use `--json`: ] ``` +The `description` field is the method's `///` doc comment. Methods +without a doc comment omit it. + --- ## Step 6: Test with `logoscore` @@ -696,9 +716,9 @@ modules/calc_module/ └── variant # Platform variant identifier ``` -### 6.3 Call methods +### 6.3 Start the daemon and load the module -Start the daemon and call methods: +Start the daemon and load `calc_module`: ```bash ./logos/bin/logoscore -D -m ./modules & @@ -712,6 +732,43 @@ sleep 3 ./logos/bin/logoscore load-module calc_module ``` +### 6.4 Inspect methods and their docs + +`module-info` lists each method with its signature and the `///` description you wrote — the same docs `lm` showed, here straight from the module's `getPluginMethods` introspection: + +```bash +./logos/bin/logoscore module-info calc_module +``` + +``` +Name: calc_module +Version: v1.0.0 +Status: loaded +PID: 48213 +Uptime: 3s + +Methods: + add(a: int, b: int) -> int + Adds two integers and returns the sum. + multiply(a: int, b: int) -> int + Multiplies two integers and returns the product. + factorial(n: int) -> int + Computes the factorial n! of a non-negative integer. + fibonacci(n: int) -> int + Returns the nth Fibonacci number (0-indexed). + libVersion() -> QString + Returns the version string of the wrapped libcalc C library. + libVersionNotify() -> void + Looks up the library version and emits it as a `versionReady` event instead of returning it. Used by the QML tutorial (Part 2). +``` + +An undocumented method would still appear, just without the indented +description line. + +### 6.5 Call methods + +Now call them: + ```bash ./logos/bin/logoscore call calc_module add 3 5 ``` diff --git a/tests/tutorial-wrapping-c-library.test.yaml b/tests/tutorial-wrapping-c-library.test.yaml index 197dc4f..4e5bb79 100644 --- a/tests/tutorial-wrapping-c-library.test.yaml +++ b/tests/tutorial-wrapping-c-library.test.yaml @@ -369,14 +369,29 @@ sections: // ── Public API — every method here is callable over IPC ────────── // The generator maps C++ types onto the wire automatically: // int64_t ↔ int std::string ↔ QString bool ↔ bool + // + // A `///` doc comment directly above a method becomes that method's + // `description` in getMethods() — surfaced by `lm`, `logoscore + // module-info`, and Basecamp's Methods list. (Plain `//` comments + // like this block are ignored, so they never leak into the API.) + + /// Adds two integers and returns the sum. int64_t add(int64_t a, int64_t b); + + /// Multiplies two integers and returns the product. int64_t multiply(int64_t a, int64_t b); + + /// Computes the factorial n! of a non-negative integer. int64_t factorial(int64_t n); + + /// Returns the nth Fibonacci number (0-indexed). int64_t fibonacci(int64_t n); + + /// Returns the version string of the wrapped libcalc C library. std::string libVersion(); - // Fire-and-forget: looks up the version, then emits it as an event - // instead of returning it. Used by the QML tutorial (Part 2). + /// Looks up the library version and emits it as a `versionReady` + /// event instead of returning it. Used by the QML tutorial (Part 2). void libVersionNotify(); // ── Events ─────────────────────────────────────────────────────── @@ -407,6 +422,7 @@ sections: | `StdLogosResult` | `LogosResult` (from ``) — `{ success, value, error }` | - Use `int64_t` for integers (not `int`) — that's the type the parser recognizes. + - **Document methods with `///`.** A doc comment (`///` or `/** … */`) directly above a method becomes its `description` in the module's introspection, surfaced by `lm`, `logoscore module-info`, and Basecamp. Plain `//` comments are ignored, so only intentional docs are exposed — you'll see this in action in Step 5. - Events are declared in a `logos_events:` section. The token is recognized by the generator before preprocessing; under a normal compile it just expands to `public`. - title: "`src/calc_module_impl.cpp` — Implementation" @@ -570,49 +586,51 @@ sections: - "int factorial(int n)" - "int fibonacci(int n)" - "QString libVersion()" + - "Description: Adds two integers and returns the sum." + - "Description: Returns the version string of the wrapped libcalc C library." post_text: | - Output: + Output — each method you declared, with its `///` doc comment shown on a + `Description:` line: ``` Plugin Methods: =============== - void eventResponse(QString eventName, QVariantList args) - Signature: eventResponse(QString,QVariantList) - Invokable: no - - void initLogos(LogosAPI* api) - Signature: initLogos(LogosAPI*) - Invokable: yes - int add(int a, int b) Signature: add(int,int) Invokable: yes + Description: Adds two integers and returns the sum. int multiply(int a, int b) Signature: multiply(int,int) Invokable: yes + Description: Multiplies two integers and returns the product. int factorial(int n) Signature: factorial(int) Invokable: yes + Description: Computes the factorial n! of a non-negative integer. int fibonacci(int n) Signature: fibonacci(int) Invokable: yes + Description: Returns the nth Fibonacci number (0-indexed). QString libVersion() Signature: libVersion() Invokable: yes + Description: Returns the version string of the wrapped libcalc C library. void libVersionNotify() Signature: libVersionNotify() Invokable: yes + Description: Looks up the library version and emits it as a `versionReady` event instead of returning it. Used by the QML tutorial (Part 2). ``` - Notice the signatures are **Qt-typed** (`int`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue at work: `lm` is inspecting the synthesized Qt plugin, not your impl class. Your `int64_t add(int64_t, int64_t)` shows up on the wire as `add(int,int)`. + Two things to notice: - The `eventResponse` signal and `initLogos` method are also part of the generated wrapper — you didn't write them. `initLogos` is how the host hands the module its `LogosAPI`; `eventResponse` is the channel your `versionReady` event travels over. Both come for free with `interface: universal`. + - **Signatures are Qt-typed** (`int`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue: `lm` reports the wire types the synthesized Qt plugin exposes, so `int64_t add(int64_t, int64_t)` shows up as `add(int,int)`. + - **Each `Description:` line is your `///` doc comment**, carried through the module's `getMethods()` introspection. Plain `//` comments (like the type-mapping note in the header) are deliberately ignored, so only intentional docs surface; an undocumented method simply omits the line. The same descriptions appear in `logoscore module-info` and Basecamp's Methods list. - title: "JSON output" text: "For scripting and CI, use `--json`:" @@ -625,10 +643,12 @@ sections: ./lm/bin/lm methods result/lib/calc_module_plugin.dylib --json expect_contains: - '"name": "add"' + - '"description": "Adds two integers and returns the sum."' post_text: | ```json [ { + "description": "Adds two integers and returns the sum.", "isInvokable": true, "name": "add", "parameters": [ @@ -642,6 +662,9 @@ sections: ] ``` + The `description` field is the method's `///` doc comment. Methods + without a doc comment omit it. + # ── Step 6: Test with logoscore ───────────────────────────────────────────── - title: "Test with `logoscore`" step: true @@ -667,15 +690,49 @@ sections: └── variant # Platform variant identifier ``` - - title: "Call methods" - text: "Start the daemon and call methods:" + - title: "Start the daemon and load the module" + text: "Start the daemon and load `calc_module`:" run: "./logos/bin/logoscore -D -m ./modules &" - run: "sleep 3" - run: "./logos/bin/logoscore load-module calc_module" - - run: "./logos/bin/logoscore call calc_module add 3 5" + - title: "Inspect methods and their docs" + text: "`module-info` lists each method with its signature and the `///` description you wrote — the same docs `lm` showed, here straight from the module's `getPluginMethods` introspection:" + run: "./logos/bin/logoscore module-info calc_module" + expect_contains: + - "Adds two integers and returns the sum." + - "Returns the version string of the wrapped libcalc C library." + post_text: | + ``` + Name: calc_module + Version: v1.0.0 + Status: loaded + PID: 48213 + Uptime: 3s + + Methods: + add(a: int, b: int) -> int + Adds two integers and returns the sum. + multiply(a: int, b: int) -> int + Multiplies two integers and returns the product. + factorial(n: int) -> int + Computes the factorial n! of a non-negative integer. + fibonacci(n: int) -> int + Returns the nth Fibonacci number (0-indexed). + libVersion() -> QString + Returns the version string of the wrapped libcalc C library. + libVersionNotify() -> void + Looks up the library version and emits it as a `versionReady` event instead of returning it. Used by the QML tutorial (Part 2). + ``` + + An undocumented method would still appear, just without the indented + description line. + + - title: "Call methods" + text: "Now call them:" + run: "./logos/bin/logoscore call calc_module add 3 5" expect_contains: - '"result":8'