@ui5/builder 3.0.0-alpha.1 → 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.
Files changed (66) hide show
  1. package/CHANGELOG.md +867 -0
  2. package/index.js +0 -43
  3. package/lib/lbt/analyzer/FioriElementsAnalyzer.js +23 -12
  4. package/lib/lbt/analyzer/JSModuleAnalyzer.js +115 -61
  5. package/lib/lbt/analyzer/SmartTemplateAnalyzer.js +23 -12
  6. package/lib/lbt/analyzer/XMLCompositeAnalyzer.js +29 -19
  7. package/lib/lbt/analyzer/XMLTemplateAnalyzer.js +2 -1
  8. package/lib/lbt/analyzer/analyzeLibraryJS.js +15 -0
  9. package/lib/lbt/bundle/Builder.js +365 -138
  10. package/lib/lbt/bundle/BundleWriter.js +17 -0
  11. package/lib/lbt/bundle/Resolver.js +2 -2
  12. package/lib/lbt/calls/SapUiDefine.js +13 -7
  13. package/lib/lbt/resources/LocatorResource.js +7 -7
  14. package/lib/lbt/resources/LocatorResourcePool.js +8 -4
  15. package/lib/lbt/resources/ResourceCollector.js +22 -15
  16. package/lib/lbt/resources/ResourceInfoList.js +0 -1
  17. package/lib/lbt/resources/ResourcePool.js +7 -6
  18. package/lib/lbt/utils/ASTUtils.js +45 -18
  19. package/lib/lbt/utils/escapePropertiesFile.js +3 -6
  20. package/lib/lbt/utils/parseUtils.js +1 -1
  21. package/lib/processors/bundlers/moduleBundler.js +31 -10
  22. package/lib/processors/jsdoc/lib/createIndexFiles.js +1 -1
  23. package/lib/processors/jsdoc/lib/transformApiJson.js +78 -22
  24. package/lib/processors/jsdoc/lib/ui5/plugin.js +414 -122
  25. package/lib/processors/jsdoc/lib/ui5/template/publish.js +112 -91
  26. package/lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js +1 -1
  27. package/lib/processors/manifestCreator.js +8 -45
  28. package/lib/processors/minifier.js +11 -5
  29. package/lib/tasks/buildThemes.js +1 -1
  30. package/lib/tasks/bundlers/generateBundle.js +70 -30
  31. package/lib/tasks/bundlers/generateComponentPreload.js +26 -19
  32. package/lib/tasks/bundlers/generateFlexChangesBundle.js +10 -5
  33. package/lib/tasks/bundlers/generateLibraryPreload.js +113 -94
  34. package/lib/tasks/bundlers/generateManifestBundle.js +8 -10
  35. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +42 -10
  36. package/lib/tasks/bundlers/utils/createModuleNameMapping.js +31 -0
  37. package/lib/tasks/generateCachebusterInfo.js +7 -3
  38. package/lib/tasks/generateLibraryManifest.js +6 -8
  39. package/lib/tasks/generateResourcesJson.js +3 -3
  40. package/lib/tasks/generateThemeDesignerResources.js +118 -2
  41. package/lib/tasks/generateVersionInfo.js +5 -5
  42. package/lib/tasks/jsdoc/generateJsdoc.js +1 -1
  43. package/lib/tasks/minify.js +14 -4
  44. package/lib/tasks/taskRepository.js +1 -13
  45. package/lib/tasks/transformBootstrapHtml.js +6 -1
  46. package/package.json +13 -11
  47. package/lib/builder/BuildContext.js +0 -56
  48. package/lib/builder/ProjectBuildContext.js +0 -57
  49. package/lib/builder/builder.js +0 -419
  50. package/lib/tasks/TaskUtil.js +0 -160
  51. package/lib/types/AbstractBuilder.js +0 -270
  52. package/lib/types/AbstractFormatter.js +0 -66
  53. package/lib/types/AbstractUi5Formatter.js +0 -95
  54. package/lib/types/application/ApplicationBuilder.js +0 -211
  55. package/lib/types/application/ApplicationFormatter.js +0 -227
  56. package/lib/types/application/applicationType.js +0 -15
  57. package/lib/types/library/LibraryBuilder.js +0 -231
  58. package/lib/types/library/LibraryFormatter.js +0 -519
  59. package/lib/types/library/libraryType.js +0 -15
  60. package/lib/types/module/ModuleBuilder.js +0 -7
  61. package/lib/types/module/ModuleFormatter.js +0 -54
  62. package/lib/types/module/moduleType.js +0 -15
  63. package/lib/types/themeLibrary/ThemeLibraryBuilder.js +0 -63
  64. package/lib/types/themeLibrary/ThemeLibraryFormatter.js +0 -90
  65. package/lib/types/themeLibrary/themeLibraryType.js +0 -15
  66. package/lib/types/typeRepository.js +0 -46
