ek9_query_traits
Answers first: status, implementedByAll (when asked), traitCount, traitNames - complete for the workspace or the filters given - then traits[] {name, module, file, line, traitOf, implementedBy, implementedByCount, methods, methodCount}.
When to use it
'Which traits exist, and is there a contract I can adopt' is one call - no arguments for the workspace, nameFilter / methodNameFilter / moduleFilter to narrow.
When not to use it
- concrete classes (use
ek9_query_classes) - data shapes (use
ek9_query_records) - a trait's depth-by-depth implementer graph (
ek9_query_type_hierarchywith symbol:'TraitName'); the implementers themselves come back here as implementedBy - a trait's full source (use
ek9_read_construct)
Details
nameFilter/methodNameFilter are plain case-insensitive substrings (not regex), moduleFilter an exact module-name allow-list; built-in org.ek9.* traits are excluded. status is ok (traits returned) / empty (no match — meta.unmatchedFilters[] lists any moduleFilter values naming non-existent modules as module:<value>) / not-compiled (no compiled program — run ek9_compile first). traitOf lists only directly-declared super-traits (with trait of ...); methods[] are EK9-syntax signatures capped at 8, including the synthesized operator ?; unresolved types render as <unresolved>. implementedBy is every construct carrying the trait workspace-wide - classes, traits that extend it, and types that get it through a sub-trait or a superclass - nothing to verify; records and components cannot carry traits, and a dynamic class inside a function body is not listed. implementedByAll names traits exactly (bare or module::Name) and intersects their implementedBy; a name that names no trait is in meta.unmatchedFilters[] as trait:<value>, with meta.didYouMean naming the traits that contain it.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
implementedByAll | array of string | Trait names (exact, bare or module::Name). Answers implementedByAll: the constructs that carry EVERY one of them, transitively. | |
includeMethodSummary | boolean | Default true. When true each entry includes methods[] (the contract signatures). Set false for a lighter response. | |
methodNameFilter | string | Filter to traits declaring a method whose name matches (case-insensitive substring). | |
moduleFilter | array of string | Restrict to specific modules (exact names). Default: workspace-wide. | |
nameFilter | string | Case-insensitive substring match on trait names. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it.
List all
Request
{ }
Response
{
"meta" : {
"serverMs" : "<timing>"
},
"status" : "ok",
"summary" : {
"moduleCount" : 1
},
"traitCount" : 2,
"traitNames" : [ "Identifiable", "Describable" ],
"traits" : [ {
"file" : "contracts.ek9",
"implementedBy" : [ ],
"implementedByCount" : 0,
"line" : 6,
"methodCount" : 2,
"methods" : [ "identity()\n <- rtn as String", "operator ?\n <- rtn as Boolean" ],
"module" : "com.example.contracts",
"name" : "Identifiable",
"traitOf" : [ ]
}, {
"file" : "contracts.ek9",
"implementedBy" : [ ],
"implementedByCount" : 0,
...
Cut short here: 8 more lines. The whole recorded call.
Implemented by all
Request
{
"implementedByAll" : [ "Identifiable", "Describable" ],
"includeMethodSummary" : false
}
Response
{
"implementedByAll" : [ "Catalogued", "Both", "ViaCatalogue" ],
"meta" : {
"serverMs" : "<timing>"
},
"status" : "ok",
"summary" : {
"moduleCount" : 1
},
"traitCount" : 3,
"traitNames" : [ "Identifiable", "Describable", "Catalogued" ],
"traits" : [ {
"file" : "traits.ek9",
"implementedBy" : [ "Catalogued", "OnlyIdentified", "Both", "ViaCatalogue" ],
"implementedByCount" : 4,
"line" : 6,
"methodCount" : 2,
"module" : "com.example.both",
"name" : "Identifiable",
"traitOf" : [ ]
}, {
"file" : "traits.ek9",
"implementedBy" : [ "Catalogued", "Both", "ViaCatalogue" ],
"implementedByCount" : 3,
...
Cut short here: 16 more lines. The whole recorded call.