ek9_introduce_parameter

Appends a new parameter to the enclosing method/function, replaces the selected in-body expression with it and passes the ORIGINAL expression at every call site (Fowler "Introduce Parameter"); answers status, edits[] and conflicts[] (value-expression-not-a-single-expression, type-not-inferable, ...).

Category: Editor · Compare: Refactor → Introduce Parameter (IntelliJ)

When to use it

'Give greet a parameter greeting and use it instead of the literal "Hello "' is one call with file, expression:'"Hello "' and name:'greeting' - the body uses the parameter and every existing call site is passed the original value. Use it (not ek9_change_signature, which adds the parameter but leaves the body unchanged) when a body hard-codes a value callers should be able to vary - in a statement or in the '<- rtn as T: ...' initialiser.

When not to use it

Details

Parameter type is inferred from the expression unless parameterType is supplied; V1 always APPENDS (no position arg), and when the post-change parameter count reaches 4+ all call sites are rewritten to named-argument form per E11062. Promoting in a method that overrides a trait/supertype contract resolves to the root contract and cascades the parameter across the whole override family (resolved-to-contract advisory). would-fail (gate-caught): the expression references a method-local unresolvable at call sites (E50001) or hides impurity in a pure method (E08130); conflicts: value-expression-not-a-single-expression (bad/partial span), expression-not-in-body, type-not-inferable (supply parameterType), no-promotable-declaration; a name colliding with an existing parameter is an error.

Arguments

ArgumentTypeRequiredWhat it is
endColumninteger1-based EXCLUSIVE column of the END of the span (an IDE selection). Omit it - pass the text instead.
expressionstringThe expression to turn into the parameter, exactly as written (e.g. '"Hello "' - quotes included for a string). Its first occurrence in file, or on 'line' when given.
filestringyesWorkspace-relative path to the .ek9 source file holding the expression (and its enclosing method/function).
lineintegerOptional 1-based line holding the expression - when it occurs more than once.
namestringyesIdentifier for the new parameter (camelCase by convention); kept verbatim. Rename later with ek9_rename_symbol.
parameterTypestringOptional explicit parameter type. Inferred from the expression when omitted; supply when inference yields type-not-inferable or you want a wider type than the expression's.
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 9 recorded are shown.

Introduce bad span conflict

Request

{
  "dryRun" : true,
  "endColumn" : 17,
  "file" : "Report.ek9",
  "line" : 8,
  "newParameterName" : "amount",
  "startColumn" : 16
}

Response

{
  "conflicts" : [ {
    "kind" : "value-expression-not-a-single-expression",
    "message" : "The range on line 8 (columns 16–17) does not span a single complete EK9 expression. Adjust startColumn/endColumn to the exact bounds of one expression."
  } ],
  "edits" : [ ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 0,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "conflicts",
  "summary" : "Cannot introduce parameter on function report — 1 conflict",
  "workspaceHash" : "<workspace-hash>",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Field rebound at caller

Request

{
  "endColumn" : 32,
  "file" : "Tax.ek9",
  "line" : 11,
  "newParameterName" : "rate",
  "startColumn" : 25
}

Response

{
  "conflicts" : [ {
    "col" : 35,
    "file" : "<workspace-root>/Tax.ek9",
    "kind" : "threaded-value-changes-meaning",
    "line" : 20,
    "message" : "`taxRate` is the property `taxRate` declared on line 6 here, but at this call site it would read the property `taxRate` declared on line 17. Not changed: pass this caller its own value with ek9_change_signature (add-parameter with valueForExistingCalls), or introduce the parameter from an expression that reads only values every caller can see."
  } ],
  "edits" : [ ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 0,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "conflicts",
  "summary" : "Cannot introduce parameter on method charge — 1 conflict",
  "workspaceHash" : "<workspace-hash>",
  "wouldBeDiagnostics" : [ ],
...

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

Introduce promote local apply

Request

{
  "endColumn" : 18,
  "file" : "Report.ek9",
  "line" : 8,
  "newParameterName" : "total",
  "startColumn" : 7
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "before" : "      total <- 10",
    "endLine" : 8,
    "file" : "Report.ek9",
    "startLine" : 8,
    "type" : "delete"
  }, {
    "after" : "    report()\n      ->\n        label as String\n        total as Integer",
    "before" : "    report()\n      -> label as String",
    "endLine" : 6,
    "file" : "Report.ek9",
    "startLine" : 5,
    "type" : "replace"
  }, {
    "after" : "      report(\"a\", 10)",
    "before" : "      report(\"a\")",
    "endLine" : 13,
    "file" : "Report.ek9",
    "startLine" : 13,
    "type" : "replace"
  }, {
    "after" : "      report(\"b\", 10)",
...

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

See also