package/index.js CHANGED
@@ -3,10 +3,6 @@
3
3
  * @public
4
4
  */
5
5
  module.exports = {
6
- /**
7
- * @type {import('./lib/builder/builder')}
8
- */
9
- builder: "./lib/builder/builder",
10
6
  /**
11
7
  * @public
12
8
  * @alias module:@ui5/builder.processors
@@ -156,45 +152,6 @@ module.exports = {
156
152
  * @type {import('./lib/tasks/taskRepository')}
157
153
  */
158
154
  taskRepository: "./lib/tasks/taskRepository",
159
- /**
160
- * @type {import('./lib/tasks/TaskUtil')}
161
- */
162
- TaskUtil: "./lib/tasks/TaskUtil"
163
- },
164
- /**
165
- * @private
166
- * @alias module:@ui5/builder.types
167
- * @namespace
168
- */
169
- types: {
170
- /**
171
- * @type {typeof import('./lib/types/AbstractBuilder')}
172
- */
173
- AbstractBuilder: "./lib/types/AbstractBuilder",
174
- /**
175
- * @type {typeof import('./lib/types/AbstractFormatter')}
176
- */
177
- AbstractFormatter: "./lib/types/AbstractFormatter",
178
- /**
179
- * @type {import('./lib/types/application/applicationType')}
180
- */
181
- application: "./lib/types/application/applicationType",
182
- /**
183
- * @type {import('./lib/types/library/libraryType')}
184
- */
185
- library: "./lib/types/library/libraryType",
186
- /**
187
- * @type {import('./lib/types/themeLibrary/themeLibraryType')}
188
- */
189
- themeLibrary: "./lib/types/themeLibrary/themeLibraryType",
190
- /**
191
- * @type {import('./lib/types/module/moduleType')}
192
- */
193
- module: "./lib/types/module/moduleType",
194
- /**
195
- * @type {import('./lib/types/typeRepository')}
196
- */
197
- typeRepository: "./lib/types/typeRepository"
198
155
  }
199
156
  };
200
157
 
