ek9_push_down

Removes the named methods/operators from a superclass and copies them into each named direct subclass; answers status, edits[] (one DELETE + one INSERT per subclass) and conflicts[] (subclass-not-direct, target-is-only-source-class).

Category: Editor · Compare: Push Members Down (IntelliJ)

When to use it

'Move fly() from Shape down into Eagle and Sparrow' is one call with symbol:'Shape', members:['fly'], subclasses:['Eagle','Sparrow'] - no file or line needed. Use it when a superclass member is only needed by some direct subclasses (the abstraction was over-promoted).

When not to use it

Details

Class hierarchies ONLY, methods/operators ONLY (fields not yet supported); each named DIRECT subclass gets an identical copy of every member (no per-subclass body customisation). 'override' is DROPPED from copies by default (no parent left to override, else E05100); set keepAsOverride:true ONLY for multi-level hierarchies where an ancestor above the source still declares the member. status:conflicts kinds: subclass-not-direct, target-is-only-source-class; external callers reaching the member via the superclass type surface as status:would-fail from the scratch compile.

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.
keepAsOverridebooleanKeep the 'override' modifier on the subclass copies (only for multi-level hierarchies where an ancestor above the superclass still declares the member).
lineinteger1-based line of the declaration or a reference - OMIT it and pass symbol:'<name>' to let the tool find the line (a model counting lines in a file miscounts); if you do count, use ek9_read_file(lineNumbers:true).
membersarray of stringyesNames of methods/operators on the superclass to push down. Operators use their symbol form (e.g. '==', '<=>').
subclassesarray of stringyesNames of DIRECT subclasses to receive the pushed-down members. Empty errors.
symbolstringA construct NAME alone ('Shape', 'sample.deps.core::Validator') - no file needed, the tool finds it workspace-wide; or, with file (+ line), the identifier you mean there.

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.

Subclass not direct conflict

Request

{
  "file" : "shapes.ek9",
  "line" : 6,
  "members" : [ "area" ],
  "subclasses" : [ "Square", "NotASubclass" ]
}

Response

{
  "conflicts" : [ {
    "kind" : "subclass-not-direct",
    "message" : "Not direct subclasses of 'Shape': NotASubclass (direct subclasses: Circle, Square)"
  } ],
  "edits" : [ ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 0,
    "lineCount" : 0,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "conflicts",
  "summary" : "Not all subclasses are direct subclasses of Shape",
  "workspaceHash" : "<workspace-hash>",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Apply to subclass

Request

{
  "file" : "shapes.ek9",
  "line" : 6,
  "members" : [ "area" ],
  "subclasses" : [ "Circle" ]
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "before" : "      area()\n        <- rtn as Float: 0.0",
    "endLine" : 9,
    "file" : "shapes.ek9",
    "startLine" : 8,
    "type" : "delete"
  }, {
    "after" : "\n      area()\n        <- rtn as Float: 0.0",
    "endLine" : 14,
    "file" : "shapes.ek9",
    "startLine" : 14,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "high",
    "fileCount" : 1,
    "lineCount" : 3,
    "touchesPublicApi" : true,
...

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

Dry run ready

Request

{
  "dryRun" : true,
  "file" : "shapes.ek9",
  "line" : 6,
  "members" : [ "area" ],
  "subclasses" : [ "Circle" ]
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "before" : "      area()\n        <- rtn as Float: 0.0",
    "endLine" : 9,
    "file" : "shapes.ek9",
    "startLine" : 8,
    "type" : "delete"
  }, {
    "after" : "\n      area()\n        <- rtn as Float: 0.0",
    "endLine" : 14,
    "file" : "shapes.ek9",
    "startLine" : 14,
    "type" : "insert"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "high",
    "fileCount" : 1,
    "lineCount" : 3,
    "touchesPublicApi" : true,
...

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

See also