ek9_insert_statements

Splices EK9 statement(s) into a named method/function/operator body at anchor top, bottom, replace or a body line, re-indented by the tool; answers status, edits[] (one INSERT), insertedLineRange and resultingBodySnippet, or error.problems[] naming the entry that does not parse.

Category: Editor · Compare: IntelliJ "Generate" menu / LSP code action "Insert at cursor"

When to use it

'Add a statement to the end of Greeter.hello' is one call with file, symbol:'Greeter.hello', anchor:'bottom', statements:[...] - the tool owns indent and formatting. Use it to ADD statement(s) into an existing method/function/operator body (a log line, a guard at the head, a new field's first use) without a full-text rewrite.

When not to use it

Details

anchor: position top/bottom, or afterLine/beforeLine (a line inside the body). Statement text is re-indented to body level (common leading whitespace stripped, relative indent kept), one top-level statement per statements[] entry - an entry MAY be a multi-line block (switch/if/for/try/while, with '\n' and two-space nesting). Every entry is parsed alone BEFORE the splice: a syntax error or a tab is status:error, written:false, error.problems[{path:'statements[i]', line, message}] with nothing written (the compile gate stays the semantic check). position:top resolves to the first valid statement position (after any `<- rtn` declaration) and REPLACES a scaffold's placeholder body (the require guards survive; appliedAnchor.replacedPlaceholder:true). Conflict kinds: dynamic-body-not-supported (dynamic function/class bodies rejected fail-fast) and inserted-content-includes-return-value-declaration; unknown construct/method surfaces as status:error, and success carries appliedIndent, appliedAnchor, insertedLineRange and resultingBodySnippet (±2-line window; includeBodySnippet:true swaps in the full post-insert body — check bodySnippetSource).

Arguments

ArgumentTypeRequiredWhat it is
anchoranyyesWHERE in the body: 'top' (first statement position; replaces a scaffold's placeholder), 'bottom' (after the last statement), 'replace' (the whole body - re-implement the member), a bare line number N (= {afterLine:N}), or {beforeLine:N} - a 1-based line INSIDE the body; with ek9_remove_statements(startLine, endLine) this replaces lines in the middle of a body.
filestringWorkspace-relative path to the .ek9 source file containing the target body (optional - found from symbol when omitted).
includeBodySnippetbooleanWhen true, response.resultingBodySnippet carries the entire method/function body post-insert (delegated to ConstructSourceExtractor against the post-write program). Default false returns a ±2-line context window around the insert — usually enough to eyeball indent and position. Always check response.bodySnippetSource to confirm which path produced the snippet: "extractor" = full body delivered; "contextWindowFallback" = opt-in requested but the response carries the cheap window despite your request (typically because this call was dryRun:true — no file written, so no post-write extractor probe runs).
memberNamestringMethod or operator name within symbol when symbol is the bare type ('Greeter' + memberName:'hello' is the same as symbol:'Greeter.hello'). OMIT for a program or a top-level function - do not send the string "null".
statementsarray of stringyesOrdered list of EK9 statements to insert. Each entry is ONE top-level statement and MAY span several lines with '\n' - a switch, an if, a for, a try - with its relative indentation preserved (two spaces per level); the tool owns the absolute indent. Write a block as ONE entry: "switch code\n case 1\n rtn: \"active\"\n default\n rtn: \"unknown\"" (one line per entry also works when the nested lines are indented deeper than the first entry). Every entry is parsed alone before anything is written; a syntax error is rejected as error.problems[{path:'statements[i]', line}] with nothing written. Spaces only - a tab is rejected.
symbolstringyesThe body's owner: a program or top-level function by name ('Main', 'findLabel'), or a member as 'Type.member' ('Greeter.hello', an operator by its bare symbol: 'Order.$'). 'mod::Name' is understood.

It also takes the arguments every tool takes.

Recorded calls

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

After line anchor outside body

Request

{
  "anchor" : {
    "afterLine" : 3
  },
  "construct" : "Main",
  "file" : "Hello.ek9",
  "statements" : [ "stdout.println(\"Middle\")" ]
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "afterLine 3 is not inside this body (its statements are lines 6-8); use position:'top'/'bottom' or a line in that range"
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "status" : "error",
  "summary" : "afterLine 3 is not inside this body (its statements are lines 6-8); use position:'top'/'bottom' or a line in that range",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Overloaded name refused with signatures

Request

{
  "anchor" : "bottom",
  "file" : "task.ek9",
  "statements" : [ "rtn: rtn.upperCase()" ],
  "symbol" : "Formatter.format"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "'Formatter.format' names 2 overloads - this acts on ONE member, so name it by its signature: Formatter.format(Integer) (line 9), Formatter.format(String) (line 13). (Or anchor inside the one you mean with {afterLine:N} or {beforeLine:N}.)"
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "status" : "error",
  "summary" : "'Formatter.format' names 2 overloads - this acts on ONE member, so name it by its signature: Formatter.format(Integer) (line 9), Formatter.format(String) (line 13). (Or anchor inside the one you mean with {afterLine:N} or {beforeLine:N}.)",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Syntax error in entry rejected

Request

{
  "anchor" : {
    "position" : "top"
  },
  "construct" : "Main",
  "file" : "Hello.ek9",
  "statements" : [ "stdout.println(\"ok\")", "switch code\n  case 1\n    stdout.println(\"one\")\n  default" ]
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "Cannot insert statements into Main - 1 argument problem; nothing was rendered or written",
    "problems" : [ {
      "line" : 4,
      "message" : "statements[1] line 4: extraneous dedentation expecting indentation or newline near 'dedentation'",
      "path" : "statements[1]"
    } ]
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "nextStep" : "Resend the same call with statements[1] line 4 corrected: statements[1] line 4: extraneous dedentation expecting indentation or newline near 'dedentation'",
  "status" : "error",
  "summary" : "Cannot insert statements into Main - 1 argument problem; nothing was rendered or written",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}