@@ -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, isString} = require("../utils/ASTUtils");
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.body.body.forEach( (stmt) => {
169
- if ( stmt.type === Syntax.ReturnStatement &&
170
- isMethodCall(stmt.argument, [TA, "getTemplateComponent"]) &&
171
- stmt.argument.arguments.length > 2 &&
172
- stmt.argument.arguments[2].type === "ObjectExpression" ) {
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
- const defaultValue = getValue(clazz, ["metadata", "properties", "templateName", "defaultValue"]);
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 {findOwnProperty, getLocation, getPropertyKey, isMethodCall, isString} = require("../utils/ASTUtils");
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: [],
@@ -175,12 +177,11 @@ const EnrichedVisitorKeys = (function() {
175
177
 
176
178
  // merge with 'official' visitor keys
177
179
  Object.keys(VisitorKeys).forEach( (type) => {
178
- // Check if the visitor-key exists in the available Syntax because
179
- // the list of visitor-keys does not match the available Syntax.
180
- if (!Syntax[type]) {
181
- // Deprecated / removed:
182
- // ExperimentalRestProperty
183
- // ExperimentalSpreadProperty
180
+ // Ignore deprecated keys:
181
+ // - ExperimentalSpreadProperty => SpreadElement
182
+ // - ExperimentalRestProperty => RestElement
183
+ // They are about to be removed, see: https://github.com/eslint/eslint-visitor-keys/pull/36
184
+ if (type === "ExperimentalSpreadProperty" || type === "ExperimentalRestProperty") {
184
185
  return;
185
186
  }
186
187
  // Ignore JSX visitor-keys because they aren't used.
@@ -188,6 +189,15 @@ const EnrichedVisitorKeys = (function() {
188
189
  return;
189
190
  }
190
191
 
192
+ // Ignore new ES2022 syntax as we currently use ES2021 (see parseUtils.js)
193
+ if (
194
+ type === "PrivateIdentifier" ||
195
+ type === "PropertyDefinition" ||
196
+ type === "StaticBlock"
197
+ ) {
198
+ return;
199
+ }
200
+
191
201
  const visitorKeys = VisitorKeys[type];
192
202
  const condKeys = TempKeys[type];
193
203
  if ( condKeys === undefined ) {
@@ -293,6 +303,9 @@ class JSModuleAnalyzer {
293
303
  */
294
304
  let bIsUi5Module = false;
295
305
 
306
+ // Module name via @ui5-bundle comment in first line. Overrides all other main module candidates.
307
+ let firstLineBundleName;
308
+
296
309
  // first analyze the whole AST...
297
310
  visit(ast, false);
298
311
 
@@ -306,7 +319,12 @@ class JSModuleAnalyzer {
306
319
  log.verbose(`bundle include directive ${subModule}`);
307
320
  } else if ( comment.value.startsWith("@ui5-bundle ") ) {
308
321
  const bundleName = comment.value.slice("@ui5-bundle ".length);
309
- setMainModuleInfo(bundleName, null);
322
+ if (comment.start === 0) {
323
+ // Remember the name from the first line to use it as final name
324
+ firstLineBundleName = bundleName;
325
+ } else {
326
+ setMainModuleInfo(bundleName, null);
327
+ }
310
328
  log.verbose(`bundle name directive ${bundleName}`);
311
329
  } else {
312
330
  log.warn(`unrecognized bundle directive ${comment.value}`);
@@ -316,7 +334,10 @@ class JSModuleAnalyzer {
316
334
  }
317
335
 
318
336
  // ...and finally take conclusions about the file's content
319
- if ( !mainModuleFound ) {
337
+ if ( firstLineBundleName ) {
338
+ // If the first line has a bundle name, use it and override all other found names
339
+ info.name = firstLineBundleName;
340
+ } else if ( !mainModuleFound ) {
320
341
  // if there's exactly one module definition in this file but it didn't
321
342
  // immediately qualify as main module, make it now the main module
322
343
  if ( candidateName != null && nModuleDeclarations == 1 ) {
@@ -522,21 +543,27 @@ class JSModuleAnalyzer {
522
543
 
523
544
  function onDeclare(node) {
524
545
  const args = node.arguments;
525
- if ( args.length > 0 && isString(args[0]) ) {
526
- const name = ModuleName.fromUI5LegacyName( args[0].value );
527
- if ( nModuleDeclarations === 1 && !mainModuleFound) {
528
- // if this is the first declaration, then this is the main module declaration
529
- // note that this overrides an already given name
530
- setMainModuleInfo(name, getDocumentation(node));
531
- } else if ( nModuleDeclarations > 1 && name === info.name ) {
532
- // ignore duplicate declarations (e.g. in behavior file of design time controls)
533
- log.warn(`duplicate declaration of module name at ${getLocation(args)} in ${name}`);
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;
534
562
  } else {
535
- // otherwise it is just a submodule declaration
536
- info.addSubModule(name);
563
+ log.error("jQuery.sap.declare: module name could not be determined from first argument:", args[0]);
537
564
  }
538
565
  } else {
539
- log.error("jQuery.sap.declare: module name could not be determined from first argument:", args[0]);
566
+ log.error("jQuery.sap.declare: module name could not be determined, no arguments are given");
540
567
  }
541
568
  }
542
569
 
@@ -550,20 +577,26 @@ class JSModuleAnalyzer {
550
577
 
551
578
  // determine the name of the module
552
579
  let name = null;
553
- if ( i < nArgs && isString(args[i]) ) {
554
- name = ModuleName.fromRequireJSName( args[i++].value );
555
- if ( name === defaultName ) {
556
- // hardcoded name equals the file name, so this definition qualifies as main module definition
557
- setMainModuleInfo(name, desc);
558
- } else {
559
- info.addSubModule(name);
560
- if ( candidateName == null ) {
561
- // remember the name and description in case no other module qualifies as main module
562
- candidateName = name;
563
- candidateDescription = desc;
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
+ }
564
594
  }
595
+ i++;
565
596
  }
566
- } else {
597
+ }
598
+
599
+ if ( !name ) {
567
600
  nUnnamedDefines++;
568
601
  if ( nUnnamedDefines > 1 ) {
569
602
  throw new Error(
@@ -595,15 +628,25 @@ class JSModuleAnalyzer {
595
628
  // UI5 signature with one or many required modules
596
629
  for (let i = 0; i < nArgs; i++) {
597
630
  const arg = args[i];
598
- if ( isString(arg) ) {
599
- const requiredModuleName = ModuleName.fromUI5LegacyName( arg.value );
631
+ const value = getStringValue(arg);
632
+ if ( value !== undefined ) {
633
+ const requiredModuleName = ModuleName.fromUI5LegacyName( value );
600
634
  info.addDependency(requiredModuleName, conditional);
601
- } else if ( arg.type == Syntax.ConditionalExpression &&
602
- isString(arg.consequent) && isString(arg.alternate) ) {
603
- const requiredModuleName1 = ModuleName.fromUI5LegacyName( arg.consequent.value );
604
- info.addDependency(requiredModuleName1, true);
605
- const requiredModuleName2 = ModuleName.fromUI5LegacyName( arg.alternate.value );
606
- info.addDependency(requiredModuleName2, true);
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
+ }
607
650
  } else {
608
651
  log.verbose("jQuery.sap.require: cannot evaluate dynamic arguments: ", arg && arg.type);
609
652
  info.dynamicDependencies = true;
@@ -618,9 +661,10 @@ class JSModuleAnalyzer {
618
661
  const i = 0;
619
662
 
620
663
  if ( i < nArgs ) {
621
- if ( isString(args[i]) ) {
664
+ const value = getStringValue(args[i]);
665
+ if ( value !== undefined ) {
622
666
  // sap.ui.requireSync does not support relative dependencies
623
- const moduleName = ModuleName.fromRequireJSName( args[i].value );
667
+ const moduleName = ModuleName.fromRequireJSName( value );
624
668
  info.addDependency(moduleName, conditional);
625
669
  } else {
626
670
  log.verbose("sap.ui.requireSync: cannot evaluate dynamic arguments: ", args[i] && args[i].type);
@@ -635,18 +679,24 @@ class JSModuleAnalyzer {
635
679
  let i = 0;
636
680
 
637
681
  // determine the name of the module
638
- if ( i < nArgs && isString(args[i]) ) {
639
- const moduleName = ModuleName.fromRequireJSName( args[i++].value );
640
- info.addSubModule(moduleName);
641
-
642
- // add dependencies
643
- // to correctly identify dependencies e.g. of a library-preload
644
- const elementArg = args[i++];
645
- if (elementArg && elementArg.type === Syntax.ArrayExpression) {
646
- elementArg.elements.forEach((element) => {
647
- const dependencyName = ModuleName.resolveRelativeRequireJSName(moduleName, element.value);
648
- info.addDependency(dependencyName, conditional);
649
- });
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)");
650
700
  }
651
701
  } else {
652
702
  log.warn("sap.ui.predefine call is missing a module name (ignored)");
@@ -673,6 +723,9 @@ class JSModuleAnalyzer {
673
723
  if ( modules && modules.type == Syntax.ObjectExpression ) {
674
724
  modules.properties.forEach( function(property) {
675
725
  let moduleName = getPropertyKey(property);
726
+ if ( !moduleName ) {
727
+ return;
728
+ }
676
729
  if ( namesUseLegacyNotation ) {
677
730
  moduleName = ModuleName.fromUI5LegacyName(moduleName);
678
731
  }
@@ -686,16 +739,17 @@ class JSModuleAnalyzer {
686
739
  function analyzeDependencyArray(array, conditional, name) {
687
740
  // console.log(array);
688
741
  array.forEach( (item) => {
689
- if ( isString(item) ) {
742
+ const value = getStringValue(item);
743
+ if ( value !== undefined ) {
690
744
  // ignore special AMD dependencies (require, exports, module)
691
- if ( SPECIAL_AMD_DEPENDENCIES.indexOf(item.value) >= 0 ) {
745
+ if ( SPECIAL_AMD_DEPENDENCIES.indexOf(value) >= 0 ) {
692
746
  return;
693
747
  }
694
748
  let requiredModule;
695
749
  if (name == null) {
696
- requiredModule = ModuleName.fromRequireJSName( item.value );
750
+ requiredModule = ModuleName.fromRequireJSName( value );
697
751
  } else {
698
- requiredModule = ModuleName.resolveRelativeRequireJSName(name, item.value);
752
+ requiredModule = ModuleName.resolveRelativeRequireJSName(name, value);
699
753
  }
700
754
  info.addDependency( requiredModule, conditional );
701
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, isString} = require("../utils/ASTUtils");
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.body.body.forEach( (stmt) => {
138
- if ( stmt.type === Syntax.ReturnStatement &&
139
- isMethodCall(stmt.argument, [TA, "getTemplateComponent"]) &&
140
- stmt.argument.arguments.length > 2 &&
141
- stmt.argument.arguments[2].type === "ObjectExpression" ) {
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
- const defaultValue = getValue(clazz, ["metadata", "properties", "templateName", "defaultValue"]);
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, isString} = require("../utils/ASTUtils");
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.body.body.forEach( (stmt) => {
23
- if ( stmt.type === Syntax.VariableDeclaration ) {
24
- stmt.declarations.forEach( (decl) => {
25
- fragmentName = this._checkForXMLCClassDefinition( XMLC, decl.init ) || fragmentName;
26
- });
27
- } else if ( stmt.type === Syntax.ExpressionStatement &&
28
- stmt.expression.type === Syntax.AssignmentExpression ) {
29
- fragmentName = this._checkForXMLCClassDefinition( XMLC, stmt.expression.right ) || fragmentName;
30
- }
31
- });
32
- if ( fragmentName ) {
33
- const fragmentModule = ModuleName.fromUI5LegacyName( fragmentName, ".control.xml" );
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
- if ( stmt.arguments.length > 0 && isString(stmt.arguments[0]) ) {
46
- fragmentName = stmt.arguments[0].value;
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
- const fragmentName = getValue(clazz, ["fragment"]);
58
- if ( isString(fragmentName) ) {
59
- return fragmentName.value;
60
- }
70
+ return getStringValue(getValue(clazz, ["fragment"]));
61
71
  }
62
72
  }
63
73
 
@@ -231,9 +231,10 @@ class XMLTemplateAnalyzer {
231
231
  // looks like a UI5 library or package name
232
232
  const moduleName = ModuleName.fromUI5LegacyName( (namespace ? namespace + "." : "") + localName );
233
233
 
234
+ this._analyzeCoreRequire(node);
235
+
234
236
  // ignore FragmentDefinition (also skipped by runtime XMLTemplateProcessor)
235
237
  if ( FRAGMENTDEFINITION_MODULE !== moduleName ) {
236
- this._analyzeCoreRequire(node);
237
238
  this.promises.push(this._analyzeModuleDependency(node, moduleName, this.conditional));
238
239
  }
239
240
  }
@@ -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