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).
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
- Adding a regular METHOD or an operator like == / <=> - use
ek9_add_method/ek9_add_operator. - Implementing trait methods on a class - use
ek9_implement_methods. - The TYPE doesn't exist yet - create it with
ek9_new_constructfirst, constructors second. - Target must be a class, record, or component - functions, traits, services, and enumerations have no constructors.
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
| Argument | Type | Required | What it is |
|---|---|---|---|
fields | array of string | fields mode - names of the fields to take as constructor parameters, in order. | |
file | string | The EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site. | |
mode | string: no-arg | all-fields | fields | no-arg: a bodyless 'default' constructor blocking default construction; all-fields: every field as a parameter; fields: the named subset (inferred when fields[] is given). | |
pure | boolean | Add 'as pure'. Default false. | |
symbol | string | yes | The 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. |
visibility | string: public | private | protected | no-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
- Show me in the IDE: Chapter 14: a record, built
- Show me in the IDE: Chapter 17: an abstract type and its subtypes, built
- Show me in the IDE: Chapter 18: traits and delegation, built
- Show me in the IDE: Chapter 21: operators, built
- Show me in the IDE: Chapter 21: promotion, #^
- Show me in the IDE: Chapter 23: the game, built and played