@@ -222,60 +222,24 @@ export function convertClassToUI5Extend(
222
222
// @transformControllerExtension marker, because it is not a type assignment. In the resulting code, the
223
223
// "ControllerExtension.use(...)" part should be removed and the content of the brackets should be assigned
224
224
// directly to the member property.
225
+ const rightSide = member . value ;
226
+ if ( isCallToControllerExtensionUse ( rightSide , memberPath ) ) {
227
+ member . value = rightSide . arguments [ 0 ] ;
228
+ extendProps . unshift ( buildObjectProperty ( member ) ) ; // add it to the properties of the extend() config object
229
+ continue ; // prevent the member from also being added to the constructor
230
+ }
231
+
232
+ // code instrumentation sometimes wraps ControllerExtension.use() calls like:
233
+ // this.routing = (cov_1uvvg22e7l().s[5]++, ControllerExtension.use(Routing.override({ … })));
225
234
if (
226
- t . isCallExpression ( member . value ) ||
227
- t . isSequenceExpression ( member . value )
235
+ t . isSequenceExpression ( rightSide ) &&
236
+ rightSide . expressions . some ( ( expression ) =>
237
+ isCallToControllerExtensionUse ( expression , memberPath )
238
+ )
228
239
) {
229
- let callExpression = member . value ;
230
-
231
- // code instrumentation sometimes wraps it like:
232
- // this.routing = (cov_1uvvg22e7l().s[5]++, ControllerExtension.use(Routing.override({ … })));
233
- if ( t . isSequenceExpression ( member . value ) ) {
234
- // iterate through the expressions in the sequence
235
- for ( const expr of member . value . expressions ) {
236
- if ( t . isCallExpression ( expr ) ) {
237
- callExpression = expr ;
238
- break ;
239
- }
240
- }
241
- }
242
-
243
- if ( t . isCallExpression ( callExpression ) ) {
244
- const callee = callExpression . callee ;
245
- if (
246
- t . isMemberExpression ( callee ) &&
247
- t . isIdentifier ( callee . object ) &&
248
- t . isIdentifier ( callee . property ) &&
249
- callee . property . name === "use" // we are looking for "ControllerExtension.use(...)"
250
- ) {
251
- const importDeclaration = getImportDeclaration (
252
- memberPath ?. hub ?. file ?. opts ?. filename ,
253
- callee ?. object ?. name // usually, but not necessarily always: "ControllerExtension"...
254
- ) ;
255
- // ...hence we rather look at the imported module name to be sure
256
- if (
257
- importDeclaration ?. source ?. value ===
258
- "sap/ui/core/mvc/ControllerExtension"
259
- ) {
260
- if (
261
- ! callExpression . arguments ||
262
- callExpression . arguments . length !== 1
263
- ) {
264
- // exactly one argument must be there
265
- throw memberPath . buildCodeFrameError (
266
- `ControllerExtension.use() must be called with exactly one argument but has ${
267
- callExpression . arguments
268
- ? callExpression . arguments . length
269
- : 0
270
- } `
271
- ) ;
272
- }
273
- member . value = callExpression . arguments [ 0 ] ;
274
- extendProps . unshift ( buildObjectProperty ( member ) ) ; // add it to the properties of the extend() config object
275
- continue ; // prevent the member from also being added to the constructor
276
- }
277
- }
278
- }
240
+ member . value = rightSide ;
241
+ extendProps . unshift ( buildObjectProperty ( member ) ) ; // add it to the properties of the extend() config object
242
+ continue ; // prevent the member from also being added to the constructor
279
243
}
280
244
281
245
// Special handling for TypeScript limitation where metadata, renderer and overrides must be properties.
@@ -314,6 +278,47 @@ export function convertClassToUI5Extend(
314
278
}
315
279
}
316
280
281
+ /**
282
+ * Checks whether the given thing is a CallExpression that calls ControllerExtension.use(...)
283
+ *
284
+ * @param {* } expression the thing to check - does not need to be a CallExpression
285
+ * @param {string } memberPath
286
+ * @returns true if the given expression is a CallExpression that calls ControllerExtension.use(...)
287
+ */
288
+ function isCallToControllerExtensionUse ( expression , memberPath ) {
289
+ if ( ! t . isCallExpression ( expression ) ) {
290
+ return false ;
291
+ }
292
+ const callee = expression . callee ;
293
+ if (
294
+ t . isMemberExpression ( callee ) &&
295
+ t . isIdentifier ( callee . object ) &&
296
+ t . isIdentifier ( callee . property ) &&
297
+ callee . property . name === "use" // we are looking for "ControllerExtension.use(...)"
298
+ ) {
299
+ const importDeclaration = getImportDeclaration (
300
+ memberPath ?. hub ?. file ?. opts ?. filename ,
301
+ callee ?. object ?. name // usually, but not necessarily always: "ControllerExtension"...
302
+ ) ;
303
+ // ...hence we rather look at the imported module name to be sure
304
+ if (
305
+ importDeclaration ?. source ?. value ===
306
+ "sap/ui/core/mvc/ControllerExtension"
307
+ ) {
308
+ if ( ! expression . arguments || expression . arguments . length !== 1 ) {
309
+ // exactly one argument must be there
310
+ throw memberPath . buildCodeFrameError (
311
+ `ControllerExtension.use() must be called with exactly one argument but has ${
312
+ expression . arguments ? expression . arguments . length : 0
313
+ } `
314
+ ) ;
315
+ }
316
+ return true ;
317
+ }
318
+ }
319
+ return false ; // return false if not a match
320
+ }
321
+
317
322
// Arrow function properties need to get moved to the constructor so that
318
323
// they're bound properly to the class instance, to align with the spec.
319
324
// For controllers, use onInit rather than constructor, since controller constructors don't work.
0 commit comments