@abaplint/transpiler-cli 2.13.98 → 2.13.100

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 (2) hide show
  1. package/build/bundle.js +402 -70
  2. package/package.json +3 -3
package/build/bundle.js CHANGED
@@ -17464,7 +17464,9 @@ class ModifyLine {
17464
17464
  const ocp = (0, combi_1.str)("OF CURRENT PAGE");
17465
17465
  const intensified = (0, combi_1.seq)("INTENSIFIED", onOff);
17466
17466
  const intensifiedOpt = (0, combi_1.seq)("INTENSIFIED", (0, combi_1.opt)(onOff));
17467
- const lineFormat = (0, combi_1.seq)("LINE FORMAT", (0, combi_1.per)("INPUT OFF", "INVERSE", "RESET", intensifiedOpt, expressions_1.Color));
17467
+ const inputOpt = (0, combi_1.seq)("INPUT", (0, combi_1.opt)((0, combi_1.alt)(eq, onOff)));
17468
+ const inverseOpt = (0, combi_1.seq)("INVERSE", (0, combi_1.opt)((0, combi_1.alt)(eq, onOff)));
17469
+ const lineFormat = (0, combi_1.seq)("LINE FORMAT", (0, combi_1.per)(inputOpt, inverseOpt, "RESET", intensifiedOpt, expressions_1.Color));
17468
17470
  const options = (0, combi_1.per)(index, value, format, page, lineFormat, lineValue, ocp, intensified, expressions_1.Color);
17469
17471
  const ret = (0, combi_1.seq)("MODIFY", (0, combi_1.altPrio)("CURRENT LINE", (0, combi_1.seq)("LINE", expressions_1.Source)), (0, combi_1.opt)(options));
17470
17472
  return (0, combi_1.verNotLang)(version_1.LanguageVersion.Cloud, ret);
@@ -27023,6 +27025,7 @@ class CurrentScope {
27023
27025
  if (name === undefined) {
27024
27026
  return undefined;
27025
27027
  }
27028
+ name = name.replace(/^!/, "");
27026
27029
  const found = (_a = this.current) === null || _a === void 0 ? void 0 : _a.findVariable(name);
27027
27030
  if (found) {
27028
27031
  return found;
@@ -27128,6 +27131,17 @@ class CurrentScope {
27128
27131
  var _a;
27129
27132
  return ((_a = this.localFriends.get(className.toUpperCase())) === null || _a === void 0 ? void 0 : _a.includes(friendName.toUpperCase())) === true;
27130
27133
  }
27134
+ getEnclosingMethodName() {
27135
+ let curr = this.current;
27136
+ while (curr !== undefined) {
27137
+ const stype = curr.getIdentifier().stype;
27138
+ if (stype === _scope_type_1.ScopeType.Method || stype === _scope_type_1.ScopeType.MethodInstance) {
27139
+ return curr.getIdentifier().sname;
27140
+ }
27141
+ curr = curr.getParent();
27142
+ }
27143
+ return undefined;
27144
+ }
27131
27145
  getEnclosingClassName() {
27132
27146
  let curr = this.current;
27133
27147
  while (curr !== undefined) {
@@ -27352,6 +27366,97 @@ class ObjectOriented {
27352
27366
  }
27353
27367
  // does the supplied class have friendship with "friendName"?
27354
27368
  // note that interfaces of the friend, and subclasses of the friend also have friendship
27369
+ // returns the visibility as text if a member declared in foundDef, reached via def, cannot be accessed from enclosing
27370
+ memberNotVisible(visibility, def, foundDef, enclosing) {
27371
+ var _a, _b;
27372
+ if (visibility === visibility_1.Visibility.Public || foundDef === undefined) {
27373
+ return undefined;
27374
+ }
27375
+ else if (!(foundDef instanceof types_1.ClassDefinition)) {
27376
+ // interface members are always public
27377
+ return undefined;
27378
+ }
27379
+ const name = foundDef.getName().toUpperCase();
27380
+ enclosing = enclosing === null || enclosing === void 0 ? void 0 : enclosing.toUpperCase();
27381
+ if (enclosing === undefined || enclosing === name) {
27382
+ return undefined;
27383
+ }
27384
+ // friendship with the class used at the call site also gives access to inherited members
27385
+ const visited = [];
27386
+ let current = def instanceof types_1.ClassDefinition ? def : foundDef;
27387
+ while (current !== undefined && visited.includes(current.getName().toUpperCase()) === false) {
27388
+ visited.push(current.getName().toUpperCase());
27389
+ if (this.hasFriendship(current, enclosing)) {
27390
+ return undefined;
27391
+ }
27392
+ const sup = current.getSuperClass();
27393
+ current = sup === undefined ? undefined : this.scope.findClassDefinition(sup);
27394
+ }
27395
+ if (visibility === visibility_1.Visibility.Protected) {
27396
+ // subclasses can access protected members
27397
+ let sup = (_a = this.scope.findClassDefinition(enclosing)) === null || _a === void 0 ? void 0 : _a.getSuperClass();
27398
+ while (sup !== undefined) {
27399
+ if (sup.toUpperCase() === name) {
27400
+ return undefined;
27401
+ }
27402
+ sup = (_b = this.scope.findClassDefinition(sup)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
27403
+ }
27404
+ return "protected";
27405
+ }
27406
+ return "private";
27407
+ }
27408
+ // the fixture methods of a test class are called by ABAP Unit only, returns the message otherwise
27409
+ checkSpecialTestMethodCall(method, foundDef) {
27410
+ if (method === undefined
27411
+ || !(foundDef instanceof types_1.ClassDefinition)
27412
+ || foundDef.isForTesting() === false) {
27413
+ return undefined;
27414
+ }
27415
+ const name = method.getName().toUpperCase();
27416
+ if (["SETUP", "TEARDOWN", "CLASS_SETUP", "CLASS_TEARDOWN"].includes(name) === false) {
27417
+ return undefined;
27418
+ }
27419
+ return `The special method "${name}" cannot be called directly`;
27420
+ }
27421
+ // SUPER-> can only call the previous implementation of the method it is used in, returns the message otherwise
27422
+ // both names are resolved in the super class, so an alias and the method it stands for are the same
27423
+ checkSuperCall(superDef, methodName) {
27424
+ const enclosing = this.scope.getEnclosingMethodName();
27425
+ if (methodName === undefined
27426
+ || enclosing === undefined
27427
+ || methodName.toUpperCase() === enclosing.toUpperCase()) {
27428
+ return undefined;
27429
+ }
27430
+ const message = "SUPER-> can only be used to call the previous implementation of the same method";
27431
+ // a method that is not a redefinition has no previous implementation
27432
+ const enclosingClass = this.scope.findClassDefinition(this.scope.getEnclosingClassName());
27433
+ const ownDefinition = enclosingClass === null || enclosingClass === void 0 ? void 0 : enclosingClass.getMethodDefinitions().getByName(enclosing);
27434
+ if (ownDefinition !== undefined && ownDefinition.isRedefinition() === false) {
27435
+ return message;
27436
+ }
27437
+ const called = this.searchMethodName(superDef, methodName).method;
27438
+ const own = this.searchMethodName(superDef, enclosing).method;
27439
+ if (called === undefined || own === undefined || called === own) {
27440
+ return undefined;
27441
+ }
27442
+ return message;
27443
+ }
27444
+ // the class declaring the attribute or constant, searched from def up through the super classes
27445
+ findAttributeOwner(def, found) {
27446
+ const visited = [];
27447
+ let current = def;
27448
+ while (current instanceof types_1.ClassDefinition && visited.includes(current.getName().toUpperCase()) === false) {
27449
+ visited.push(current.getName().toUpperCase());
27450
+ const attributes = current.getAttributes();
27451
+ if (attributes.getAll().includes(found)
27452
+ || attributes.getConstants().includes(found)) {
27453
+ return current;
27454
+ }
27455
+ const sup = current.getSuperClass();
27456
+ current = sup === undefined ? undefined : this.findSuperDefinition(sup);
27457
+ }
27458
+ return undefined;
27459
+ }
27355
27460
  hasFriendship(cd, friendName) {
27356
27461
  var _a;
27357
27462
  const friends = cd.getFriends().map(f => f.toUpperCase());
@@ -30328,6 +30433,8 @@ const _object_oriented_1 = __webpack_require__(/*! ../_object_oriented */ "./nod
30328
30433
  const data_reference_type_1 = __webpack_require__(/*! ../../types/basic/data_reference_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/data_reference_type.js");
30329
30434
  const _reference_1 = __webpack_require__(/*! ../_reference */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_reference.js");
30330
30435
  const basic_1 = __webpack_require__(/*! ../../types/basic */ "./node_modules/@abaplint/core/build/src/abap/types/basic/index.js");
30436
+ const class_attribute_1 = __webpack_require__(/*! ../../types/class_attribute */ "./node_modules/@abaplint/core/build/src/abap/types/class_attribute.js");
30437
+ const class_constant_1 = __webpack_require__(/*! ../../types/class_constant */ "./node_modules/@abaplint/core/build/src/abap/types/class_constant.js");
30331
30438
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
30332
30439
  class AttributeName {
30333
30440
  static runSyntax(context, node, input, type, error = true) {
@@ -30356,6 +30463,15 @@ class AttributeName {
30356
30463
  }
30357
30464
  return void_type_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
30358
30465
  }
30466
+ if (found instanceof class_attribute_1.ClassAttribute || found instanceof class_constant_1.ClassConstant) {
30467
+ const owner = helper.findAttributeOwner(def, found);
30468
+ const notVisible = helper.memberNotVisible(found.getVisibility(), def, owner, input.scope.getEnclosingClassName());
30469
+ if (notVisible !== undefined) {
30470
+ const message = `Attribute "${name}" is ${notVisible} and cannot be accessed`;
30471
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, token, message));
30472
+ return void_type_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
30473
+ }
30474
+ }
30359
30475
  if (type) {
30360
30476
  input.scope.addReference(token, found, type, input.filename);
30361
30477
  }
@@ -32372,6 +32488,9 @@ class FormParam {
32372
32488
  else if (typeName === "P" && bfound instanceof basic_1.PackedType) {
32373
32489
  bfound = basic_1.PGenericType.get();
32374
32490
  }
32491
+ else if (typeName === "N" && bfound instanceof basic_1.NumericType) {
32492
+ bfound = basic_1.NGenericType.get();
32493
+ }
32375
32494
  }
32376
32495
  if (nameToken && bfound) {
32377
32496
  return new _typed_identifier_1.TypedIdentifier(nameToken, input.filename, bfound, ["form_parameter" /* IdentifierMeta.FormParameter */]);
@@ -33294,8 +33413,6 @@ const _reference_1 = __webpack_require__(/*! ../_reference */ "./node_modules/@a
33294
33413
  const component_name_1 = __webpack_require__(/*! ./component_name */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/component_name.js");
33295
33414
  const attribute_name_1 = __webpack_require__(/*! ./attribute_name */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/attribute_name.js");
33296
33415
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
33297
- const visibility_1 = __webpack_require__(/*! ../../4_file_information/visibility */ "./node_modules/@abaplint/core/build/src/abap/4_file_information/visibility.js");
33298
- const class_definition_1 = __webpack_require__(/*! ../../types/class_definition */ "./node_modules/@abaplint/core/build/src/abap/types/class_definition.js");
33299
33416
  class MethodCallChain {
33300
33417
  static runSyntax(node, input, targetType) {
33301
33418
  var _a, _b;
@@ -33325,6 +33442,14 @@ class MethodCallChain {
33325
33442
  const methodToken = (_a = current.findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
33326
33443
  const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
33327
33444
  const def = input.scope.findObjectDefinition(className);
33445
+ const isSuper = current === children[2]
33446
+ && first.get() instanceof Expressions.FieldChain
33447
+ && first.concatTokens().toUpperCase() === "SUPER";
33448
+ const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
33449
+ if (superMessage !== undefined) {
33450
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
33451
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33452
+ }
33328
33453
  // eslint-disable-next-line prefer-const
33329
33454
  let { method, def: foundDef } = helper.searchMethodName(def, methodName);
33330
33455
  if (method === undefined && current === first) {
@@ -33344,12 +33469,19 @@ class MethodCallChain {
33344
33469
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
33345
33470
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33346
33471
  }
33347
- const notVisible = method ? this.checkVisibility(method, def, foundDef, input) : undefined;
33472
+ const notVisible = method
33473
+ ? helper.memberNotVisible(method.getVisibility(), def, foundDef, input.scope.getEnclosingClassName())
33474
+ : undefined;
33348
33475
  if (notVisible !== undefined) {
33349
33476
  const message = `Method "${methodName}" is ${notVisible} and cannot be accessed`;
33350
33477
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
33351
33478
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33352
33479
  }
33480
+ const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
33481
+ if (specialMessage !== undefined) {
33482
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
33483
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33484
+ }
33353
33485
  const voidedName = context instanceof basic_1.VoidType ? context.getVoided() : undefined;
33354
33486
  const extra = helper.methodReferenceExtras(foundDef, className || voidedName);
33355
33487
  input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
@@ -33392,47 +33524,6 @@ class MethodCallChain {
33392
33524
  return context;
33393
33525
  }
33394
33526
  //////////////////////////////////////
33395
- // returns the visibility as text if the method cannot be accessed from the current scope
33396
- static checkVisibility(method, def, foundDef, input) {
33397
- var _a, _b, _c;
33398
- const visibility = method.getVisibility();
33399
- if (visibility === visibility_1.Visibility.Public || foundDef === undefined) {
33400
- return undefined;
33401
- }
33402
- else if (!(foundDef instanceof class_definition_1.ClassDefinition)) {
33403
- // interface members are always public
33404
- return undefined;
33405
- }
33406
- const name = foundDef.getName().toUpperCase();
33407
- const enclosing = (_a = input.scope.getEnclosingClassName()) === null || _a === void 0 ? void 0 : _a.toUpperCase();
33408
- if (enclosing === undefined || enclosing === name) {
33409
- return undefined;
33410
- }
33411
- // friendship with the class used at the call site also gives access to inherited members
33412
- const helper = new _object_oriented_1.ObjectOriented(input.scope);
33413
- const visited = [];
33414
- let current = def instanceof class_definition_1.ClassDefinition ? def : foundDef;
33415
- while (current !== undefined && visited.includes(current.getName().toUpperCase()) === false) {
33416
- visited.push(current.getName().toUpperCase());
33417
- if (helper.hasFriendship(current, enclosing)) {
33418
- return undefined;
33419
- }
33420
- const sup = current.getSuperClass();
33421
- current = sup === undefined ? undefined : input.scope.findClassDefinition(sup);
33422
- }
33423
- if (visibility === visibility_1.Visibility.Protected) {
33424
- // subclasses can access protected members
33425
- let sup = (_b = input.scope.findClassDefinition(enclosing)) === null || _b === void 0 ? void 0 : _b.getSuperClass();
33426
- while (sup !== undefined) {
33427
- if (sup.toUpperCase() === name) {
33428
- return undefined;
33429
- }
33430
- sup = (_c = input.scope.findClassDefinition(sup)) === null || _c === void 0 ? void 0 : _c.getSuperClass();
33431
- }
33432
- return "protected";
33433
- }
33434
- return "private";
33435
- }
33436
33527
  static findTop(first, input, targetType) {
33437
33528
  var _a;
33438
33529
  if (first.get() instanceof Expressions.ClassName) {
@@ -33786,6 +33877,9 @@ class MethodParam {
33786
33877
  else if (concat === "TYPE P" || concat.startsWith("TYPE P ")) {
33787
33878
  return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.PGenericType.get(), meta);
33788
33879
  }
33880
+ else if (concat === "TYPE N" || concat.startsWith("TYPE N ")) {
33881
+ return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, basic_1.NGenericType.get(), meta);
33882
+ }
33789
33883
  const found = new basic_types_1.BasicTypes(input).parseType(type);
33790
33884
  if (found) {
33791
33885
  return new _typed_identifier_1.TypedIdentifier(name.getFirstToken(), input.filename, found, meta);
@@ -34254,6 +34348,14 @@ class MethodSource {
34254
34348
  const methodToken = current.getFirstToken();
34255
34349
  const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
34256
34350
  const def = input.scope.findObjectDefinition(className);
34351
+ const isSuper = implicitMe === false
34352
+ && first.get() instanceof Expressions.SourceField
34353
+ && first.concatTokens().toUpperCase() === "SUPER";
34354
+ const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
34355
+ if (superMessage !== undefined) {
34356
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
34357
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34358
+ }
34257
34359
  // eslint-disable-next-line prefer-const
34258
34360
  let { method, def: foundDef } = helper.searchMethodName(def, methodName);
34259
34361
  if (implicitMe && current === first && (method === null || method === void 0 ? void 0 : method.isStatic()) === false && input.scope.isInStaticMethod() === true) {
@@ -34270,6 +34372,11 @@ class MethodSource {
34270
34372
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34271
34373
  }
34272
34374
  else if (method) {
34375
+ const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
34376
+ if (specialMessage !== undefined) {
34377
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
34378
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34379
+ }
34273
34380
  const extra = helper.methodReferenceExtras(foundDef, className);
34274
34381
  input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
34275
34382
  context = method;
@@ -35368,6 +35475,7 @@ const corresponding_body_1 = __webpack_require__(/*! ./corresponding_body */ "./
35368
35475
  const _builtin_1 = __webpack_require__(/*! ../_builtin */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_builtin.js");
35369
35476
  const attribute_chain_1 = __webpack_require__(/*! ./attribute_chain */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/attribute_chain.js");
35370
35477
  const dereference_1 = __webpack_require__(/*! ./dereference */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/dereference.js");
35478
+ const cast_1 = __webpack_require__(/*! ./cast */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/cast.js");
35371
35479
  const _typed_identifier_1 = __webpack_require__(/*! ../../types/_typed_identifier */ "./node_modules/@abaplint/core/build/src/abap/types/_typed_identifier.js");
35372
35480
  const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
35373
35481
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
@@ -35591,6 +35699,10 @@ class Source {
35591
35699
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
35592
35700
  }
35593
35701
  }
35702
+ else if (get instanceof Expressions.Cast) {
35703
+ const found = cast_1.Cast.runSyntax(first, input, targetType);
35704
+ context = arithmetic === true ? this.infer(context, found, true) : found;
35705
+ }
35594
35706
  else if (get instanceof Expressions.FieldChain) {
35595
35707
  const found = field_chain_1.FieldChain.runSyntax(first, input, type, allowGenericDeference);
35596
35708
  context = arithmetic === true ? this.infer(context, found, true) : found;
@@ -35607,6 +35719,11 @@ class Source {
35607
35719
  context = this.infer(context, found, arithmetic);
35608
35720
  }
35609
35721
  else if (get instanceof Expressions.Dereference) {
35722
+ if (this.isNewObjectDereference(node, first)) {
35723
+ const message = "NEW cannot be dereferenced directly";
35724
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, first.getFirstToken(), message));
35725
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
35726
+ }
35610
35727
  context = dereference_1.Dereference.runSyntax(first, context, input);
35611
35728
  }
35612
35729
  else if (get instanceof Expressions.ComponentChain) {
@@ -35794,6 +35911,16 @@ class Source {
35794
35911
  }
35795
35912
  return targetType;
35796
35913
  }
35914
+ // "NEW ty( )->*" is a syntax error, also in releases where a method call can be dereferenced
35915
+ static isNewObjectDereference(node, deref) {
35916
+ var _a;
35917
+ const children = node.getChildren();
35918
+ const before = children[children.indexOf(deref) - 1];
35919
+ return before instanceof nodes_1.ExpressionNode
35920
+ && before.get() instanceof Expressions.MethodCallChain
35921
+ && before.getChildren().length === 1
35922
+ && ((_a = before.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.NewObject;
35923
+ }
35797
35924
  }
35798
35925
  exports.Source = Source;
35799
35926
  //# sourceMappingURL=source.js.map
@@ -36761,6 +36888,7 @@ const expressions_1 = __webpack_require__(/*! ../../2_statements/expressions */
36761
36888
  const field_length_1 = __webpack_require__(/*! ./field_length */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/field_length.js");
36762
36889
  const cast_1 = __webpack_require__(/*! ./cast */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/cast.js");
36763
36890
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
36891
+ const version_1 = __webpack_require__(/*! ../../../version */ "./node_modules/@abaplint/core/build/src/version.js");
36764
36892
  class Target {
36765
36893
  static runSyntax(node, input) {
36766
36894
  const concat = node.concatTokens();
@@ -36826,6 +36954,12 @@ class Target {
36826
36954
  if (!(context instanceof basic_1.VoidType)) {
36827
36955
  context = context.getType();
36828
36956
  }
36957
+ if ((context === null || context === void 0 ? void 0 : context.isGeneric()) === true
36958
+ && !(0, version_1.releaseAtLeast)(input.scope.getRelease(), version_1.Release.v756)
36959
+ && input.scope.getLanguageVersion() !== version_1.LanguageVersion.Cloud
36960
+ && !input.scope.getOpenABAP()) {
36961
+ throw new Error("A generic reference cannot be dereferenced");
36962
+ }
36829
36963
  }
36830
36964
  else if (current.get() instanceof Expressions.ComponentName) {
36831
36965
  context = component_name_1.ComponentName.runSyntax(context, current, input);
@@ -40448,9 +40582,9 @@ class CreateObject {
40448
40582
  if (name === undefined) {
40449
40583
  continue;
40450
40584
  }
40451
- const source = p.findDirectExpression(Expressions.Source);
40452
- const sourceType = source_1.Source.runSyntax(source, input);
40453
40585
  const found = allImporting === null || allImporting === void 0 ? void 0 : allImporting.find(p => p.getName().toUpperCase() === name);
40586
+ const source = p.findDirectExpression(Expressions.Source);
40587
+ const sourceType = source_1.Source.runSyntax(source, input, found === null || found === void 0 ? void 0 : found.getType());
40454
40588
  if (found === undefined) {
40455
40589
  const message = `constructor parameter "${name}" does not exist`;
40456
40590
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, node.getFirstToken(), message));
@@ -51907,6 +52041,7 @@ __exportStar(__webpack_require__(/*! ./generic_object_reference_type */ "./node_
51907
52041
  __exportStar(__webpack_require__(/*! ./hex_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/hex_type.js"), exports);
51908
52042
  __exportStar(__webpack_require__(/*! ./integer_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/integer_type.js"), exports);
51909
52043
  __exportStar(__webpack_require__(/*! ./integer8_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/integer8_type.js"), exports);
52044
+ __exportStar(__webpack_require__(/*! ./ngeneric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js"), exports);
51910
52045
  __exportStar(__webpack_require__(/*! ./numeric_generic_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js"), exports);
51911
52046
  __exportStar(__webpack_require__(/*! ./numeric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_type.js"), exports);
51912
52047
  __exportStar(__webpack_require__(/*! ./object_reference_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/object_reference_type.js"), exports);
@@ -52015,6 +52150,39 @@ IntegerType.singletons = new Map();
52015
52150
 
52016
52151
  /***/ },
52017
52152
 
52153
+ /***/ "./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js"
52154
+ /*!*********************************************************************************!*\
52155
+ !*** ./node_modules/@abaplint/core/build/src/abap/types/basic/ngeneric_type.js ***!
52156
+ \*********************************************************************************/
52157
+ (__unused_webpack_module, exports, __webpack_require__) {
52158
+
52159
+ "use strict";
52160
+
52161
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
52162
+ exports.NGenericType = void 0;
52163
+ const numeric_type_1 = __webpack_require__(/*! ./numeric_type */ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_type.js");
52164
+ // "TYPE n" of a method or FORM parameter, where no length can be given.
52165
+ // It is a NumericType, so everything that handles n keeps treating it as such
52166
+ class NGenericType extends numeric_type_1.NumericType {
52167
+ static get() {
52168
+ return this.singleton;
52169
+ }
52170
+ constructor() {
52171
+ super(1);
52172
+ }
52173
+ toText() {
52174
+ return "```n```";
52175
+ }
52176
+ isGeneric() {
52177
+ return true;
52178
+ }
52179
+ }
52180
+ exports.NGenericType = NGenericType;
52181
+ NGenericType.singleton = new NGenericType();
52182
+ //# sourceMappingURL=ngeneric_type.js.map
52183
+
52184
+ /***/ },
52185
+
52018
52186
  /***/ "./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js"
52019
52187
  /*!****************************************************************************************!*\
52020
52188
  !*** ./node_modules/@abaplint/core/build/src/abap/types/basic/numeric_generic_type.js ***!
@@ -70615,6 +70783,7 @@ class Indent {
70615
70783
  || type instanceof Statements.ProcessBeforeOutput
70616
70784
  || type instanceof Statements.ProcessOnValueRequest
70617
70785
  || type instanceof Statements.TopOfPage
70786
+ || type instanceof Statements.EndOfPage
70618
70787
  || type instanceof Statements.Get
70619
70788
  || type instanceof Statements.EndOfSelection
70620
70789
  || type instanceof Statements.LoadOfProgram) {
@@ -70710,6 +70879,7 @@ class Indent {
70710
70879
  || type instanceof Statements.Initialization
70711
70880
  || type instanceof Statements.AtUserCommand
70712
70881
  || type instanceof Statements.TopOfPage
70882
+ || type instanceof Statements.EndOfPage
70713
70883
  || type instanceof Statements.EndOfSelection
70714
70884
  || type instanceof Statements.Public
70715
70885
  || type instanceof Statements.Protected
@@ -70907,7 +71077,7 @@ class Registry {
70907
71077
  }
70908
71078
  static abaplintVersion() {
70909
71079
  // magic, see build script "version.js"
70910
- return "2.120.66";
71080
+ return "2.120.69";
70911
71081
  }
70912
71082
  getDDICReferences() {
70913
71083
  return this.ddicReferences;
@@ -80406,8 +80576,17 @@ ${indentation} output = ${uniqueName}.\n`;
80406
80576
  const extra = (valueBody === null || valueBody === void 0 ? void 0 : valueBody.findDirectExpression(Expressions.For)) ? " " : "";
80407
80577
  data = indentation + extra + `DATA ${structureName} LIKE LINE OF ${uniqueName}.\n`;
80408
80578
  }
80579
+ // all rows are built in the same work area, a component a row leaves out must be initial,
80580
+ // not what an earlier row (or an earlier pass of a surrounding loop) put there
80581
+ const clearRows = valueBody !== undefined && this.valueRowsNeedClear(valueBody);
80582
+ const prefix = [];
80409
80583
  for (const a of (valueBody === null || valueBody === void 0 ? void 0 : valueBody.getChildren()) || []) {
80410
80584
  if (a.get() instanceof Expressions.FieldAssignment) {
80585
+ if (clearRows === true) {
80586
+ // the shared prefix applies to every following row, re-applied after each CLEAR
80587
+ prefix.push(a.concatTokens());
80588
+ continue;
80589
+ }
80411
80590
  if (added === false) {
80412
80591
  body += data;
80413
80592
  added = true;
@@ -80431,6 +80610,16 @@ ${indentation} output = ${uniqueName}.\n`;
80431
80610
  }
80432
80611
  if (a instanceof nodes_1.ExpressionNode && a.get() instanceof Expressions.ValueBodyLine) {
80433
80612
  let skip = false;
80613
+ if (clearRows === true && this.isStructuredValueRow(a)) {
80614
+ if (added === false) {
80615
+ body += data;
80616
+ added = true;
80617
+ }
80618
+ body += indentation + `CLEAR ${structureName}.\n`;
80619
+ for (const p of prefix) {
80620
+ body += indentation + structureName + "-" + p + ".\n";
80621
+ }
80622
+ }
80434
80623
  for (const b of (a === null || a === void 0 ? void 0 : a.getChildren()) || []) {
80435
80624
  if (b.get() instanceof Expressions.FieldAssignment) {
80436
80625
  if (added === false) {
@@ -80509,6 +80698,39 @@ ${indentation} output = ${uniqueName}.\n`;
80509
80698
  }
80510
80699
  return undefined;
80511
80700
  }
80701
+ /** a row that is built in the work area, ie. not "( source )" or "( LINES OF source )" */
80702
+ isStructuredValueRow(row) {
80703
+ return row.findDirectExpression(Expressions.Source) === undefined
80704
+ && row.findDirectExpression(Expressions.ValueBodyLines) === undefined;
80705
+ }
80706
+ /** true if a row can observe a component that an earlier row, or an earlier pass of a surrounding loop,
80707
+ * left in the shared work area. Not the case if all rows assign the same components, and the shared
80708
+ * prefix is not changed between rows, eg. FOR rows or "( a = 1 b = 2 ) ( a = 3 b = 4 )" */
80709
+ valueRowsNeedClear(valueBody) {
80710
+ let shape = undefined;
80711
+ let rowSeen = false;
80712
+ for (const c of valueBody.getChildren()) {
80713
+ if (c.get() instanceof Expressions.FieldAssignment) {
80714
+ if (rowSeen === true) {
80715
+ return true;
80716
+ }
80717
+ }
80718
+ else if (c instanceof nodes_1.ExpressionNode
80719
+ && c.get() instanceof Expressions.ValueBodyLine
80720
+ && this.isStructuredValueRow(c)) {
80721
+ rowSeen = true;
80722
+ const current = c.findDirectExpressions(Expressions.FieldAssignment)
80723
+ .map(f => { var _a; return (_a = f.findDirectExpression(Expressions.FieldSub)) === null || _a === void 0 ? void 0 : _a.concatTokens().toUpperCase().replace(/\s/g, ""); })
80724
+ .sort()
80725
+ .join(",");
80726
+ if (shape !== undefined && shape !== current) {
80727
+ return true;
80728
+ }
80729
+ shape = current;
80730
+ }
80731
+ }
80732
+ return false;
80733
+ }
80512
80734
  outlineLet(node, indentation, highSyntax, lowFile) {
80513
80735
  var _a;
80514
80736
  let ret = "";
@@ -95784,7 +96006,9 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
95784
96006
  title: "RFC error handling",
95785
96007
  tags: [_irule_1.RuleTag.SingleFile],
95786
96008
  shortDescription: `Checks that exceptions 'system_failure' and 'communication_failure' are handled in RFC calls`,
95787
- extendedInformation: `https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
96009
+ extendedInformation: `RESOURCE_FAILURE is also required for asynchronous calls with DESTINATION IN GROUP.
96010
+
96011
+ https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/abenrfc_exception.html`,
95788
96012
  badExample: `CALL FUNCTION 'ZRFC'
95789
96013
  DESTINATION lv_rfc.`,
95790
96014
  goodExample: `CALL FUNCTION 'ZRFC'
@@ -95792,12 +96016,12 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
95792
96016
  EXCEPTIONS
95793
96017
  system_failure = 1 MESSAGE msg
95794
96018
  communication_failure = 2 MESSAGE msg
95795
- resource_failure = 3
95796
- OTHERS = 4.`,
96019
+ OTHERS = 3.`,
95797
96020
  };
95798
96021
  }
95799
- getMessage() {
95800
- return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE, RESOURCE_FAILURE";
96022
+ getMessage(requireResourceFailure) {
96023
+ return "RFC error handling: At least one unhandled exception from SYSTEM_FAILURE, COMMUNICATION_FAILURE"
96024
+ + (requireResourceFailure ? ", RESOURCE_FAILURE" : "");
95801
96025
  }
95802
96026
  getConfig() {
95803
96027
  return this.conf;
@@ -95812,12 +96036,15 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
95812
96036
  if (!(stat.get() instanceof Statements.CallFunction)) {
95813
96037
  continue;
95814
96038
  }
95815
- if (!stat.findFirstExpression(Expressions.Destination)) {
96039
+ const destination = stat.findFirstExpression(Expressions.Destination);
96040
+ if (destination === undefined) {
95816
96041
  continue;
95817
96042
  }
96043
+ const requireResourceFailure = stat.findDirectTokenByText("STARTING") !== undefined
96044
+ && destination.findDirectTokenByText("GROUP") !== undefined;
95818
96045
  const list = stat.findFirstExpression(Expressions.ParameterListExceptions);
95819
96046
  if (list === undefined) {
95820
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
96047
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
95821
96048
  output.push(issue);
95822
96049
  continue;
95823
96050
  }
@@ -95828,8 +96055,8 @@ class RFCErrorHandling extends _abap_rule_1.ABAPRule {
95828
96055
  }
95829
96056
  if (names.indexOf("SYSTEM_FAILURE") < 0
95830
96057
  || names.indexOf("COMMUNICATION_FAILURE") < 0
95831
- || names.indexOf("RESOURCE_FAILURE") < 0) {
95832
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
96058
+ || (requireResourceFailure && names.indexOf("RESOURCE_FAILURE") < 0)) {
96059
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(requireResourceFailure), this.getMetadata().key, this.conf.severity);
95833
96060
  output.push(issue);
95834
96061
  continue;
95835
96062
  }
@@ -121098,8 +121325,18 @@ class SelectTranspiler {
121098
121325
  const having = node.findDirectExpression(abaplint.Expressions.Select)
121099
121326
  ?.findDirectExpression(abaplint.Expressions.SQLHaving);
121100
121327
  const havingCond = having?.findFirstExpression(abaplint.Expressions.SQLCond);
121328
+ let dynamicHaving;
121101
121329
  if (havingCond) {
121102
- select += "HAVING " + new expressions_1.SQLCondTranspiler().transpile(havingCond, traversal, table).getCode() + " ";
121330
+ const dynamic = havingCond.findFirstExpression(abaplint.Expressions.Dynamic);
121331
+ const chain = dynamic?.findFirstExpression(abaplint.Expressions.FieldChain);
121332
+ if (chain && havingCond.concatTokens() === dynamic?.concatTokens()) {
121333
+ dynamicHaving = dynamic;
121334
+ const code = new expressions_1.FieldChainTranspiler(false).transpile(chain, traversal).getCode();
121335
+ select += `" + ${this.dynamicHavingClause(code)} + " `;
121336
+ }
121337
+ else {
121338
+ select += "HAVING " + new expressions_1.SQLCondTranspiler().transpile(havingCond, traversal, table).getCode() + " ";
121339
+ }
121103
121340
  }
121104
121341
  const upTo = node.findFirstExpression(abaplint.Expressions.SQLUpTo);
121105
121342
  if (upTo) {
@@ -121119,6 +121356,9 @@ class SelectTranspiler {
121119
121356
  const groupByDynamics = new Set(groupBy?.findAllExpressionsRecursive(abaplint.Expressions.Dynamic) || []);
121120
121357
  const orderByDynamics = new Set(orderBy?.findAllExpressionsRecursive(abaplint.Expressions.Dynamic) || []);
121121
121358
  for (const d of node.findAllExpressionsRecursive(abaplint.Expressions.Dynamic)) {
121359
+ if (d === dynamicHaving) {
121360
+ continue;
121361
+ }
121122
121362
  const chain = d.findFirstExpression(abaplint.Expressions.FieldChain);
121123
121363
  if (chain) {
121124
121364
  const search = d.concatTokens();
@@ -121275,6 +121515,13 @@ abap.builtin.sy.get().dbcnt.set(${target}.getArrayLength());
121275
121515
  + ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(", "))`
121276
121516
  + ` : (("" + ${code}.get()).trim() === "" ? "" : "${keyword} " + ${code}.get()))`;
121277
121517
  }
121518
+ dynamicHavingClause(code) {
121519
+ return `((value) => {
121520
+ const condition = value instanceof abap.types.Table || value instanceof abap.types.HashedTable
121521
+ ? value.array().map(row => row.get()).join(" ") : value.get();
121522
+ return condition.trim() === "" ? "" : "HAVING " + abap.expandDynamic(condition, (name) => {try { return eval(name);} catch {}});
121523
+ })(${code})`;
121524
+ }
121278
121525
  isWhereExpression(node, expression) {
121279
121526
  // check if previous token before sqlCond is "WHERE". It could also be "ON" in case of join condition
121280
121527
  let prevToken;
@@ -125598,6 +125845,10 @@ class Traversal {
125598
125845
  doOrWhileIndexBackups = new Map();
125599
125846
  statementsInsideLoop = new WeakSet();
125600
125847
  enclosingDoOrWhile = new WeakMap();
125848
+ /** DATA, CONSTANTS and FIELD-SYMBOLS nested in blocks, already declared in front of the block */
125849
+ declaredEarly = new WeakSet();
125850
+ emittingEarly = false;
125851
+ blockDepth = 0;
125601
125852
  reg;
125602
125853
  options;
125603
125854
  constructor(spaghetti, file, obj, reg, options) {
@@ -126436,17 +126687,15 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126436
126687
  }
126437
126688
  else if (c.get() instanceof abaplint.Expressions.AttributeName
126438
126689
  && context instanceof abaplint.BasicTypes.ObjectReferenceType) {
126439
- const id = context.getIdentifier();
126440
- if (id instanceof abaplint.Types.ClassDefinition || id instanceof abaplint.Types.InterfaceDefinition) {
126441
- const concat = c.concatTokens();
126442
- if (concat.includes("~")) {
126443
- const [iname, aname] = concat.split("~");
126444
- const intf = this.findInterfaceDefinition(iname, scope);
126445
- context = intf?.getAttributes().findByName(aname)?.getType();
126446
- }
126447
- else {
126448
- context = id.getAttributes().findByName(concat)?.getType();
126449
- }
126690
+ const concat = c.concatTokens();
126691
+ if (concat.includes("~")) {
126692
+ const [iname, aname] = concat.split("~");
126693
+ const intf = this.findInterfaceDefinition(iname, scope);
126694
+ context = intf?.getAttributes().findByName(aname)?.getType();
126695
+ }
126696
+ else {
126697
+ // Global references can carry an identifier rather than a class definition.
126698
+ context = this.narrowContextAttribute(context, concat, scope);
126450
126699
  }
126451
126700
  }
126452
126701
  else if (c.get() instanceof abaplint.Expressions.AttributeName
@@ -126460,7 +126709,7 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126460
126709
  return context;
126461
126710
  }
126462
126711
  isInsideLoop(node) {
126463
- return this.statementsInsideLoop.has(node);
126712
+ return this.statementsInsideLoop.has(node) && !this.declaredEarly.has(node);
126464
126713
  }
126465
126714
  isInsideDoOrWhile(node) {
126466
126715
  return this.findCurrentDoOrWhileIndexBackup(node) !== undefined;
@@ -126555,7 +126804,87 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126555
126804
  return this.obj.getType() + "-" + this.obj.getName() + "-";
126556
126805
  }
126557
126806
  ////////////////////////////
126807
+ /** In ABAP, DATA, CONSTANTS and FIELD-SYMBOLS are visible in the whole method/form/program, but a
126808
+ * javascript "let" inside the block of an IF, LOOP, TRY etc. is not. So before each block on
126809
+ * method/form/program level the declarations nested in it are output, in source order, and
126810
+ * skipped inside the block. They then exist after the block even if the branch did not run,
126811
+ * and are initialized once, also when the block is a loop */
126812
+ traverseProcedureLevel(node) {
126813
+ const ret = new chunk_1.Chunk();
126814
+ for (const c of node.getChildren()) {
126815
+ if (c instanceof abaplint.Nodes.StructureNode && Traversal.isDeclaration(c) === false) {
126816
+ ret.appendChunk(this.declareNestedEarly(c));
126817
+ this.blockDepth++;
126818
+ try {
126819
+ ret.appendChunk(this.traverseStructure(c));
126820
+ }
126821
+ finally {
126822
+ this.blockDepth--;
126823
+ }
126824
+ }
126825
+ else {
126826
+ ret.appendChunk(this.traverse(c));
126827
+ }
126828
+ }
126829
+ return ret;
126830
+ }
126831
+ declareNestedEarly(block) {
126832
+ const found = [];
126833
+ Traversal.findNestedDeclarations(block, found);
126834
+ for (const node of found) {
126835
+ this.declaredEarly.add(node);
126836
+ if (node instanceof abaplint.Nodes.StructureNode) {
126837
+ for (const statement of node.findAllStatementNodes()) {
126838
+ this.declaredEarly.add(statement);
126839
+ }
126840
+ }
126841
+ }
126842
+ const ret = new chunk_1.Chunk();
126843
+ this.emittingEarly = true;
126844
+ try {
126845
+ for (const node of found) {
126846
+ ret.appendChunk(this.traverse(node));
126847
+ }
126848
+ }
126849
+ finally {
126850
+ this.emittingEarly = false;
126851
+ }
126852
+ return ret;
126853
+ }
126854
+ static isDeclaration(node) {
126855
+ const get = node.get();
126856
+ return get instanceof abaplint.Structures.Data
126857
+ || get instanceof abaplint.Structures.Constants
126858
+ || get instanceof abaplint.Structures.Types;
126859
+ }
126860
+ static findNestedDeclarations(node, found) {
126861
+ for (const c of node.getChildren()) {
126862
+ if (c instanceof abaplint.Nodes.StatementNode) {
126863
+ const get = c.get();
126864
+ if (get instanceof abaplint.Statements.Data
126865
+ || get instanceof abaplint.Statements.Constant
126866
+ || get instanceof abaplint.Statements.FieldSymbol) {
126867
+ found.push(c);
126868
+ }
126869
+ }
126870
+ else if (c instanceof abaplint.Nodes.StructureNode) {
126871
+ const get = c.get();
126872
+ if (get instanceof abaplint.Structures.Data || get instanceof abaplint.Structures.Constants) {
126873
+ found.push(c);
126874
+ }
126875
+ else {
126876
+ Traversal.findNestedDeclarations(c, found);
126877
+ }
126878
+ }
126879
+ }
126880
+ }
126558
126881
  traverseStructure(node) {
126882
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
126883
+ return new chunk_1.Chunk();
126884
+ }
126885
+ else if (this.blockDepth === 0 && node.get() instanceof abaplint.Structures.Normal) {
126886
+ return this.traverseProcedureLevel(node);
126887
+ }
126559
126888
  const list = StructureTranspilers;
126560
126889
  const ret = new chunk_1.Chunk();
126561
126890
  const search = node.get().constructor.name + "Transpiler";
@@ -126578,6 +126907,9 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126578
126907
  return ret;
126579
126908
  }
126580
126909
  traverseStatement(node) {
126910
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
126911
+ return new chunk_1.Chunk();
126912
+ }
126581
126913
  const list = StatementTranspilers;
126582
126914
  const search = node.get().constructor.name + "Transpiler";
126583
126915
  if (list[search]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/transpiler-cli",
3
- "version": "2.13.98",
3
+ "version": "2.13.100",
4
4
  "description": "Transpiler - Command Line Interface",
5
5
  "funding": "https://github.com/sponsors/larshp",
6
6
  "bin": {
@@ -27,8 +27,8 @@
27
27
  "author": "abaplint",
28
28
  "license": "MIT",
29
29
  "devDependencies": {
30
- "@abaplint/core": "^2.120.66",
31
- "@abaplint/transpiler": "^2.13.98",
30
+ "@abaplint/core": "^2.120.69",
31
+ "@abaplint/transpiler": "^2.13.100",
32
32
  "@types/glob": "^9.0.0",
33
33
  "@types/node": "^26.6.2",
34
34
  "@types/progress": "^2.0.7",