The AST Schema
Every handler invocation receives one entity AST node, JSON-encoded. Call json.decode(input) to get a Lua table. This page describes the fields available on the most common node kinds. The full per-kind schema is auto-generated and available under AST Schemas.
What the engine adds before the handler sees the JSON
Section titled “What the engine adds before the handler sees the JSON”The engine takes the codex toJSON output and:
- Removes “heavy” fields the handler rarely needs:
memberFunctions,staticMemberFunctions,constructors,destructors,operators,nestedTypes,statements. Use the native introspection API (get_node,get_base_classes, etc.) to retrieve them on demand. - Adds
_namespaces(array of namespace strings, outermost first). - Adds
_registryId(an opaque integer; pass it toget_node,get_base_classes, etc.). - Adds
params(a copy ofrule.paramsfrom the config).
Struct / class node
Section titled “Struct / class node”{ "kind": "Struct", "identifier": { "name": "ConnectionOptions", "templateArguments": [] }, "_namespaces": ["network", "internal"], "memberVariables": [ /* see below */ ], "attributes": [ { "ns": "codegen", "name": "MarkdownDocs", "arguments": [] } ]}| Field | Type | Description |
|---|---|---|
kind | string | "Struct", "Class", or "Union" |
identifier.name | string | Unqualified type name |
identifier.templateArguments | array | Template parameter / argument nodes (if templated) |
_namespaces | string[] | Enclosing namespace stack, outermost first |
memberVariables | array | Member variable nodes (see below) |
attributes | array | C++ attributes on this declaration. Each entry has ns, name, arguments |
Building the qualified name
Section titled “Building the qualified name”local ns = table.concat(node._namespaces, "::")local qualified = ns ~= "" and (ns .. "::" .. node.identifier.name) or node.identifier.name-- result: "network::internal::ConnectionOptions"Enum node
Section titled “Enum node”enum declarations with a body have kind = "EnumeratorSpecifier" (the codex NodeKind::EnumSpecifier stringified):
{ "kind": "EnumeratorSpecifier", "identifier": { "name": "Color" }, "_namespaces": [], "isScoped": true, "isForwardDeclaration": false, "enumerators": [ { "name": "Red", "value": null }, { "name": "Green", "value": null }, { "name": "Blue", "value": "2" } ]}| Field | Type | Description |
|---|---|---|
isScoped | bool | true for enum class, false for unscoped enum |
isForwardDeclaration | bool | true for declarations without a body |
enumerators | array | Enumerator nodes |
enumerators[].name | string | Enumerator identifier |
enumerators[].value | string | null | Explicit value as source text, or null |
Forward declarations have kind = "Enumerator" (codex NodeKind::Enum). Anchor-triggered handlers also receive the appropriate kind via the same payload.
Member variable node
Section titled “Member variable node”{ "kind": "Variable", "identifier": { "name": "port" }, "typeSignature": { "identifier": { "name": "uint16_t", "templateArguments": [] }, "isConst": false, "isPointer": false, "isReference": false }}For groups of variables sharing a type (int x, y, z;), the kind is "VariableGroup" with a variables array. Always handle both:
for _, var in ipairs(node.memberVariables or {}) do if var.kind == "Variable" then process(var) elseif var.kind == "VariableGroup" then for _, v in ipairs(var.variables or {}) do process(v) end endendType signatures
Section titled “Type signatures”local function typeName(tSig) if not tSig or not tSig.identifier then return "?" end local name = tSig.identifier.name local args = tSig.identifier.templateArguments or {} -- e.g. name = "vector", args = [{ identifier = { name = "string" }, ... }] return nameendTemplate arguments are themselves type-signature-shaped — navigate them recursively.
Inspecting a header before writing a rule
Section titled “Inspecting a header before writing a rule”Use the ast-dump tool to dump any header in the codex JSON form:
ast-dump -m codex -i include/color.hppThe shape printed is the same the handler decodes, minus the _namespaces, _registryId, and params synthetic keys, and minus the heavy fields the engine strips.
- Structs/classes/unions carry
_namespaces(outermost-first),memberVariables, andattributes(note:attributes, the C++ term, notannotations). - Enum declarations with a body have
kind = "EnumeratorSpecifier"; forward declarations havekind = "Enumerator". - Member variables have a
typeSignature; templates recurse viaidentifier.templateArguments. - Heavy fields are stripped before the handler sees the JSON; recover them with the native introspection API.
- Use
ast-dump -m codex -i <file>to preview the exact JSON your handler will receive.