ek9_add_constructor

Inserts one constructor at the construct's canonical member position; answers status, edits[] and summary, a same-shape constructor as conflicts[] (constructor-already-exists, with its line).

Category: Editor · Compare: Generate Constructor (IntelliJ)

When to use it

'Add a constructor to Order' is one call with symbol:'Order' and mode:'no-arg' | 'all-fields' | 'fields' (+ fields:[...]) - no file or line needed.

When not to use it

Details

Modes: no-arg (emits a bodyless 'default' constructor; visibility default private, honours pure), all-fields (honours pure), fields (requires non-empty fields[]; purity auto-detected - greenfield defaults pure). In the field modes purity is auto-forced when any existing constructor is pure (mixed purity won't compile); assignment is ':' non-pure, ':=?' when pure (never the copy operator ':=:'). A duplicate parameter shape returns status:'conflicts' kind 'constructor-already-exists' naming the existing constructor's line and the insert_statements / change_signature / safe_delete routes (nothing written); a pure constructor over a field DECLARED with a value returns status:'error' (E08095) - declare those fields unset (String()/Integer()) or request non-pure.

Arguments

ArgumentTypeRequiredWhat it is
fieldsarray of stringfields mode - names of the fields to take as constructor parameters, in order.
filestringThe EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site.
modestring: no-arg | all-fields | fieldsno-arg: a bodyless 'default' constructor blocking default construction; all-fields: every field as a parameter; fields: the named subset (inferred when fields[] is given).
purebooleanAdd 'as pure'. Default false.
symbolstringyesThe class, record or component the constructor is added to - a bare name ('Order') finds its file workspace-wide; 'mod::Order' when the name is declared in two modules.
visibilitystring: public | private | protectedno-arg only - the constructor's access. Default 'private' (the typical force-a-factory use).

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

Default no arg apply

Request

{
  "constructName" : "Greeter",
  "file" : "Greeter.ek9",
  "mode" : "default-no-arg"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "\n      default private Greeter()",
    "endLine" : 7,
    "file" : "Greeter.ek9",
    "startLine" : 7,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/Greeter.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Added default private no-arg constructor to Greeter",
  "workspaceHash" : "<workspace-hash>",
...

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

From fields subset sets uncovered apply

Request

{
  "constructName" : "Tally",
  "fields" : [ "name" ],
  "file" : "Tally.ek9",
  "mode" : "from-fields"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "\n      Tally()\n        -> name as String\n        this.name: name\n        this.count :=? Integer()",
    "endLine" : 17,
    "file" : "Tally.ek9",
    "startLine" : 17,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/Tally.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Added constructor from 1 fields to Tally; also sets count (unset at declaration, and every constructor must initialise them - E08060)",
  "workspaceHash" : "<workspace-hash>",
...

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

Extending constructor names still live calls

Request

{
  "fields" : [ "customerName", "total" ],
  "mode" : "fields",
  "symbol" : "Order"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "\n      Order()\n        ->\n          customerName as String\n          total as Float\n        this.customerName: customerName\n        this.total: total",
    "endLine" : 15,
    "file" : "task.ek9",
    "startLine" : 15,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "nextStep" : "The existing Order(customerName) is still there and still called - task.ek9:25 'order <- Order(\"Ann\")'. Those calls keep building with it, so the new parameters stay unset there. In one call: ek9_edit_file path:'<workspace-root>/task.ek9' edits:[{mode:'find-replace', find:'Order(\"Ann\")', replace:'Order(\"Ann\", <total>)'}] - replace each <...> with the value to pass. Edit the call; do not add a second declaration. (To EXTEND that constructor instead of adding one: ek9_change_signature symbol:'Order.Order' add-parameter, which updates its calls too.)",
  "resolvedPath" : "<workspace-root>/task.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Added constructor from 2 fields to Order",
...

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

See also