@abaplint/core 2.120.18 → 2.120.20

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 (38) hide show
  1. package/build/abaplint.d.ts +3 -0
  2. package/build/src/abap/2_statements/expressions/message_source.js +1 -1
  3. package/build/src/abap/2_statements/expressions/source.js +1 -1
  4. package/build/src/abap/5_syntax/_current_scope.js +14 -0
  5. package/build/src/abap/5_syntax/_type_utils.js +2 -1
  6. package/build/src/abap/5_syntax/expressions/attribute_chain.js +105 -4
  7. package/build/src/abap/5_syntax/expressions/message_source.js +3 -0
  8. package/build/src/abap/5_syntax/expressions/method_call_chain.js +5 -0
  9. package/build/src/abap/5_syntax/expressions/method_source.js +7 -0
  10. package/build/src/abap/5_syntax/expressions/target.js +1 -1
  11. package/build/src/abap/types/class_definition.js +9 -0
  12. package/build/src/objects/_abap_object.js +10 -8
  13. package/build/src/objects/_dynpros.js +8 -5
  14. package/build/src/objects/authorization_check_field.js +3 -3
  15. package/build/src/objects/class.js +3 -4
  16. package/build/src/objects/data_element.js +6 -0
  17. package/build/src/objects/enhancement_implementation.js +4 -3
  18. package/build/src/objects/enhancement_spot.js +2 -2
  19. package/build/src/objects/function_group.js +20 -8
  20. package/build/src/objects/icf_service.js +4 -3
  21. package/build/src/objects/interface.js +3 -2
  22. package/build/src/objects/lock_object.js +4 -4
  23. package/build/src/objects/maintenance_and_transport_object.js +5 -5
  24. package/build/src/objects/message_class.js +5 -5
  25. package/build/src/objects/mime_object.js +5 -4
  26. package/build/src/objects/oauth2_profile.js +2 -2
  27. package/build/src/objects/program.js +3 -3
  28. package/build/src/objects/proxy_object.js +11 -12
  29. package/build/src/objects/table.js +12 -9
  30. package/build/src/objects/table_type.js +7 -4
  31. package/build/src/objects/view.js +9 -4
  32. package/build/src/objects/web_mime.js +7 -4
  33. package/build/src/registry.js +1 -1
  34. package/build/src/rules/clear_exporting_parameters.js +54 -0
  35. package/build/src/rules/remove_descriptions.js +10 -3
  36. package/build/src/rules/xml_consistency.js +40 -0
  37. package/build/src/xml_utils.js +7 -7
  38. package/package.json +4 -3
@@ -64,7 +64,7 @@ class MaintenanceAndTransportObject extends _abstract_object_1.AbstractObject {
64
64
  }
65
65
  }
