@ui5/builder 3.0.0-alpha.8 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.reuse/dep5 +2 -2
- package/CHANGELOG.md +50 -2
- package/CONTRIBUTING.md +1 -1
- package/README.md +4 -4
- package/jsdoc.json +2 -2
- package/lib/lbt/UI5ClientConstants.js +7 -8
- package/lib/lbt/analyzer/ComponentAnalyzer.js +60 -22
- package/lib/lbt/analyzer/FioriElementsAnalyzer.js +31 -20
- package/lib/lbt/analyzer/JSModuleAnalyzer.js +107 -65
- package/lib/lbt/analyzer/SmartTemplateAnalyzer.js +31 -20
- package/lib/lbt/analyzer/XMLCompositeAnalyzer.js +35 -25
- package/lib/lbt/analyzer/XMLTemplateAnalyzer.js +71 -18
- package/lib/lbt/analyzer/analyzeLibraryJS.js +22 -6
- package/lib/lbt/bundle/AutoSplitter.js +10 -11
- package/lib/lbt/bundle/Builder.js +33 -36
- package/lib/lbt/bundle/BundleDefinition.js +1 -5
- package/lib/lbt/bundle/BundleWriter.js +1 -2
- package/lib/lbt/bundle/ResolvedBundleDefinition.js +6 -7
- package/lib/lbt/bundle/Resolver.js +11 -12
- package/lib/lbt/calls/SapUiDefine.js +16 -11
- package/lib/lbt/graph/dependencyGraph.js +3 -4
- package/lib/lbt/graph/dominatorTree.js +3 -3
- package/lib/lbt/graph/topologicalSort.js +3 -3
- package/lib/lbt/resources/LibraryFileAnalyzer.js +5 -8
- package/lib/lbt/resources/LocatorResource.js +2 -2
- package/lib/lbt/resources/LocatorResourcePool.js +3 -3
- package/lib/lbt/resources/ModuleInfo.js +1 -2
- package/lib/lbt/resources/Resource.js +3 -4
- package/lib/lbt/resources/ResourceCollector.js +7 -8
- package/lib/lbt/resources/ResourceFilterList.js +38 -40
- package/lib/lbt/resources/ResourceInfo.js +1 -1
- package/lib/lbt/resources/ResourceInfoList.js +5 -3
- package/lib/lbt/resources/ResourcePool.js +15 -21
- package/lib/lbt/utils/ASTUtils.js +58 -44
- package/lib/lbt/utils/JSTokenizer.js +4 -4
- package/lib/lbt/utils/ModuleName.js +10 -20
- package/lib/lbt/utils/escapePropertiesFile.js +3 -3
- package/lib/lbt/utils/parseUtils.js +4 -10
- package/lib/processors/bootstrapHtmlTransformer.js +15 -7
- package/lib/processors/bundlers/flexChangesBundler.js +16 -8
- package/lib/processors/bundlers/manifestBundler.js +19 -10
- package/lib/processors/bundlers/moduleBundler.js +26 -15
- package/lib/processors/jsdoc/apiIndexGenerator.js +16 -9
- package/lib/processors/jsdoc/jsdocGenerator.js +31 -17
- package/lib/processors/jsdoc/lib/{createIndexFiles.js → createIndexFiles.cjs} +0 -0
- package/lib/processors/jsdoc/lib/{transformApiJson.js → transformApiJson.cjs} +58 -2
- package/lib/processors/jsdoc/lib/ui5/{plugin.js → plugin.cjs} +306 -119
- package/lib/processors/jsdoc/lib/ui5/template/{publish.js → publish.cjs} +1 -1
- package/lib/processors/jsdoc/lib/ui5/template/utils/{versionUtil.js → versionUtil.cjs} +0 -0
- package/lib/processors/jsdoc/sdkTransformer.js +18 -11
- package/lib/processors/libraryLessGenerator.js +28 -16
- package/lib/processors/manifestCreator.js +14 -13
- package/lib/processors/minifier.js +22 -16
- package/lib/processors/nonAsciiEscaper.js +16 -6
- package/lib/processors/resourceListCreator.js +13 -13
- package/lib/processors/stringReplacer.js +13 -6
- package/lib/processors/themeBuilder.js +33 -24
- package/lib/processors/versionInfoGenerator.js +33 -23
- package/lib/tasks/buildThemes.js +18 -11
- package/lib/tasks/bundlers/generateBundle.js +23 -12
- package/lib/tasks/bundlers/generateComponentPreload.js +18 -10
- package/lib/tasks/bundlers/generateFlexChangesBundle.js +16 -8
- package/lib/tasks/bundlers/generateLibraryPreload.js +22 -12
- package/lib/tasks/bundlers/generateManifestBundle.js +15 -6
- package/lib/tasks/bundlers/generateStandaloneAppBundle.js +21 -13
- package/lib/tasks/bundlers/utils/createModuleNameMapping.js +6 -6
- package/lib/tasks/escapeNonAsciiCharacters.js +12 -5
- package/lib/tasks/generateCachebusterInfo.js +16 -8
- package/lib/tasks/generateLibraryManifest.js +14 -8
- package/lib/tasks/generateResourcesJson.js +15 -9
- package/lib/tasks/generateThemeDesignerResources.js +19 -9
- package/lib/tasks/generateVersionInfo.js +12 -5
- package/lib/tasks/jsdoc/executeJsdocSdkTransformation.js +17 -9
- package/lib/tasks/jsdoc/generateApiIndex.js +16 -10
- package/lib/tasks/jsdoc/generateJsdoc.js +131 -119
- package/lib/tasks/minify.js +14 -7
- package/lib/tasks/replaceBuildtime.js +12 -5
- package/lib/tasks/replaceCopyright.js +12 -5
- package/lib/tasks/replaceVersion.js +12 -5
- package/lib/tasks/taskRepository.js +24 -29
- package/lib/tasks/transformBootstrapHtml.js +6 -5
- package/package.json +33 -18
- package/index.js +0 -177
- package/lib/tasks/TaskUtil.js +0 -237
|
@@ -53,7 +53,14 @@
|
|
|
53
53
|
*/
|
|
54
54
|
|
|
55
55
|
/* imports */
|
|
56
|
-
const Syntax =
|
|
56
|
+
const Syntax = {
|
|
57
|
+
// Those are currently not in the syntax.js file.
|
|
58
|
+
ChainExpression: "ChainExpression",
|
|
59
|
+
OptionalMemberExpression: "OptionalMemberExpression",
|
|
60
|
+
OptionalCallExpression: "OptionalCallExpression",
|
|
61
|
+
|
|
62
|
+
...require("jsdoc/src/syntax").Syntax,
|
|
63
|
+
};
|
|
57
64
|
const Doclet = require('jsdoc/doclet').Doclet;
|
|
58
65
|
const fs = require('jsdoc/fs');
|
|
59
66
|
const path = require('jsdoc/path');
|
|
@@ -234,9 +241,8 @@ function resolveModuleName(base, name) {
|
|
|
234
241
|
function analyzeModuleDefinition(node) {
|
|
235
242
|
const args = node.arguments;
|
|
236
243
|
let arg = 0;
|
|
237
|
-
if ( arg < args.length
|
|
238
|
-
|
|
239
|
-
currentModule.name = args[arg].value;
|
|
244
|
+
if ( arg < args.length && isStringLiteral(args[arg]) ) {
|
|
245
|
+
currentModule.name = convertValue(args[arg]);
|
|
240
246
|
warning(`module explicitly defined a module name '${currentModule.name}'`);
|
|
241
247
|
const resourceModuleName = getModuleName(currentModule.resource);
|
|
242
248
|
if (currentModule.name !== resourceModuleName) {
|
|
@@ -249,13 +255,19 @@ function analyzeModuleDefinition(node) {
|
|
|
249
255
|
currentModule.dependencies = convertValue(args[arg], "string[]");
|
|
250
256
|
arg++;
|
|
251
257
|
}
|
|
252
|
-
if ( arg < args.length &&
|
|
258
|
+
if ( arg < args.length &&
|
|
259
|
+
[Syntax.FunctionExpression, Syntax.ArrowFunctionExpression].includes(args[arg].type)) {
|
|
260
|
+
|
|
253
261
|
currentModule.factory = args[arg];
|
|
254
262
|
arg++;
|
|
255
263
|
}
|
|
256
264
|
if ( currentModule.dependencies && currentModule.factory ) {
|
|
257
265
|
for ( let i = 0; i < currentModule.dependencies.length && i < currentModule.factory.params.length; i++ ) {
|
|
258
|
-
const name =
|
|
266
|
+
const name =
|
|
267
|
+
(currentModule.factory.params[i].type === Syntax.ObjectPattern)
|
|
268
|
+
? currentModule.factory.params[i].properties[0].value.name // ObjectPattern means destructuring of the parameter
|
|
269
|
+
: currentModule.factory.params[i].name; // simple Identifier
|
|
270
|
+
|
|
259
271
|
const module = resolveModuleName(currentModule.module, currentModule.dependencies[i]);
|
|
260
272
|
debug(` import ${name} from '${module}'`);
|
|
261
273
|
currentModule.localNames[name] = {
|
|
@@ -265,7 +277,7 @@ function analyzeModuleDefinition(node) {
|
|
|
265
277
|
}
|
|
266
278
|
}
|
|
267
279
|
if ( currentModule.factory ) {
|
|
268
|
-
collectShortcuts(currentModule.factory
|
|
280
|
+
collectShortcuts(currentModule.factory);
|
|
269
281
|
}
|
|
270
282
|
}
|
|
271
283
|
|
|
@@ -276,16 +288,19 @@ function analyzeModuleDefinition(node) {
|
|
|
276
288
|
*
|
|
277
289
|
* @param {ASTNode} body AST node of a function body that shall be searched for shortcuts
|
|
278
290
|
*/
|
|
279
|
-
function collectShortcuts(
|
|
291
|
+
function collectShortcuts(factory) {
|
|
292
|
+
const body = factory.body;
|
|
280
293
|
|
|
281
294
|
function checkAssignment(name, valueNode) {
|
|
295
|
+
valueNode = resolvePotentialWrapperExpression(valueNode);
|
|
296
|
+
|
|
282
297
|
if ( valueNode.type === Syntax.Literal ) {
|
|
283
298
|
currentModule.localNames[name] = {
|
|
284
299
|
value: valueNode.value,
|
|
285
300
|
raw: valueNode.raw
|
|
286
301
|
};
|
|
287
302
|
debug("compile time constant found ", name, valueNode.value);
|
|
288
|
-
} else if ( valueNode
|
|
303
|
+
} else if ( isMemberExpression(valueNode) ) {
|
|
289
304
|
const _import = getLeftmostName(valueNode);
|
|
290
305
|
const local = _import && currentModule.localNames[_import];
|
|
291
306
|
const objectName = getObjectName(valueNode);
|
|
@@ -297,11 +312,9 @@ function collectShortcuts(body) {
|
|
|
297
312
|
debug(` found local shortcut: ${name} ${currentModule.localNames[name]}`);
|
|
298
313
|
}
|
|
299
314
|
} else if ( isRequireSyncCall(valueNode) || isProbingRequireCall(valueNode) ) {
|
|
300
|
-
if ( valueNode.arguments[0]
|
|
301
|
-
&& valueNode.arguments[0].type === Syntax.Literal
|
|
302
|
-
&& typeof valueNode.arguments[0].value === 'string' ) {
|
|
315
|
+
if ( valueNode.arguments[0] && isStringLiteral(valueNode.arguments[0]) ) {
|
|
303
316
|
currentModule.localNames[name] = {
|
|
304
|
-
module: valueNode.arguments[0]
|
|
317
|
+
module: convertValue(valueNode.arguments[0])
|
|
305
318
|
// no (or empty) path
|
|
306
319
|
};
|
|
307
320
|
debug(` found local import: ${name} = ${valueNode.callee.property.name}('${valueNode.arguments[0].value}')`);
|
|
@@ -315,8 +328,8 @@ function collectShortcuts(body) {
|
|
|
315
328
|
}
|
|
316
329
|
}
|
|
317
330
|
|
|
318
|
-
if ( body.type === Syntax.BlockStatement ) {
|
|
319
|
-
|
|
331
|
+
if ( body.type === Syntax.BlockStatement || isArrowFuncExpression(factory) ) {
|
|
332
|
+
const itemsResolver = function ( stmt ) {
|
|
320
333
|
// console.log(stmt);
|
|
321
334
|
if ( stmt.type === Syntax.FunctionDeclaration ) {
|
|
322
335
|
if ( stmt.id && stmt.id.type === Syntax.Identifier && stmt.loc && stmt.loc.start ) {
|
|
@@ -336,15 +349,28 @@ function collectShortcuts(body) {
|
|
|
336
349
|
&& stmt.expression.type === Syntax.AssignmentExpression
|
|
337
350
|
&& stmt.expression.left.type === Syntax.Identifier ) {
|
|
338
351
|
checkAssignment(stmt.expression.left.name, stmt.expression.right);
|
|
339
|
-
} else if ( stmt
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
352
|
+
} else if ( isReturningNode(stmt) ) {
|
|
353
|
+
const stmtArgument = isArrowFuncExpression(stmt)
|
|
354
|
+
? stmt.body
|
|
355
|
+
: resolvePotentialWrapperExpression(stmt).argument;
|
|
356
|
+
|
|
357
|
+
if ( stmtArgument && stmtArgument.type === Syntax.Identifier ) {
|
|
358
|
+
currentModule.defaultExport = stmtArgument.name;
|
|
359
|
+
} else if ( stmtArgument && stmtArgument.type === Syntax.ClassExpression && stmtArgument.id && stmtArgument.id.type === Syntax.Identifier ) {
|
|
360
|
+
debug(` found default export class definition: return class '${stmtArgument.id.name}'`);
|
|
361
|
+
currentModule.defaultExportClass = stmtArgument.id.name;
|
|
362
|
+
} else if ( stmtArgument && isExtendCall(stmtArgument) ) {
|
|
363
|
+
debug(` found default export class definition: return .extend('${stmtArgument.arguments[0].value}', ...)`);
|
|
364
|
+
currentModule.defaultExportClass = convertValue(stmtArgument.arguments[0]);
|
|
345
365
|
}
|
|
346
366
|
}
|
|
347
|
-
}
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
if (isArrowFuncExpression(factory)) {
|
|
370
|
+
itemsResolver(factory);
|
|
371
|
+
} else {
|
|
372
|
+
body.body.forEach(itemsResolver);
|
|
373
|
+
}
|
|
348
374
|
}
|
|
349
375
|
|
|
350
376
|
if ( currentModule.defaultExport && currentModule.localNames[currentModule.defaultExport] ) {
|
|
@@ -369,12 +395,12 @@ function guessSingularName(sPluralName) {
|
|
|
369
395
|
}
|
|
370
396
|
|
|
371
397
|
function getPropertyKey(prop) {
|
|
372
|
-
if ( prop.
|
|
398
|
+
if ( prop.type === Syntax.SpreadElement ) {
|
|
399
|
+
return;
|
|
400
|
+
} else if ( prop.key.type === Syntax.Identifier && prop.computed !== true ) {
|
|
373
401
|
return prop.key.name;
|
|
374
402
|
} else if ( prop.key.type === Syntax.Literal ) {
|
|
375
403
|
return String(prop.key.value);
|
|
376
|
-
} else {
|
|
377
|
-
return prop.key.toSource();
|
|
378
404
|
}
|
|
379
405
|
}
|
|
380
406
|
|
|
@@ -432,80 +458,180 @@ function createPropertyMap(node, defaultKey) {
|
|
|
432
458
|
return result;
|
|
433
459
|
}
|
|
434
460
|
|
|
461
|
+
/**
|
|
462
|
+
* Resolves potential wrapper expressions like: ChainExpression, AwaitExpression, etc.
|
|
463
|
+
* @param {Node} node
|
|
464
|
+
* @returns {Node} the resolved node
|
|
465
|
+
*/
|
|
466
|
+
function resolvePotentialWrapperExpression(node) {
|
|
467
|
+
switch (node && node.type) {
|
|
468
|
+
case Syntax.ChainExpression:
|
|
469
|
+
return node.expression;
|
|
470
|
+
|
|
471
|
+
case Syntax.AwaitExpression:
|
|
472
|
+
return node.argument;
|
|
473
|
+
|
|
474
|
+
case Syntax.ExpressionStatement:
|
|
475
|
+
if ( node.expression.type === Syntax.YieldExpression ) {
|
|
476
|
+
return node.expression.argument.type === Syntax.UpdateExpression
|
|
477
|
+
? node.expression.argument
|
|
478
|
+
: node.expression;
|
|
479
|
+
}
|
|
480
|
+
default:
|
|
481
|
+
return node;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Strips the ChainExpression wrapper if such
|
|
487
|
+
*
|
|
488
|
+
* @param {Node} rootNode
|
|
489
|
+
* @param {String} path
|
|
490
|
+
* @returns {Node}
|
|
491
|
+
*/
|
|
492
|
+
function stripChainWrappers(rootNode, path) {
|
|
493
|
+
const strip = (node) =>
|
|
494
|
+
node && node.type === Syntax.ChainExpression ? node.expression : node;
|
|
495
|
+
|
|
496
|
+
let curNode = strip(rootNode);
|
|
497
|
+
let chunks = path && path.split(".");
|
|
498
|
+
let name;
|
|
499
|
+
|
|
500
|
+
while (chunks && chunks.length) {
|
|
501
|
+
name = chunks.shift();
|
|
502
|
+
curNode = curNode && strip(curNode[name]);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return curNode;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function isTemplateLiteralWithoutExpression(node) {
|
|
509
|
+
return (
|
|
510
|
+
node?.type === Syntax.TemplateLiteral &&
|
|
511
|
+
node?.expressions?.length === 0 &&
|
|
512
|
+
node?.quasis?.length === 1
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Checks whether a node is Literal or TemplateLiteral without an expression
|
|
518
|
+
*
|
|
519
|
+
* @param {Node} node
|
|
520
|
+
* @returns {String}
|
|
521
|
+
*/
|
|
522
|
+
function isStringLiteral(node) {
|
|
523
|
+
return (
|
|
524
|
+
(node && node.type === Syntax.Literal && typeof node.value === "string")
|
|
525
|
+
|| isTemplateLiteralWithoutExpression(node)
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function isMemberExpression(node) {
|
|
530
|
+
return node && [Syntax.MemberExpression, Syntax.OptionalMemberExpression].includes(node.type);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function isCaleeMemberExpression(node) {
|
|
534
|
+
return (
|
|
535
|
+
node &&
|
|
536
|
+
[Syntax.CallExpression, Syntax.OptionalCallExpression].includes(node.type) &&
|
|
537
|
+
isMemberExpression(node.callee)
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
435
541
|
function isExtendCall(node) {
|
|
542
|
+
node = stripChainWrappers(node);
|
|
436
543
|
|
|
437
544
|
return (
|
|
438
545
|
node
|
|
439
|
-
&& node
|
|
440
|
-
&& node
|
|
441
|
-
&& node
|
|
442
|
-
&& node.callee.property.name === 'extend'
|
|
546
|
+
&& isCaleeMemberExpression(node)
|
|
547
|
+
&& stripChainWrappers(node, "callee.property").type === Syntax.Identifier
|
|
548
|
+
&& stripChainWrappers(node, "callee.property").name === 'extend'
|
|
443
549
|
&& node.arguments.length >= 2
|
|
444
|
-
&& node.arguments[0]
|
|
445
|
-
&& typeof node.arguments[0].value === "string"
|
|
550
|
+
&& isStringLiteral(node.arguments[0])
|
|
446
551
|
&& node.arguments[1].type === Syntax.ObjectExpression
|
|
447
552
|
);
|
|
448
553
|
|
|
449
554
|
}
|
|
450
555
|
|
|
556
|
+
function isArrowFuncExpression(node) {
|
|
557
|
+
return (
|
|
558
|
+
node &&
|
|
559
|
+
node.type === Syntax.ArrowFunctionExpression &&
|
|
560
|
+
node.expression === true
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Checks whether the node is of a "returning" type
|
|
566
|
+
*
|
|
567
|
+
* @param {Node} node
|
|
568
|
+
* @returns {Boolean}
|
|
569
|
+
*/
|
|
570
|
+
function isReturningNode(node) {
|
|
571
|
+
return (node && node.type === Syntax.ReturnStatement)
|
|
572
|
+
|| (node && node.type === Syntax.ExpressionStatement && node.expression.type === Syntax.YieldExpression)
|
|
573
|
+
|| isArrowFuncExpression(node);
|
|
574
|
+
}
|
|
575
|
+
|
|
451
576
|
function isSapUiDefineCall(node) {
|
|
452
577
|
|
|
453
578
|
return (
|
|
454
|
-
node
|
|
455
|
-
&& node
|
|
456
|
-
&& node
|
|
457
|
-
&& node
|
|
458
|
-
&& node
|
|
459
|
-
&& node
|
|
460
|
-
&& node
|
|
461
|
-
&& node
|
|
462
|
-
&& node
|
|
463
|
-
&& node.callee.property.name === 'define'
|
|
579
|
+
stripChainWrappers(node)
|
|
580
|
+
&& isCaleeMemberExpression(stripChainWrappers(node))
|
|
581
|
+
&& isMemberExpression(stripChainWrappers(node, "callee.object"))
|
|
582
|
+
&& stripChainWrappers(node, "callee.property").type === Syntax.Identifier
|
|
583
|
+
&& stripChainWrappers(node, "callee.property").name === 'define'
|
|
584
|
+
&& stripChainWrappers(node, "callee.object.object").type === Syntax.Identifier
|
|
585
|
+
&& stripChainWrappers(node, "callee.object.object").name === 'sap'
|
|
586
|
+
&& stripChainWrappers(node, "callee.object.property").type === Syntax.Identifier
|
|
587
|
+
&& stripChainWrappers(node, "callee.object.property").name === 'ui'
|
|
464
588
|
);
|
|
465
589
|
|
|
466
590
|
}
|
|
467
591
|
|
|
468
592
|
function isCreateDataTypeCall(node) {
|
|
593
|
+
node = stripChainWrappers(node);
|
|
594
|
+
|
|
469
595
|
return (
|
|
470
596
|
node
|
|
471
|
-
&& node
|
|
472
|
-
&& node
|
|
473
|
-
&&
|
|
474
|
-
&& node
|
|
475
|
-
&& node.callee.property.name === 'createType'
|
|
597
|
+
&& isCaleeMemberExpression(node)
|
|
598
|
+
&& getResolvedObjectName(stripChainWrappers(node, "callee.object")) === "sap.ui.base.DataType"
|
|
599
|
+
&& stripChainWrappers(node, "callee.property").type === Syntax.Identifier
|
|
600
|
+
&& stripChainWrappers(node, "callee.property").name === 'createType'
|
|
476
601
|
);
|
|
477
602
|
}
|
|
478
603
|
|
|
479
604
|
function isRequireSyncCall(node) {
|
|
605
|
+
node = stripChainWrappers(node);
|
|
606
|
+
|
|
480
607
|
return (
|
|
481
608
|
node
|
|
482
|
-
&& node
|
|
483
|
-
&& node
|
|
484
|
-
&& node
|
|
485
|
-
&& node
|
|
486
|
-
&& node
|
|
487
|
-
&& node
|
|
488
|
-
&& node
|
|
489
|
-
&& node
|
|
490
|
-
&& node.callee.property.name === 'requireSync'
|
|
609
|
+
&& isCaleeMemberExpression(node)
|
|
610
|
+
&& isMemberExpression( stripChainWrappers(node, "callee.object") )
|
|
611
|
+
&& stripChainWrappers(node, "callee.object.object").type === Syntax.Identifier
|
|
612
|
+
&& stripChainWrappers(node, "callee.object.object").name === 'sap'
|
|
613
|
+
&& stripChainWrappers(node, "callee.object.property").type === Syntax.Identifier
|
|
614
|
+
&& stripChainWrappers(node, "callee.object.property").name === 'ui'
|
|
615
|
+
&& stripChainWrappers(node, "callee.property").type === Syntax.Identifier
|
|
616
|
+
&& stripChainWrappers(node, "callee.property").name === 'requireSync'
|
|
491
617
|
);
|
|
492
618
|
}
|
|
493
619
|
|
|
494
620
|
function isProbingRequireCall(node) {
|
|
621
|
+
node = stripChainWrappers(node);
|
|
622
|
+
|
|
495
623
|
return (
|
|
496
624
|
node
|
|
497
|
-
&& node
|
|
498
|
-
&& node
|
|
499
|
-
&& node
|
|
500
|
-
&& node
|
|
501
|
-
&& node
|
|
502
|
-
&& node
|
|
503
|
-
&& node
|
|
504
|
-
&& node
|
|
505
|
-
&& node.callee.property.name === 'require'
|
|
625
|
+
&& isCaleeMemberExpression(node)
|
|
626
|
+
&& isMemberExpression( stripChainWrappers(node, "callee.object") )
|
|
627
|
+
&& stripChainWrappers(node, "callee.object.object").type === Syntax.Identifier
|
|
628
|
+
&& stripChainWrappers(node, "callee.object.object").name === 'sap'
|
|
629
|
+
&& stripChainWrappers(node, "callee.object.property").type === Syntax.Identifier
|
|
630
|
+
&& stripChainWrappers(node, "callee.object.property").name === 'ui'
|
|
631
|
+
&& stripChainWrappers(node, "callee.property").type === Syntax.Identifier
|
|
632
|
+
&& stripChainWrappers(node, "callee.property").name === 'require'
|
|
506
633
|
&& node.arguments.length === 1
|
|
507
|
-
&& node.arguments[0]
|
|
508
|
-
&& typeof node.arguments[0].value === 'string' // TODO generalize to statically analyzable constants
|
|
634
|
+
&& isStringLiteral(node.arguments[0])
|
|
509
635
|
);
|
|
510
636
|
}
|
|
511
637
|
|
|
@@ -521,7 +647,7 @@ function isCompileTimeConstant(node) {
|
|
|
521
647
|
}
|
|
522
648
|
|
|
523
649
|
function getObjectName(node) {
|
|
524
|
-
if ( node
|
|
650
|
+
if ( isMemberExpression(node) && !node.computed && node.property.type === Syntax.Identifier ) {
|
|
525
651
|
const prefix = getObjectName(node.object);
|
|
526
652
|
return prefix ? prefix + "." + node.property.name : null;
|
|
527
653
|
} else if ( node.type === Syntax.Identifier ) {
|
|
@@ -536,7 +662,7 @@ function getObjectName(node) {
|
|
|
536
662
|
* returns the leftmost identifier a
|
|
537
663
|
*/
|
|
538
664
|
function getLeftmostName(node) {
|
|
539
|
-
while ( node
|
|
665
|
+
while ( isMemberExpression(node) ) {
|
|
540
666
|
node = node.object;
|
|
541
667
|
}
|
|
542
668
|
if ( node.type === Syntax.Identifier ) {
|
|
@@ -604,7 +730,7 @@ function convertValueWithRaw(node, type, propertyName) {
|
|
|
604
730
|
raw: node.operator + node.argument.raw
|
|
605
731
|
};
|
|
606
732
|
|
|
607
|
-
} else if ( node
|
|
733
|
+
} else if ( isMemberExpression(node) && type ) {
|
|
608
734
|
|
|
609
735
|
// enum value (a.b.c)
|
|
610
736
|
value = getResolvedObjectName(node);
|
|
@@ -674,6 +800,11 @@ function convertValueWithRaw(node, type, propertyName) {
|
|
|
674
800
|
};
|
|
675
801
|
}
|
|
676
802
|
|
|
803
|
+
} else if ( isTemplateLiteralWithoutExpression(node) ) {
|
|
804
|
+
return {
|
|
805
|
+
value: node?.quasis?.[0]?.value?.cooked,
|
|
806
|
+
raw: node?.quasis?.[0]?.value?.raw,
|
|
807
|
+
};
|
|
677
808
|
}
|
|
678
809
|
|
|
679
810
|
value = "...see text or source";
|
|
@@ -697,10 +828,10 @@ function convertStringArray(node) {
|
|
|
697
828
|
}
|
|
698
829
|
const result = [];
|
|
699
830
|
for ( let i = 0; i < node.elements.length; i++ ) {
|
|
700
|
-
if ( node.elements[i]
|
|
831
|
+
if ( !isStringLiteral(node.elements[i]) ) {
|
|
701
832
|
throw new Error("not a string literal");
|
|
702
833
|
}
|
|
703
|
-
result.push(node.elements[i]
|
|
834
|
+
result.push( convertValue(node.elements[i]) );
|
|
704
835
|
}
|
|
705
836
|
// console.log(result);
|
|
706
837
|
return result;
|
|
@@ -736,7 +867,7 @@ function collectClassInfo(extendCall, classDoclet) {
|
|
|
736
867
|
if ( classDoclet && classDoclet.augments && classDoclet.augments.length === 1 ) {
|
|
737
868
|
baseType = classDoclet.augments[0];
|
|
738
869
|
}
|
|
739
|
-
if ( extendCall.callee
|
|
870
|
+
if ( isMemberExpression(extendCall.callee) ) {
|
|
740
871
|
const baseCandidate = getResolvedObjectName(extendCall.callee.object);
|
|
741
872
|
if ( baseCandidate && baseType == null ) {
|
|
742
873
|
baseType = baseCandidate;
|
|
@@ -746,7 +877,7 @@ function collectClassInfo(extendCall, classDoclet) {
|
|
|
746
877
|
}
|
|
747
878
|
|
|
748
879
|
const oClassInfo = {
|
|
749
|
-
name : extendCall.arguments[0]
|
|
880
|
+
name : convertValue(extendCall.arguments[0]),
|
|
750
881
|
baseType : baseType,
|
|
751
882
|
interfaces : [],
|
|
752
883
|
doc : classDoclet && classDoclet.description,
|
|
@@ -988,7 +1119,7 @@ function collectClassInfo(extendCall, classDoclet) {
|
|
|
988
1119
|
return oClassInfo;
|
|
989
1120
|
}
|
|
990
1121
|
|
|
991
|
-
function collectDesigntimeInfo(
|
|
1122
|
+
function collectDesigntimeInfo(dtNodeArgument) {
|
|
992
1123
|
|
|
993
1124
|
function each(node, defaultKey, callback) {
|
|
994
1125
|
const map = node && createPropertyMap(node.value);
|
|
@@ -1010,7 +1141,7 @@ function collectDesigntimeInfo(dtNode) {
|
|
|
1010
1141
|
|
|
1011
1142
|
let oDesigntimeInfo;
|
|
1012
1143
|
|
|
1013
|
-
const map = createPropertyMap(
|
|
1144
|
+
const map = createPropertyMap(dtNodeArgument);
|
|
1014
1145
|
|
|
1015
1146
|
if (map.annotations) {
|
|
1016
1147
|
|
|
@@ -1095,12 +1226,19 @@ function determineValueRangeBorder(range, expression, varname, inverse) {
|
|
|
1095
1226
|
function determineValueRange(expression, varname, inverse) {
|
|
1096
1227
|
const range = {};
|
|
1097
1228
|
if ( expression.type === Syntax.LogicalExpression
|
|
1098
|
-
&& expression.operator === '&&'
|
|
1099
1229
|
&& expression.left.type === Syntax.BinaryExpression
|
|
1100
|
-
&& expression.right.type === Syntax.BinaryExpression
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1230
|
+
&& expression.right.type === Syntax.BinaryExpression ) {
|
|
1231
|
+
|
|
1232
|
+
if ( expression.operator === "&&"
|
|
1233
|
+
&& determineValueRangeBorder(range, expression.left, varname, inverse)
|
|
1234
|
+
&& determineValueRangeBorder(range, expression.right, varname, inverse) ) {
|
|
1235
|
+
return range;
|
|
1236
|
+
} else if ( ["||", "??"].includes(expression.operator)
|
|
1237
|
+
&& ( determineValueRangeBorder(range, expression.left, varname, inverse)
|
|
1238
|
+
|| determineValueRangeBorder(range, expression.right, varname, inverse) )) {
|
|
1239
|
+
return range;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1104
1242
|
} else if ( expression.type === Syntax.BinaryExpression
|
|
1105
1243
|
&& determineValueRangeBorder(range, expression, varname, inverse) ) {
|
|
1106
1244
|
return range;
|
|
@@ -1113,24 +1251,24 @@ function collectDataTypeInfo(extendCall, classDoclet) {
|
|
|
1113
1251
|
let i = 0,
|
|
1114
1252
|
name, def, base, pattern, range;
|
|
1115
1253
|
|
|
1116
|
-
if ( i < args.length && args[i]
|
|
1117
|
-
name = args[i++]
|
|
1254
|
+
if ( i < args.length && isStringLiteral(args[i]) ) {
|
|
1255
|
+
name = convertValue(args[i++]);
|
|
1118
1256
|
}
|
|
1119
1257
|
if ( i < args.length && args[i].type === Syntax.ObjectExpression ) {
|
|
1120
1258
|
def = createPropertyMap(args[i++]);
|
|
1121
1259
|
}
|
|
1122
1260
|
if ( i < args.length ) {
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
&&
|
|
1129
|
-
&&
|
|
1130
|
-
&&
|
|
1131
|
-
&&
|
|
1132
|
-
&&
|
|
1133
|
-
base = args[i++].arguments[0]
|
|
1261
|
+
const node = resolvePotentialWrapperExpression(args[i]);
|
|
1262
|
+
|
|
1263
|
+
if ( isStringLiteral(args[i]) ) {
|
|
1264
|
+
base = convertValue(args[i++]);
|
|
1265
|
+
} else if ( isCaleeMemberExpression(node)
|
|
1266
|
+
&& getResolvedObjectName(node.callee.object) === "sap.ui.base.DataType"
|
|
1267
|
+
&& node.callee.property.type === Syntax.Identifier
|
|
1268
|
+
&& node.callee.property.name === 'getType'
|
|
1269
|
+
&& node.arguments.length === 1
|
|
1270
|
+
&& isStringLiteral(node.arguments[0]) ) {
|
|
1271
|
+
base = convertValue(args[i++].arguments[0]);
|
|
1134
1272
|
} else {
|
|
1135
1273
|
future(`could not identify base type of data type '${name}'`);
|
|
1136
1274
|
}
|
|
@@ -1138,25 +1276,31 @@ function collectDataTypeInfo(extendCall, classDoclet) {
|
|
|
1138
1276
|
base = "any";
|
|
1139
1277
|
}
|
|
1140
1278
|
|
|
1279
|
+
const isArrowExpression = isArrowFuncExpression(def && def.isValid && def.isValid.value);
|
|
1280
|
+
|
|
1141
1281
|
if ( def
|
|
1142
1282
|
&& def.isValid
|
|
1143
|
-
&& def.isValid.value.type
|
|
1283
|
+
&& [Syntax.FunctionExpression, Syntax.ArrowFunctionExpression].includes(def.isValid.value.type)
|
|
1144
1284
|
&& def.isValid.value.params.length === 1
|
|
1145
1285
|
&& def.isValid.value.params[0].type === Syntax.Identifier
|
|
1146
|
-
&& def.isValid.value.body.body.length === 1 ) {
|
|
1286
|
+
&& (isArrowExpression || def.isValid.value.body.body.length === 1) ) {
|
|
1287
|
+
|
|
1147
1288
|
const varname = def.isValid.value.params[0].name;
|
|
1148
|
-
const stmt = def.isValid.value.body.body[0];
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
&&
|
|
1156
|
-
|
|
1289
|
+
const stmt = isArrowExpression ? def.isValid.value.body : def.isValid.value.body.body[0];
|
|
1290
|
+
|
|
1291
|
+
if ( isReturningNode(stmt) || isArrowExpression ) {
|
|
1292
|
+
const stmtArgument = resolvePotentialWrapperExpression(
|
|
1293
|
+
isArrowExpression ? stmt : stmt.argument
|
|
1294
|
+
);
|
|
1295
|
+
if ( isCaleeMemberExpression(stmtArgument)
|
|
1296
|
+
&& stmtArgument.callee.object.type === Syntax.Literal
|
|
1297
|
+
&& stmtArgument.callee.object.regex
|
|
1298
|
+
&& stmtArgument.callee.property.type === Syntax.Identifier
|
|
1299
|
+
&& stmtArgument.callee.property.name === 'test' ) {
|
|
1300
|
+
pattern = stmtArgument.callee.object.regex.pattern;
|
|
1157
1301
|
// console.log(pattern);
|
|
1158
1302
|
} else {
|
|
1159
|
-
range = determineValueRange(
|
|
1303
|
+
range = determineValueRange(stmtArgument, varname, false);
|
|
1160
1304
|
}
|
|
1161
1305
|
} else if ( stmt.type === Syntax.IfStatement
|
|
1162
1306
|
&& stmt.consequent.type === Syntax.BlockStatement
|
|
@@ -1741,7 +1885,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1741
1885
|
newJSDoc([
|
|
1742
1886
|
"Removes an " + n1 + " from the association named " + link + ".",
|
|
1743
1887
|
"@param {int | sap.ui.core.ID | " + info.type + "} " + varname(n1, "variant") + " The " + n1 + " to be removed or its index or ID",
|
|
1744
|
-
"@returns {sap.ui.core.ID} The removed " + n1 + " or <code>null</code>",
|
|
1888
|
+
"@returns {sap.ui.core.ID|null} The removed " + n1 + " or <code>null</code>",
|
|
1745
1889
|
info.since ? "@since " + info.since : "",
|
|
1746
1890
|
info.deprecation ? "@deprecated " + info.deprecation : "",
|
|
1747
1891
|
info.experimental ? "@experimental " + info.experimental : "",
|
|
@@ -2583,24 +2727,37 @@ exports.astNodeVisitor = {
|
|
|
2583
2727
|
}
|
|
2584
2728
|
}
|
|
2585
2729
|
|
|
2586
|
-
if (
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2730
|
+
if ( [Syntax.ExpressionStatement, Syntax.LogicalExpression].includes(node.type) ) {
|
|
2731
|
+
let nodeToAnalyze;
|
|
2732
|
+
if (isSapUiDefineCall(node.expression)) {
|
|
2733
|
+
nodeToAnalyze = node.expression;
|
|
2734
|
+
|
|
2735
|
+
/*
|
|
2590
2736
|
} else if ( isJQuerySapDeclareCall(node.expression)
|
|
2591
2737
|
&& node.expression.arguments.length > 0
|
|
2592
2738
|
&& node.expression.arguments[0].type === Syntax.Literal
|
|
2593
2739
|
&& typeof node.expression.arguments[0].value === "string" ) {
|
|
2594
2740
|
warning(`module has explicit module name ${node.expression.arguments[0].value}`);
|
|
2595
2741
|
*/
|
|
2742
|
+
} else if (isSapUiDefineCall(node.left)) {
|
|
2743
|
+
nodeToAnalyze = node.left;
|
|
2744
|
+
} else if (isSapUiDefineCall(node.right)) {
|
|
2745
|
+
nodeToAnalyze = node.right;
|
|
2596
2746
|
}
|
|
2597
2747
|
|
|
2748
|
+
nodeToAnalyze && analyzeModuleDefinition(
|
|
2749
|
+
resolvePotentialWrapperExpression(nodeToAnalyze)
|
|
2750
|
+
);
|
|
2598
2751
|
}
|
|
2599
2752
|
|
|
2600
|
-
|
|
2753
|
+
const isArrowExpression = isArrowFuncExpression(node) && node.body.type === Syntax.ObjectExpression;
|
|
2754
|
+
const nodeArgument = isArrowExpression
|
|
2755
|
+
? node.body
|
|
2756
|
+
: resolvePotentialWrapperExpression(node).argument;
|
|
2757
|
+
if (isArrowExpression || (isReturningNode(node) && nodeArgument && nodeArgument.type === Syntax.ObjectExpression) && /\.designtime\.js$/.test(currentSourceName) ) {
|
|
2601
2758
|
|
|
2602
2759
|
// assume this node to return designtime metadata. Collect it and remember it by its module name
|
|
2603
|
-
const oDesigntimeInfo = collectDesigntimeInfo(
|
|
2760
|
+
const oDesigntimeInfo = collectDesigntimeInfo(nodeArgument);
|
|
2604
2761
|
if ( oDesigntimeInfo ) {
|
|
2605
2762
|
designtimeInfos[currentModule.module] = oDesigntimeInfo;
|
|
2606
2763
|
info(`collected designtime info ${currentModule.module}`);
|
|
@@ -2630,14 +2787,19 @@ exports.astNodeVisitor = {
|
|
|
2630
2787
|
}
|
|
2631
2788
|
});
|
|
2632
2789
|
|
|
2633
|
-
} else if (
|
|
2790
|
+
} else if ( isReturningNode(node)
|
|
2791
|
+
&& isExtendCall(resolvePotentialWrapperExpression(node).argument || node.body) ) {
|
|
2792
|
+
|
|
2793
|
+
const nodeArgument = isArrowFuncExpression(node)
|
|
2794
|
+
? node.body
|
|
2795
|
+
: resolvePotentialWrapperExpression(node).argument;
|
|
2634
2796
|
|
|
2635
2797
|
// return Something.extend(...)
|
|
2636
2798
|
|
|
2637
|
-
const className =
|
|
2638
|
-
const comment = getLeadingCommentNode(node, className) || getLeadingCommentNode(
|
|
2799
|
+
const className = convertValue(nodeArgument.arguments[0]);
|
|
2800
|
+
const comment = getLeadingCommentNode(node, className) || getLeadingCommentNode(nodeArgument, className);
|
|
2639
2801
|
// console.log(`ast node with comment ${comment}`);
|
|
2640
|
-
processExtendCall(
|
|
2802
|
+
processExtendCall(nodeArgument, comment, true);
|
|
2641
2803
|
} else if ( node.type === Syntax.ExpressionStatement && node.expression.type === Syntax.AssignmentExpression ) {
|
|
2642
2804
|
|
|
2643
2805
|
if ( isCreateDataTypeCall(node.expression.right) ) {
|
|
@@ -2689,7 +2851,8 @@ exports.astNodeVisitor = {
|
|
|
2689
2851
|
/*
|
|
2690
2852
|
* This function has been copied from jsdoc/lib/jsdoc/tag/type (version 3.6.7)
|
|
2691
2853
|
* The copy has been enhanced with the changes from https://github.com/jsdoc/jsdoc/pull/1735
|
|
2692
|
-
* to retain the full function signature for function types
|
|
2854
|
+
* to retain the full function signature for function types and with a further change
|
|
2855
|
+
* to retain the full record type structure.
|
|
2693
2856
|
*
|
|
2694
2857
|
* JSDoc is copyright (c) 2011-present Michael Mathews micmath@gmail.com and the contributors to JSDoc.
|
|
2695
2858
|
*/
|
|
@@ -2731,7 +2894,29 @@ exports.astNodeVisitor = {
|
|
|
2731
2894
|
// types.push('Object');
|
|
2732
2895
|
if (Array.isArray(parsedType.fields)) {
|
|
2733
2896
|
typeString = `{${parsedType.fields.map(
|
|
2734
|
-
({key,value}) =>
|
|
2897
|
+
({key,value}) => {
|
|
2898
|
+
const keyString = catharsis.stringify(key);
|
|
2899
|
+
if (value) {
|
|
2900
|
+
var propertyPlusType = `${keyString}: ${toTypeString(value)}`;
|
|
2901
|
+
return propertyPlusType;
|
|
2902
|
+
} else {
|
|
2903
|
+
let pos;
|
|
2904
|
+
if (keyString && (pos = keyString.indexOf(":")) > -1) {
|
|
2905
|
+
// When no space is present between colon and type (e.g. the structure looks like "{x:number}" with no space after
|
|
2906
|
+
// the colon), then Catharsis parses this as property name "x:number" with no type given.
|
|
2907
|
+
// In this case give a clear hint that this space is needed and throw an error to prevent such issues from being merged
|
|
2908
|
+
const realName = keyString.substring(0, pos);
|
|
2909
|
+
const realValue = keyString.substring(pos + 1, keyString.length);
|
|
2910
|
+
let message = `Cannot parse the "${keyString}" part of "${parsedType.typeExpression}" in RecordType (log output above may give a hint in which file).\n`;
|
|
2911
|
+
message += `Did you mean to specify a property "${realName}" of type "${realValue}"? Then insert a space after the colon and write "${realName}: ${realValue}".`
|
|
2912
|
+
error(message);
|
|
2913
|
+
return "x: any"; // unparseable property set to "any" - but the JSDoc run will fail now, anyway
|
|
2914
|
+
} else {
|
|
2915
|
+
// only property given without type; this will be turned into type "any" further downstream
|
|
2916
|
+
return keyString;
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2735
2920
|
).join(', ')}}`;
|
|
2736
2921
|
types.push(typeString);
|
|
2737
2922
|
} else {
|
|
@@ -2772,7 +2957,9 @@ exports.astNodeVisitor = {
|
|
|
2772
2957
|
const origParse = jsdocType.parse;
|
|
2773
2958
|
jsdocType.parse = function() {
|
|
2774
2959
|
const tagInfo = origParse.apply(this, arguments);
|
|
2775
|
-
|
|
2960
|
+
// #### BEGIN: MODIFIED BY SAP
|
|
2961
|
+
if ( tagInfo && (/function/.test(tagInfo.typeExpression) || /\{.*\}/.test(tagInfo.typeExpression)) && tagInfo.parsedType ) {
|
|
2962
|
+
// #### END: MODIFIED BY SAP
|
|
2776
2963
|
// console.info("old typeExpression", tagInfo.typeExpression);
|
|
2777
2964
|
// console.info("old parse tree", tagInfo.parsedType);
|
|
2778
2965
|
// console.info("old parse result", tagInfo.type);
|