ek9_read_construct
Answers first: source.text with source.file/startLine/endLine from the compiled symbol-table boundaries (no line guessing), construct {name, fullyQualifiedName, kind}, members[{name, kind, signature, startLine, endLine}] and source.contentHash.
When to use it
You want the source text of one construct or member - one call with symbol:'Shape', 'mod::Shape', 'Shape.computeTotal' or 'Shape.?'; no file or line needed. Anchor file + line only from an IDE cursor.
When not to use it
- The WHOLE file, not one construct - use
ek9_read_file(path). - Structure only, no bodies — use
ek9_query_construct(declared members/signatures; cheaper) orek9_query_effective_api(full visible set incl. inherited/trait/defaulted). - Semantic info (type, set/unset state, mutability) at a cursor, not source text — use
ek9_inspect_symbol_at_cursor. - Keyword search across the workspace — use
ek9_search_text.
Details
Ambiguity is keyed on the DEFINING module only — a construct reachable via a references block is not a second definition; when a name is declared in several modules the refusal lists them and the qualified form ('mod::Name') picks one. An overloaded member name returns EVERY overload (scope:'overloads', each with its signature and source); a dispatcher's name returns its entry point; 'Shape.render(Circle)' returns that overload alone. source.contentHash is the whole file's hash for expectedContentHash on ek9_edit_file. Requires the workspace compiled (ek9_compile) at least to symbols_defined; types_resolved gives reliable signatures.
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
file | string | IDE cursor form: the .ek9 file (workspace-relative or absolute inside the workspace). OPTIONAL - a symbol alone finds its file. | |
includeBody | boolean | When false, returns signatures only (declaration lines, no bodies). | |
line | integer | 1-based line anywhere inside the target with file - OMIT it and pass symbol:'<name>' instead (a model counting lines miscounts). | |
lineNumbers | boolean | When true, each line of source.text is prefixed 'N| ' (the ek9_read_file form). Default false - source.startLine/endLine already anchor the slice. | |
memberName | string | Narrows a bare construct symbol to ONE member (method / operator / constructor / field name; operators by symbol: ?, <=>, $). 'Shape.member' says the same in one key. | |
module | string | Exact module name that picks one declaration when symbol is a bare name declared in several modules; 'mod::Shape' says the same in one key. | |
symbol | string | The construct or member: 'Shape' | 'mod::Shape' (when the name is declared in several modules) | 'Shape.computeTotal' | 'Shape.?' (an operator by its EK9 symbol). No file or line needed. With file, the identifier to anchor on there. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 6 recorded are shown.
Built in type member
Request
{
"symbol" : "String.first"
}
Response
{
"error" : {
"kind" : "built-in-type",
"message" : "'String' is a built-in EK9 type - it has no source to read"
},
"meta" : {
"serverMs" : "<timing>"
},
"nextStep" : "ek9_help 'String' lists its constructors, methods and operators - including first; ek9_query_effective_api does the same for a type in this workspace.",
"status" : "not-found"
}
Read unknown symbol not found
Request
{
"symbol" : "NoSuchRecord"
}
Response
{
"error" : {
"kind" : "unknown-construct",
"message" : "Construct not found: NoSuchRecord"
},
"meta" : {
"serverMs" : "<timing>"
},
"nextStep" : "No construct named 'NoSuchRecord' in the compiled workspace - find the spelling with ek9_find_constructs_by_name (names are case-sensitive), or recompile if it was just added.",
"status" : "not-found"
}
Read member by symbol
Request
{
"lineNumbers" : true,
"symbol" : "MyRecord.name"
}
Response
{
"construct" : {
"fullyQualifiedName" : "com.example::MyRecord",
"kind" : "record",
"name" : "MyRecord"
},
"member" : {
"endLine" : 6,
"kind" : "field",
"name" : "name",
"startLine" : 6
},
"meta" : {
"serverMs" : "<timing>"
},
"scope" : "member",
"source" : {
"contentHash" : "sha256:7f5d05c57b329129ca15e7987b5459766b0b8be769d09ca971ed9e360e492d29",
"endLine" : 6,
"file" : "MyRecord.ek9",
"startLine" : 6,
"text" : "6| name as String: String()"
},
"status" : "ok",
...
Cut short here: 2 more lines. The whole recorded call.