@ui5/builder 3.0.0-alpha.10 → 3.0.0-alpha.11
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 +19 -2
- package/lib/lbt/analyzer/FioriElementsAnalyzer.js +23 -12
- package/lib/lbt/analyzer/JSModuleAnalyzer.js +88 -53
- package/lib/lbt/analyzer/SmartTemplateAnalyzer.js +23 -12
- package/lib/lbt/analyzer/XMLCompositeAnalyzer.js +29 -19
- package/lib/lbt/analyzer/analyzeLibraryJS.js +15 -0
- package/lib/lbt/bundle/Builder.js +1 -1
- package/lib/lbt/calls/SapUiDefine.js +13 -7
- package/lib/lbt/utils/ASTUtils.js +45 -18
- package/lib/processors/jsdoc/lib/transformApiJson.js +58 -2
- package/lib/processors/jsdoc/lib/ui5/plugin.js +306 -119
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,10 +2,26 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
-
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.
|
|
5
|
+
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.11...HEAD).
|
|
6
|
+
|
|
7
|
+
<a name="v3.0.0-alpha.11"></a>
|
|
8
|
+
## [v3.0.0-alpha.11] - 2022-10-12
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
- **package.json:** Downgrade es5-ext dependency [`2b71707`](https://github.com/SAP/ui5-builder/commit/2b71707683480b26aab9957c09e5d22bce8a6450)
|
|
11
|
+
|
|
12
|
+
### Dependency Updates
|
|
13
|
+
- Bump escope from 3.6.0 to 4.0.0 [`e25af0d`](https://github.com/SAP/ui5-builder/commit/e25af0d9c1184916aa037b4b4ca23d15c5f2a408)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
- **builder:** Improve support for ES6+ syntax ([#774](https://github.com/SAP/ui5-builder/issues/774)) [`90385fe`](https://github.com/SAP/ui5-builder/commit/90385feb7cea1e5b864cff035b01263a492972a9)
|
|
17
|
+
- **jsdoc:** Improve support for ES6+ syntax ([#785](https://github.com/SAP/ui5-builder/issues/785)) [`187a6a3`](https://github.com/SAP/ui5-builder/commit/187a6a35000145d70bf41e0d8b724e5ea8d8dc78)
|
|
18
|
+
|
|
19
|
+
### Reverts
|
|
20
|
+
- [FIX] package.json: Downgrade es5-ext dependency
|
|
21
|
+
|
|
6
22
|
|
|
7
23
|
<a name="v3.0.0-alpha.10"></a>
|
|
8
|
-
## [v3.0.0-alpha.10] - 2022-08-
|
|
24
|
+
## [v3.0.0-alpha.10] - 2022-08-09
|
|
9
25
|
|
|
10
26
|
<a name="v3.0.0-alpha.9"></a>
|
|
11
27
|
## [v3.0.0-alpha.9] - 2022-07-27
|
|
@@ -753,6 +769,7 @@ to load the custom bundle file instead.
|
|
|
753
769
|
- Add ability to configure component preloads and custom bundles [`2241e5f`](https://github.com/SAP/ui5-builder/commit/2241e5ff98fd95f1f80cc74959655ae7a9c660e7)
|
|
754
770
|
|
|
755
771
|
|
|
772
|
+
[v3.0.0-alpha.11]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.10...v3.0.0-alpha.11
|
|
756
773
|
[v3.0.0-alpha.10]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.9...v3.0.0-alpha.10
|
|
757
774
|
[v3.0.0-alpha.9]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.8...v3.0.0-alpha.9
|
|
758
775
|
[v3.0.0-alpha.8]: https://github.com/SAP/ui5-builder/compare/v3.0.0-alpha.7...v3.0.0-alpha.8
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
const ModuleName = require("../utils/ModuleName");
|
|
62
62
|
const SapUiDefine = require("../calls/SapUiDefine");
|
|
63
63
|
const {parseJS, Syntax} = require("../utils/parseUtils");
|
|
64
|
-
const {getValue, isMethodCall,
|
|
64
|
+
const {getValue, isMethodCall, getStringValue} = require("../utils/ASTUtils");
|
|
65
65
|
const log = require("@ui5/logger").getLogger("lbt:analyzer:FioriElementAnalyzer");
|
|
66
66
|
|
|
67
67
|
// ---------------------------------------------------------------------------------------------------------
|
|
@@ -165,24 +165,35 @@ class FioriElementsAnalyzer {
|
|
|
165
165
|
const TA = defineCall.findImportName("sap/fe/core/TemplateAssembler.js");
|
|
166
166
|
// console.log("local name for TemplateAssembler: %s", TA);
|
|
167
167
|
if ( TA && defineCall.factory ) {
|
|
168
|
-
defineCall.factory.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
templateName = this._analyzeTemplateClassDefinition(stmt.argument.arguments[2]) || templateName;
|
|
168
|
+
if (defineCall.factory.type === Syntax.ArrowFunctionExpression &&
|
|
169
|
+
defineCall.factory.expression === true) {
|
|
170
|
+
if ( this._isTemplateClassDefinition(TA, defineCall.factory.body) ) {
|
|
171
|
+
templateName =
|
|
172
|
+
this._analyzeTemplateClassDefinition(defineCall.factory.body.arguments[2]) || templateName;
|
|
174
173
|
}
|
|
175
|
-
}
|
|
174
|
+
} else {
|
|
175
|
+
defineCall.factory.body.body.forEach( (stmt) => {
|
|
176
|
+
if ( stmt.type === Syntax.ReturnStatement &&
|
|
177
|
+
this._isTemplateClassDefinition(TA, stmt.argument)
|
|
178
|
+
) {
|
|
179
|
+
templateName =
|
|
180
|
+
this._analyzeTemplateClassDefinition(stmt.argument.arguments[2]) || templateName;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
176
184
|
}
|
|
177
185
|
}
|
|
178
186
|
return templateName;
|
|
179
187
|
}
|
|
180
188
|
|
|
189
|
+
_isTemplateClassDefinition(TA, node) {
|
|
190
|
+
return isMethodCall(node, [TA, "getTemplateComponent"]) &&
|
|
191
|
+
node.arguments.length > 2 &&
|
|
192
|
+
node.arguments[2].type === "ObjectExpression";
|
|
193
|
+
}
|
|
194
|
+
|
|
181
195
|
_analyzeTemplateClassDefinition(clazz) {
|
|
182
|
-
|
|
183
|
-
if ( isString(defaultValue) ) {
|
|
184
|
-
return defaultValue.value;
|
|
185
|
-
}
|
|
196
|
+
return getStringValue(getValue(clazz, ["metadata", "properties", "templateName", "defaultValue"]));
|
|
186
197
|
}
|
|
187
198
|
}
|
|
188
199
|
|
|
@@ -5,7 +5,9 @@ const escope = require("escope");
|
|
|
5
5
|
const ModuleName = require("../utils/ModuleName");
|
|
6
6
|
const {Format: ModuleFormat} = require("../resources/ModuleInfo");
|
|
7
7
|
const UI5ClientConstants = require("../UI5ClientConstants");
|
|
8
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
findOwnProperty, getLocation, getPropertyKey,
|
|
10
|
+
isMethodCall, isString, getStringValue} = require("../utils/ASTUtils");
|
|
9
11
|
const log = require("@ui5/logger").getLogger("lbt:analyzer:JSModuleAnalyzer");
|
|
10
12
|
|
|
11
13
|
// ------------------------------------------------------------------------------------------------------------------
|
|
@@ -64,7 +66,7 @@ const EnrichedVisitorKeys = (function() {
|
|
|
64
66
|
BreakStatement: [],
|
|
65
67
|
CallExpression: [], // special handling
|
|
66
68
|
CatchClause: ["param", "body"],
|
|
67
|
-
ChainExpression: [],
|
|
69
|
+
ChainExpression: ["expression"],
|
|
68
70
|
ClassBody: [],
|
|
69
71
|
ClassDeclaration: [],
|
|
70
72
|
ClassExpression: [],
|
|
@@ -114,7 +116,7 @@ const EnrichedVisitorKeys = (function() {
|
|
|
114
116
|
ImportSpecifier: [], // imported, local
|
|
115
117
|
Literal: [],
|
|
116
118
|
LabeledStatement: [],
|
|
117
|
-
LogicalExpression: [],
|
|
119
|
+
LogicalExpression: ["right"],
|
|
118
120
|
MemberExpression: [],
|
|
119
121
|
MetaProperty: toBeDone(["meta", "property"]),
|
|
120
122
|
MethodDefinition: [],
|
|
@@ -541,21 +543,27 @@ class JSModuleAnalyzer {
|
|
|
541
543
|
|
|
542
544
|
function onDeclare(node) {
|
|
543
545
|
const args = node.arguments;
|
|
544
|
-
if (
|
|
545
|
-
const
|
|
546
|
-
if (
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
546
|
+
if (args.length > 0) {
|
|
547
|
+
const value = getStringValue(args[0]);
|
|
548
|
+
if (value !== undefined) {
|
|
549
|
+
const name = ModuleName.fromUI5LegacyName(value);
|
|
550
|
+
if ( nModuleDeclarations === 1 && !mainModuleFound) {
|
|
551
|
+
// if this is the first declaration, then this is the main module declaration
|
|
552
|
+
// note that this overrides an already given name
|
|
553
|
+
setMainModuleInfo(name, getDocumentation(node));
|
|
554
|
+
} else if ( nModuleDeclarations > 1 && name === info.name ) {
|
|
555
|
+
// ignore duplicate declarations (e.g. in behavior file of design time controls)
|
|
556
|
+
log.warn(`duplicate declaration of module name at ${getLocation(args)} in ${name}`);
|
|
557
|
+
} else {
|
|
558
|
+
// otherwise it is just a submodule declaration
|
|
559
|
+
info.addSubModule(name);
|
|
560
|
+
}
|
|
561
|
+
return;
|
|
553
562
|
} else {
|
|
554
|
-
|
|
555
|
-
info.addSubModule(name);
|
|
563
|
+
log.error("jQuery.sap.declare: module name could not be determined from first argument:", args[0]);
|
|
556
564
|
}
|
|
557
565
|
} else {
|
|
558
|
-
log.error("jQuery.sap.declare: module name could not be determined
|
|
566
|
+
log.error("jQuery.sap.declare: module name could not be determined, no arguments are given");
|
|
559
567
|
}
|
|
560
568
|
}
|
|
561
569
|
|
|
@@ -569,20 +577,26 @@ class JSModuleAnalyzer {
|
|
|
569
577
|
|
|
570
578
|
// determine the name of the module
|
|
571
579
|
let name = null;
|
|
572
|
-
if ( i < nArgs
|
|
573
|
-
|
|
574
|
-
if (
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
candidateName
|
|
582
|
-
|
|
580
|
+
if ( i < nArgs ) {
|
|
581
|
+
const value = getStringValue( args[i] );
|
|
582
|
+
if ( value !== undefined ) {
|
|
583
|
+
name = ModuleName.fromRequireJSName(value);
|
|
584
|
+
if ( name === defaultName ) {
|
|
585
|
+
// hardcoded name equals the file name, so this definition qualifies as main module definition
|
|
586
|
+
setMainModuleInfo(name, desc);
|
|
587
|
+
} else {
|
|
588
|
+
info.addSubModule(name);
|
|
589
|
+
if ( candidateName == null ) {
|
|
590
|
+
// remember the name and description in case no other module qualifies as main module
|
|
591
|
+
candidateName = name;
|
|
592
|
+
candidateDescription = desc;
|
|
593
|
+
}
|
|
583
594
|
}
|
|
595
|
+
i++;
|
|
584
596
|
}
|
|
585
|
-
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if ( !name ) {
|
|
586
600
|
nUnnamedDefines++;
|
|
587
601
|
if ( nUnnamedDefines > 1 ) {
|
|
588
602
|
throw new Error(
|
|
@@ -614,15 +628,25 @@ class JSModuleAnalyzer {
|
|
|
614
628
|
// UI5 signature with one or many required modules
|
|
615
629
|
for (let i = 0; i < nArgs; i++) {
|
|
616
630
|
const arg = args[i];
|
|
617
|
-
|
|
618
|
-
|
|
631
|
+
const value = getStringValue(arg);
|
|
632
|
+
if ( value !== undefined ) {
|
|
633
|
+
const requiredModuleName = ModuleName.fromUI5LegacyName( value );
|
|
619
634
|
info.addDependency(requiredModuleName, conditional);
|
|
620
|
-
} else if ( arg.type == Syntax.ConditionalExpression
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
635
|
+
} else if ( arg.type == Syntax.ConditionalExpression) {
|
|
636
|
+
const consequentValue = getStringValue(arg.consequent);
|
|
637
|
+
const alternateValue = getStringValue(arg.alternate);
|
|
638
|
+
if ( consequentValue !== undefined ) {
|
|
639
|
+
const requiredModuleName1 = ModuleName.fromUI5LegacyName( consequentValue );
|
|
640
|
+
info.addDependency(requiredModuleName1, true);
|
|
641
|
+
}
|
|
642
|
+
if ( alternateValue !== undefined ) {
|
|
643
|
+
const requiredModuleName2 = ModuleName.fromUI5LegacyName( alternateValue );
|
|
644
|
+
info.addDependency(requiredModuleName2, true);
|
|
645
|
+
}
|
|
646
|
+
if ( consequentValue === undefined || alternateValue === undefined ) {
|
|
647
|
+
log.verbose("jQuery.sap.require: cannot evaluate dynamic arguments: ", arg && arg.type);
|
|
648
|
+
info.dynamicDependencies = true;
|
|
649
|
+
}
|
|
626
650
|
} else {
|
|
627
651
|
log.verbose("jQuery.sap.require: cannot evaluate dynamic arguments: ", arg && arg.type);
|
|
628
652
|
info.dynamicDependencies = true;
|
|
@@ -637,9 +661,10 @@ class JSModuleAnalyzer {
|
|
|
637
661
|
const i = 0;
|
|
638
662
|
|
|
639
663
|
if ( i < nArgs ) {
|
|
640
|
-
|
|
664
|
+
const value = getStringValue(args[i]);
|
|
665
|
+
if ( value !== undefined ) {
|
|
641
666
|
// sap.ui.requireSync does not support relative dependencies
|
|
642
|
-
const moduleName = ModuleName.fromRequireJSName(
|
|
667
|
+
const moduleName = ModuleName.fromRequireJSName( value );
|
|
643
668
|
info.addDependency(moduleName, conditional);
|
|
644
669
|
} else {
|
|
645
670
|
log.verbose("sap.ui.requireSync: cannot evaluate dynamic arguments: ", args[i] && args[i].type);
|
|
@@ -654,18 +679,24 @@ class JSModuleAnalyzer {
|
|
|
654
679
|
let i = 0;
|
|
655
680
|
|
|
656
681
|
// determine the name of the module
|
|
657
|
-
if ( i < nArgs
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
elementArg
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
682
|
+
if ( i < nArgs ) {
|
|
683
|
+
const value = getStringValue(args[i++]);
|
|
684
|
+
if ( value !== undefined ) {
|
|
685
|
+
const moduleName = ModuleName.fromRequireJSName( value );
|
|
686
|
+
info.addSubModule(moduleName);
|
|
687
|
+
|
|
688
|
+
// add dependencies
|
|
689
|
+
// to correctly identify dependencies e.g. of a library-preload
|
|
690
|
+
const elementArg = args[i++];
|
|
691
|
+
if (elementArg && elementArg.type === Syntax.ArrayExpression) {
|
|
692
|
+
elementArg.elements.forEach((element) => {
|
|
693
|
+
const dependencyName = ModuleName.resolveRelativeRequireJSName(moduleName,
|
|
694
|
+
getStringValue(element));
|
|
695
|
+
info.addDependency(dependencyName, conditional);
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
} else {
|
|
699
|
+
log.warn("sap.ui.predefine call has a non supported type for module name (ignored)");
|
|
669
700
|
}
|
|
670
701
|
} else {
|
|
671
702
|
log.warn("sap.ui.predefine call is missing a module name (ignored)");
|
|
@@ -692,6 +723,9 @@ class JSModuleAnalyzer {
|
|
|
692
723
|
if ( modules && modules.type == Syntax.ObjectExpression ) {
|
|
693
724
|
modules.properties.forEach( function(property) {
|
|
694
725
|
let moduleName = getPropertyKey(property);
|
|
726
|
+
if ( !moduleName ) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
695
729
|
if ( namesUseLegacyNotation ) {
|
|
696
730
|
moduleName = ModuleName.fromUI5LegacyName(moduleName);
|
|
697
731
|
}
|
|
@@ -705,16 +739,17 @@ class JSModuleAnalyzer {
|
|
|
705
739
|
function analyzeDependencyArray(array, conditional, name) {
|
|
706
740
|
// console.log(array);
|
|
707
741
|
array.forEach( (item) => {
|
|
708
|
-
|
|
742
|
+
const value = getStringValue(item);
|
|
743
|
+
if ( value !== undefined ) {
|
|
709
744
|
// ignore special AMD dependencies (require, exports, module)
|
|
710
|
-
if ( SPECIAL_AMD_DEPENDENCIES.indexOf(
|
|
745
|
+
if ( SPECIAL_AMD_DEPENDENCIES.indexOf(value) >= 0 ) {
|
|
711
746
|
return;
|
|
712
747
|
}
|
|
713
748
|
let requiredModule;
|
|
714
749
|
if (name == null) {
|
|
715
|
-
requiredModule = ModuleName.fromRequireJSName(
|
|
750
|
+
requiredModule = ModuleName.fromRequireJSName( value );
|
|
716
751
|
} else {
|
|
717
|
-
requiredModule = ModuleName.resolveRelativeRequireJSName(name,
|
|
752
|
+
requiredModule = ModuleName.resolveRelativeRequireJSName(name, value);
|
|
718
753
|
}
|
|
719
754
|
info.addDependency( requiredModule, conditional );
|
|
720
755
|
} else {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
const ModuleName = require("../utils/ModuleName");
|
|
29
29
|
const SapUiDefine = require("../calls/SapUiDefine");
|
|
30
30
|
const {parseJS, Syntax} = require("../utils/parseUtils");
|
|
31
|
-
const {getValue, isMethodCall,
|
|
31
|
+
const {getValue, isMethodCall, getStringValue} = require("../utils/ASTUtils");
|
|
32
32
|
const log = require("@ui5/logger").getLogger("lbt:analyzer:SmartTemplateAnalyzer");
|
|
33
33
|
|
|
34
34
|
// ---------------------------------------------------------------------------------------------------------
|
|
@@ -134,24 +134,35 @@ class TemplateComponentAnalyzer {
|
|
|
134
134
|
const TA = defineCall.findImportName("sap/suite/ui/generic/template/lib/TemplateAssembler.js");
|
|
135
135
|
// console.log("local name for TemplateAssembler: %s", TA);
|
|
136
136
|
if ( TA && defineCall.factory ) {
|
|
137
|
-
defineCall.factory.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
templateName = this._analyzeTemplateClassDefinition(stmt.argument.arguments[2]) || templateName;
|
|
137
|
+
if (defineCall.factory.type === Syntax.ArrowFunctionExpression &&
|
|
138
|
+
defineCall.factory.expression === true) {
|
|
139
|
+
if ( this._isTemplateClassDefinition(TA, defineCall.factory.body) ) {
|
|
140
|
+
templateName =
|
|
141
|
+
this._analyzeTemplateClassDefinition(defineCall.factory.body.arguments[2]) || templateName;
|
|
143
142
|
}
|
|
144
|
-
}
|
|
143
|
+
} else {
|
|
144
|
+
defineCall.factory.body.body.forEach( (stmt) => {
|
|
145
|
+
if ( stmt.type === Syntax.ReturnStatement &&
|
|
146
|
+
this._isTemplateClassDefinition(TA, stmt.argument)
|
|
147
|
+
) {
|
|
148
|
+
templateName =
|
|
149
|
+
this._analyzeTemplateClassDefinition(stmt.argument.arguments[2]) || templateName;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
145
153
|
}
|
|
146
154
|
}
|
|
147
155
|
return templateName;
|
|
148
156
|
}
|
|
149
157
|
|
|
158
|
+
_isTemplateClassDefinition(TA, node) {
|
|
159
|
+
return isMethodCall(node, [TA, "getTemplateComponent"]) &&
|
|
160
|
+
node.arguments.length > 2 &&
|
|
161
|
+
node.arguments[2].type === "ObjectExpression";
|
|
162
|
+
}
|
|
163
|
+
|
|
150
164
|
_analyzeTemplateClassDefinition(clazz) {
|
|
151
|
-
|
|
152
|
-
if ( isString(defaultValue) ) {
|
|
153
|
-
return defaultValue.value;
|
|
154
|
-
}
|
|
165
|
+
return getStringValue(getValue(clazz, ["metadata", "properties", "templateName", "defaultValue"]));
|
|
155
166
|
}
|
|
156
167
|
}
|
|
157
168
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {Syntax} = require("../utils/parseUtils");
|
|
4
4
|
const SapUiDefine = require("../calls/SapUiDefine");
|
|
5
|
-
const {getValue, isMethodCall,
|
|
5
|
+
const {getValue, isMethodCall, getStringValue} = require("../utils/ASTUtils");
|
|
6
6
|
const ModuleName = require("../utils/ModuleName");
|
|
7
7
|
const log = require("@ui5/logger").getLogger("lbt:analyzer:XMLCompositeAnalyzer");
|
|
8
8
|
|
|
@@ -19,18 +19,30 @@ class XMLCompositeAnalyzer {
|
|
|
19
19
|
const XMLC = defineCall.findImportName("sap/ui/core/XMLComposite.js");
|
|
20
20
|
// console.log("local name for XMLComposite: %s", XMLC);
|
|
21
21
|
if ( XMLC && defineCall.factory ) {
|
|
22
|
-
defineCall.factory.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
if (defineCall.factory.type === Syntax.ArrowFunctionExpression &&
|
|
23
|
+
defineCall.factory.expression === true) {
|
|
24
|
+
fragmentName = this._checkForXMLCClassDefinition(XMLC, defineCall.factory.body);
|
|
25
|
+
} else {
|
|
26
|
+
defineCall.factory.body.body.forEach((stmt) => {
|
|
27
|
+
if (stmt.type === Syntax.VariableDeclaration) {
|
|
28
|
+
stmt.declarations.forEach((decl) => {
|
|
29
|
+
fragmentName = this._checkForXMLCClassDefinition(XMLC, decl.init) || fragmentName;
|
|
30
|
+
});
|
|
31
|
+
} else if (
|
|
32
|
+
stmt.type === Syntax.ReturnStatement &&
|
|
33
|
+
( stmt?.argument?.type === Syntax.CallExpression && stmt.argument.arguments?.length > 1 &&
|
|
34
|
+
stmt.argument.arguments[1].type === Syntax.ObjectExpression)) {
|
|
35
|
+
fragmentName =
|
|
36
|
+
this._checkForXMLCClassDefinition(XMLC, stmt.argument) || fragmentName;
|
|
37
|
+
} else if (stmt.type === Syntax.ExpressionStatement &&
|
|
38
|
+
stmt.expression.type === Syntax.AssignmentExpression) {
|
|
39
|
+
fragmentName =
|
|
40
|
+
this._checkForXMLCClassDefinition(XMLC, stmt.expression.right) || fragmentName;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (fragmentName) {
|
|
45
|
+
const fragmentModule = ModuleName.fromUI5LegacyName(fragmentName, ".control.xml");
|
|
34
46
|
log.verbose("fragment control: add dependency to template fragment %s", fragmentModule);
|
|
35
47
|
info.addDependency(fragmentModule);
|
|
36
48
|
}
|
|
@@ -42,8 +54,9 @@ class XMLCompositeAnalyzer {
|
|
|
42
54
|
let fragmentName;
|
|
43
55
|
if ( isMethodCall(stmt, [XMLC, "extend"]) ) {
|
|
44
56
|
// log.verbose(stmt);
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
const value = getStringValue(stmt.arguments[0]);
|
|
58
|
+
if ( stmt.arguments.length > 0 && value ) {
|
|
59
|
+
fragmentName = value;
|
|
47
60
|
}
|
|
48
61
|
if ( stmt.arguments.length > 1 && stmt.arguments[1].type === Syntax.ObjectExpression ) {
|
|
49
62
|
fragmentName = this._analyzeXMLCClassDefinition(stmt.arguments[1]) || fragmentName;
|
|
@@ -54,10 +67,7 @@ class XMLCompositeAnalyzer {
|
|
|
54
67
|
|
|
55
68
|
_analyzeXMLCClassDefinition(clazz) {
|
|
56
69
|
// log.verbose(clazz);
|
|
57
|
-
|
|
58
|
-
if ( isString(fragmentName) ) {
|
|
59
|
-
return fragmentName.value;
|
|
60
|
-
}
|
|
70
|
+
return getStringValue(getValue(clazz, ["fragment"]));
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const {parseJS, Syntax, VisitorKeys} = require("../utils/parseUtils");
|
|
3
3
|
const {getPropertyKey, isMethodCall, isIdentifier, getStringArray} = require("../utils/ASTUtils");
|
|
4
|
+
const log = require("@ui5/logger").getLogger("lbt:analyzer:LibraryJS");
|
|
4
5
|
|
|
5
6
|
const CALL__SAP_UI_GETCORE = ["sap", "ui", "getCore"];
|
|
6
7
|
|
|
@@ -25,8 +26,14 @@ async function analyze(resource) {
|
|
|
25
26
|
node.arguments.length === 1 &&
|
|
26
27
|
node.arguments[0].type === Syntax.ObjectExpression ) {
|
|
27
28
|
node.arguments[0].properties.forEach( (prop) => {
|
|
29
|
+
if (prop.type === Syntax.SpreadElement) {
|
|
30
|
+
// SpreadElements are currently not supported
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
const key = getPropertyKey(prop);
|
|
29
35
|
const value = prop.value;
|
|
36
|
+
|
|
30
37
|
if ( key === "noLibraryCSS" &&
|
|
31
38
|
(value.type === Syntax.Literal && typeof value.value === "boolean") ) {
|
|
32
39
|
libInfo.noLibraryCSS = value.value;
|
|
@@ -38,6 +45,14 @@ async function analyze(resource) {
|
|
|
38
45
|
libInfo.controls = getStringArray(value, true);
|
|
39
46
|
} else if ( key === "elements" && value.type == Syntax.ArrayExpression ) {
|
|
40
47
|
libInfo.elements = getStringArray(value, true);
|
|
48
|
+
} else if ( ["designtime", "dependencies", "extensions", "name", "version"].includes(key) ) {
|
|
49
|
+
// do nothing, for all other supported properties
|
|
50
|
+
} else {
|
|
51
|
+
log.error(
|
|
52
|
+
"Unexpected property '" + key +
|
|
53
|
+
"' or wrong type for '" + key +
|
|
54
|
+
"' in sap.ui.getCore().initLibrary call in '" + resource.getPath() + "'"
|
|
55
|
+
);
|
|
41
56
|
}
|
|
42
57
|
});
|
|
43
58
|
|
|
@@ -648,7 +648,7 @@ async function rewriteDefine({moduleName, moduleContent, moduleSourceMap}) {
|
|
|
648
648
|
|
|
649
649
|
// Inject module name if missing
|
|
650
650
|
if ( defineCall.arguments.length == 0 ||
|
|
651
|
-
defineCall.arguments[0].type
|
|
651
|
+
![Syntax.Literal, Syntax.TemplateLiteral].includes(defineCall.arguments[0].type)) {
|
|
652
652
|
let value = `"${ModuleName.toRequireJSName(moduleName)}"`;
|
|
653
653
|
let index;
|
|
654
654
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {Syntax} = require("../utils/parseUtils");
|
|
4
4
|
const ModuleName = require("../utils/ModuleName");
|
|
5
|
-
const {
|
|
5
|
+
const {isBoolean, getStringValue} = require("../utils/ASTUtils");
|
|
6
6
|
|
|
7
7
|
class SapUiDefineCall {
|
|
8
8
|
constructor(node, moduleName) {
|
|
@@ -11,6 +11,7 @@ class SapUiDefineCall {
|
|
|
11
11
|
this.dependencyArray = null;
|
|
12
12
|
this.factory = null;
|
|
13
13
|
this.exportAsGlobal = false;
|
|
14
|
+
this.paramNames = null;
|
|
14
15
|
|
|
15
16
|
const args = node.arguments;
|
|
16
17
|
if ( args == null ) {
|
|
@@ -27,28 +28,33 @@ class SapUiDefineCall {
|
|
|
27
28
|
let i = 0;
|
|
28
29
|
let params;
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
const name = getStringValue(args[i]);
|
|
32
|
+
if ( i < args.length && name ) {
|
|
31
33
|
// assert(String)
|
|
32
|
-
this.name =
|
|
34
|
+
this.name = name;
|
|
35
|
+
i++;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
if ( i < args.length && args[i].type === Syntax.ArrayExpression ) {
|
|
36
39
|
this.dependencyArray = args[i++];
|
|
37
40
|
this.dependencies = this.dependencyArray.elements.map( (elem) => {
|
|
38
|
-
|
|
41
|
+
const value = getStringValue(elem);
|
|
42
|
+
if ( !value ) {
|
|
39
43
|
throw new TypeError();
|
|
40
44
|
}
|
|
41
|
-
return ModuleName.resolveRelativeRequireJSName(this.name,
|
|
45
|
+
return ModuleName.resolveRelativeRequireJSName(this.name, value);
|
|
42
46
|
});
|
|
43
47
|
this.dependencyInsertionIdx = this.dependencyArray.elements.length;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
if ( i < args.length &&
|
|
50
|
+
if ( i < args.length && (
|
|
51
|
+
args[i].type === Syntax.FunctionExpression || args[i].type === Syntax.ArrowFunctionExpression)
|
|
52
|
+
) {
|
|
47
53
|
this.factory = args[i++];
|
|
48
54
|
params = this.factory.params;
|
|
49
55
|
this.paramNames = params.map( (param) => {
|
|
50
56
|
if ( param.type !== Syntax.Identifier ) {
|
|
51
|
-
|
|
57
|
+
return null;
|
|
52
58
|
}
|
|
53
59
|
return param.name;
|
|
54
60
|
});
|
|
@@ -13,10 +13,31 @@ const {Syntax} = require("../utils/parseUtils");
|
|
|
13
13
|
* @returns {boolean} Whether the node is a literal and whether its value matches the given string
|
|
14
14
|
*/
|
|
15
15
|
function isString(node, literal) {
|
|
16
|
-
|
|
16
|
+
const value = getStringValue(node);
|
|
17
|
+
if (value === undefined) {
|
|
17
18
|
return false;
|
|
18
19
|
}
|
|
19
|
-
return literal == null ? true
|
|
20
|
+
return literal == null ? true: value === literal;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getStringValue(node) {
|
|
24
|
+
if (isLiteral(node)) {
|
|
25
|
+
return node.value;
|
|
26
|
+
} else if (isTemplateLiteralWithoutExpression(node)) {
|
|
27
|
+
return node?.quasis?.[0]?.value?.cooked;
|
|
28
|
+
} else {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isLiteral(node) {
|
|
34
|
+
return node && node.type === Syntax.Literal && typeof node.value === "string";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isTemplateLiteralWithoutExpression(node) {
|
|
38
|
+
return node?.type === Syntax.TemplateLiteral &&
|
|
39
|
+
node?.expressions?.length === 0 &&
|
|
40
|
+
node?.quasis?.length === 1;
|
|
20
41
|
}
|
|
21
42
|
|
|
22
43
|
function isBoolean(node, literal) {
|
|
@@ -47,27 +68,27 @@ function isNamedObject(node, objectPath, length) {
|
|
|
47
68
|
}
|
|
48
69
|
|
|
49
70
|
function isIdentifier(node, name) {
|
|
50
|
-
if ( node.type
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
if ( typeof name == "string" ) {
|
|
71
|
+
if ( node.type === Syntax.Identifier && typeof name == "string" ) {
|
|
54
72
|
return name === node.name;
|
|
73
|
+
} else if ( node.type === Syntax.Identifier && Array.isArray(name) ) {
|
|
74
|
+
return name.find((name) => name === node.name || name === "*") !== undefined;
|
|
75
|
+
} else if ( node.type === Syntax.ObjectPattern ) {
|
|
76
|
+
return node.properties.filter((childnode) => isIdentifier(childnode.key, name)).length > 0;
|
|
77
|
+
} else if ( node.type === Syntax.ArrayPattern ) {
|
|
78
|
+
return node.elements.filter((childnode) => isIdentifier(childnode, name)).length > 0;
|
|
79
|
+
} else {
|
|
80
|
+
return false;
|
|
55
81
|
}
|
|
56
|
-
for (let i = 0; i < name.length; i++) {
|
|
57
|
-
if ( name[i] === node.name || name[i] === "*" ) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
82
|
}
|
|
63
83
|
|
|
64
84
|
function getPropertyKey(property) {
|
|
65
|
-
if ( property.
|
|
85
|
+
if ( property.type === Syntax.SpreadElement ) {
|
|
86
|
+
// TODO: Support interpreting SpreadElements
|
|
87
|
+
return;
|
|
88
|
+
} else if ( property.key.type === Syntax.Identifier && property.computed !== true ) {
|
|
66
89
|
return property.key.name;
|
|
67
90
|
} else if ( property.key.type === Syntax.Literal ) {
|
|
68
91
|
return String(property.key.value);
|
|
69
|
-
} else {
|
|
70
|
-
throw new Error();
|
|
71
92
|
}
|
|
72
93
|
}
|
|
73
94
|
|
|
@@ -102,10 +123,15 @@ function getValue(obj, names) {
|
|
|
102
123
|
*/
|
|
103
124
|
function getStringArray(array, skipNonStringLiterals) {
|
|
104
125
|
return array.elements.reduce( (result, item) => {
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
const value = getStringValue(item);
|
|
127
|
+
if ( value !== undefined ) {
|
|
128
|
+
result.push(value);
|
|
107
129
|
} else if ( !skipNonStringLiterals ) {
|
|
108
|
-
|
|
130
|
+
if (item.type === Syntax.TemplateLiteral) {
|
|
131
|
+
throw new TypeError("array element is a template literal with expressions");
|
|
132
|
+
} else {
|
|
133
|
+
throw new TypeError("array element is not a string literal: " + item.type);
|
|
134
|
+
}
|
|
109
135
|
}
|
|
110
136
|
return result;
|
|
111
137
|
}, []);
|
|
@@ -113,6 +139,7 @@ function getStringArray(array, skipNonStringLiterals) {
|
|
|
113
139
|
|
|
114
140
|
module.exports = {
|
|
115
141
|
isString,
|
|
142
|
+
getStringValue,
|
|
116
143
|
isBoolean,
|
|
117
144
|
isMethodCall,
|
|
118
145
|
isNamedObject,
|