@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.
@@ -5,9 +5,7 @@
5
5
  * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
6
6
  */
7
7
 
8
- /* global env: true */
9
- /* eslint-env es6,node */
10
- /* eslint strict: [2, "global"] */
8
+ /* global env */
11
9
 
12
10
  "use strict";
13
11
 
@@ -27,6 +25,7 @@ const warning = logger.warn.bind(logger);
27
25
  const error = logger.error.bind(logger);
28
26
 
29
27
  const {extractVersion, extractSince} = require("./utils/versionUtil");
28
+ const {ASTBuilder, TypeParser} = require("./utils/typeParser");
30
29
 
31
30
  /* errors that might fail the build in future */
32
31
  function future(msg) {
@@ -42,39 +41,7 @@ function future(msg) {
42
41
  /* globals, constants */
43
42
  const MY_TEMPLATE_NAME = "ui5",
44
43
  MY_ALT_TEMPLATE_NAME = "sapui5-jsdoc3",
45
- ANONYMOUS_LONGNAME = doclet.ANONYMOUS_LONGNAME,
46
- A_SECURITY_TAGS = [
47
- {
48
- name : "SecSource",
49
- caption : "Taint Source",
50
- description : "APIs that might introduce tainted data into an application, e.g. due to user input or network access",
51
- params : ["out","flags"]
52
- },
53
- {
54
- name : "SecEntryPoint",
55
- caption : "Taint Entry Point",
56
- description: "APIs that are called implicitly by a framework or server and trigger execution of application logic",
57
- params : ["in","flags"]
58
- },
59
- {
60
- name : "SecSink",
61
- caption : "Taint Sink",
62
- description : "APIs that pose a security risk when they receive tainted data",
63
- params : ["in","flags"]
64
- },
65
- {
66
- name : "SecPassthrough",
67
- caption : "Taint Passthrough",
68
- description : "APIs that might propagate tainted data when they receive it as input",
69
- params : ["in","out","flags"]
70
- },
71
- {
72
- name : "SecValidate",
73
- caption : "Validation",
74
- description : "APIs that (partially) cleanse tainted data so that it no longer poses a security risk in the further data flow of an application",
75
- params : ["in","out","flags"]
76
- }
77
- ];
44
+ ANONYMOUS_LONGNAME = doclet.ANONYMOUS_LONGNAME;
78
45
 
79
46
  const templatesConf = (env.conf.templates || {}),
80
47
  templateConf = templatesConf[MY_TEMPLATE_NAME] || templatesConf[MY_ALT_TEMPLATE_NAME] || {};
@@ -83,7 +50,7 @@ let conf = {};
83
50
 
84
51
  let __symbols;
85
52
  let __longnames;
86
- let __missingLongnames = {};
53
+ const __missingLongnames = {};
87
54
 
88
55
  function merge(target, source) {
89
56
  if ( source != null ) {
@@ -119,7 +86,7 @@ function lookup(key) {
119
86
  function createSymbol(longname, lines = []) {
120
87
  const comment = [
121
88
  "@name " + longname,
122
- ... lines
89
+ ...lines
123
90
  ];
124
91
 
125
92
  const symbol = new doclet.Doclet("/**\n * " + comment.join("\n * ") + "\n */", {});
@@ -215,7 +182,7 @@ function writeSymbols(symbols, filename, caption) {
215
182
  v.base = value.base.longname;
216
183
  }
217
184
  if ( value.implementations ) {
218
- v.base = value.implementations.map(($)=> $.longname);
185
+ v.base = value.implementations.map(($) => $.longname);
219
186
  }
220
187
  if ( value.parent ) {
221
188
  v.parent = value.parent.longname;
@@ -454,7 +421,7 @@ function createInheritanceTree(allSymbols) {
454
421
  } else {
455
422
  warning(`create missing class ${sClass} (extended by ${sExtendingClass})`);
456
423
  }
457
- let oBaseClass = getOrCreateClass(sBaseClass, sClass);
424
+ const oBaseClass = getOrCreateClass(sBaseClass, sClass);
458
425
  oClass = createSymbol(sClass, [
459
426
  "@extends " + sBaseClass,
460
427
  "@" + sKind,
@@ -485,7 +452,7 @@ function createInheritanceTree(allSymbols) {
485
452
  aRootTypes.push(oClass);
486
453
  }
487
454
 
488
- let oBaseClass = getOrCreateClass(sBaseClass, oClass.longname);
455
+ const oBaseClass = getOrCreateClass(sBaseClass, oClass.longname);
489
456
  oClass.__ui5.base = oBaseClass;
490
457
  oBaseClass.__ui5.derived = oBaseClass.__ui5.derived || [];
491
458
  oBaseClass.__ui5.derived.push(oClass);
@@ -667,60 +634,8 @@ function sortByAlias(a, b) {
667
634
  return 0;
668
635
  }
669
636
 
670
- /* Make a symbol sorter by some attribute. */
671
- function makeSortby(/* fields ...*/) {
672
- const aFields = Array.prototype.slice.apply(arguments),
673
- aNorms = [],
674
- aFuncs = [];
675
- for (let i = 0; i < arguments.length; i++) {
676
- aNorms[i] = 1;
677
- if ( typeof aFields[i] === 'function' ) {
678
- aFuncs[i] = aFields[i];
679
- continue;
680
- }
681
- aFuncs[i] = function($,n) { return $[n]; };
682
- if ( aFields[i].indexOf("!") === 0 ) {
683
- aNorms[i] = -1;
684
- aFields[i] = aFields[i].slice(1);
685
- }
686
- if ( aFields[i] === 'deprecated' ) {
687
- aFuncs[i] = function($,n) { return !!$[n]; };
688
- } else if ( aFields[i] === 'static' ) {
689
- aFields[i] = 'scope';
690
- aFuncs[i] = function($,n) { return $[n] === 'static'; };
691
- } else if ( aFields[i].indexOf("#") === 0 ) {
692
- aFields[i] = aFields[i].slice(1);
693
- aFuncs[i] = function($,n) { return $.comment.getTag(n).length > 0; };
694
- }
695
- }
696
- return function(a, b) {
697
- // debug(`compare ${a.longname} : ${b.longname}`);
698
- let r = 0;
699
- for (let i = 0; r === 0 && i < aFields.length; i++) {
700
- let va = aFuncs[i](a,aFields[i]);
701
- let vb = aFuncs[i](b,aFields[i]);
702
- if ( va && !vb ) {
703
- r = -aNorms[i];
704
- } else if ( !va && vb ) {
705
- r = aNorms[i];
706
- } else if ( va && vb ) {
707
- va = String(va).toLowerCase();
708
- vb = String(vb).toLowerCase();
709
- if (va < vb) {
710
- r = -aNorms[i];
711
- }
712
- if (va > vb) {
713
- r = aNorms[i];
714
- }
715
- }
716
- // debug(` ${aFields[i]}: ${va} ? ${vb} = ${r}`);
717
- }
718
- return r;
719
- };
720
- }
721
-
722
637
  function getMembersOfKind(data, kind) {
723
- let oResult = [];
638
+ const oResult = [];
724
639
  //debug(`calculating kind ${kind} from ${data.longname}`);
725
640
  //console.log(data);
726
641
  let fnFilter;
@@ -759,94 +674,6 @@ function getMembersOfKind(data, kind) {
759
674
 
760
675
  // ---- type parsing ---------------------------------------------------------------------------------------------
761
676
 
762
- class ASTBuilder {
763
- literal(str) {
764
- return {
765
- type: "literal",
766
- value: str
767
- };
768
- }
769
- simpleType(type) {
770
- return {
771
- type: "simpleType",
772
- name: type
773
- };
774
- }
775
- array(componentType) {
776
- return {
777
- type: "array",
778
- component: componentType
779
- };
780
- }
781
- object(keyType, valueType) {
782
- return {
783
- type: "object",
784
- key: keyType,
785
- value: valueType
786
- };
787
- }
788
- set(elementType) {
789
- return {
790
- type: "set",
791
- element: elementType
792
- };
793
- }
794
- promise(fulfillmentType) {
795
- return {
796
- type: "promise",
797
- fulfill: fulfillmentType
798
- };
799
- }
800
- "function"(paramTypes, returnType, thisType, constructorType) {
801
- return {
802
- "type": "function",
803
- "params": paramTypes,
804
- "return": returnType,
805
- "this": thisType,
806
- "constructor": constructorType
807
- };
808
- }
809
- structure(structure) {
810
- return {
811
- type: "structure",
812
- fields: structure
813
- };
814
- }
815
- union(types) {
816
- return {
817
- type: "union",
818
- types: types
819
- };
820
- }
821
- synthetic(type) {
822
- type.synthetic = true;
823
- return type;
824
- }
825
- nullable(type) {
826
- type.nullable = true;
827
- return type;
828
- }
829
- mandatory(type) {
830
- type.mandatory = true;
831
- return type;
832
- }
833
- optional(type) {
834
- type.optional = true;
835
- return type;
836
- }
837
- repeatable(type) {
838
- type.repeatable = true;
839
- return type;
840
- }
841
- typeApplication(type, templateTypes) {
842
- return {
843
- type: "typeApplication",
844
- baseType: type,
845
- templateTypes: templateTypes
846
- };
847
- }
848
- }
849
-
850
677
  class TypeStringBuilder {
851
678
  constructor() {
852
679
  this.lt = "<";
@@ -906,7 +733,7 @@ class TypeStringBuilder {
906
733
  "function"(paramTypes, returnType) {
907
734
  return {
908
735
  simpleComponent: false,
909
- str: "function(" + paramTypes.map(type => type.str).join(',') + ")" + ( returnType ? " : " + this.safe(returnType) : "")
736
+ str: "function(" + paramTypes.map((type) => type.str).join(',') + ")" + ( returnType ? " : " + this.safe(returnType) : "")
910
737
  };
911
738
  }
912
739
  structure(structure) {
@@ -934,7 +761,7 @@ class TypeStringBuilder {
934
761
  union(types) {
935
762
  return {
936
763
  needsParenthesis: true,
937
- str: types.map(type => this.safe(type)).join('|')
764
+ str: types.map((type) => this.safe(type)).join('|')
938
765
  };
939
766
  }
940
767
  synthetic(type) {
@@ -960,248 +787,11 @@ class TypeStringBuilder {
960
787
  typeApplication(type, templateTypes) {
961
788
  return {
962
789
  simpleComponent: false,
963
- str: this.safe(type) + this.lt + templateTypes.map(type => this.safe(type)).join(',') + this.gt
790
+ str: this.safe(type) + this.lt + templateTypes.map((type) => this.safe(type)).join(',') + this.gt
964
791
  };
965
792
  }
966
793
  }
967
794
 
968
- function TypeParser(defaultBuilder = new ASTBuilder()) {
969
- const rLexer = /\s*(Array\.?<|Object\.?<|Set\.?<|Promise\.?<|function\(|\{|:|\(|\||\}|\.?<|>|\)|,|\[\]|\*|\?|!|=|\.\.\.)|\s*(false|true|(?:\+|-)?(?:\d+(?:\.\d+)?|NaN|Infinity)|'[^']*'|"[^"]*"|null|undefined)|\s*((?:module:)?\w+(?:[/.#~][$\w_]+)*)|./g;
970
-
971
- let input;
972
- let builder;
973
- let token;
974
- let tokenStr;
975
-
976
- function next(expected) {
977
- if ( expected !== undefined && token !== expected ) {
978
- throw new SyntaxError(
979
- `TypeParser: expected '${expected}', but found '${tokenStr}' ` +
980
- `(pos: ${rLexer.lastIndex}, input='${input}')`
981
- );
982
- }
983
- const match = rLexer.exec(input);
984
- if ( match ) {
985
- tokenStr = match[1] || match[2] || match[3];
986
- token = match[1] || (match[2] && "literal") || (match[3] && "symbol");
987
- if ( !token ) {
988
- throw new SyntaxError(`TypeParser: unexpected '${match[0]}' (pos: ${match.index}, input='${input}')`);
989
- }
990
- } else {
991
- tokenStr = token = null;
992
- }
993
- }
994
-
995
- function parseType() {
996
- let nullable = false;
997
- let mandatory = false;
998
- if ( token === "?" ) {
999
- next();
1000
- nullable = true;
1001
- } else if ( token === "!" ) {
1002
- next();
1003
- mandatory = true;
1004
- }
1005
-
1006
- let type;
1007
-
1008
- if ( token === "literal" ) {
1009
- type = builder.literal(tokenStr);
1010
- next();
1011
- } else if ( token === "Array.<" || token === "Array<" ) {
1012
- next();
1013
- const componentType = parseTypes();
1014
- next(">");
1015
- type = builder.array(componentType);
1016
- } else if ( token === "Object.<" || token === "Object<" ) {
1017
- next();
1018
- let keyType;
1019
- let valueType = parseTypes();
1020
- if ( token === "," ) {
1021
- next();
1022
- keyType = valueType;
1023
- valueType = parseTypes();
1024
- } else {
1025
- keyType = builder.synthetic(builder.simpleType("string"));
1026
- }
1027
- next(">");
1028
- type = builder.object(keyType, valueType);
1029
- } else if ( token === "Set.<" || token === "Set<" ) {
1030
- next();
1031
- const elementType = parseTypes();
1032
- next(">");
1033
- type = builder.set(elementType);
1034
- } else if ( token === "Promise.<" || token === "Promise<" ) {
1035
- next();
1036
- const resultType = parseTypes();
1037
- next(">");
1038
- type = builder.promise(resultType);
1039
- } else if ( token === "function(" ) {
1040
- next();
1041
- let thisType;
1042
- let constructorType;
1043
- const paramTypes = [];
1044
- let returnType;
1045
- if ( tokenStr === "this" ) {
1046
- next();
1047
- next(":");
1048
- thisType = parseType();
1049
- if ( token !== ")" ) {
1050
- next(",");
1051
- }
1052
- } else if ( tokenStr === "new" ) {
1053
- next();
1054
- next(":");
1055
- constructorType = parseType();
1056
- if ( token !== ")" ) {
1057
- next(",");
1058
- }
1059
- }
1060
- while ( token !== ")" ) {
1061
- const repeatable = token === "...";
1062
- if ( repeatable ) {
1063
- next();
1064
- }
1065
- let paramType = parseTypes();
1066
- if ( repeatable ) {
1067
- paramType = builder.repeatable(paramType);
1068
- }
1069
- const optional = token === "=";
1070
- if ( optional ) {
1071
- paramType = builder.optional(paramType);
1072
- next();
1073
- }
1074
- paramTypes.push(paramType);
1075
-
1076
- // exit if there are no more parameters
1077
- if ( token !== "," ) {
1078
- break;
1079
- }
1080
-
1081
- if ( repeatable ) {
1082
- throw new SyntaxError(
1083
- `TypeParser: only the last parameter of a function can be repeatable ` +
1084
- `(pos: ${rLexer.lastIndex}, input='${input}')`
1085
- );
1086
- }
1087
-
1088
- // consume the comma
1089
- next();
1090
- }
1091
- next(")");
1092
- if ( token === ":" ) {
1093
- next(":");
1094
- returnType = parseType();
1095
- }
1096
- type = builder.function(paramTypes, returnType, thisType, constructorType);
1097
- } else if ( token === "{" ) {
1098
- const structure = Object.create(null);
1099
- next();
1100
- do {
1101
- const propName = tokenStr;
1102
- if ( !/^\w+$/.test(propName) ) {
1103
- throw new SyntaxError(
1104
- `TypeParser: structure field must have a simple name ` +
1105
- `(pos: ${rLexer.lastIndex}, input='${input}', field:'${propName}')`
1106
- );
1107
- }
1108
- next("symbol");
1109
- let propType;
1110
- const optional = token === "=";
1111
- if ( optional ) {
1112
- next();
1113
- }
1114
- if ( token === ":" ) {
1115
- next();
1116
- propType = parseTypes();
1117
- } else {
1118
- propType = builder.synthetic(builder.simpleType("any"));
1119
- }
1120
- if ( optional ) {
1121
- propType = builder.optional(propType);
1122
- }
1123
- structure[propName] = propType;
1124
- if ( token === "}" ) {
1125
- break;
1126
- }
1127
- next(",");
1128
- } while (token);
1129
- next("}");
1130
- type = builder.structure(structure);
1131
- } else if ( token === "(" ) {
1132
- next();
1133
- type = parseTypes();
1134
- next(")");
1135
- } else if ( token === "*" ) {
1136
- next();
1137
- type = builder.simpleType("*");
1138
- } else {
1139
- type = builder.simpleType(tokenStr);
1140
- next("symbol");
1141
- // check for suffix operators: either 'type application' (generics) or 'array', but not both of them
1142
- if ( token === "<" || token === ".<" ) {
1143
- next();
1144
- const templateTypes = [];
1145
- do {
1146
- const templateType = parseTypes();
1147
- templateTypes.push(templateType);
1148
- if ( token === ">" ) {
1149
- break;
1150
- }
1151
- next(",");
1152
- } while (token);
1153
- next(">");
1154
- type = builder.typeApplication(type, templateTypes);
1155
- } else {
1156
- while ( token === "[]" ) {
1157
- next();
1158
- type = builder.array(type);
1159
- }
1160
- }
1161
- }
1162
- if ( builder.normalizeType ) {
1163
- type = builder.normalizeType(type);
1164
- }
1165
- if ( nullable ) {
1166
- type = builder.nullable(type);
1167
- }
1168
- if ( mandatory ) {
1169
- type = builder.mandatory(type);
1170
- }
1171
- return type;
1172
- }
1173
-
1174
- function parseTypes() {
1175
- const types = [];
1176
- do {
1177
- types.push(parseType());
1178
- if ( token !== "|" ) {
1179
- break;
1180
- }
1181
- next();
1182
- } while (token);
1183
- return types.length === 1 ? types[0] : builder.union(types);
1184
- }
1185
-
1186
- this.parse = function(typeStr, tempBuilder = defaultBuilder) {
1187
- /*
1188
- try {
1189
- const r = catharsis.parse(typeStr, { jsdoc: true});
1190
- console.log(JSON.stringify(typeStr, null, "\t"), r);
1191
- } catch (err) {
1192
- console.log(typeStr, err);
1193
- }
1194
- */
1195
- builder = tempBuilder;
1196
- input = String(typeStr);
1197
- rLexer.lastIndex = 0;
1198
- next();
1199
- const type = parseTypes();
1200
- next(null);
1201
- return type;
1202
- };
1203
- }
1204
-
1205
795
  const typeParser = new TypeParser();
1206
796
  const _TEXT_BUILDER = new TypeStringBuilder();
1207
797
 
@@ -1235,6 +825,7 @@ function _processTypeString(type, builder) {
1235
825
  return type;
1236
826
  }
1237
827
  }
828
+ return undefined;
1238
829
  }
1239
830
 
1240
831
  function listTypes(type) {
@@ -1341,13 +932,13 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1341
932
  const obj = [];
1342
933
  let curr = obj;
1343
934
  let attribForKind = 'kind';
1344
- let stack = [];
935
+ const stack = [];
1345
936
 
1346
937
  function isEmpty(obj) {
1347
938
  if ( !obj ) {
1348
939
  return true;
1349
940
  }
1350
- for (let n in obj) {
941
+ for (const n in obj) {
1351
942
  if ( obj.hasOwnProperty(n) ) {
1352
943
  return false;
1353
944
  }
@@ -1448,7 +1039,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1448
1039
  }
1449
1040
  if (info.since === null) {
1450
1041
  future(`**** Failed to parse version in string '${value}'. ` +
1451
- `Version might be missing or has an unexpected format.`)
1042
+ `Version might be missing or has an unexpected format.`);
1452
1043
  }
1453
1044
  if ( info.value ) {
1454
1045
  curr["text"] = normalizeWS(info.value);
@@ -1513,7 +1104,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1513
1104
  if ( $.access === 'restricted' ) {
1514
1105
  return $.__ui5.stakeholders;
1515
1106
  }
1516
- // return undefined
1107
+ return undefined;
1517
1108
  }
1518
1109
 
1519
1110
  function exceptions(symbol) {
@@ -1604,7 +1195,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1604
1195
 
1605
1196
  if ( metadata.specialSettings && Object.keys(metadata.specialSettings).length > 0 ) {
1606
1197
  collection("specialSettings");
1607
- for ( let n in metadata.specialSettings ) {
1198
+ for ( const n in metadata.specialSettings ) {
1608
1199
  const special = metadata.specialSettings[n];
1609
1200
  tag("specialSetting");
1610
1201
  attrib("name", special.name);
@@ -1625,7 +1216,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1625
1216
 
1626
1217
  if ( metadata.properties && Object.keys(metadata.properties).length > 0 ) {
1627
1218
  collection("properties");
1628
- for ( let n in metadata.properties ) {
1219
+ for ( const n in metadata.properties ) {
1629
1220
  const prop = metadata.properties[n];
1630
1221
  let defaultValue = prop.defaultValue != null ? prop.defaultValue.value : null;
1631
1222
  // JSON can't transport a value of undefined, so represent it as string
@@ -1670,7 +1261,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1670
1261
 
1671
1262
  if ( metadata.aggregations && Object.keys(metadata.aggregations).length > 0 ) {
1672
1263
  collection("aggregations");
1673
- for ( let n in metadata.aggregations ) {
1264
+ for ( const n in metadata.aggregations ) {
1674
1265
  const aggr = metadata.aggregations[n];
1675
1266
  tag("aggregation");
1676
1267
  attrib("name", aggr.name);
@@ -1707,7 +1298,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1707
1298
 
1708
1299
  if ( metadata.associations && Object.keys(metadata.associations).length > 0 ) {
1709
1300
  collection("associations");
1710
- for ( let n in metadata.associations ) {
1301
+ for ( const n in metadata.associations ) {
1711
1302
  const assoc = metadata.associations[n];
1712
1303
  tag("association");
1713
1304
  attrib("name", assoc.name);
@@ -1731,7 +1322,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1731
1322
 
1732
1323
  if ( metadata.events && Object.keys(metadata.events).length > 0 ) {
1733
1324
  collection("events");
1734
- for ( let n in metadata.events ) {
1325
+ for ( const n in metadata.events ) {
1735
1326
  const event = metadata.events[n];
1736
1327
  tag("event");
1737
1328
  attrib("name", event.name);
@@ -1751,7 +1342,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1751
1342
  tagWithSince("deprecated", event.deprecation);
1752
1343
  if ( event.parameters && Object.keys(event.parameters).length > 0 ) {
1753
1344
  tag("parameters");
1754
- for ( let pn in event.parameters ) {
1345
+ for ( const pn in event.parameters ) {
1755
1346
  if ( event.parameters.hasOwnProperty(pn) ) {
1756
1347
  const param = event.parameters[pn];
1757
1348
  tag(pn);
@@ -1774,7 +1365,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
1774
1365
 
1775
1366
  if ( metadata.annotations && Object.keys(metadata.annotations).length > 0 ) {
1776
1367
  collection("annotations");
1777
- for ( let n in metadata.annotations ) {
1368
+ for ( const n in metadata.annotations ) {
1778
1369
  const anno = metadata.annotations[n];
1779
1370
  tag("annotation");
1780
1371
  attrib("name", anno.name);
@@ -2308,7 +1899,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
2308
1899
  if ( symbol.__ui5.stereotype !== 'xmlmacro' && ownMethods.length > 0 ) {
2309
1900
  collection("methods");
2310
1901
  ownMethods.forEach(function(member) {
2311
- writeMethod(member, undefined, symbol.kind === 'interface' || symbol.kind === 'class');
1902
+ writeMethod(member, undefined, symbol.kind === 'interface' || symbol.kind === 'class');
2312
1903
  if ( member.__ui5.members ) {
2313
1904
  // HACK: export nested static functions as siblings of the current function
2314
1905
  // A correct representation has to be discussed with the SDK / WebIDE
@@ -2377,7 +1968,7 @@ function postProcessAPIJSON(api) {
2377
1968
  function guessExports(moduleName, symbols) {
2378
1969
 
2379
1970
  // a non-stringifiable special value for unresolved exports
2380
- let UNRESOLVED = function() {};
1971
+ const UNRESOLVED = function() {};
2381
1972
 
2382
1973
  symbols = symbols.sort((a,b) => {
2383
1974
  if ( a.name === b.name ) {
@@ -2457,7 +2048,7 @@ function postProcessAPIJSON(api) {
2457
2048
 
2458
2049
  }
2459
2050
 
2460
- for ( let n in modules ) {
2051
+ for ( const n in modules ) {
2461
2052
  guessExports(n, modules[n]);
2462
2053
  }
2463
2054
 
@@ -2478,7 +2069,7 @@ function postProcessAPIJSON(api) {
2478
2069
  }
2479
2070
  symbol = findSymbol(symbol.extends);
2480
2071
  }
2481
- // return undefined
2072
+ return undefined;
2482
2073
  }
2483
2074
 
2484
2075
  // See sap/ui/base/ManagedObjectMetadata
@@ -2525,6 +2116,37 @@ function postProcessAPIJSON(api) {
2525
2116
  `doesn't match containing library '${api.library}'. Library must be explicitly defined in class metadata!`);
2526
2117
  }
2527
2118
  }
2119
+ if (Array.isArray(symbol["ui5-metadata"].properties)) {
2120
+ for (const prop of symbol["ui5-metadata"].properties) {
2121
+ let moduleType;
2122
+ // cut off array brackets for symbol lookup
2123
+ const arrType = isArrayType(prop.type);
2124
+ let lookupType = prop.type;
2125
+ if (arrType) {
2126
+ lookupType = lookupType.replace("[]", "");
2127
+ }
2128
+ if (prop.dataType === undefined
2129
+ && findSymbol(lookupType) == null
2130
+ && !lookupType?.startsWith("module:")
2131
+ && findSymbol(moduleType = `module:${lookupType.replace(/\./g, "/")}`) != null) {
2132
+ // note: the dataType must be the original, including array brackets if present
2133
+ prop.dataType = prop.type;
2134
+ // the moduleType also needs to include the array brackets if present in the original dataType
2135
+ prop.type = moduleType + (arrType ? "[]" : "");
2136
+ for (const methodName of prop.methods) {
2137
+ const method = symbol.methods?.find((m) => m.name === methodName);
2138
+ if (methodName.startsWith("get")
2139
+ && method?.returnValue?.type === prop.dataType) {
2140
+ method.returnValue.type = prop.type;
2141
+ } else if (methodName.startsWith("set")
2142
+ && method?.parameters?.[0]?.type === prop.dataType) {
2143
+ method.parameters[0].type = prop.type;
2144
+ }
2145
+ }
2146
+ info(`${symbol.name}: adapted type of ${prop.name} and its accessors from '${prop.dataType}' to '${prop.type}'`);
2147
+ }
2148
+ }
2149
+ }
2528
2150
  });
2529
2151
 
2530
2152
  }
@@ -2568,16 +2190,22 @@ const builtinTypes = {
2568
2190
  Attr:true,
2569
2191
  Blob:true,
2570
2192
  DataTransfer:true,
2193
+ DragEvent:true,
2571
2194
  Document:true,
2572
2195
  DOMException:true,
2196
+ DOMRect:true,
2573
2197
  Element:true,
2574
2198
  Event:true,
2575
2199
  File:true,
2576
2200
  FileList:true,
2201
+ FormData:true,
2577
2202
  Headers:true,
2578
2203
  HTMLDocument:true,
2579
2204
  HTMLElement:true,
2580
2205
  Node:true,
2206
+ PerformanceResourceTiming:true,
2207
+ Request:true,
2208
+ Response:true,
2581
2209
  Storage:true,
2582
2210
  Touch:true,
2583
2211
  TouchList:true,
@@ -2628,7 +2256,9 @@ function validateAPIJSON(api) {
2628
2256
  // create map of defined symbols (built-in types, dependency libraries, current library)
2629
2257
  const defined = Object.assign(Object.create(null), builtinTypes, externalSymbols);
2630
2258
  if ( api.symbols ) {
2631
- api.symbols.forEach((symbol) => defined[symbol.name] = symbol);
2259
+ api.symbols.forEach((symbol) => {
2260
+ defined[symbol.name] = symbol;
2261
+ });
2632
2262
  }
2633
2263
 
2634
2264
  const naming = Object.create(null);
@@ -2783,12 +2413,10 @@ function validateAPIJSON(api) {
2783
2413
  if ( !intfParam.optional ) {
2784
2414
  reportError(oIntfAPI.name, `parameter ${intfParam.name} missing in implementation of ${symbol.name}#${intfMethod.name}`);
2785
2415
  }
2786
- } else {
2787
- if ( implParam.type !== intfParam.type ) {
2788
- reportError(oIntfAPI.name, `type of parameter ${intfParam.name} of interface method differs from type in implementation ${symbol.name}#${intfMethod.name}`);
2789
- }
2790
- // TODO check nested properties
2416
+ } else if ( implParam.type !== intfParam.type ) {
2417
+ reportError(oIntfAPI.name, `type of parameter ${intfParam.name} of interface method differs from type in implementation ${symbol.name}#${intfMethod.name}`);
2791
2418
  }
2419
+ // TODO check nested properties
2792
2420
  });
2793
2421
  }
2794
2422
  if ( intfMethod.returnValue != null && implMethod.returnValue == null ) {
@@ -2830,7 +2458,7 @@ function validateAPIJSON(api) {
2830
2458
  if ( symbol.implements ) {
2831
2459
  symbol.implements.forEach((intf) => {
2832
2460
  checkSimpleType(intf, `interface of ${symbol.name}`);
2833
- let oIntfAPI = defined[intf];
2461
+ const oIntfAPI = defined[intf];
2834
2462
  if ( oIntfAPI ) {
2835
2463
  checkClassAgainstInterface(symbol, oIntfAPI);
2836
2464
  }
@@ -3085,6 +2713,7 @@ function createAPIXML(symbols, filename, options = {}) {
3085
2713
  */
3086
2714
  function toRaw(value, type) {
3087
2715
  if ( typeof value === "string" && !isEnum(type) ) {
2716
+ // eslint-disable-next-line no-control-regex
3088
2717
  return "\"" + value.replace(/[\u0000-\u001f"\\]/g,
3089
2718
  (c) => replacement[c] || "\\u" + c.charCodeAt(0).toString(16).padStart(4, "0")) + "\"";
3090
2719
  }
@@ -3229,7 +2858,7 @@ function createAPIXML(symbols, filename, options = {}) {
3229
2858
  tagWithSince("deprecated", event.deprecated);
3230
2859
  if ( event.parameters ) {
3231
2860
  tag("parameters");
3232
- for ( let pn in event.parameters ) {
2861
+ for ( const pn in event.parameters ) {
3233
2862
  if ( event.parameters.hasOwnProperty(pn) ) {
3234
2863
  const param = event.parameters[pn];
3235
2864
 
@@ -3374,7 +3003,7 @@ function createAPIXML(symbols, filename, options = {}) {
3374
3003
  let count = 0;
3375
3004
 
3376
3005
  if ( props ) {
3377
- for (let n in props ) {
3006
+ for (const n in props ) {
3378
3007
  if ( props.hasOwnProperty(n) ) {
3379
3008
 
3380
3009
  param = props[n];
@@ -3526,7 +3155,7 @@ function createAPIXML(symbols, filename, options = {}) {
3526
3155
  }
3527
3156
 
3528
3157
  if ( !legacyContent ) {
3529
- if ( hasSettings && j == 1 && /setting/i.test(param.name) && /object/i.test(param.type) ) {
3158
+ if ( hasSettings && j === 1 && /setting/i.test(param.name) && /object/i.test(param.type) ) {
3530
3159
  if ( addRedundancy ) {
3531
3160
  tag("parameterProperties");
3532
3161
  writeParameterPropertiesForMSettings(symbolAPI);