@abaplint/core 2.120.68 → 2.120.70

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.
@@ -513,6 +513,7 @@ declare namespace BasicTypes {
513
513
  HexType,
514
514
  IntegerType,
515
515
  Integer8Type,
516
+ NGenericType,
516
517
  NumericGenericType,
517
518
  NumericType,
518
519
  ObjectReferenceType,
@@ -5133,6 +5134,14 @@ declare class NewPage implements IStatement {
5133
5134
  getMatcher(): IStatementRunnable;
5134
5135
  }
5135
5136
 
5137
+ declare class NGenericType extends NumericType {
5138
+ private static readonly singleton;
5139
+ static get(): NGenericType;
5140
+ private constructor();
5141
+ toText(): string;
5142
+ isGeneric(): boolean;
5143
+ }
5144
+
5136
5145
  declare namespace Nodes {
5137
5146
  export {
5138
5147
  ExpressionNode,
@@ -52,6 +52,9 @@ class FormParam {
52
52
  else if (typeName === "P" && bfound instanceof basic_1.PackedType) {
53
53
  bfound = basic_1.PGenericType.get();
54
54
  }
55
+ else if (typeName === "N" && bfound instanceof basic_1.NumericType) {
56
+ bfound = basic_1.NGenericType.get();
57
+ }
55
58
  }
56
59
  if (nameToken && bfound) {
57
60
  return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, bfound, ["form_parameter" /* IdentifierMeta.FormParameter */]);
@@ -70,6 +70,9 @@ class MethodParam {
70
70
  else if (concat === "TYPE P" || concat.startsWith("TYPE P ")) {
71
71
  return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.PGenericType.get(), meta);
72
72
  }
73
+ else if (concat === "TYPE N" || concat.startsWith("TYPE N ")) {
74
+ return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.NGenericType.get(), meta);
75
+ }
73
76
  const found = new basic_types_1.BasicTypes(input).parseType(type);
74
77
  if (found) {
75
78
  return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, found, meta);
@@ -203,9 +203,9 @@ class CreateObject {
203
203
  if (name === undefined) {
204
204
  continue;
205
205
  }
206
- const source = p.findDirectExpression(Expressions.Source);
207
- const sourceType = source_1.Source.runSyntax(source, input);
208
206
  const found = allImporting === null || allImporting === void 0 ? void 0 : allImporting.find(p => p.getName().toUpperCase() === name);
207
+ const source = p.findDirectExpression(Expressions.Source);
208
+ const sourceType = source_1.Source.runSyntax(source, input, found === null || found === void 0 ? void 0 : found.getType());
209
209
  if (found === undefined) {
210
210
  const message = `constructor parameter "${name}" does not exist`;
211
211
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
@@ -32,6 +32,7 @@ __exportStar(require("./generic_object_reference_type"), exports);
32
32
  __exportStar(require("./hex_type"), exports);
33
33
  __exportStar(require("./integer_type"), exports);
34
34
  __exportStar(require("./integer8_type"), exports);
35
+ __exportStar(require("./ngeneric_type"), exports);
35
36
  __exportStar(require("./numeric_generic_type"), exports);
36
37
  __exportStar(require("./numeric_type"), exports);
37
38
  __exportStar(require("./object_reference_type"), exports);
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NGenericType = void 0;
4
+ const numeric_type_1 = require("./numeric_type");
5
+ // "TYPE n" of a method or FORM parameter, where no length can be given.
6
+ // It is a NumericType, so everything that handles n keeps treating it as such
7
+ class NGenericType extends numeric_type_1.NumericType {
8
+ static get() {
9
+ return this.singleton;
10
+ }
11
+ constructor() {
12
+ super(1);
13
+ }
14
+ toText() {
15
+ return "```n```";
16
+ }
17
+ isGeneric() {
18
+ return true;
19
+ }
20
+ }
21
+ exports.NGenericType = NGenericType;
22
+ NGenericType.singleton = new NGenericType();
23
+ //# sourceMappingURL=ngeneric_type.js.map
@@ -75,7 +75,7 @@ class Registry {
75
75
  }
76
76
  static abaplintVersion() {
77
77
  // magic, see build script "version.js"
78
- return "2.120.68";
78
+ return "2.120.70";
79
79
  }
80
80
  getDDICReferences() {
81
81
  return this.ddicReferences;
@@ -2419,8 +2419,17 @@ ${indentation} output = ${uniqueName}.\n`;
2419
2419
  const extra = (valueBody === null || valueBody === void 0 ? void 0 : valueBody.findDirectExpression(Expressions.For)) ? " " : "";
2420
2420
  data = indentation + extra + `DATA ${structureName} LIKE LINE OF ${uniqueName}.\n`;
2421
2421
  }
2422
+ // all rows are built in the same work area, a component a row leaves out must be initial,
2423
+ // not what an earlier row (or an earlier pass of a surrounding loop) put there
2424
+ const clearRows = valueBody !== undefined && this.valueRowsNeedClear(valueBody);
2425
+ const prefix = [];
2422
2426
  for (const a of (valueBody === null || valueBody === void 0 ? void 0 : valueBody.getChildren()) || []) {
2423
2427
  if (a.get() instanceof Expressions.FieldAssignment) {
2428
+ if (clearRows === true) {
2429
+ // the shared prefix applies to every following row, re-applied after each CLEAR
2430
+ prefix.push(a.concatTokens());
2431
+ continue;
2432
+ }
2424
2433
  if (added === false) {
2425
2434
  body += data;
2426
2435
  added = true;
@@ -2444,6 +2453,16 @@ ${indentation} output = ${uniqueName}.\n`;
2444
2453
  }
2445
2454
  if (a instanceof nodes_1.ExpressionNode && a.get() instanceof Expressions.ValueBodyLine) {
2446
2455
  let skip = false;
2456
+ if (clearRows === true && this.isStructuredValueRow(a)) {
2457
+ if (added === false) {
2458
+ body += data;
2459
+ added = true;
2460
+ }
2461
+ body += indentation + `CLEAR ${structureName}.\n`;
2462
+ for (const p of prefix) {
2463
+ body += indentation + structureName + "-" + p + ".\n";
2464
+ }
2465
+ }
2447
2466
  for (const b of (a === null || a === void 0 ? void 0 : a.getChildren()) || []) {
2448
2467
  if (b.get() instanceof Expressions.FieldAssignment) {
2449
2468
  if (added === false) {
@@ -2522,6 +2541,39 @@ ${indentation} output = ${uniqueName}.\n`;
2522
2541
  }
2523
2542
  return undefined;
2524
2543
  }
2544
+ /** a row that is built in the work area, ie. not "( source )" or "( LINES OF source )" */
2545
+ isStructuredValueRow(row) {
2546
+ return row.findDirectExpression(Expressions.Source) === undefined
2547
+ && row.findDirectExpression(Expressions.ValueBodyLines) === undefined;
2548
+ }
2549
+ /** true if a row can observe a component that an earlier row, or an earlier pass of a surrounding loop,
2550
+ * left in the shared work area. Not the case if all rows assign the same components, and the shared
2551
+ * prefix is not changed between rows, eg. FOR rows or "( a = 1 b = 2 ) ( a = 3 b = 4 )" */
2552
+ valueRowsNeedClear(valueBody) {
2553
+ let shape = undefined;
2554
+ let rowSeen = false;
2555
+ for (const c of valueBody.getChildren()) {
2556
+ if (c.get() instanceof Expressions.FieldAssignment) {
2557
+ if (rowSeen === true) {
2558
+ return true;
2559
+ }
2560
+ }
2561
+ else if (c instanceof nodes_1.ExpressionNode
2562
+ && c.get() instanceof Expressions.ValueBodyLine
2563
+ && this.isStructuredValueRow(c)) {
2564
+ rowSeen = true;
2565
+ const current = c.findDirectExpressions(Expressions.FieldAssignment)
2566
+ .map(f => { var _a; return (_a = f.findDirectExpression(Expressions.FieldSub)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase().replace(/\s/g, ""); })
2567
+ .sort()
2568
+ .join(",");
2569
+ if (shape !== undefined && shape !== current) {
2570
+ return true;
2571
+ }
2572
+ shape = current;
2573
+ }
2574
+ }
2575
+ return false;
2576
+ }
2525
2577
  outlineLet(node, indentation, highSyntax, lowFile) {
2526
2578
  var _a;
2527
2579
  let ret = "";
@@ -54,7 +54,9 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
54
54
  title: "RFC error handling",
55
55
  tags: [_irule_1.RuleTag.SingleFile],
56
56
  shortDescription: `Checks that exceptions 'system_failure' and 'communication_failure' are handled in RFC calls`,
57
- extendedInformation: `https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
57
+ extendedInformation: `RESOURCE_FAILURE is also required for asynchronous calls with DESTINATION IN GROUP.
58
+
59
+ https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
58
60
  badExample: `CALL FUNCTION 'ZRFC'
59
61
  DESTINATION lv_rfc.`,
60
62
  goodExample: `CALL FUNCTION 'ZRFC'
@@ -62,12 +64,12 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
62
64
  EXCEPTIONS
63
65
  system_failure = 1 MESSAGE msg
64
66
  communication_failure = 2 MESSAGE msg
65
- resource_failure = 3
66
- OTHERS = 4.`,
67
+ OTHERS = 3.`,
67
68
  };
68
69
  }
69
- getMessage() {
70
- return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE, RESOURCE_FAILURE";
70
+ getMessage(requireResourceFailure) {
71
+ return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE"
72
+ + (requireResourceFailure ? ", RESOURCE_FAILURE" : "");
71
73
  }
72
74
  getConfig() {
73
75
  return this.conf;
@@ -82,12 +84,15 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
82
84
  if (!(stat.get() instanceof Statements.CallFunction)) {
83
85
  continue;
84
86
  }
85
- if (!stat.findFirstExpression(Expressions.Destination)) {
87
+ const destination = stat.findFirstExpression(Expressions.Destination);
88
+ if (destination === undefined) {
86
89
  continue;
87
90
  }
91
+ const requireResourceFailure = stat.findDirectTokenByText("STARTING") !== undefined
92
+ && destination.findDirectTokenByText("GROUP") !== undefined;
88
93
  const list = stat.findFirstExpression(Expressions.ParameterListExceptions);
89
94
  if (list === undefined) {
90
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
95
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
91
96
  output.push(issue);
92
97
  continue;
93
98
  }
@@ -98,8 +103,8 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
98
103
  }
99
104
  if (names.indexOf("SYSTEM_FAILURE") < 0
100
105
  || names.indexOf("COMMUNICATION_FAILURE") < 0
101
- || names.indexOf("RESOURCE_FAILURE") < 0) {
102
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
106
+ || (requireResourceFailure && names.indexOf("RESOURCE_FAILURE") < 0)) {
107
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
103
108
  output.push(issue);
104
109
  continue;
105
110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/core",
3
- "version": "2.120.68",
3
+ "version": "2.120.70",
4
4
  "description": "abaplint - Core API",
5
5
  "main": "build/src/index.js",
6
6
  "typings": "build/abaplint.d.ts",