ek9_expand_default_operator

Replaces the 'default operator' declaration with the explicit body the compiler would synthesise from the fields, ready to customise; answers status, edits[] and summary, a missing default line as conflicts[] (target-not-a-default-operator).

Category: Editor · Compare: Generate Default Implementation (no direct equivalent)

When to use it

'Expand Order's default operator <=> so I can customise it' is one call with symbol:'Order' and operator:'<=>' - omit operator to expand the bare block.

When not to use it

Details

Class / record / component targets with at least one field - traits and field-less constructs are refused (no properties to derive a body from). mode is inferred (operator → one, none → all); a contradicting mode is a mode-contradicts-arguments conflict. The 'after' body mirrors the compiler's synthesis: == ANDs each property's ==, <=> cascades to the first non-zero in declaration order (< <= > >= delegate to <=>), ? ANDs each _isSet, #? XORs each _hashcode, $ interpolates the fields, :=: copies each field; all emit 'as pure' except :=:, chaining via super.<op>(...) first when a real superclass declares the operator. Conflict kinds: target-not-a-default-operator (no such 'default operator' line - a hand-written body is changed with ek9_insert_statements), target-operator-not-supported-for-default; the all form skips operators already explicitly declared and errors when none remain.

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.
lineintegerIDE refinement: the 1-based line of the 'default operator' declaration. Omit it - the declaration is found by symbol + operator.
modestring: one | allOptional - inferred: operator given → one, none → all.
operatorstringThe one operator to expand, in EK9 source form ('==', '<=>', '$'). Omit it to expand the bare 'default operator' block into every defaultable operator.
symbolstringyesThe class, record or component holding the default operator - a bare name ('Order') finds its file workspace-wide; 'mod::Order' when the name is declared in two modules.

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.

Single finds line by name apply

Request

{
  "constructName" : "Order",
  "cursorLine" : 7,
  "file" : "Order.ek9",
  "mode" : "single",
  "operator" : "$"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      operator $ as pure\n        <- rtn as String: `Order(${name})`",
    "endLine" : 8,
    "file" : "Order.ek9",
    "startLine" : 8,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/Order.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Expanded 'default operator $' to skeleton in Order",
  "workspaceHash" : "<workspace-hash>",
...

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

Single on hand written operator conflicts

Request

{
  "constructName" : "Order",
  "cursorLine" : 7,
  "file" : "Order.ek9",
  "mode" : "single",
  "operator" : "$"
}

Response

{
  "conflicts" : [ {
    "description" : "Order has no 'default operator $' line (line 7 is 'operator $ as pure') - nothing was written. An operator that already has a body is changed with ek9_insert_statements(symbol:'Order', method:'$', anchor:{position:'replace'}, statements:['rtn: <expression>']).",
    "file" : "Order.ek9",
    "kind" : "target-not-a-default-operator"
  } ],
  "edits" : [ ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 0,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "conflicts",
  "summary" : "Order has no 'default operator $' line (line 7 is 'operator $ as pure') - nothing was written. An operator that already has a body is changed with ek9_insert_statements(symbol:'Order', method:'$', anchor:{position:'replace'}, statements:['rtn: <expression>']).",
  "workspaceHash" : "<workspace-hash>",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Expand all apply

Request

{
  "constructName" : "MyRecord",
  "cursorLine" : 7,
  "file" : "MyRecord.ek9",
  "mode" : "all"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      operator <=> as pure\n        -> other as MyRecord\n        <- rtn as Integer: 0\n        rtn: name <=> other.name\n\n      override operator ? as pure\n        <- rtn as Boolean: name?\n\n      operator $ as pure\n        <- rtn as String: `MyRecord(${name})`\n\n      operator $$ as pure\n        <- rtn as JSON: JSON()\n\n      operator #? as pure\n        <- rtn as Integer: #?name\n\n      operator :=:\n        -> source as MyRecord\n        name :=: source.name",
    "endLine" : 7,
    "file" : "MyRecord.ek9",
    "startLine" : 7,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/MyRecord.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Expanded 'default operator' to 20 skeleton lines in MyRecord",
  "workspaceHash" : "<workspace-hash>",
...

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

See also