ek9_inspect_symbol_at_cursor
Answers first: name, fullyQualifiedName, kind, type, state, declaredAt, then the modifiers, flags, scope, purityContext and the type's operators - one symbol, cursor-precise.
When to use it
What exactly is the identifier at this cursor - kind, type, tri-state, declaration, scope - one call with file + symbol:'<name>'. An IDE cursor passes file + line + column instead.
When not to use it
- The WHOLE construct containing the cursor (class/record/etc.), not the precise symbol at it — use
ek9_query_construct. - The FULL callable API of a type (methods + operators + constructors, inherited members) — use
ek9_query_effective_apion the returned type. - Enumerating ALL symbols in scope at a position — use
ek9_list_visible_symbols. - Language reference for a built-in type rather than a workspace symbol — use
ek9_help.
Details
Resolved symbols carry symbol:'found' with a uniform core (kind, type, state, mutable, purityContext, modifiers, declaredAt, scope, flags); kind is FIELD or PARAMETER where applicable, otherwise the symbol category (VARIABLE/METHOD/FUNCTION/TYPE/...), and METHOD adds methodDetails (parameters, returns, pure, abstract). state is the symbol's STATIC declared tri-state, not flow-sensitive (an assignment lines earlier still reads unset) — except state:'absent', which IS position-aware: a REAL variable out of lexical scope here (reason scope-closed or before-declaration) is recovered from its declaration with an absence block, while a name declared nowhere stays not_found. declaredAt is line+column only (no file yet); operators lists the type's operators only (?, $, <=>, ==, ...) — plain methods are deliberately excluded. displayName appears only when it differs from name (a parameterised or synthetic symbol).
Arguments
| Argument | Type | Required | What it is |
|---|---|---|---|
column | integer | 0-based char offset of the target identifier on 'line' (an IDE cursor). OMIT it and pass symbol:'<name>' instead, or omit both and the first identifier on the line is taken (right for a declaration line). Reuse a column from ek9_inspect_symbol_at_cursor verbatim. | |
file | string | yes | The EK9 source file path |
line | integer | 1-based line of the declaration or a reference - OMIT it and pass symbol:'<name>' to let the tool find the line (a model counting lines in a file miscounts); if you do count, use ek9_read_file(lineNumbers:true). | |
symbol | string | The identifier you mean on 'line' (e.g. 'sayHello'); the tool finds its column. Prefer this to column - a column is a 0-based character offset an IDE supplies. |
Recorded calls
Real calls, recorded against small projects and checked on every build - a changed answer fails it.
Inspect shape
Request
{
"file" : "MyRecord.ek9",
"line" : 5
}
Response
{
"callSite" : false,
"category" : "TYPE",
"declaredAt" : {
"column" : 4,
"line" : 5
},
"flags" : {
"abstract" : false,
"constant" : false,
"field" : false,
"incomingParameter" : false,
"initialised" : true,
"injectionExpected" : false,
"mutable" : false,
"pure" : false,
"returningParameter" : false
},
"fullyQualifiedName" : "com.example::MyRecord",
"genus" : "RECORD",
"kind" : "TYPE",
"meta" : {
"serverMs" : "<timing>"
},
...
Cut short here: 71 more lines. The whole recorded call.
Hover local
Request
{
"file" : "task.ek9",
"line" : 18,
"symbol" : "count"
}
Response
{
"callSite" : false,
"category" : "VARIABLE",
"declaredAt" : {
"column" : 8,
"line" : 18
},
"displayName" : "count as Integer",
"flags" : {
"abstract" : false,
"constant" : false,
"field" : false,
"incomingParameter" : false,
"initialised" : true,
"injectionExpected" : false,
"mutable" : true,
"pure" : false,
"returningParameter" : false
},
"fullyQualifiedName" : "coder.f9::count",
"genus" : "VALUE",
"kind" : "VARIABLE",
"meta" : {
"serverMs" : "<timing>"
...
Cut short here: 177 more lines. The whole recorded call.