ek9_apply_symbolic_fix

Inserts the 'require <divisor> <> 0' line guard-first (an inline-initialised return becomes '<- rtn as T?' + ':=?'), re-finding the counterexample server-side, and migrates a pinning @Test to assertPanic in the same changeset; answers status, edits[] and summary.

Category: Editor · Compare: IDE quick-fix: add precondition (design-by-contract guard)

When to use it

After ek9_verify_method reports DIV_BY_ZERO, 'add the guard' is one call with symbol:'safeAverage' - it inserts the 'require <divisor> <> 0' precondition. V1: DIV_BY_ZERO only.

When not to use it

Details

V1 scope: DIV_BY_ZERO only (single named-parameter divisor); other obligations (CALLEE_REQUIRE, CONSTRAINED_CONSTRUCTION) are rejected with a message, not a guessed edit. The finding is re-found by re-running the engine at apply time and matched by obligation+witness on the function at line — a drifted or already-discharged line errors, several fixable divisions demand a witness ('<param>=<value>') to pick one, and the require line is derived server-side (no free-text guard param). Pinned-test migration is off-when-unsure: a hand-edited test it does not recognise is left untouched and named for manual migration.

Arguments

ArgumentTypeRequiredWhat it is
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).
obligationstringOptional counterexample selector when the function has several findings. V1 accepts only 'DIV_BY_ZERO'.
symbolstringyesThe function (or 'Type.method') to fix - a bare name finds its file workspace-wide; 'mod::name' when the name is declared in two modules.
witnessstringOptional counterexample selector ('<param>=<value>', e.g. 'quantity=0') when the function has several fixable divisions.

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 4 recorded are shown.

Apply unsupported obligation

Request

{
  "file" : "Maths.ek9",
  "line" : 5,
  "obligation" : "CALLEE_REQUIRE"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "Apply-fix V1 handles DIV_BY_ZERO only; 'CALLEE_REQUIRE' is not yet supported."
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "status" : "error",
  "summary" : "Apply-fix V1 handles DIV_BY_ZERO only; 'CALLEE_REQUIRE' is not yet supported.",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Apply div fix dryrun

Request

{
  "dryRun" : true,
  "file" : "Maths.ek9",
  "line" : 5
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      <- rtn as Integer?\n      require count <> 0\n      rtn :=? total / count",
    "before" : "      <- rtn as Integer: total / count",
    "endLine" : 9,
    "file" : "Maths.ek9",
    "startLine" : 9,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "ready",
  "summary" : "Add precondition 'require count <> 0' to discharge the division-by-zero.",
  "workspaceHash" : "<workspace-hash>",
...

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

Apply pure fn assign if unset

Request

{
  "dryRun" : true,
  "file" : "Maths.ek9",
  "line" : 5
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      <- rtn as Integer?\n      require count <> 0\n      rtn :=? total / count",
    "before" : "      <- rtn as Integer: total / count",
    "endLine" : 9,
    "file" : "Maths.ek9",
    "startLine" : 9,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "ready",
  "summary" : "Add precondition 'require count <> 0' to discharge the division-by-zero.",
  "workspaceHash" : "<workspace-hash>",
...

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