ek9_add_field

Inserts the field declaration at the construct's canonical field position; answers status, edits[] and summary, a clashing name as conflicts[] (name-collision).

Category: Editor · Compare: Generate Field (IntelliJ) / Quick Fix - Add Field

When to use it

'Add a field to CustomerOrder' is one call with symbol:'CustomerOrder', fieldName and defaultValue (or rawDeclaration:'logger as Logger!') - no file or line.

When not to use it

Details

Two forms: structured (fieldName + defaultValue; defaultValue REQUIRED for records) or raw (rawDeclaration as typed, e.g. `name as String?` or `logger as Logger!`); mode is inferred from which is given and a contradicting mode is a conflict. Visibility is genus-fixed: class/component fields are always private, record fields always public - no access-modifier syntax exists. A pre-existing field name is a name-collision conflict (structured) or hard error (raw); an UNINITIALISED field can trip E07175/E07170 (public no-arg ctor would build a partial object) → would-fail - fix with an initialiser, a private no-arg ctor, or an explicit ctor.

Arguments

ArgumentTypeRequiredWhat it is
defaultValuestringDefault value expression for the field, e.g. '0', '""', 'String()'. Required for records in the structured form.
fieldNamestringThe new field's name (structured form) - with 'type' or 'defaultValue'; a name alone renders a typeless field (E07110).
filestringThe EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site.
modestring: structured | rawOptional - inferred: rawDeclaration → raw, fieldName → structured.
rawDeclarationstringThe whole declaration line as you would type it (raw form), e.g. 'name as String?' or 'logger as Logger!' (DI).
symbolstringyesThe class, record or component the field is added to - a bare name ('Order') finds its file workspace-wide; 'mod::Order' when the name is declared in two modules.
typestringThe field's type in the structured form, e.g. 'Float', 'List of String' - rendered 'name as Type: Type()' (present, unset until assigned) unless defaultValue is given.
withConstructorbooleanInsert a NEW pure constructor taking this field, in the SAME change - the fields-mode rendering ek9_add_constructor mode:'fields' uses. Only applies when the field is left with no value ('name as Type?' / rawDeclaration ending '?', or the structured form with 'type' and no 'defaultValue') - that is the one shape a publicly-constructible class can leave uninitialised (E07170/E08070/E08060) until a second ek9_add_constructor call lands one; any other form already has what it needs and the option is a no-op. Default false.

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

Add structured field dry run ready

Request

{
  "constructName" : "Greeter",
  "defaultValue" : "0",
  "dryRun" : true,
  "fieldName" : "cachedCount",
  "file" : "Greeter.ek9",
  "mode" : "structured"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      cachedCount <- 0",
    "endLine" : 7,
    "file" : "Greeter.ek9",
    "startLine" : 7,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "ready",
  "summary" : "Added field 'cachedCount' to Greeter",
  "workspaceHash" : "<workspace-hash>",
  "wouldBeDiagnostics" : [ ],
...

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

Add structured field apply

Request

{
  "constructName" : "Greeter",
  "defaultValue" : "0",
  "fieldName" : "cachedCount",
  "file" : "Greeter.ek9",
  "mode" : "structured"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      cachedCount <- 0",
    "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 field 'cachedCount' to Greeter",
  "workspaceHash" : "<workspace-hash>",
...

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

No type refusal example lands

Request

{
  "rawDeclaration" : "total as Float: Float()",
  "symbol" : "Order"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      total as Float: Float()",
    "endLine" : 8,
    "file" : "task.ek9",
    "startLine" : 8,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/task.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Added field 'total as Float: Float()' to Order",
  "workspaceHash" : "<workspace-hash>",
...

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

See also