66
66
  parse() {
67
- var _a, _b, _c, _d;
67
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
68
68
  if (this.parsedXML) {
69
69
  return { updated: false, runtime: 0 };
70
70
  }
@@ -73,12 +73,12 @@ class MaintenanceAndTransportObject extends _abstract_object_1.AbstractObject {
73
73
  const parsed = super.parseRaw2();
74
74
  if (parsed === undefined
75
75
  || parsed.abapGit === undefined
76
- || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
76
+ || ((_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === undefined) {
77
77
  return { updated: false, runtime: 0 };
78
78
  }
79
- this.parsedXML.area = (_b = (_a = parsed.abapGit["asx:abap"]["asx:values"].TOBJ) === null || _a === void 0 ? void 0 : _a.TVDIR) === null || _b === void 0 ? void 0 : _b.AREA;
80
- this.parsedXML.objectName = (_c = parsed.abapGit["asx:abap"]["asx:values"].OBJH) === null || _c === void 0 ? void 0 : _c.OBJECTNAME;
81
- this.parsedXML.objectType = (_d = parsed.abapGit["asx:abap"]["asx:values"].OBJH) === null || _d === void 0 ? void 0 : _d.OBJECTTYPE;
79
+ this.parsedXML.area = (_g = (_f = (_e = (_d = (_c = parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"]) === null || _e === void 0 ? void 0 : _e.TOBJ) === null || _f === void 0 ? void 0 : _f.TVDIR) === null || _g === void 0 ? void 0 : _g.AREA;
80
+ this.parsedXML.objectName = (_l = (_k = (_j = (_h = parsed.abapGit) === null || _h === void 0 ? void 0 : _h["asx:abap"]) === null || _j === void 0 ? void 0 : _j["asx:values"]) === null || _k === void 0 ? void 0 : _k.OBJH) === null || _l === void 0 ? void 0 : _l.OBJECTNAME;
81
+ this.parsedXML.objectType = (_q = (_p = (_o = (_m = parsed.abapGit) === null || _m === void 0 ? void 0 : _m["asx:abap"]) === null || _o === void 0 ? void 0 : _o["asx:values"]) === null || _p === void 0 ? void 0 : _p.OBJH) === null || _q === void 0 ? void 0 : _q.OBJECTTYPE;
82
82
  const end = Date.now();
83
83
  return { updated: true, runtime: end - start };
84
84
  }
@@ -54,7 +54,7 @@ class MessageClass extends _abstract_object_1.AbstractObject {
54
54
  }
55
55
  /////////////////////////////////
56
56
  parseXML() {
57
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
57
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
58
58
  if (this.xml !== undefined) {
59
59
  return;
60
60
  }
@@ -68,16 +68,16 @@ class MessageClass extends _abstract_object_1.AbstractObject {
68
68
  if (parsed === undefined) {
69
69
  return;
70
70
  }
71
- this.xml.topName = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]["asx:values"]) === null || _b === void 0 ? void 0 : _b.T100A) === null || _c === void 0 ? void 0 : _c.ARBGB;
72
- this.xml.description = (_f = (_e = (_d = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _d === void 0 ? void 0 : _d["asx:abap"]["asx:values"]) === null || _e === void 0 ? void 0 : _e.T100A) === null || _f === void 0 ? void 0 : _f.STEXT;
73
- const t100 = (_h = (_g = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _g === void 0 ? void 0 : _g["asx:abap"]["asx:values"]) === null || _h === void 0 ? void 0 : _h.T100;
71
+ this.xml.topName = (_d = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.T100A) === null || _d === void 0 ? void 0 : _d.ARBGB;
72
+ this.xml.description = (_h = (_g = (_f = (_e = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _e === void 0 ? void 0 : _e["asx:abap"]) === null || _f === void 0 ? void 0 : _f["asx:values"]) === null || _g === void 0 ? void 0 : _g.T100A) === null || _h === void 0 ? void 0 : _h.STEXT;
73
+ const t100 = (_l = (_k = (_j = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _j === void 0 ? void 0 : _j["asx:abap"]) === null || _k === void 0 ? void 0 : _k["asx:values"]) === null || _l === void 0 ? void 0 : _l.T100;
74
74
  if (t100 === undefined) {
75
75
  return;
76
76
  }
77
77
  for (const msg of (0, xml_utils_1.xmlToArray)(t100.T100)) {
78
78
  this.xml.parsedMessages.push(new message_1.Message(msg.MSGNR, (0, xml_utils_1.unescape)(msg.TEXT), msg.ARBGB));
79
79
  }
80
- const t100_texts = (_k = (_j = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _j === void 0 ? void 0 : _j["asx:abap"]["asx:values"]) === null || _k === void 0 ? void 0 : _k.T100_TEXTS;
80
+ const t100_texts = (_p = (_o = (_m = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _m === void 0 ? void 0 : _m["asx:abap"]) === null || _o === void 0 ? void 0 : _o["asx:values"]) === null || _p === void 0 ? void 0 : _p.T100_TEXTS;
81
81
  if (t100_texts === undefined) {
82
82
  return;
83
83
  }
@@ -44,6 +44,7 @@ class MIMEObject extends _abstract_object_1.AbstractObject {
44
44
  return undefined;
45
45
  }
46
46
  parse() {
47
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
47
48
  if (this.parsedXML) {
48
49
  return { updated: false, runtime: 0 };
49
50
  }
@@ -52,12 +53,12 @@ class MIMEObject extends _abstract_object_1.AbstractObject {
52
53
  const parsed = super.parseRaw2();
53
54
  if (parsed === undefined
54
55
  || parsed.abapGit === undefined
55
- || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
56
+ || ((_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === undefined) {
56
57
  return { updated: false, runtime: 0 };
57
58
  }
58
- this.parsedXML.URL = parsed.abapGit["asx:abap"]["asx:values"].URL;
59
- this.parsedXML.CLASS = parsed.abapGit["asx:abap"]["asx:values"].CLASS;
60
- this.parsedXML.FOLDER = parsed.abapGit["asx:abap"]["asx:values"].FOLDER;
59
+ this.parsedXML.URL = (_e = (_d = (_c = parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"]) === null || _e === void 0 ? void 0 : _e.URL;
60
+ this.parsedXML.CLASS = (_h = (_g = (_f = parsed.abapGit) === null || _f === void 0 ? void 0 : _f["asx:abap"]) === null || _g === void 0 ? void 0 : _g["asx:values"]) === null || _h === void 0 ? void 0 : _h.CLASS;
61
+ this.parsedXML.FOLDER = (_l = (_k = (_j = parsed.abapGit) === null || _j === void 0 ? void 0 : _j["asx:abap"]) === null || _k === void 0 ? void 0 : _k["asx:values"]) === null || _l === void 0 ? void 0 : _l.FOLDER;
61
62
  const end = Date.now();
62
63
  return { updated: true, runtime: end - start };
63
64
  }
@@ -18,10 +18,10 @@ class Oauth2Profile extends _abstract_object_1.AbstractObject {
18
18
  return undefined;
19
19
  }
20
20
  listScopes() {
21
- var _a, _b, _c;
21
+ var _a, _b, _c, _d, _e;
22
22
  const ret = [];
23
23
  const parsed = super.parseRaw2();
24
- for (const t of (0, xml_utils_1.xmlToArray)((_c = (_b = (_a = parsed.abapGit["asx:abap"]["asx:values"]) === null || _a === void 0 ? void 0 : _a.PROFILE) === null || _b === void 0 ? void 0 : _b.T_SCOPES) === null || _c === void 0 ? void 0 : _c.OA2P_SCOPES)) {
24
+ for (const t of (0, xml_utils_1.xmlToArray)((_e = (_d = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.PROFILE) === null || _d === void 0 ? void 0 : _d.T_SCOPES) === null || _e === void 0 ? void 0 : _e.OA2P_SCOPES)) {
25
25
  ret.push(t.SCOPE);
26
26
  }
27
27
  return ret;
@@ -48,7 +48,7 @@ class Program extends _abap_object_1.ABAPObject {
48
48
  }
49
49
  ////////////////////////////
50
50
  parseXML() {
51
- var _a, _b, _c;
51
+ var _a, _b, _c, _d;
52
52
  if (this.parsedXML !== undefined) {
53
53
  return;
54
54
  }
@@ -66,11 +66,11 @@ class Program extends _abap_object_1.ABAPObject {
66
66
  }
67
67
  let description = "";
68
68
  const selectionTexts = {};
69
- for (const t of (0, xml_utils_1.xmlToArray)((_c = (_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]["asx:values"]) === null || _b === void 0 ? void 0 : _b.TPOOL) === null || _c === void 0 ? void 0 : _c.item)) {
69
+ for (const t of (0, xml_utils_1.xmlToArray)((_d = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.TPOOL) === null || _d === void 0 ? void 0 : _d.item)) {
70
70
  if ((t === null || t === void 0 ? void 0 : t.ID) === "R") {
71
71
  description = t.ENTRY ? (0, xml_utils_1.unescape)(t.ENTRY) : "";
72
72
  }
73
- else if ((t === null || t === void 0 ? void 0 : t.ID) === "S" && t.KEY !== undefined) {
73
+ else if ((t === null || t === void 0 ? void 0 : t.ID) === "S" && typeof t.KEY === "string") {
74
74
  selectionTexts[t.KEY.toUpperCase()] = { entry: t.ENTRY ? (0, xml_utils_1.unescape)(t.ENTRY) : "", maxLength: parseInt(t.LENGTH, 10) };
75
75
  }
76
76
  }
@@ -39,20 +39,19 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
39
39
  return { updated: true, runtime: end - start };
40
40
  }
41
41
  parseXML() {
42
- var _a, _b;
42
+ var _a, _b, _c, _d, _e;
43
43
  const result = { proxyData: [] };
44
44
  const parsed = super.parseRaw2();
45
45
  if (parsed === undefined
46
46
  || parsed.abapGit === undefined
47
- || ((_a = parsed.abapGit["asx:abap"]) === null || _a === void 0 ? void 0 : _a["asx:values"]) === undefined) {
47
+ || ((_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === undefined) {
48
48
  return result;
49
49
  }
50
- const values = parsed.abapGit["asx:abap"]["asx:values"];
51
- result.proxyData = (0, xml_utils_1.xmlToArray)((_b = values.PROXY_DATA) === null || _b === void 0 ? void 0 : _b.item);
50
+ const values = (_d = (_c = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"];
51
+ result.proxyData = (0, xml_utils_1.xmlToArray)((_e = values.PROXY_DATA) === null || _e === void 0 ? void 0 : _e.item);
52
52
  return result;
53
53
  }
54
54
  generateABAPObjects() {
55
- var _a, _b, _c, _d, _e;
56
55
  this.parse();
57
56
  const result = [];
58
57
  if (!this.parsedXML) {
@@ -60,7 +59,7 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
60
59
  }
61
60
  // Find interface definition
62
61
  const intfItem = this.parsedXML.proxyData.find(i => i.R3_TYPE === "INTF");
63
- if (!intfItem || !intfItem.R3_NAME) {
62
+ if (!intfItem || typeof intfItem.R3_NAME !== "string") {
64
63
  return result;
65
64
  }
66
65
  const intfName = intfItem.R3_NAME.toLowerCase();
@@ -69,10 +68,10 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
69
68
  // Build interface code
70
69
  let code = `INTERFACE ${intfName} PUBLIC.\n`;
71
70
  for (const method of methods) {
72
- const methodName = (_a = method.R3_NAME) === null || _a === void 0 ? void 0 : _a.toLowerCase();
73
- if (!methodName) {
71
+ if (typeof method.R3_NAME !== "string") {
74
72
  continue;
75
73
  }
74
+ const methodName = method.R3_NAME.toLowerCase();
76
75
  // Find parameters for this method
77
76
  const importingParameters = this.parsedXML.proxyData.filter(i => i.R3_TYPE === "PAIM" && i.OBJ_NAME1 === method.OBJ_NAME1);
78
77
  const exportingParameters = this.parsedXML.proxyData.filter(i => i.R3_TYPE === "PAEX" && i.OBJ_NAME1 === method.OBJ_NAME1);
@@ -81,8 +80,8 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
81
80
  code += ` IMPORTING\n`;
82
81
  for (let i = 0; i < importingParameters.length; i++) {
83
82
  const param = importingParameters[i];
84
- const paramName = (_b = param.OBJ_NAME2) === null || _b === void 0 ? void 0 : _b.toLowerCase();
85
- const paramType = (_c = param.OBJ_NAME_R) === null || _c === void 0 ? void 0 : _c.toLowerCase();
83
+ const paramName = typeof param.OBJ_NAME2 === "string" ? param.OBJ_NAME2.toLowerCase() : undefined;
84
+ const paramType = typeof param.OBJ_NAME_R === "string" ? param.OBJ_NAME_R.toLowerCase() : undefined;
86
85
  const isLast = i === importingParameters.length - 1 && exportingParameters.length === 0;
87
86
  code += ` ${paramName} TYPE ${paramType}${isLast ? "." : ""}\n`;
88
87
  }
@@ -91,8 +90,8 @@ class ProxyObject extends _abstract_object_1.AbstractObject {
91
90
  code += ` EXPORTING\n`;
92
91
  for (let i = 0; i < exportingParameters.length; i++) {
93
92
  const param = exportingParameters[i];
94
- const paramName = (_d = param.OBJ_NAME2) === null || _d === void 0 ? void 0 : _d.toLowerCase();
95
- const paramType = (_e = param.OBJ_NAME_R) === null || _e === void 0 ? void 0 : _e.toLowerCase();
93
+ const paramName = typeof param.OBJ_NAME2 === "string" ? param.OBJ_NAME2.toLowerCase() : undefined;
94
+ const paramType = typeof param.OBJ_NAME_R === "string" ? param.OBJ_NAME_R.toLowerCase() : undefined;
96
95
  const isLast = i === exportingParameters.length - 1;
97
96
  code += ` ${paramName} TYPE ${paramType}${isLast ? "." : ""}\n`;
98
97
  }
@@ -337,7 +337,7 @@ class Table extends _abstract_object_1.AbstractObject {
337
337
  return false;
338
338
  }
339
339
  parseXML() {
340
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
340
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
341
341
  const parsed = super.parseRaw2();
342
342
  if (parsed === undefined) {
343
343
  return;
@@ -347,19 +347,22 @@ class Table extends _abstract_object_1.AbstractObject {
347
347
  return;
348
348
  }
349
349
  // enhancement category
350
- if (((_b = (_a = parsed.abapGit["asx:abap"]["asx:values"]) === null || _a === void 0 ? void 0 : _a.DD02V) === null || _b === void 0 ? void 0 : _b.EXCLASS) === undefined) {
350
+ if (((_d = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD02V) === null || _d === void 0 ? void 0 : _d.EXCLASS) === undefined) {
351
351
  this.parsedData.enhancementCategory = EnhancementCategory.NotClassified;
352
352
  }
353
353
  else {
354
- this.parsedData.enhancementCategory = (_d = (_c = parsed.abapGit["asx:abap"]["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD02V) === null || _d === void 0 ? void 0 : _d.EXCLASS;
354
+ this.parsedData.enhancementCategory = (_h = (_g = (_f = (_e = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _e === void 0 ? void 0 : _e["asx:abap"]) === null || _f === void 0 ? void 0 : _f["asx:values"]) === null || _g === void 0 ? void 0 : _g.DD02V) === null || _h === void 0 ? void 0 : _h.EXCLASS;
355
355
  }
356
356
  // table category
357
- this.parsedData.tableCategory = (_f = (_e = parsed.abapGit["asx:abap"]["asx:values"]) === null || _e === void 0 ? void 0 : _e.DD02V) === null || _f === void 0 ? void 0 : _f.TABCLASS;
358
- this.parsedData.description = (_h = (_g = parsed.abapGit["asx:abap"]["asx:values"]) === null || _g === void 0 ? void 0 : _g.DD02V) === null || _h === void 0 ? void 0 : _h.DDTEXT;
359
- this.parsedData.dataClass = (_k = (_j = parsed.abapGit["asx:abap"]["asx:values"]) === null || _j === void 0 ? void 0 : _j.DD09L) === null || _k === void 0 ? void 0 : _k.TABART;
357
+ this.parsedData.tableCategory = (_m = (_l = (_k = (_j = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _j === void 0 ? void 0 : _j["asx:abap"]) === null || _k === void 0 ? void 0 : _k["asx:values"]) === null || _l === void 0 ? void 0 : _l.DD02V) === null || _m === void 0 ? void 0 : _m.TABCLASS;
358
+ this.parsedData.description = (_r = (_q = (_p = (_o = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _o === void 0 ? void 0 : _o["asx:abap"]) === null || _p === void 0 ? void 0 : _p["asx:values"]) === null || _q === void 0 ? void 0 : _q.DD02V) === null || _r === void 0 ? void 0 : _r.DDTEXT;
359
+ this.parsedData.dataClass = (_v = (_u = (_t = (_s = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _s === void 0 ? void 0 : _s["asx:abap"]) === null || _t === void 0 ? void 0 : _t["asx:values"]) === null || _u === void 0 ? void 0 : _u.DD09L) === null || _v === void 0 ? void 0 : _v.TABART;
360
360
  // fields
361
- const fields = (_l = parsed.abapGit["asx:abap"]["asx:values"]) === null || _l === void 0 ? void 0 : _l.DD03P_TABLE;
361
+ const fields = (_y = (_x = (_w = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _w === void 0 ? void 0 : _w["asx:abap"]) === null || _x === void 0 ? void 0 : _x["asx:values"]) === null || _y === void 0 ? void 0 : _y.DD03P_TABLE;
362
362
  for (const field of (0, xml_utils_1.xmlToArray)(fields === null || fields === void 0 ? void 0 : fields.DD03P)) {
363
+ if (typeof (field === null || field === void 0 ? void 0 : field.FIELDNAME) !== "string") {
364
+ continue;
365
+ }
363
366
  this.parsedData.fields.push({
364
367
  FIELDNAME: field.FIELDNAME,
365
368
  ROLLNAME: field.ROLLNAME,
@@ -379,13 +382,13 @@ class Table extends _abstract_object_1.AbstractObject {
379
382
  });
380
383
  }
381
384
  // secondary indexes
382
- const indexes = (_m = parsed.abapGit["asx:abap"]["asx:values"]) === null || _m === void 0 ? void 0 : _m.DD12V;
385
+ const indexes = (_1 = (_0 = (_z = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _z === void 0 ? void 0 : _z["asx:abap"]) === null || _0 === void 0 ? void 0 : _0["asx:values"]) === null || _1 === void 0 ? void 0 : _1.DD12V;
383
386
  ;
384
387
  this.parsedData.secondaryIndexes = [];
385
388
  for (const index of (0, xml_utils_1.xmlToArray)(indexes === null || indexes === void 0 ? void 0 : indexes.DD12V)) {
386
389
  const indexName = index.INDEXNAME;
387
390
  const indexFields = [];
388
- const indexFieldsXml = (_o = parsed.abapGit["asx:abap"]["asx:values"]) === null || _o === void 0 ? void 0 : _o.DD17V;
391
+ const indexFieldsXml = (_4 = (_3 = (_2 = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _2 === void 0 ? void 0 : _2["asx:abap"]) === null || _3 === void 0 ? void 0 : _3["asx:values"]) === null || _4 === void 0 ? void 0 : _4.DD17V;
389
392
  for (const indexField of (0, xml_utils_1.xmlToArray)(indexFieldsXml === null || indexFieldsXml === void 0 ? void 0 : indexFieldsXml.DD17V)) {
390
393
  if (indexField.INDEXNAME === indexName) {
391
394
  // assumption: fields are listed by POSITION in the xml
@@ -195,7 +195,7 @@ class TableType extends _abstract_object_1.AbstractObject {
195
195
  }
196
196
  ////////////////////
197
197
  parseXML() {
198
- var _a, _b;
198
+ var _a, _b, _c, _d;
199
199
  if (this.parsedXML !== undefined) {
200
200
  return;
201
201
  }
@@ -207,11 +207,14 @@ class TableType extends _abstract_object_1.AbstractObject {
207
207
  if (parsed === undefined || parsed.abapGit === undefined) {
208
208
  return;
209
209
  }
210
- const values = parsed.abapGit["asx:abap"]["asx:values"];
210
+ const values = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"];
211
211
  if (values === undefined) {
212
212
  return;
213
213
  }
214
214
  const dd40v = values.DD40V;
215
+ if (dd40v === undefined) {
216
+ return;
217
+ }
215
218
  this.parsedXML.rowtype = dd40v.ROWTYPE ? dd40v.ROWTYPE : "";
216
219
  this.parsedXML.rowkind = dd40v.ROWKIND ? dd40v.ROWKIND : "";
217
220
  this.parsedXML.datatype = dd40v.DATATYPE;
@@ -221,13 +224,13 @@ class TableType extends _abstract_object_1.AbstractObject {
221
224
  this.parsedXML.keykind = dd40v.KEYKIND;
222
225
  this.parsedXML.ddtext = dd40v.DDTEXT;
223
226
  this.parsedXML.keydef = dd40v.KEYDEF;
224
- for (const x of (0, xml_utils_1.xmlToArray)((_a = values.DD42V) === null || _a === void 0 ? void 0 : _a.DD42V)) {
227
+ for (const x of (0, xml_utils_1.xmlToArray)((_c = values.DD42V) === null || _c === void 0 ? void 0 : _c.DD42V)) {
225
228
  this.parsedXML.dd42v.push({
226
229
  keyname: x.SECKEYNAME || "",
227
230
  keyfield: x.KEYFIELD || "",
228
231
  });
229
232
  }
230
- for (const x of (0, xml_utils_1.xmlToArray)((_b = values.DD43V) === null || _b === void 0 ? void 0 : _b.DD43V)) {
233
+ for (const x of (0, xml_utils_1.xmlToArray)((_d = values.DD43V) === null || _d === void 0 ? void 0 : _d.DD43V)) {
231
234
  this.parsedXML.dd43v.push({
232
235
  keyname: x.SECKEYNAME || "",
233
236
  accessmode: x.ACCESSMODE || "",
@@ -146,7 +146,7 @@ class View extends _abstract_object_1.AbstractObject {
146
146
  }
147
147
  ///////////////
148
148
  parseXML() {
149
- var _a, _b, _c;
149
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
150
150
  this.parsedData = {
151
151
  header: {
152
152
  VIEWCLASS: "",
@@ -159,13 +159,18 @@ class View extends _abstract_object_1.AbstractObject {
159
159
  if (parsed === undefined || parsed.abapGit === undefined) {
160
160
  return;
161
161
  }
162
- const header = (_a = parsed.abapGit["asx:abap"]["asx:values"]) === null || _a === void 0 ? void 0 : _a.DD25V;
162
+ const header = (_c = (_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD25V;
163
163
  this.parsedData.header = {
164
164
  VIEWCLASS: (header === null || header === void 0 ? void 0 : header.VIEWCLASS) || "",
165
165
  DDTEXT: (header === null || header === void 0 ? void 0 : header.DDTEXT) || "",
166
166
  };
167
- const fields = (_b = parsed.abapGit["asx:abap"]["asx:values"]) === null || _b === void 0 ? void 0 : _b.DD27P_TABLE;
167
+ const fields = (_f = (_e = (_d = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _d === void 0 ? void 0 : _d["asx:abap"]) === null || _e === void 0 ? void 0 : _e["asx:values"]) === null || _f === void 0 ? void 0 : _f.DD27P_TABLE;
168
168
  for (const field of (0, xml_utils_1.xmlToArray)(fields === null || fields === void 0 ? void 0 : fields.DD27P)) {
169
+ if (typeof (field === null || field === void 0 ? void 0 : field.VIEWFIELD) !== "string"
170
+ || typeof (field === null || field === void 0 ? void 0 : field.TABNAME) !== "string"
171
+ || typeof (field === null || field === void 0 ? void 0 : field.FIELDNAME) !== "string") {
172
+ continue;
173
+ }
169
174
  this.parsedData.fields.push({
170
175
  VIEWFIELD: field.VIEWFIELD,
171
176
  TABNAME: field.TABNAME,
@@ -173,7 +178,7 @@ class View extends _abstract_object_1.AbstractObject {
173
178
  KEYFLAG: field.KEYFLAG,
174
179
  });
175
180
  }
176
- const join = (_c = parsed.abapGit["asx:abap"]["asx:values"]) === null || _c === void 0 ? void 0 : _c.DD28J_TABLE;
181
+ const join = (_j = (_h = (_g = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _g === void 0 ? void 0 : _g["asx:abap"]) === null || _h === void 0 ? void 0 : _h["asx:values"]) === null || _j === void 0 ? void 0 : _j.DD28J_TABLE;
177
182
  for (const j of (0, xml_utils_1.xmlToArray)(join === null || join === void 0 ? void 0 : join.DD28J)) {
178
183
  this.parsedData.join.push({
179
184
  LTAB: j.LTAB,
@@ -43,7 +43,7 @@ class WebMIME extends _abstract_object_1.AbstractObject {
43
43
  return undefined;
44
44
  }
45
45
  parse() {
46
- var _a;
46
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
47
47
  if (this.parsedXML) {
48
48
  return { updated: false, runtime: 0 };
49
49
  }
@@ -52,11 +52,14 @@ class WebMIME extends _abstract_object_1.AbstractObject {
52
52
  const parsed = super.parseRaw2();
53
53
  if (parsed === undefined
54
54
  || parsed.abapGit === undefined
55
- || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
55
+ || ((_b = (_a = parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === undefined) {
56
56
  return { updated: false, runtime: 0 };
57
57
  }
58
- this.parsedXML.description = parsed.abapGit["asx:abap"]["asx:values"].TEXT;
59
- for (const param of (0, xml_utils_1.xmlToArray)((_a = parsed.abapGit["asx:abap"]["asx:values"].PARAMS) === null || _a === void 0 ? void 0 : _a.WWWPARAMS)) {
58
+ this.parsedXML.description = (_e = (_d = (_c = parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"]) === null || _e === void 0 ? void 0 : _e.TEXT;
59
+ for (const param of (0, xml_utils_1.xmlToArray)((_j = (_h = (_g = (_f = parsed.abapGit) === null || _f === void 0 ? void 0 : _f["asx:abap"]) === null || _g === void 0 ? void 0 : _g["asx:values"]) === null || _h === void 0 ? void 0 : _h.PARAMS) === null || _j === void 0 ? void 0 : _j.WWWPARAMS)) {
60
+ if (typeof (param === null || param === void 0 ? void 0 : param.NAME) !== "string") {
61
+ continue;
62
+ }
60
63
  this.parsedXML.params[param.NAME.toLowerCase()] = param.VALUE;
61
64
  }
62
65
  const end = Date.now();
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.18";
78
+ return "2.120.20";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -12,6 +12,8 @@ const objects_1 = require("../objects");
12
12
  const _reference_1 = require("../abap/5_syntax/_reference");
13
13
  const basic_1 = require("../abap/types/basic");
14
14
  const _statement_1 = require("../abap/2_statements/statements/_statement");
15
+ const statements_1 = require("../abap/2_statements/statements");
16
+ const expressions_1 = require("../abap/2_statements/expressions");
15
17
  class ClearExportingParametersConf extends _basic_rule_config_1.BasicRuleConfig {
16
18
  constructor() {
17
19
  super(...arguments);
@@ -43,6 +45,8 @@ Note: EXPORTING parameters passed by VALUE are always initialized and are theref
43
45
  Reading and writing the parameter in the same statement (e.g. "ev_result = ev_result + 1") is reported,
44
46
  as the source is evaluated before the parameter is assigned.
45
47
  Objects containing parser or syntax errors are not reported.
48
+ "IS SUPPLIED"/"IS REQUESTED" checks are not considered reads, and "GET REFERENCE OF" plus
49
+ "ASSIGN ... TO <fs>" are considered writes, as the value can be written via the reference.
46
50
 
47
51
  Class and interface method implementations and function modules are checked.`,
48
52
  tags: [_irule_1.RuleTag.Styleguide],
@@ -168,6 +172,16 @@ ENDCLASS.`,
168
172
  }
169
173
  const pos = reference.position.getStart();
170
174
  if (reference.referenceType === _reference_1.ReferenceType.DataReadReference) {
175
+ if (this.isSuppliedOrRequested(reference, obj)) {
176
+ continue; // "IS SUPPLIED" / "IS REQUESTED" does not read the value
177
+ }
178
+ if (this.isReferenceOrAssign(reference, obj)) {
179
+ // "GET REFERENCE OF" and "ASSIGN ... TO <fs>" may be used for writing the value
180
+ if (earliestWrite === undefined || pos.isBefore(earliestWrite.position.getStart())) {
181
+ earliestWrite = reference;
182
+ }
183
+ continue;
184
+ }
171
185
  if (firstRead === undefined || pos.isBefore(firstRead.position.getStart())) {
172
186
  firstRead = reference;
173
187
  }
@@ -190,6 +204,46 @@ ENDCLASS.`,
190
204
  const message = `EXPORTING parameter "${parameter.getName().toLowerCase()}" read before it is cleared or assigned`;
191
205
  return issue_1.Issue.atIdentifier(firstRead.position, message, this.getMetadata().key, this.conf.severity);
192
206
  }
207
+ isReferenceOrAssign(reference, obj) {
208
+ const file = obj.getABAPFileByName(reference.position.getFilename());
209
+ const pos = reference.position.getStart();
210
+ for (const statement of (file === null || file === void 0 ? void 0 : file.getStatements()) || []) {
211
+ const start = statement.getStart();
212
+ const end = statement.getEnd();
213
+ if (pos.equals(start) === false && (pos.isAfter(start) === false || pos.isBefore(end) === false)) {
214
+ continue;
215
+ }
216
+ const type = statement.get();
217
+ return type instanceof statements_1.GetReference || type instanceof statements_1.Assign;
218
+ }
219
+ return false;
220
+ }
221
+ isSuppliedOrRequested(reference, obj) {
222
+ const file = obj.getABAPFileByName(reference.position.getFilename());
223
+ const pos = reference.position.getStart();
224
+ for (const statement of (file === null || file === void 0 ? void 0 : file.getStatements()) || []) {
225
+ const start = statement.getStart();
226
+ const end = statement.getEnd();
227
+ if (pos.equals(start) === false && (pos.isAfter(start) === false || pos.isBefore(end) === false)) {
228
+ continue;
229
+ }
230
+ for (const compare of statement.findAllExpressionsRecursive(expressions_1.Compare)) {
231
+ const upper = compare.concatTokens().toUpperCase();
232
+ if (upper.includes(" IS SUPPLIED") === false
233
+ && upper.includes(" IS REQUESTED") === false
234
+ && upper.includes(" IS NOT SUPPLIED") === false
235
+ && upper.includes(" IS NOT REQUESTED") === false) {
236
+ continue;
237
+ }
238
+ const cStart = compare.getFirstToken().getStart();
239
+ const cEnd = compare.getLastToken().getEnd();
240
+ if ((pos.equals(cStart) || pos.isAfter(cStart)) && pos.isBefore(cEnd)) {
241
+ return true;
242
+ }
243
+ }
244
+ }
245
+ return false;
246
+ }
193
247
  statementStart(reference, obj) {
194
248
  const file = obj.getABAPFileByName(reference.position.getFilename());
195
249
  for (const statement of (file === null || file === void 0 ? void 0 : file.getStatements()) || []) {
@@ -128,11 +128,18 @@ Consider using ABAP Doc for documentation.`,
128
128
  return this.checkXML(xml, file);
129
129
  }
130
130
  checkXML(xml, file) {
131
- const parsed = new fast_xml_parser_1.XMLParser({ parseTagValue: false, ignoreAttributes: true, trimValues: false }).parse(xml);
132
- if (parsed === undefined || parsed.abapGit["asx:abap"]["asx:values"] === undefined) {
131
+ var _a, _b, _c, _d, _e;
132
+ let parsed;
133
+ try {
134
+ parsed = new fast_xml_parser_1.XMLParser({ parseTagValue: false, ignoreAttributes: true, trimValues: false }).parse(xml);
135
+ }
136
+ catch (_f) {
137
+ return [];
138
+ }
139
+ if (((_b = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _a === void 0 ? void 0 : _a["asx:abap"]) === null || _b === void 0 ? void 0 : _b["asx:values"]) === undefined) {
133
140
  return [];
134
141
  }
135
- const desc = parsed.abapGit["asx:abap"]["asx:values"].DESCRIPTIONS;
142
+ const desc = (_e = (_d = (_c = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _c === void 0 ? void 0 : _c["asx:abap"]) === null || _d === void 0 ? void 0 : _d["asx:values"]) === null || _e === void 0 ? void 0 : _e.DESCRIPTIONS;
136
143
  if (desc === undefined) {
137
144
  return [];
138
145
  }
@@ -191,6 +191,40 @@ class XMLConsistency {
191
191
  const issues = [];
192
192
  const texts = obj.getTexts();
193
193
  const maxLengths = obj.getTextMaxLengths();
194
+ const hasLabelTexts = (texts === null || texts === void 0 ? void 0 : texts.short) !== undefined
195
+ || (texts === null || texts === void 0 ? void 0 : texts.medium) !== undefined
196
+ || (texts === null || texts === void 0 ? void 0 : texts.long) !== undefined
197
+ || (texts === null || texts === void 0 ? void 0 : texts.heading) !== undefined;
198
+ if ((texts === null || texts === void 0 ? void 0 : texts.short) !== undefined) {
199
+ const issue = this.checkRequiredField(file, "SCRLEN1", maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.short);
200
+ if (issue) {
201
+ issues.push(issue);
202
+ }
203
+ }
204
+ if ((texts === null || texts === void 0 ? void 0 : texts.medium) !== undefined) {
205
+ const issue = this.checkRequiredField(file, "SCRLEN2", maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.medium);
206
+ if (issue) {
207
+ issues.push(issue);
208
+ }
209
+ }
210
+ if ((texts === null || texts === void 0 ? void 0 : texts.long) !== undefined) {
211
+ const issue = this.checkRequiredField(file, "SCRLEN3", maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.long);
212
+ if (issue) {
213
+ issues.push(issue);
214
+ }
215
+ }
216
+ if ((texts === null || texts === void 0 ? void 0 : texts.heading) !== undefined) {
217
+ const issue = this.checkRequiredField(file, "HEADLEN", maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.heading);
218
+ if (issue) {
219
+ issues.push(issue);
220
+ }
221
+ }
222
+ if (hasLabelTexts) {
223
+ const issue = this.checkRequiredField(file, "DTELMASTER", obj.getDtelMaster());
224
+ if (issue) {
225
+ issues.push(issue);
226
+ }
227
+ }
194
228
  for (const issue of [
195
229
  this.checkTextLength(file, "DDTEXT", obj.getDescription(), 60),
196
230
  this.checkTextLength(file, "SCRTEXT_S", texts === null || texts === void 0 ? void 0 : texts.short, maxLengths === null || maxLengths === void 0 ? void 0 : maxLengths.short),
@@ -218,6 +252,12 @@ class XMLConsistency {
218
252
  }
219
253
  return issues;
220
254
  }
255
+ checkRequiredField(file, fieldName, value) {
256
+ if (value === undefined || value === "") {
257
+ return issue_1.Issue.atRow(file, 1, `Missing required field ${fieldName} in DD04V`, this.getMetadata().key, this.conf.severity);
258
+ }
259
+ return undefined;
260
+ }
221
261
  runDomain(obj, file) {
222
262
  var _a, _b;
223
263
  const maxTextLength = 60;
@@ -14,14 +14,14 @@ function xmlToArray(data) {
14
14
  }
15
15
  }
16
16
  function unescape(str) {
17
- if (str === undefined) {
17
+ if (typeof str !== "string") {
18
18
  return "";
19
19
  }
20
- str = str.replace(/&amp;/g, "&");
21
- str = str.replace(/&gt;/g, ">");
22
- str = str.replace(/&lt;/g, "<");
23
- str = str.replace(/&quot;/g, "\"");
24
- str = str.replace(/&apos;/g, "'");
25
- return str;
20
+ let result = str.replace(/&amp;/g, "&");
21
+ result = result.replace(/&gt;/g, ">");
22
+ result = result.replace(/&lt;/g, "<");
23
+ result = result.replace(/&quot;/g, "\"");
24
+ result = result.replace(/&apos;/g, "'");
25
+ return result;
26
26
  }
27
27
  //# sourceMappingURL=xml_utils.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.18",
3
+ "version": "2.120.20",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",
@@ -8,7 +8,7 @@
8
8
  "scripts": {
9
9
  "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
10
10
  "lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" --fix",
11
- "clean": "rm -rf build",
11
+ "clean": "rimraf build",
12
12
  "compile": "npm run clean && tsc && node scripts/version.js",
13
13
  "watch": "tsc --watch",
14
14
  "test": "npm run compile && mocha --timeout 1000 && npm run lint && npm run schema && api-extractor run",
@@ -39,7 +39,7 @@
39
39
  "url": "git+https://github.com/abaplint/abaplint.git"
40
40
  },
41
41
  "engines": {
42
- "node": ">=18.0.0"
42
+ "node": ">=22.0.0"
43
43
  },
44
44
  "keywords": [
45
45
  "ABAP",
@@ -60,6 +60,7 @@
60
60
  "chai": "^4.5.0",
61
61
  "eslint": "^9.39.5",
62
62
  "mocha": "^11.7.6",
63
+ "rimraf": "^6.1.3",
63
64
  "source-map-support": "^0.5.21",
64
65
  "ts-json-schema-generator": "^2.9.0",
65
66
  "typescript": "^7.0.2"