ek9_insert_coalescing

Splices `LEFT <op> RIGHT` in place of a selected single-line left operand using one of the EK9 coalescing / elvis operators; answers status, edits[] (one REPLACE) and conflicts[] (kind 'selection-not-an-expression'), with a type-incompatible pairing surfacing as would-fail.

Category: Editor · Compare: no direct precedent — EK9-specific coalescing / elvis operators

When to use it

'Default name to "Anonymous" when unset' is one call with file, the LEFT operand as written (operand:'name'), operator:'?:' and rightOperand:'"Anonymous"'. Use it to wrap an existing single-line expression in one of EK9's null-safe operators (?: <? >?) without hand-writing tokens.

When not to use it

Details

The splice is syntactic but gated by a semantic scratch-compile: `?:` works on any tri-state type, while `<?`/`>?` need the operand's type to define `<=>` (`_cmp`), so a bad pairing or type-incompatible rightOperand surfaces as status:'would-fail' with the compiler diagnostic, not a broken edit. A compound left operand (e.g. `a + b`) is parenthesised for unambiguous binding, as is a compound rightOperand (`count ?: (base + 1)`) and the whole new expression when the operand sits inside another operator (`x + (a <? c)`), so the value never silently changes. The operand text names its occurrence; when it is an operand on several lines and no line is given, the call is refused naming them. A declaration's LHS is an identifier, not an expression (status:'conflicts', kind 'selection-not-an-expression') — and V1 supports a single-line left operand only.

Arguments

ArgumentTypeRequiredWhat it is
endColumninteger1-based EXCLUSIVE column of the END of the span (an IDE selection). Omit it - pass the text instead.
filestringyesWorkspace-relative path to the .ek9 source file containing the expression.
lineintegerOptional 1-based line of the operand. Needed only when the operand text is an operand on more than one line.
operandstringThe LEFT operand exactly as written in the source ('name', 'a + b').
operatorstring: ?: | <? | >?yesThe coalescing operator to insert: `?:` first SET - the one that defaults an unset value ('name ?: "Anonymous"'); `<?` min, `>?` max (the LEFT operand on a tie).
rightOperandstringyesThe RIGHT operand expression as source text — e.g. a fallback literal (`"Anonymous"`), another variable (`y`), or a further chained expression (`b ?: c`). Spliced verbatim.
startColumninteger1-based column of the START of the span on 'line' (an IDE selection). Omit it - pass the text instead.

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

Operand text ambiguous without line

Request

{
  "file" : "Bounds.ek9",
  "operand" : "alpha",
  "operator" : "<?",
  "rightOperand" : "beta"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "operand 'alpha' is on lines [9, 10] - pass line (one of [9, 10]) to say which one to coalesce."
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "status" : "error",
  "summary" : "operand 'alpha' is on lines [9, 10] - pass line (one of [9, 10]) to say which one to coalesce.",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Min dry run

Request

{
  "dryRun" : true,
  "endColumn" : 23,
  "file" : "Bounds.ek9",
  "line" : 9,
  "operator" : "<?",
  "rightOperand" : "beta",
  "startColumn" : 18
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      smaller <- alpha <? beta",
    "before" : "      smaller <- alpha",
    "endLine" : 9,
    "file" : "Bounds.ek9",
    "startLine" : 9,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "ready",
  "summary" : "Would wrap `alpha` as `alpha <? beta`",
  "workspaceHash" : "<workspace-hash>",
...

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

Right operand parenthesised

Request

{
  "dryRun" : true,
  "endColumn" : 23,
  "file" : "Bounds.ek9",
  "line" : 9,
  "operator" : "?:",
  "rightOperand" : "beta + 1",
  "startColumn" : 18
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      smaller <- alpha ?: (beta + 1)",
    "before" : "      smaller <- alpha",
    "endLine" : 9,
    "file" : "Bounds.ek9",
    "startLine" : 9,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "ready",
  "summary" : "Would wrap `alpha` as `alpha ?: (beta + 1)`",
  "workspaceHash" : "<workspace-hash>",
...

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

See also