mirror of
https://github.com/logos-co/logos-cpp-sdk.git
synced 2026-08-31 01:31:10 +00:00
fix(lidl): carry method/event descriptions across the .lidl round-trip
Header-first universal modules go header -> .lidl -> cdylib backend. The impl-header parser captures /// and /** */ doc comments into method/event descriptions, but the .lidl serializer emitted only the signature, so the descriptions were dropped — introspection (lm methods / --json, getMethods) then showed no docs (regressing the wrap-external-lib + tutorial doctests). Serialize each method/event's description as a trailing `description "..."` clause (escaped for the string literal; the lexer already decodes \\ \" \n \t) and parse it back in parseMethodDef/parseEventDef. Module description now escaped too. Verified: /// docs survive header -> .lidl -> getMethods. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1f18c92096
commit
84280b89d9
@@ -158,6 +158,14 @@ private:
|
||||
if (!expect(LidlToken::RParen, "method parameters")) return false;
|
||||
if (!expect(LidlToken::Arrow, "method return type")) return false;
|
||||
if (!parseTypeExpr(md.returnType)) return false;
|
||||
// Optional trailing doc: `-> ret description "..."`. Carries the
|
||||
// method's doc comment across a .lidl round-trip so introspection
|
||||
// (lm / getMethods) still surfaces it.
|
||||
if (at(LidlToken::Description)) {
|
||||
++m_pos;
|
||||
if (!at(LidlToken::StringLit)) { error("Expected string after method 'description'"); return false; }
|
||||
md.description = current().text; ++m_pos;
|
||||
}
|
||||
// Restore the return-shape flags from the parsed type so a .lidl
|
||||
// round-trip carries the same semantics the impl-header parser sets
|
||||
// (it derives them from C++ types: StdLogosResult -> result,
|
||||
@@ -185,6 +193,11 @@ private:
|
||||
if (!expect(LidlToken::LParen, "event parameters")) return false;
|
||||
if (!parseParams(ed.params)) return false;
|
||||
if (!expect(LidlToken::RParen, "event parameters")) return false;
|
||||
if (at(LidlToken::Description)) {
|
||||
++m_pos;
|
||||
if (!at(LidlToken::StringLit)) { error("Expected string after event 'description'"); return false; }
|
||||
ed.description = current().text; ++m_pos;
|
||||
}
|
||||
mod.events.append(ed); return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
#include "lidl_serializer.h"
|
||||
#include <QTextStream>
|
||||
|
||||
// Escape a description for a "..."-delimited LIDL string literal (the lexer
|
||||
// decodes \\ \" \n \t). Keeps method/event docs intact across a .lidl
|
||||
// round-trip so introspection (lm / getMethods) still shows them.
|
||||
static QString lidlEscapeStr(QString in) {
|
||||
in.replace('\\', "\\\\");
|
||||
in.replace('"', "\\\"");
|
||||
in.replace('\n', "\\n");
|
||||
in.replace('\t', "\\t");
|
||||
return in;
|
||||
}
|
||||
|
||||
static QString serializeTypeExpr(const TypeExpr& te) {
|
||||
switch (te.kind) {
|
||||
case TypeExpr::Primitive: case TypeExpr::Named: return te.name;
|
||||
@@ -23,16 +34,16 @@ QString lidlSerialize(const ModuleDecl& module) {
|
||||
QTextStream s(&out);
|
||||
s << "module " << module.name << " {\n";
|
||||
if (!module.version.isEmpty()) s << " version \"" << module.version << "\"\n";
|
||||
if (!module.description.isEmpty()) s << " description \"" << module.description << "\"\n";
|
||||
if (!module.description.isEmpty()) s << " description \"" << lidlEscapeStr(module.description) << "\"\n";
|
||||
if (!module.category.isEmpty()) s << " category \"" << module.category << "\"\n";
|
||||
s << " depends [";
|
||||
for (int i = 0; i < module.depends.size(); ++i) { s << module.depends[i]; if (i + 1 < module.depends.size()) s << ", "; }
|
||||
s << "]\n";
|
||||
for (const TypeDecl& td : module.types) { s << "\n type " << td.name << " {\n"; for (const FieldDecl& fd : td.fields) { s << " "; if (fd.optional) s << "? "; s << fd.name << ": " << serializeTypeExpr(fd.type) << "\n"; } s << " }\n"; }
|
||||
if (!module.methods.isEmpty()) s << "\n";
|
||||
for (const MethodDecl& md : module.methods) { s << " method " << md.name << "("; serializeParams(s, md.params); s << ") -> " << serializeTypeExpr(md.returnType) << "\n"; }
|
||||
for (const MethodDecl& md : module.methods) { s << " method " << md.name << "("; serializeParams(s, md.params); s << ") -> " << serializeTypeExpr(md.returnType); if (!md.description.isEmpty()) s << " description \"" << lidlEscapeStr(md.description) << "\""; s << "\n"; }
|
||||
if (!module.events.isEmpty()) s << "\n";
|
||||
for (const EventDecl& ed : module.events) { s << " event " << ed.name << "("; serializeParams(s, ed.params); s << ")\n"; }
|
||||
for (const EventDecl& ed : module.events) { s << " event " << ed.name << "("; serializeParams(s, ed.params); s << ")"; if (!ed.description.isEmpty()) s << " description \"" << lidlEscapeStr(ed.description) << "\""; s << "\n"; }
|
||||
s << "}\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user