ek9_query_construct_neighbourhood

Answers first: nodeCount, nodes[] (name, fullyQualifiedName, module, genus, file, line, distance), edges[] (from, to, kind) and edgesByKind - the N-hop typed ego graph merging inheritance, calls, composition, references and DI.

Category: Enquiry · Compare: EK9 IDE — construct neighbourhood / blast-radius ego graph around the cursor

When to use it

If I change this construct, what is structurally affected - one call with symbol:'Order' and direction:'incoming' (the blast radius), no file needed.

When not to use it

Details

Edge kinds: extends/implements/composes(field types)/references(param/return types)/calls(phase-5 call graph)/injects(DI fields)/dispatches(dispatcher overload group) — all types generic-unwrapped, only user-construct↔user-construct edges kept, each node carries 'distance' from the target. A virtual call THROUGH an injected abstract field is a 'calls' edge to the abstract type, which has a 'calls' edge on to each implementation that is constructed somewhere (a register in the application counts) - one hop more, never none. A function's implicit generic super ('Consumer of Address') gives 'references', not 'extends', to its type argument. Also emits 'requirements[]' (whose anchoring tests can REACH this construct) over the FULL transitive closure — never limited by 'depth', over-inclusive by construction (reach is change-impact, NOT what this construct implements); reachResolved=false means no call graph to answer from; test nodes carry isTest/requirementRef.

Arguments

ArgumentTypeRequiredWhat it is
depthintegerHow many edges out from the target (default 1, max 5).
directionstring: both | incoming | outgoing'outgoing' = what it depends on, 'incoming' = what depends on it (the blast radius), 'both' (default).
edgeKindsarray of string: extends | implements | composes | references | calls | injects | dispatchesRestrict to these relationships. Omit for all.
filestringThe EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site.
lineinteger1-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).
symbolstringThe construct: a bare name ('Order') or a qualified name ('com.acme.orders::Order') - no file needed, the tool finds it workspace-wide; 'Type.member' anchors on the member's construct.

Recorded calls

Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 4 recorded are shown.

Parameterised super references its argument

Request

{
  "direction" : "incoming",
  "symbol" : "sample.arch.model::Address"
}

Response

{
  "depth" : 1,
  "direction" : "incoming",
  "edgeCount" : 1,
  "edges" : [ {
    "from" : "sample.arch.model::stamp",
    "kind" : "references",
    "to" : "sample.arch.model::Address"
  } ],
  "edgesByKind" : {
    "references" : 1
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "nodeCount" : 2,
  "nodes" : [ {
    "distance" : 0,
    "file" : "model.ek9",
    "fullyQualifiedName" : "sample.arch.model::Address",
    "genus" : "RECORD",
    "line" : 6,
    "module" : "sample.arch.model",
    "name" : "Address"
...

Cut short here: 24 more lines. The whole recorded call.

Requirements beyond hop budget

Request

{
  "depth" : 1,
  "direction" : "incoming",
  "symbol" : "com.example.trace::deepCore"
}

Response

{
  "depth" : 1,
  "direction" : "incoming",
  "edgeCount" : 1,
  "edges" : [ {
    "from" : "com.example.trace::mid",
    "kind" : "calls",
    "to" : "com.example.trace::deepCore"
  } ],
  "edgesByKind" : {
    "calls" : 1
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "nodeCount" : 2,
  "nodes" : [ {
    "distance" : 0,
    "file" : "main.ek9",
    "fullyQualifiedName" : "com.example.trace::deepCore",
    "genus" : "FUNCTION",
    "line" : 6,
    "module" : "com.example.trace",
    "name" : "deepCore"
...

Cut short here: 27 more lines. The whole recorded call.

Test node carries anchor

Request

{
  "depth" : 1,
  "direction" : "incoming",
  "symbol" : "com.example.trace::outer"
}

Response

{
  "depth" : 1,
  "direction" : "incoming",
  "edgeCount" : 1,
  "edges" : [ {
    "from" : "com.example.trace.tests::DeepTest",
    "kind" : "calls",
    "to" : "com.example.trace::outer"
  } ],
  "edgesByKind" : {
    "calls" : 1
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "nodeCount" : 2,
  "nodes" : [ {
    "distance" : 0,
    "file" : "main.ek9",
    "fullyQualifiedName" : "com.example.trace::outer",
    "genus" : "FUNCTION",
    "line" : 12,
    "module" : "com.example.trace",
    "name" : "outer"
...

Cut short here: 29 more lines. The whole recorded call.