@abaplint/transpiler-cli 2.13.98 → 2.13.99

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 +273 -58
  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
  }
@@ -33294,8 +33410,6 @@ const _reference_1 = __webpack_require__(/*! ../_reference */ "./node_modules/@a
33294
33410
  const component_name_1 = __webpack_require__(/*! ./component_name */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/component_name.js");
33295
33411
  const attribute_name_1 = __webpack_require__(/*! ./attribute_name */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/attribute_name.js");
33296
33412
  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
33413
  class MethodCallChain {
33300
33414
  static runSyntax(node, input, targetType) {
33301
33415
  var _a, _b;
@@ -33325,6 +33439,14 @@ class MethodCallChain {
33325
33439
  const methodToken = (_a = current.findDirectExpression(Expressions.MethodName)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
33326
33440
  const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
33327
33441
  const def = input.scope.findObjectDefinition(className);
33442
+ const isSuper = current === children[2]
33443
+ && first.get() instanceof Expressions.FieldChain
33444
+ && first.concatTokens().toUpperCase() === "SUPER";
33445
+ const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
33446
+ if (superMessage !== undefined) {
33447
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
33448
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33449
+ }
33328
33450
  // eslint-disable-next-line prefer-const
33329
33451
  let { method, def: foundDef } = helper.searchMethodName(def, methodName);
33330
33452
  if (method === undefined && current === first) {
@@ -33344,12 +33466,19 @@ class MethodCallChain {
33344
33466
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
33345
33467
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33346
33468
  }
33347
- const notVisible = method ? this.checkVisibility(method, def, foundDef, input) : undefined;
33469
+ const notVisible = method
33470
+ ? helper.memberNotVisible(method.getVisibility(), def, foundDef, input.scope.getEnclosingClassName())
33471
+ : undefined;
33348
33472
  if (notVisible !== undefined) {
33349
33473
  const message = `Method "${methodName}" is ${notVisible} and cannot be accessed`;
33350
33474
  input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, message));
33351
33475
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33352
33476
  }
33477
+ const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
33478
+ if (specialMessage !== undefined) {
33479
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
33480
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
33481
+ }
33353
33482
  const voidedName = context instanceof basic_1.VoidType ? context.getVoided() : undefined;
33354
33483
  const extra = helper.methodReferenceExtras(foundDef, className || voidedName);
33355
33484
  input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
@@ -33392,47 +33521,6 @@ class MethodCallChain {
33392
33521
  return context;
33393
33522
  }
33394
33523
  //////////////////////////////////////
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
33524
  static findTop(first, input, targetType) {
33437
33525
  var _a;
33438
33526
  if (first.get() instanceof Expressions.ClassName) {
@@ -34254,6 +34342,14 @@ class MethodSource {
34254
34342
  const methodToken = current.getFirstToken();
34255
34343
  const methodName = methodToken === null || methodToken === void 0 ? void 0 : methodToken.getStr();
34256
34344
  const def = input.scope.findObjectDefinition(className);
34345
+ const isSuper = implicitMe === false
34346
+ && first.get() instanceof Expressions.SourceField
34347
+ && first.concatTokens().toUpperCase() === "SUPER";
34348
+ const superMessage = isSuper ? helper.checkSuperCall(def, methodName) : undefined;
34349
+ if (superMessage !== undefined) {
34350
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, superMessage));
34351
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34352
+ }
34257
34353
  // eslint-disable-next-line prefer-const
34258
34354
  let { method, def: foundDef } = helper.searchMethodName(def, methodName);
34259
34355
  if (implicitMe && current === first && (method === null || method === void 0 ? void 0 : method.isStatic()) === false && input.scope.isInStaticMethod() === true) {
@@ -34270,6 +34366,11 @@ class MethodSource {
34270
34366
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34271
34367
  }
34272
34368
  else if (method) {
34369
+ const specialMessage = isSuper ? undefined : helper.checkSpecialTestMethodCall(method, foundDef);
34370
+ if (specialMessage !== undefined) {
34371
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, methodToken, specialMessage));
34372
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
34373
+ }
34273
34374
  const extra = helper.methodReferenceExtras(foundDef, className);
34274
34375
  input.scope.addReference(methodToken, method, _reference_1.ReferenceType.MethodReference, input.filename, extra);
34275
34376
  context = method;
@@ -35368,6 +35469,7 @@ const corresponding_body_1 = __webpack_require__(/*! ./corresponding_body */ "./
35368
35469
  const _builtin_1 = __webpack_require__(/*! ../_builtin */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_builtin.js");
35369
35470
  const attribute_chain_1 = __webpack_require__(/*! ./attribute_chain */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/attribute_chain.js");
35370
35471
  const dereference_1 = __webpack_require__(/*! ./dereference */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/dereference.js");
35472
+ const cast_1 = __webpack_require__(/*! ./cast */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/cast.js");
35371
35473
  const _typed_identifier_1 = __webpack_require__(/*! ../../types/_typed_identifier */ "./node_modules/@abaplint/core/build/src/abap/types/_typed_identifier.js");
35372
35474
  const _type_utils_1 = __webpack_require__(/*! ../_type_utils */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_type_utils.js");
35373
35475
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
@@ -35591,6 +35693,10 @@ class Source {
35591
35693
  return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
35592
35694
  }
35593
35695
  }
35696
+ else if (get instanceof Expressions.Cast) {
35697
+ const found = cast_1.Cast.runSyntax(first, input, targetType);
35698
+ context = arithmetic === true ? this.infer(context, found, true) : found;
35699
+ }
35594
35700
  else if (get instanceof Expressions.FieldChain) {
35595
35701
  const found = field_chain_1.FieldChain.runSyntax(first, input, type, allowGenericDeference);
35596
35702
  context = arithmetic === true ? this.infer(context, found, true) : found;
@@ -35607,6 +35713,11 @@ class Source {
35607
35713
  context = this.infer(context, found, arithmetic);
35608
35714
  }
35609
35715
  else if (get instanceof Expressions.Dereference) {
35716
+ if (this.isNewObjectDereference(node, first)) {
35717
+ const message = "NEW cannot be dereferenced directly";
35718
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, first.getFirstToken(), message));
35719
+ return basic_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
35720
+ }
35610
35721
  context = dereference_1.Dereference.runSyntax(first, context, input);
35611
35722
  }
35612
35723
  else if (get instanceof Expressions.ComponentChain) {
@@ -35794,6 +35905,16 @@ class Source {
35794
35905
  }
35795
35906
  return targetType;
35796
35907
  }
35908
+ // "NEW ty( )->*" is a syntax error, also in releases where a method call can be dereferenced
35909
+ static isNewObjectDereference(node, deref) {
35910
+ var _a;
35911
+ const children = node.getChildren();
35912
+ const before = children[children.indexOf(deref) - 1];
35913
+ return before instanceof nodes_1.ExpressionNode
35914
+ && before.get() instanceof Expressions.MethodCallChain
35915
+ && before.getChildren().length === 1
35916
+ && ((_a = before.getFirstChild()) === null || _a === void 0 ? void 0 : _a.get()) instanceof Expressions.NewObject;
35917
+ }
35797
35918
  }
35798
35919
  exports.Source = Source;
35799
35920
  //# sourceMappingURL=source.js.map
@@ -36761,6 +36882,7 @@ const expressions_1 = __webpack_require__(/*! ../../2_statements/expressions */
36761
36882
  const field_length_1 = __webpack_require__(/*! ./field_length */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/field_length.js");
36762
36883
  const cast_1 = __webpack_require__(/*! ./cast */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/expressions/cast.js");
36763
36884
  const _syntax_input_1 = __webpack_require__(/*! ../_syntax_input */ "./node_modules/@abaplint/core/build/src/abap/5_syntax/_syntax_input.js");
36885
+ const version_1 = __webpack_require__(/*! ../../../version */ "./node_modules/@abaplint/core/build/src/version.js");
36764
36886
  class Target {
36765
36887
  static runSyntax(node, input) {
36766
36888
  const concat = node.concatTokens();
@@ -36826,6 +36948,12 @@ class Target {
36826
36948
  if (!(context instanceof basic_1.VoidType)) {
36827
36949
  context = context.getType();
36828
36950
  }
36951
+ if ((context === null || context === void 0 ? void 0 : context.isGeneric()) === true
36952
+ && !(0, version_1.releaseAtLeast)(input.scope.getRelease(), version_1.Release.v756)
36953
+ && input.scope.getLanguageVersion() !== version_1.LanguageVersion.Cloud
36954
+ && !input.scope.getOpenABAP()) {
36955
+ throw new Error("A generic reference cannot be dereferenced");
36956
+ }
36829
36957
  }
36830
36958
  else if (current.get() instanceof Expressions.ComponentName) {
36831
36959
  context = component_name_1.ComponentName.runSyntax(context, current, input);
@@ -70615,6 +70743,7 @@ class Indent {
70615
70743
  || type instanceof Statements.ProcessBeforeOutput
70616
70744
  || type instanceof Statements.ProcessOnValueRequest
70617
70745
  || type instanceof Statements.TopOfPage
70746
+ || type instanceof Statements.EndOfPage
70618
70747
  || type instanceof Statements.Get
70619
70748
  || type instanceof Statements.EndOfSelection
70620
70749
  || type instanceof Statements.LoadOfProgram) {
@@ -70710,6 +70839,7 @@ class Indent {
70710
70839
  || type instanceof Statements.Initialization
70711
70840
  || type instanceof Statements.AtUserCommand
70712
70841
  || type instanceof Statements.TopOfPage
70842
+ || type instanceof Statements.EndOfPage
70713
70843
  || type instanceof Statements.EndOfSelection
70714
70844
  || type instanceof Statements.Public
70715
70845
  || type instanceof Statements.Protected
@@ -70907,7 +71037,7 @@ class Registry {
70907
71037
  }
70908
71038
  static abaplintVersion() {
70909
71039
  // magic, see build script "version.js"
70910
- return "2.120.66";
71040
+ return "2.120.68";
70911
71041
  }
70912
71042
  getDDICReferences() {
70913
71043
  return this.ddicReferences;
@@ -125598,6 +125728,10 @@ class Traversal {
125598
125728
  doOrWhileIndexBackups = new Map();
125599
125729
  statementsInsideLoop = new WeakSet();
125600
125730
  enclosingDoOrWhile = new WeakMap();
125731
+ /** DATA, CONSTANTS and FIELD-SYMBOLS nested in blocks, already declared in front of the block */
125732
+ declaredEarly = new WeakSet();
125733
+ emittingEarly = false;
125734
+ blockDepth = 0;
125601
125735
  reg;
125602
125736
  options;
125603
125737
  constructor(spaghetti, file, obj, reg, options) {
@@ -126436,17 +126570,15 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126436
126570
  }
126437
126571
  else if (c.get() instanceof abaplint.Expressions.AttributeName
126438
126572
  && 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
- }
126573
+ const concat = c.concatTokens();
126574
+ if (concat.includes("~")) {
126575
+ const [iname, aname] = concat.split("~");
126576
+ const intf = this.findInterfaceDefinition(iname, scope);
126577
+ context = intf?.getAttributes().findByName(aname)?.getType();
126578
+ }
126579
+ else {
126580
+ // Global references can carry an identifier rather than a class definition.
126581
+ context = this.narrowContextAttribute(context, concat, scope);
126450
126582
  }
126451
126583
  }
126452
126584
  else if (c.get() instanceof abaplint.Expressions.AttributeName
@@ -126460,7 +126592,7 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126460
126592
  return context;
126461
126593
  }
126462
126594
  isInsideLoop(node) {
126463
- return this.statementsInsideLoop.has(node);
126595
+ return this.statementsInsideLoop.has(node) && !this.declaredEarly.has(node);
126464
126596
  }
126465
126597
  isInsideDoOrWhile(node) {
126466
126598
  return this.findCurrentDoOrWhileIndexBackup(node) !== undefined;
@@ -126555,7 +126687,87 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126555
126687
  return this.obj.getType() + "-" + this.obj.getName() + "-";
126556
126688
  }
126557
126689
  ////////////////////////////
126690
+ /** In ABAP, DATA, CONSTANTS and FIELD-SYMBOLS are visible in the whole method/form/program, but a
126691
+ * javascript "let" inside the block of an IF, LOOP, TRY etc. is not. So before each block on
126692
+ * method/form/program level the declarations nested in it are output, in source order, and
126693
+ * skipped inside the block. They then exist after the block even if the branch did not run,
126694
+ * and are initialized once, also when the block is a loop */
126695
+ traverseProcedureLevel(node) {
126696
+ const ret = new chunk_1.Chunk();
126697
+ for (const c of node.getChildren()) {
126698
+ if (c instanceof abaplint.Nodes.StructureNode && Traversal.isDeclaration(c) === false) {
126699
+ ret.appendChunk(this.declareNestedEarly(c));
126700
+ this.blockDepth++;
126701
+ try {
126702
+ ret.appendChunk(this.traverseStructure(c));
126703
+ }
126704
+ finally {
126705
+ this.blockDepth--;
126706
+ }
126707
+ }
126708
+ else {
126709
+ ret.appendChunk(this.traverse(c));
126710
+ }
126711
+ }
126712
+ return ret;
126713
+ }
126714
+ declareNestedEarly(block) {
126715
+ const found = [];
126716
+ Traversal.findNestedDeclarations(block, found);
126717
+ for (const node of found) {
126718
+ this.declaredEarly.add(node);
126719
+ if (node instanceof abaplint.Nodes.StructureNode) {
126720
+ for (const statement of node.findAllStatementNodes()) {
126721
+ this.declaredEarly.add(statement);
126722
+ }
126723
+ }
126724
+ }
126725
+ const ret = new chunk_1.Chunk();
126726
+ this.emittingEarly = true;
126727
+ try {
126728
+ for (const node of found) {
126729
+ ret.appendChunk(this.traverse(node));
126730
+ }
126731
+ }
126732
+ finally {
126733
+ this.emittingEarly = false;
126734
+ }
126735
+ return ret;
126736
+ }
126737
+ static isDeclaration(node) {
126738
+ const get = node.get();
126739
+ return get instanceof abaplint.Structures.Data
126740
+ || get instanceof abaplint.Structures.Constants
126741
+ || get instanceof abaplint.Structures.Types;
126742
+ }
126743
+ static findNestedDeclarations(node, found) {
126744
+ for (const c of node.getChildren()) {
126745
+ if (c instanceof abaplint.Nodes.StatementNode) {
126746
+ const get = c.get();
126747
+ if (get instanceof abaplint.Statements.Data
126748
+ || get instanceof abaplint.Statements.Constant
126749
+ || get instanceof abaplint.Statements.FieldSymbol) {
126750
+ found.push(c);
126751
+ }
126752
+ }
126753
+ else if (c instanceof abaplint.Nodes.StructureNode) {
126754
+ const get = c.get();
126755
+ if (get instanceof abaplint.Structures.Data || get instanceof abaplint.Structures.Constants) {
126756
+ found.push(c);
126757
+ }
126758
+ else {
126759
+ Traversal.findNestedDeclarations(c, found);
126760
+ }
126761
+ }
126762
+ }
126763
+ }
126558
126764
  traverseStructure(node) {
126765
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
126766
+ return new chunk_1.Chunk();
126767
+ }
126768
+ else if (this.blockDepth === 0 && node.get() instanceof abaplint.Structures.Normal) {
126769
+ return this.traverseProcedureLevel(node);
126770
+ }
126559
126771
  const list = StructureTranspilers;
126560
126772
  const ret = new chunk_1.Chunk();
126561
126773
  const search = node.get().constructor.name + "Transpiler";
@@ -126578,6 +126790,9 @@ this.INTERNAL_ID = abap.internalIdCounter++;\n`;
126578
126790
  return ret;
126579
126791
  }
126580
126792
  traverseStatement(node) {
126793
+ if (this.declaredEarly.has(node) && this.emittingEarly === false) {
126794
+ return new chunk_1.Chunk();
126795
+ }
126581
126796
  const list = StatementTranspilers;
126582
126797
  const search = node.get().constructor.name + "Transpiler";
126583
126798
  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.99",
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.68",
31
+ "@abaplint/transpiler": "^2.13.99",
32
32
  "@types/glob": "^9.0.0",
33
33
  "@types/node": "^26.6.2",
34
34
  "@types/progress": "^2.0.7",