Skip to content

Commit e09f561

Browse files
authored
feat: support optional super call (#143)
1 parent 68d15e6 commit e09f561

File tree

4 files changed

+70
-9
lines changed

4 files changed

+70
-9
lines changed

packages/plugin/__test__/__snapshots__/test.js.snap

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,27 @@ exports[`classes class-convert-calling-super-apply.controller.js 1`] = `
4949
},
5050
method: function _method(args) {
5151
Controller.prototype.init.apply(this, args);
52+
Controller.prototype.init?.apply(this, args);
53+
}
54+
});
55+
return MyController;
56+
});"
57+
`;
58+
59+
exports[`classes class-convert-calling-super-method.controller.js 1`] = `
60+
"sap.ui.define(["sap/ui/core/Controller"], function (Controller) {
61+
"use strict";
62+
63+
const MyController = Controller.extend("fixtures.classes.MyController", {
64+
constructor: function _constructor(arg) {
65+
console.log("before super");
66+
Controller.prototype.constructor.call(this, arg);
67+
console.log("after super");
68+
this.x = 1;
69+
},
70+
method: function _method(args) {
71+
Controller.prototype.init.apply(this, [...args]);
72+
Controller.prototype.init?.apply(this, [...args]);
5273
}
5374
});
5475
return MyController;

packages/plugin/__test__/fixtures/classes/class-convert-calling-super-apply.controller.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ export default class MyController extends Controller {
1010

1111
method(args) {
1212
super.init.apply(this, args);
13+
super.init?.apply(this, args);
1314
}
1415
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import Controller from "sap/ui/core/Controller";
2+
3+
export default class MyController extends Controller {
4+
constructor(arg) {
5+
console.log("before super");
6+
super(arg);
7+
console.log("after super");
8+
this.x = 1;
9+
}
10+
11+
method(args) {
12+
super.init(...args);
13+
super.init?.(...args);
14+
}
15+
}

packages/plugin/src/classes/visitor.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export const ClassTransformVisitor = {
109109
/*!
110110
* Visits function calls.
111111
*/
112-
CallExpression(path) {
112+
"OptionalCallExpression|CallExpression"(path) {
113113
const { node } = path;
114114
const { callee } = node;
115115
// If the file already has sap.ui.define, get the names of variables it creates to use for the class logic.
@@ -122,9 +122,19 @@ export const ClassTransformVisitor = {
122122
if (t.isSuper(callee)) {
123123
replaceConstructorSuperCall(path, node, this.superClassName);
124124
} else if (t.isSuper(callee.object)) {
125-
replaceObjectSuperCall(path, node, this.superClassName);
125+
replaceObjectSuperCall(
126+
path,
127+
node,
128+
this.superClassName,
129+
path.isOptionalCallExpression()
130+
);
126131
} else if (isSuperApply(callee)) {
127-
replaceSuperApplyCall(path, node, this.superClassName);
132+
replaceSuperApplyCall(
133+
path,
134+
node,
135+
this.superClassName,
136+
path.isOptionalCallExpression()
137+
);
128138
}
129139
}
130140
},
@@ -175,24 +185,37 @@ function replaceConstructorSuperCall(path, node, superClassName) {
175185
/**
176186
* Replace super.method() call
177187
*/
178-
function replaceObjectSuperCall(path, node, superClassName) {
179-
replaceSuperNamedCall(path, node, superClassName, node.callee.property.name);
188+
function replaceObjectSuperCall(path, node, superClassName, optional = false) {
189+
replaceSuperNamedCall(
190+
path,
191+
node,
192+
superClassName,
193+
node.callee.property.name,
194+
optional
195+
);
180196
}
181197

182198
/**
183199
* Replace super.method.apply() call
184200
*/
185-
function replaceSuperApplyCall(path, node, superClassName) {
201+
function replaceSuperApplyCall(path, node, superClassName, optional = false) {
186202
const methodName = node.callee.object.property.name;
203+
const op = optional ? "?." : ".";
187204
path.replaceWith(
188205
t.callExpression(
189-
t.identifier(`${superClassName}.prototype.${methodName}.apply`),
206+
t.identifier(`${superClassName}.prototype.${methodName}${op}apply`),
190207
node.arguments
191208
)
192209
);
193210
}
194211

195-
function replaceSuperNamedCall(path, node, superClassName, methodName) {
212+
function replaceSuperNamedCall(
213+
path,
214+
node,
215+
superClassName,
216+
methodName,
217+
optional = false
218+
) {
196219
// .call() is better for simple args (or not args) but doesn't work right for spread args
197220
// if it gets further transpiled by babel spread args transform (will be .call.apply(...).
198221
const thisEx = t.thisExpression();
@@ -201,9 +224,10 @@ function replaceSuperNamedCall(path, node, superClassName, methodName) {
201224
const callArgs = hasSpread
202225
? [thisEx, t.arrayExpression(node.arguments)]
203226
: [thisEx, ...node.arguments];
227+
const op = optional ? "?." : ".";
204228
path.replaceWith(
205229
t.callExpression(
206-
t.identifier(`${superClassName}.prototype.${methodName}.${caller}`),
230+
t.identifier(`${superClassName}.prototype.${methodName}${op}${caller}`),
207231
callArgs
208232
)
209233
);

0 commit comments

Comments
 (0)