@ui5/builder 4.0.4 → 4.0.5
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/CHANGELOG.md +6 -2
- package/lib/processors/jsdoc/lib/createIndexFiles.js +58 -61
- package/lib/processors/jsdoc/lib/transformApiJson.js +343 -254
- package/lib/processors/jsdoc/lib/ui5/plugin.js +169 -123
- package/lib/processors/jsdoc/lib/ui5/template/publish.js +76 -447
- package/lib/processors/jsdoc/lib/ui5/template/utils/typeParser.js +489 -0
- package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +6 -4
- package/package.json +6 -6
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
/* global
|
|
9
|
-
/* eslint-env es6,node */
|
|
10
|
-
/* eslint strict: [2, "global"] */
|
|
8
|
+
/* global env */
|
|
11
9
|
|
|
12
10
|
'use strict';
|
|
13
11
|
|
|
@@ -49,8 +47,10 @@
|
|
|
49
47
|
* newDoclet
|
|
50
48
|
*
|
|
51
49
|
* parseComplete
|
|
52
|
-
*
|
|
50
|
+
* merge collected class info, DataType info and enum values into doclets
|
|
53
51
|
*
|
|
52
|
+
* processingComplete
|
|
53
|
+
* remove undocumented/ignored/private doclets or duplicate doclets
|
|
54
54
|
*
|
|
55
55
|
* Last but not least, it implements an astNodeVisitor to detect UI5 specific "extend" calls and to create
|
|
56
56
|
* documentation for the properties, aggregations etc. that are created with the "extend" call.
|
|
@@ -189,6 +189,7 @@ const designtimeInfos = Object.create(null);
|
|
|
189
189
|
/* ---- private functions ---- */
|
|
190
190
|
|
|
191
191
|
function ui5data(doclet) {
|
|
192
|
+
// eslint-disable-next-line no-return-assign
|
|
192
193
|
return doclet.__ui5 || (doclet.__ui5 = { id: ++docletUid });
|
|
193
194
|
}
|
|
194
195
|
|
|
@@ -232,7 +233,7 @@ function resolveModuleName(base, name) {
|
|
|
232
233
|
let stack = base.split('/');
|
|
233
234
|
stack.pop();
|
|
234
235
|
name.split('/').forEach((segment, i) => {
|
|
235
|
-
if ( segment
|
|
236
|
+
if ( segment === '..' ) {
|
|
236
237
|
stack.pop();
|
|
237
238
|
} else if ( segment === '.' ) {
|
|
238
239
|
// ignore
|
|
@@ -283,7 +284,8 @@ function analyzeModuleDefinition(node) {
|
|
|
283
284
|
names = [{original: currentModule.factory.params[i].name}];
|
|
284
285
|
}
|
|
285
286
|
|
|
286
|
-
|
|
287
|
+
/*eslint-disable no-loop-func */
|
|
288
|
+
names.forEach((name) => {
|
|
287
289
|
const module = resolveModuleName(currentModule.module, currentModule.dependencies[i]);
|
|
288
290
|
debug(` import ${name.renamed || name.original} from '${module}'`);
|
|
289
291
|
|
|
@@ -292,6 +294,7 @@ function analyzeModuleDefinition(node) {
|
|
|
292
294
|
...(name.path ? {path: name.path} : {})
|
|
293
295
|
};
|
|
294
296
|
});
|
|
297
|
+
/*eslint-enable no-loop-func */
|
|
295
298
|
}
|
|
296
299
|
}
|
|
297
300
|
if ( currentModule.factory ) {
|
|
@@ -300,11 +303,11 @@ function analyzeModuleDefinition(node) {
|
|
|
300
303
|
}
|
|
301
304
|
|
|
302
305
|
/**
|
|
303
|
-
* Searches the given
|
|
306
|
+
* Searches the body of the given factory for variable declarations that can be evaluated statically,
|
|
304
307
|
* either because they refer to known AMD module imports (e.g. shortcut variables)
|
|
305
308
|
* or because they have a (design time) constant value.
|
|
306
309
|
*
|
|
307
|
-
* @param {ASTNode}
|
|
310
|
+
* @param {ASTNode} factory AST node of a factory function whose body that shall be searched for shortcuts
|
|
308
311
|
*/
|
|
309
312
|
function collectShortcuts(factory) {
|
|
310
313
|
const body = factory.body;
|
|
@@ -414,12 +417,13 @@ function guessSingularName(sPluralName) {
|
|
|
414
417
|
|
|
415
418
|
function getPropertyKey(prop) {
|
|
416
419
|
if ( prop.type === Syntax.SpreadElement ) {
|
|
417
|
-
return;
|
|
420
|
+
return undefined;
|
|
418
421
|
} else if ( prop.key.type === Syntax.Identifier && prop.computed !== true ) {
|
|
419
422
|
return prop.key.name;
|
|
420
423
|
} else if ( prop.key.type === Syntax.Literal ) {
|
|
421
424
|
return String(prop.key.value);
|
|
422
425
|
}
|
|
426
|
+
return undefined;
|
|
423
427
|
}
|
|
424
428
|
|
|
425
429
|
/**
|
|
@@ -456,14 +460,14 @@ function createPropertyMap(node, defaultKey) {
|
|
|
456
460
|
return result;
|
|
457
461
|
}
|
|
458
462
|
|
|
459
|
-
if ( node.type
|
|
463
|
+
if ( node.type !== Syntax.ObjectExpression ) {
|
|
460
464
|
// something went wrong, it's not an object literal
|
|
461
465
|
warning(`not an object literal: ${node.type}: ${node.value}`);
|
|
462
466
|
// console.log(node.toSource());
|
|
463
467
|
return undefined;
|
|
464
468
|
}
|
|
465
469
|
|
|
466
|
-
// invariant: node.type
|
|
470
|
+
// invariant: node.type === Syntax.ObjectExpression
|
|
467
471
|
result = {};
|
|
468
472
|
for (let i = 0; i < node.properties.length; i++) {
|
|
469
473
|
const prop = node.properties[i];
|
|
@@ -478,7 +482,7 @@ function createPropertyMap(node, defaultKey) {
|
|
|
478
482
|
|
|
479
483
|
/**
|
|
480
484
|
* Resolves potential wrapper expressions like: ChainExpression, AwaitExpression, etc.
|
|
481
|
-
* @param {Node} node
|
|
485
|
+
* @param {Node} node the node to unwrap
|
|
482
486
|
* @returns {Node} the resolved node
|
|
483
487
|
*/
|
|
484
488
|
function resolvePotentialWrapperExpression(node) {
|
|
@@ -495,29 +499,33 @@ function resolvePotentialWrapperExpression(node) {
|
|
|
495
499
|
? node.expression.argument
|
|
496
500
|
: node.expression;
|
|
497
501
|
}
|
|
502
|
+
// fall through
|
|
498
503
|
default:
|
|
499
504
|
return node;
|
|
500
505
|
}
|
|
501
506
|
}
|
|
502
507
|
|
|
503
508
|
/**
|
|
504
|
-
*
|
|
509
|
+
* Navigates in the given tree of AST nodes (node) along the given path of property names.
|
|
510
|
+
* Any reached ChainExpression wrappers are skipped (ignored).
|
|
505
511
|
*
|
|
506
|
-
* @param {Node} rootNode
|
|
507
|
-
* @param {
|
|
508
|
-
* @returns {Node}
|
|
512
|
+
* @param {Node} rootNode Root of a tree of MemberExpressison nodes
|
|
513
|
+
* @param {string} path Path to navigate along
|
|
514
|
+
* @returns {Node} The target node at the end of the path or undefined
|
|
509
515
|
*/
|
|
510
516
|
function stripChainWrappers(rootNode, path) {
|
|
511
517
|
const strip = (node) =>
|
|
512
|
-
node && node.type === Syntax.ChainExpression ? node.expression : node;
|
|
518
|
+
(node && node.type === Syntax.ChainExpression ? node.expression : node);
|
|
513
519
|
|
|
514
520
|
let curNode = strip(rootNode);
|
|
515
|
-
let chunks = path && path.split(".");
|
|
516
|
-
let name;
|
|
517
521
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
522
|
+
if (path) {
|
|
523
|
+
const chunks = path.split(".");
|
|
524
|
+
|
|
525
|
+
while (chunks.length) {
|
|
526
|
+
const name = chunks.shift();
|
|
527
|
+
curNode = curNode && strip(curNode[name]);
|
|
528
|
+
}
|
|
521
529
|
}
|
|
522
530
|
|
|
523
531
|
return curNode;
|
|
@@ -535,8 +543,8 @@ function isTemplateLiteralWithoutExpression(node) {
|
|
|
535
543
|
/**
|
|
536
544
|
* Checks whether a node is Literal or TemplateLiteral without an expression
|
|
537
545
|
*
|
|
538
|
-
* @param {Node} node
|
|
539
|
-
* @returns {
|
|
546
|
+
* @param {Node} node AST node to check
|
|
547
|
+
* @returns {boolean} Whether the given AST node represents a constant string
|
|
540
548
|
*/
|
|
541
549
|
function isStringLiteral(node) {
|
|
542
550
|
return (
|
|
@@ -581,10 +589,10 @@ function isArrowFuncExpression(node) {
|
|
|
581
589
|
}
|
|
582
590
|
|
|
583
591
|
/**
|
|
584
|
-
* Checks whether the node is of a "returning" type
|
|
592
|
+
* Checks whether the node is of a "returning" type.
|
|
585
593
|
*
|
|
586
|
-
* @param {Node} node
|
|
587
|
-
* @returns {
|
|
594
|
+
* @param {Node} node A statement node
|
|
595
|
+
* @returns {boolean} Whether the node is a return stmt or a yield expression statement
|
|
588
596
|
*/
|
|
589
597
|
function isReturningNode(node) {
|
|
590
598
|
return (node && node.type === Syntax.ReturnStatement)
|
|
@@ -695,7 +703,7 @@ function resolveObjectPatternChain (valueNode, keyNode, keyChain) {
|
|
|
695
703
|
}
|
|
696
704
|
} else {
|
|
697
705
|
|
|
698
|
-
|
|
706
|
+
const result = { original: keyNode.name, path: keyChain.join(".") };
|
|
699
707
|
|
|
700
708
|
if (keyNode.name !== valueNode.name) {
|
|
701
709
|
// Renaming
|
|
@@ -712,8 +720,8 @@ function resolveObjectPatternChain (valueNode, keyNode, keyChain) {
|
|
|
712
720
|
* Tries to resolve an ENUM, regardless where it is defined and being destructured.
|
|
713
721
|
*
|
|
714
722
|
* @param {Node} node
|
|
715
|
-
* @param {
|
|
716
|
-
* @returns {
|
|
723
|
+
* @param {string} type
|
|
724
|
+
* @returns {{value:any, raw: any} | undefined}
|
|
717
725
|
*/
|
|
718
726
|
function resolvePotentialEnum(node, type) {
|
|
719
727
|
let value = resolveFullyQuantifiedName(node);
|
|
@@ -726,13 +734,14 @@ function resolvePotentialEnum(node, type) {
|
|
|
726
734
|
raw: value
|
|
727
735
|
};
|
|
728
736
|
}
|
|
737
|
+
return undefined;
|
|
729
738
|
}
|
|
730
739
|
|
|
731
740
|
/**
|
|
732
|
-
* Returns the
|
|
741
|
+
* Returns the `Node` of the destructured argument of a (arrow) function.
|
|
733
742
|
*
|
|
734
743
|
* @param {Definition|ParameterDefinition} varDefinition
|
|
735
|
-
* @returns {Node}
|
|
744
|
+
* @returns {Node | undefined}
|
|
736
745
|
*/
|
|
737
746
|
function getFuncArgumentDestructNode(varDefinition) {
|
|
738
747
|
if (
|
|
@@ -745,14 +754,14 @@ function getFuncArgumentDestructNode(varDefinition) {
|
|
|
745
754
|
return varDefinition.node.params[varDefinition.index];
|
|
746
755
|
}
|
|
747
756
|
|
|
748
|
-
|
|
757
|
+
return undefined;
|
|
749
758
|
}
|
|
750
759
|
|
|
751
760
|
/**
|
|
752
761
|
* Checks whether a variable has been destructured.
|
|
753
762
|
*
|
|
754
763
|
* @param {Variable} variable
|
|
755
|
-
* @returns
|
|
764
|
+
* @returns {boolean} whether `variable` uses destructuring.
|
|
756
765
|
*/
|
|
757
766
|
function isVarDestructuring(variable) {
|
|
758
767
|
const defNode =
|
|
@@ -761,7 +770,7 @@ function isVarDestructuring(variable) {
|
|
|
761
770
|
( getFuncArgumentDestructNode(variable.defs[0]) // (arrow) function argument
|
|
762
771
|
|| variable.defs[0].node.id ); // variable definition
|
|
763
772
|
|
|
764
|
-
return defNode && [Syntax.ObjectPattern, Syntax.ArrayPattern].includes( defNode.type );
|
|
773
|
+
return defNode != null && [Syntax.ObjectPattern, Syntax.ArrayPattern].includes( defNode.type );
|
|
765
774
|
}
|
|
766
775
|
|
|
767
776
|
/**
|
|
@@ -926,7 +935,7 @@ function getObjectName(node) {
|
|
|
926
935
|
|
|
927
936
|
/*
|
|
928
937
|
* Checks whether the node is a qualified name (a.b.c) and if so,
|
|
929
|
-
* returns the leftmost identifier a
|
|
938
|
+
* returns the leftmost identifier 'a'.
|
|
930
939
|
*/
|
|
931
940
|
function getLeftmostName(node) {
|
|
932
941
|
while ( isMemberExpression(node) ) {
|
|
@@ -935,7 +944,7 @@ function getLeftmostName(node) {
|
|
|
935
944
|
if ( node.type === Syntax.Identifier ) {
|
|
936
945
|
return node.name;
|
|
937
946
|
}
|
|
938
|
-
|
|
947
|
+
return undefined;
|
|
939
948
|
}
|
|
940
949
|
|
|
941
950
|
function getResolvedObjectName(node) {
|
|
@@ -1076,7 +1085,7 @@ function convertValueWithRaw(node, type, propertyName) {
|
|
|
1076
1085
|
}
|
|
1077
1086
|
|
|
1078
1087
|
} else if ( isTemplateLiteralWithoutExpression(node) ) {
|
|
1079
|
-
|
|
1088
|
+
const value = node.quasis[0].value || {};
|
|
1080
1089
|
|
|
1081
1090
|
return {
|
|
1082
1091
|
value: value.cooked,
|
|
@@ -1145,7 +1154,7 @@ function collectVisibilityInfo(settings, doclet, className, n) {
|
|
|
1145
1154
|
let visibility = (settings.visibility && settings.visibility.value.value) || "public";
|
|
1146
1155
|
|
|
1147
1156
|
if (!validVisibilities.has(visibility)) {
|
|
1148
|
-
error(`${className}: Invalid visibility '${visibility}' in runtime metadata defined for managed setting '${n}. Valid options are ${Array.from(validVisibilities).join(', ')}.`);
|
|
1157
|
+
error(`${className}: Invalid visibility '${visibility}' in runtime metadata defined for managed setting '${n}'. Valid options are ${Array.from(validVisibilities).join(', ')}.`);
|
|
1149
1158
|
}
|
|
1150
1159
|
|
|
1151
1160
|
if (doclet?.access) {
|
|
@@ -1170,7 +1179,7 @@ function collectVisibilityInfo(settings, doclet, className, n) {
|
|
|
1170
1179
|
access = "restricted";
|
|
1171
1180
|
}
|
|
1172
1181
|
|
|
1173
|
-
if (visibility
|
|
1182
|
+
if (visibility === "public" && (access === "restricted" || access === "protected")) {
|
|
1174
1183
|
visibility = access;
|
|
1175
1184
|
}
|
|
1176
1185
|
}
|
|
@@ -1220,8 +1229,8 @@ function collectClassInfo(extendCall, classDoclet) {
|
|
|
1220
1229
|
function each(node, defaultKey, callback) {
|
|
1221
1230
|
const map = node && createPropertyMap(node.value);
|
|
1222
1231
|
if ( map ) {
|
|
1223
|
-
for (
|
|
1224
|
-
if (
|
|
1232
|
+
for (const n in map) {
|
|
1233
|
+
if ( Object.hasOwn(map, n) ) {
|
|
1225
1234
|
const doclet = getLeadingDoclet(map[n]);
|
|
1226
1235
|
const settings = createPropertyMap(map[n].value, defaultKey);
|
|
1227
1236
|
if ( settings == null ) {
|
|
@@ -1454,8 +1463,8 @@ function collectDesigntimeInfo(dtNodeArgument) {
|
|
|
1454
1463
|
function each(node, defaultKey, callback) {
|
|
1455
1464
|
const map = node && createPropertyMap(node.value);
|
|
1456
1465
|
if ( map ) {
|
|
1457
|
-
for (
|
|
1458
|
-
if (
|
|
1466
|
+
for (const n in map) {
|
|
1467
|
+
if ( Object.hasOwn(map, n) ) {
|
|
1459
1468
|
const doclet = getLeadingDoclet(map[n], true);
|
|
1460
1469
|
const settings = createPropertyMap(map[n].value, defaultKey);
|
|
1461
1470
|
if ( settings == null ) {
|
|
@@ -1645,7 +1654,7 @@ function collectDataTypeInfo(extendCall, classDoclet) {
|
|
|
1645
1654
|
&& stmt.alternate.body[0].argument
|
|
1646
1655
|
&& stmt.alternate.body[0].argument.type === Syntax.Literal
|
|
1647
1656
|
&& typeof stmt.alternate.body[0].argument.value === 'boolean'
|
|
1648
|
-
&& stmt.consequent.body[0].argument.value !==
|
|
1657
|
+
&& stmt.consequent.body[0].argument.value !== stmt.alternate.body[0].argument.value ) {
|
|
1649
1658
|
const inverse = stmt.alternate.body[0].argument.value;
|
|
1650
1659
|
range = determineValueRange(stmt.test, varname, inverse);
|
|
1651
1660
|
} else {
|
|
@@ -1679,8 +1688,8 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1679
1688
|
if ( !obj ) {
|
|
1680
1689
|
return true;
|
|
1681
1690
|
}
|
|
1682
|
-
for (
|
|
1683
|
-
if (
|
|
1691
|
+
for (const n in obj) {
|
|
1692
|
+
if ( Object.hasOwn(obj, n) ) {
|
|
1684
1693
|
return false;
|
|
1685
1694
|
}
|
|
1686
1695
|
}
|
|
@@ -1868,8 +1877,8 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1868
1877
|
if ( !isEmpty(oClassInfo.properties) ) {
|
|
1869
1878
|
lines.push("<li>Properties");
|
|
1870
1879
|
lines.push("<ul>");
|
|
1871
|
-
for (
|
|
1872
|
-
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + oClassInfo.properties[n].type + (oClassInfo.properties[n].defaultValue !== null && oClassInfo.properties[n].defaultValue.value !== null ? " (default: " + oClassInfo.properties[n].defaultValue.raw + ")" : "") + (oClassInfo.defaultProperty
|
|
1880
|
+
for (const n in oClassInfo.properties) {
|
|
1881
|
+
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + oClassInfo.properties[n].type + (oClassInfo.properties[n].defaultValue !== null && oClassInfo.properties[n].defaultValue.value !== null ? " (default: " + oClassInfo.properties[n].defaultValue.raw + ")" : "") + (oClassInfo.defaultProperty === n ? " (default)" : "") + "</li>");
|
|
1873
1882
|
}
|
|
1874
1883
|
lines.push("</ul>");
|
|
1875
1884
|
lines.push("</li>");
|
|
@@ -1877,9 +1886,9 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1877
1886
|
if ( !isEmpty(oClassInfo.aggregations) ) {
|
|
1878
1887
|
lines.push("<li>Aggregations");
|
|
1879
1888
|
lines.push("<ul>");
|
|
1880
|
-
for (
|
|
1889
|
+
for (const n in oClassInfo.aggregations) {
|
|
1881
1890
|
if ( oClassInfo.aggregations[n].visibility !== "hidden" ) {
|
|
1882
|
-
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + makeTypeString(oClassInfo.aggregations[n]) + (oClassInfo.defaultAggregation
|
|
1891
|
+
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : " + makeTypeString(oClassInfo.aggregations[n]) + (oClassInfo.defaultAggregation === n ? " (default)" : "") + "</li>");
|
|
1883
1892
|
}
|
|
1884
1893
|
}
|
|
1885
1894
|
lines.push("</ul>");
|
|
@@ -1888,7 +1897,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1888
1897
|
if ( !isEmpty(oClassInfo.associations) ) {
|
|
1889
1898
|
lines.push("<li>Associations");
|
|
1890
1899
|
lines.push("<ul>");
|
|
1891
|
-
for (
|
|
1900
|
+
for (const n in oClassInfo.associations) {
|
|
1892
1901
|
lines.push("<li>{@link " + rname("get", n) + " " + n + "} : (sap.ui.core.ID | " + oClassInfo.associations[n].type + ")" + (oClassInfo.associations[n].cardinality === "0..n" ? "[]" : "") + "</li>");
|
|
1893
1902
|
}
|
|
1894
1903
|
lines.push("</ul>");
|
|
@@ -1897,7 +1906,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1897
1906
|
if ( !isEmpty(oClassInfo.events) ) {
|
|
1898
1907
|
lines.push("<li>Events");
|
|
1899
1908
|
lines.push("<ul>");
|
|
1900
|
-
for (
|
|
1909
|
+
for (const n in oClassInfo.events) {
|
|
1901
1910
|
lines.push("<li>{@link " + "#event:" + n + " " + n + "} : fnListenerFunction or [fnListenerFunction, oListenerObject] or [oData, fnListenerFunction, oListenerObject]</li>");
|
|
1902
1911
|
}
|
|
1903
1912
|
lines.push("</ul>");
|
|
@@ -1972,7 +1981,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
1972
1981
|
]);
|
|
1973
1982
|
}
|
|
1974
1983
|
|
|
1975
|
-
for (
|
|
1984
|
+
for (const n in oClassInfo.properties ) {
|
|
1976
1985
|
const info = oClassInfo.properties[n];
|
|
1977
1986
|
if ( info.visibility === 'hidden' ) {
|
|
1978
1987
|
continue;
|
|
@@ -2044,7 +2053,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2044
2053
|
}
|
|
2045
2054
|
}
|
|
2046
2055
|
|
|
2047
|
-
for (
|
|
2056
|
+
for (const n in oClassInfo.aggregations ) {
|
|
2048
2057
|
const info = oClassInfo.aggregations[n];
|
|
2049
2058
|
if ( info.visibility === 'hidden' ) {
|
|
2050
2059
|
continue;
|
|
@@ -2067,7 +2076,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2067
2076
|
"@name " + name("get", n),
|
|
2068
2077
|
"@function"
|
|
2069
2078
|
]);
|
|
2070
|
-
if ( info.cardinality
|
|
2079
|
+
if ( info.cardinality === "0..n" ) {
|
|
2071
2080
|
const n1 = info.singularName;
|
|
2072
2081
|
newJSDoc([
|
|
2073
2082
|
"Inserts a " + n1 + " into the aggregation " + link + ".",
|
|
@@ -2188,7 +2197,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2188
2197
|
}
|
|
2189
2198
|
}
|
|
2190
2199
|
|
|
2191
|
-
for (
|
|
2200
|
+
for (const n in oClassInfo.associations ) {
|
|
2192
2201
|
const info = oClassInfo.associations[n];
|
|
2193
2202
|
if ( info.visibility === 'hidden' ) {
|
|
2194
2203
|
continue;
|
|
@@ -2262,7 +2271,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2262
2271
|
}
|
|
2263
2272
|
}
|
|
2264
2273
|
|
|
2265
|
-
for (
|
|
2274
|
+
for (const n in oClassInfo.events ) {
|
|
2266
2275
|
const info = oClassInfo.events[n];
|
|
2267
2276
|
const visibilityTags = createVisibilityTagsForSetting(info, classAccess);
|
|
2268
2277
|
|
|
@@ -2285,7 +2294,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2285
2294
|
"@param {sap.ui.base.EventProvider} oControlEvent.getSource",
|
|
2286
2295
|
"@param {object} oControlEvent.getParameters"
|
|
2287
2296
|
];
|
|
2288
|
-
for (
|
|
2297
|
+
for (const pName in info.parameters ) {
|
|
2289
2298
|
lines.push(
|
|
2290
2299
|
"@param {" + (info.parameters[pName].type || "") + "} oControlEvent.getParameters." + pName + " " + (info.parameters[pName].doc || "")
|
|
2291
2300
|
);
|
|
@@ -2351,7 +2360,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2351
2360
|
"@param {object} [mParameters] Parameters to pass along with the event"
|
|
2352
2361
|
);
|
|
2353
2362
|
if ( !isEmpty(info.parameters) ) {
|
|
2354
|
-
for (
|
|
2363
|
+
for (const pName in info.parameters) {
|
|
2355
2364
|
lines.push(
|
|
2356
2365
|
"@param {" + (info.parameters[pName].type || "any") + "} [mParameters." + pName + "] " + (info.parameters[pName].doc || "")
|
|
2357
2366
|
);
|
|
@@ -2426,6 +2435,7 @@ if ( Syntax.File === 'File' ) {
|
|
|
2426
2435
|
return leadingComments[leadingComments.length - 1];
|
|
2427
2436
|
}
|
|
2428
2437
|
}
|
|
2438
|
+
return undefined;
|
|
2429
2439
|
};
|
|
2430
2440
|
|
|
2431
2441
|
} else {
|
|
@@ -2573,7 +2583,7 @@ function preprocessComment(e) {
|
|
|
2573
2583
|
// HACK: override cli.exit() to avoid that JSDoc3 exits the VM
|
|
2574
2584
|
if ( pluginConfig.noExit ) {
|
|
2575
2585
|
info("disabling exit() call");
|
|
2576
|
-
require( path.join(
|
|
2586
|
+
require( path.join(env.dirname, 'cli') ).exit = function(retval) {
|
|
2577
2587
|
info(`cli.exit(): do nothing (ret val=${retval})`);
|
|
2578
2588
|
};
|
|
2579
2589
|
}
|
|
@@ -2915,53 +2925,20 @@ exports.handlers = {
|
|
|
2915
2925
|
currentSource = e.source;
|
|
2916
2926
|
},
|
|
2917
2927
|
|
|
2928
|
+
/**
|
|
2929
|
+
* Event `parseComplete` is fired by JSDoc after all files have been parsed,
|
|
2930
|
+
* but before inheritance, mixins or borrows are processed.
|
|
2931
|
+
*
|
|
2932
|
+
* We use this event to merge our additional data into the doclets collected by JSDoc.
|
|
2933
|
+
* The merge must happen before doclets are cloned during the prcessing of augments or borrows.
|
|
2934
|
+
*/
|
|
2918
2935
|
parseComplete : function(e) {
|
|
2919
|
-
|
|
2920
2936
|
const doclets = e.doclets;
|
|
2921
|
-
const
|
|
2922
|
-
|
|
2923
|
-
// remove undocumented symbols, ignored symbols, anonymous functions and their members, scope members
|
|
2924
|
-
let l = doclets.length, i, j;
|
|
2925
|
-
for (i = 0, j = 0; i < l; i++) {
|
|
2926
|
-
|
|
2927
|
-
const doclet = doclets[i];
|
|
2928
|
-
if ( !doclet.undocumented &&
|
|
2929
|
-
!doclet.ignore &&
|
|
2930
|
-
!(doclet.memberof && rAnonymous.test(doclet.memberof)) &&
|
|
2931
|
-
doclet.longname.indexOf("~") < 0 ) {
|
|
2932
|
-
doclets[j++] = doclet;
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
if ( j < l ) {
|
|
2936
|
-
doclets.splice(j, l - j);
|
|
2937
|
-
info(`removed ${l - j} undocumented, ignored or anonymous symbols`);
|
|
2938
|
-
l = j;
|
|
2939
|
-
}
|
|
2940
|
-
|
|
2941
|
-
// sort doclets by name, synthetic, lineno, uid
|
|
2942
|
-
// 'ignore' is a combination of criteria, see function above
|
|
2943
|
-
debug("sorting doclets by name");
|
|
2944
|
-
doclets.sort((a, b) => {
|
|
2945
|
-
if ( a.longname === b.longname ) {
|
|
2946
|
-
if ( a.synthetic === b.synthetic ) {
|
|
2947
|
-
if ( a.meta && b.meta && a.meta.filename == b.meta.filename ) {
|
|
2948
|
-
if ( a.meta.lineno !== b.meta.lineno ) {
|
|
2949
|
-
return a.meta.lineno < b.meta.lineno ? -1 : 1;
|
|
2950
|
-
}
|
|
2951
|
-
}
|
|
2952
|
-
return a.__ui5.id - b.__ui5.id;
|
|
2953
|
-
}
|
|
2954
|
-
return a.synthetic && !b.synthetic ? -1 : 1;
|
|
2955
|
-
}
|
|
2956
|
-
return a.longname < b.longname ? -1 : 1;
|
|
2957
|
-
});
|
|
2958
|
-
debug("sorting doclets by name done.");
|
|
2959
|
-
|
|
2960
|
-
for (i = 0, j = 0; i < l; i++) {
|
|
2961
|
-
|
|
2937
|
+
const l = doclets.length;
|
|
2938
|
+
for (let i = 0; i < l; i++) {
|
|
2962
2939
|
const doclet = doclets[i];
|
|
2963
2940
|
|
|
2964
|
-
// add metadata to
|
|
2941
|
+
// add metadata to class symbols
|
|
2965
2942
|
if ( classInfos[doclet.longname] ) {
|
|
2966
2943
|
// debug("class data", doclet.longname, "'" + classInfos[doclet.longname].export + "'");
|
|
2967
2944
|
if ( doclet.__ui5.export === undefined ) {
|
|
@@ -3005,6 +2982,7 @@ exports.handlers = {
|
|
|
3005
2982
|
}
|
|
3006
2983
|
}
|
|
3007
2984
|
|
|
2985
|
+
// add DataType info to typedef symbols
|
|
3008
2986
|
if ( typeInfos[doclet.longname] ) {
|
|
3009
2987
|
doclet.__ui5.stereotype = 'datatype';
|
|
3010
2988
|
doclet.__ui5.metadata = {
|
|
@@ -3014,6 +2992,7 @@ exports.handlers = {
|
|
|
3014
2992
|
};
|
|
3015
2993
|
}
|
|
3016
2994
|
|
|
2995
|
+
// add enum values to enum keys (for enum symbols)
|
|
3017
2996
|
if ( (doclet.kind === 'member' || doclet.kind === 'constant') && doclet.isEnum && Array.isArray(doclet.properties) ) {
|
|
3018
2997
|
// determine unique enum identifier from key set
|
|
3019
2998
|
let enumID = doclet.properties.map(function(prop) {
|
|
@@ -3036,31 +3015,96 @@ exports.handlers = {
|
|
|
3036
3015
|
}
|
|
3037
3016
|
}
|
|
3038
3017
|
}
|
|
3018
|
+
}
|
|
3019
|
+
},
|
|
3020
|
+
|
|
3021
|
+
/**
|
|
3022
|
+
* Event `processingComplete` is fired by JSDoc after all files have been parsed,
|
|
3023
|
+
* and after inheritance, mixins and borrows have been processed.
|
|
3024
|
+
*
|
|
3025
|
+
* The `e.doclets` contains the symbols that will be given to templates for publishing.
|
|
3026
|
+
*
|
|
3027
|
+
* We use this event to remove symbols that are not of interest:
|
|
3028
|
+
* - undocumented When JSDoc finds a class, function, object or member without a
|
|
3029
|
+
* JSDoc comment, it creates a doclet with a truthy `undocumented`
|
|
3030
|
+
* property
|
|
3031
|
+
* - ignore A symbol that has been marked with `@ignore` in the source code
|
|
3032
|
+
* - anonymous JSDoc could not infer a name for the symbol, neither from source
|
|
3033
|
+
* code nor from JSDoc comments
|
|
3034
|
+
* - local Local entities (e.g. local vars) can't be addressed from the outside
|
|
3035
|
+
* and therefore are generally not considered as API in UI5
|
|
3036
|
+
* - duplicates This plugin generates doclets for the accessor methods of
|
|
3037
|
+
* managed properties, aggregations, events, associations.
|
|
3038
|
+
* Developers might have created JSDoc comments for the same methods,
|
|
3039
|
+
* either because they have overridden them in code or because they
|
|
3040
|
+
* wanted to detail the method contract. If such duplicate doclets
|
|
3041
|
+
* are detected, the developer created doclets are preferred. If
|
|
3042
|
+
* multiple developer created doclets for the same entity exist in the
|
|
3043
|
+
* same file, the last one wins. If multiple doclets exists across
|
|
3044
|
+
* files, the one created last wins (but usually, this indicates a
|
|
3045
|
+
* copy & paste error)
|
|
3046
|
+
*
|
|
3047
|
+
* The cleanup is done in `processingComplete` as the processing of `@augments` or
|
|
3048
|
+
* `@borrows` tags might have created new non-interesting symbols.
|
|
3049
|
+
*/
|
|
3050
|
+
processingComplete(e) {
|
|
3051
|
+
const doclets = e.doclets;
|
|
3052
|
+
|
|
3053
|
+
// sort doclets by name, synthetic, lineno, uid for easier detection of duplicates
|
|
3054
|
+
debug("sorting doclets by name");
|
|
3055
|
+
doclets.sort((a, b) => {
|
|
3056
|
+
if ( a.longname === b.longname ) {
|
|
3057
|
+
if ( a.synthetic === b.synthetic ) {
|
|
3058
|
+
if ( a.meta && b.meta && a.meta.filename === b.meta.filename ) {
|
|
3059
|
+
if ( a.meta.lineno !== b.meta.lineno ) {
|
|
3060
|
+
return a.meta.lineno < b.meta.lineno ? -1 : 1;
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
return a.__ui5.id - b.__ui5.id;
|
|
3064
|
+
}
|
|
3065
|
+
return a.synthetic && !b.synthetic ? -1 : 1;
|
|
3066
|
+
}
|
|
3067
|
+
return a.longname < b.longname ? -1 : 1;
|
|
3068
|
+
});
|
|
3069
|
+
debug("sorting doclets by name done.");
|
|
3070
|
+
|
|
3071
|
+
// cleanup doclets
|
|
3072
|
+
const rAnonymous = /^<anonymous>(~|$)/;
|
|
3073
|
+
const l = doclets.length;
|
|
3074
|
+
let j = 0;
|
|
3075
|
+
for (let i = 0; i < l; i++) {
|
|
3076
|
+
const doclet = doclets[i];
|
|
3077
|
+
|
|
3078
|
+
// skip undocumented, ignored, anonymous entities as well as local entities
|
|
3079
|
+
if (doclet.undocumented
|
|
3080
|
+
|| doclet.ignore
|
|
3081
|
+
|| (doclet.memberof && rAnonymous.test(doclet.memberof))
|
|
3082
|
+
|| doclet.longname.includes("~") ) {
|
|
3083
|
+
continue;
|
|
3084
|
+
}
|
|
3039
3085
|
|
|
3040
3086
|
// check for duplicates: last one wins
|
|
3041
3087
|
if ( j > 0 && doclets[j - 1].longname === doclet.longname ) {
|
|
3042
3088
|
if ( !doclets[j - 1].synthetic && !doclet.__ui5.updatedDoclet ) {
|
|
3043
|
-
// replacing synthetic comments or updating comments are trivial
|
|
3089
|
+
// replacing synthetic comments or updating comments are trivial cases. Just log non-trivial duplicates
|
|
3044
3090
|
debug(`ignoring duplicate doclet for ${doclet.longname}: ${location(doclet)} overrides ${location(doclets[j - 1])}`);
|
|
3045
3091
|
}
|
|
3046
3092
|
doclets[j - 1] = doclet;
|
|
3047
|
-
|
|
3048
|
-
doclets[j++] = doclet;
|
|
3093
|
+
continue;
|
|
3049
3094
|
}
|
|
3095
|
+
|
|
3096
|
+
doclets[j++] = doclet;
|
|
3050
3097
|
}
|
|
3051
3098
|
|
|
3052
3099
|
if ( j < l ) {
|
|
3053
3100
|
doclets.splice(j, l - j);
|
|
3054
|
-
info(`removed ${l - j} duplicate symbols - ${doclets.length} remaining`);
|
|
3101
|
+
info(`processingComplete: removed ${l - j} undocumented, ignored, anonymous, local or duplicate symbols - ${doclets.length} remaining`);
|
|
3055
3102
|
}
|
|
3056
3103
|
|
|
3057
3104
|
if ( pluginConfig.saveSymbols ) {
|
|
3058
|
-
|
|
3059
3105
|
fs.mkPath(env.opts.destination);
|
|
3060
|
-
fs.writeFileSync(path.join(env.opts.destination, "symbols-
|
|
3061
|
-
|
|
3106
|
+
fs.writeFileSync(path.join(env.opts.destination, "symbols-processingComplete.json"), JSON.stringify(e.doclets, null, "\t"), 'utf8');
|
|
3062
3107
|
}
|
|
3063
|
-
|
|
3064
3108
|
}
|
|
3065
3109
|
};
|
|
3066
3110
|
|
|
@@ -3122,9 +3166,11 @@ exports.astNodeVisitor = {
|
|
|
3122
3166
|
nodeToAnalyze = node.right;
|
|
3123
3167
|
}
|
|
3124
3168
|
|
|
3125
|
-
nodeToAnalyze
|
|
3126
|
-
|
|
3127
|
-
|
|
3169
|
+
if (nodeToAnalyze) {
|
|
3170
|
+
analyzeModuleDefinition(
|
|
3171
|
+
resolvePotentialWrapperExpression(nodeToAnalyze)
|
|
3172
|
+
);
|
|
3173
|
+
}
|
|
3128
3174
|
}
|
|
3129
3175
|
|
|
3130
3176
|
const isArrowExpression = isArrowFuncExpression(node) && node.body.type === Syntax.ObjectExpression;
|
|
@@ -3197,7 +3243,7 @@ exports.astNodeVisitor = {
|
|
|
3197
3243
|
|
|
3198
3244
|
let programBodyStart;
|
|
3199
3245
|
if ( node.program.body.length >= 1 ) {
|
|
3200
|
-
programBodyStart = node.program.body[0].start
|
|
3246
|
+
programBodyStart = node.program.body[0].start;
|
|
3201
3247
|
} else {
|
|
3202
3248
|
// File has no code at all
|
|
3203
3249
|
programBodyStart = Infinity;
|
|
@@ -3236,6 +3282,7 @@ exports.astNodeVisitor = {
|
|
|
3236
3282
|
function getTypeStrings(parsedType, isOutermostType) {
|
|
3237
3283
|
let applications;
|
|
3238
3284
|
let typeString;
|
|
3285
|
+
let paramTypes;
|
|
3239
3286
|
let types = [];
|
|
3240
3287
|
switch (parsedType.type) {
|
|
3241
3288
|
case TYPES.AllLiteral:
|
|
@@ -3244,7 +3291,7 @@ exports.astNodeVisitor = {
|
|
|
3244
3291
|
case TYPES.FunctionType:
|
|
3245
3292
|
typeString = 'function';
|
|
3246
3293
|
// #### BEGIN: MODIFIED BY SAP
|
|
3247
|
-
|
|
3294
|
+
paramTypes = [];
|
|
3248
3295
|
if (parsedType.new) {
|
|
3249
3296
|
paramTypes.push(toTypeString(parsedType.new));
|
|
3250
3297
|
}
|
|
@@ -3291,7 +3338,7 @@ exports.astNodeVisitor = {
|
|
|
3291
3338
|
const realName = keyString.substring(0, pos);
|
|
3292
3339
|
const realValue = keyString.substring(pos + 1, keyString.length);
|
|
3293
3340
|
let message = `Cannot parse the "${keyString}" part of "${parsedType.typeExpression}" in RecordType (log output above may give a hint in which file).\n`;
|
|
3294
|
-
message += `Did you mean to specify a property "${realName}" of type "${realValue}"? Then insert a space after the colon and write "${realName}: ${realValue}"
|
|
3341
|
+
message += `Did you mean to specify a property "${realName}" of type "${realValue}"? Then insert a space after the colon and write "${realName}: ${realValue}".`;
|
|
3295
3342
|
error(message);
|
|
3296
3343
|
return "x: any"; // unparseable property set to "any" - but the JSDoc run will fail now, anyway
|
|
3297
3344
|
} else {
|
|
@@ -3310,17 +3357,16 @@ exports.astNodeVisitor = {
|
|
|
3310
3357
|
case TYPES.TypeApplication:
|
|
3311
3358
|
// if this is the outermost type, we strip the modifiers; otherwise, we keep them
|
|
3312
3359
|
if (isOutermostType) {
|
|
3313
|
-
applications = parsedType.applications.map(application =>
|
|
3360
|
+
applications = parsedType.applications.map((application) =>
|
|
3314
3361
|
catharsis.stringify(application)).join(', ');
|
|
3315
3362
|
typeString = `${getTypeStrings(parsedType.expression)[0]}.<${applications}>`;
|
|
3316
3363
|
types.push(typeString);
|
|
3317
|
-
}
|
|
3318
|
-
else {
|
|
3364
|
+
} else {
|
|
3319
3365
|
types.push( catharsis.stringify(parsedType) );
|
|
3320
3366
|
}
|
|
3321
3367
|
break;
|
|
3322
3368
|
case TYPES.TypeUnion:
|
|
3323
|
-
parsedType.elements.forEach(element => {
|
|
3369
|
+
parsedType.elements.forEach((element) => {
|
|
3324
3370
|
types = types.concat( getTypeStrings(element) );
|
|
3325
3371
|
});
|
|
3326
3372
|
break;
|
|
@@ -3350,5 +3396,5 @@ exports.astNodeVisitor = {
|
|
|
3350
3396
|
// console.info("new parse result", tagInfo.type);
|
|
3351
3397
|
}
|
|
3352
3398
|
return tagInfo;
|
|
3353
|
-
}
|
|
3399
|
+
};
|
|
3354
3400
|
}());
|