@abaplint/transpiler-cli 2.13.37 → 2.13.39

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 +563 -289
  2. package/package.json +3 -3
package/build/bundle.js CHANGED
@@ -445,6 +445,37 @@ const ModeStr = 3;
445
445
  const ModeTemplate = 4;
446
446
  const ModeComment = 5;
447
447
  const ModePragma = 6;
448
+ // character codes, used for integer comparisons in the hot loop
449
+ const EOF = -1; // no character (start/end of file)
450
+ const CH_TAB = 9; // "\t"
451
+ const CH_NL = 10; // "\n"
452
+ const CH_SPACE = 32; // " "
453
+ const CH_DQUOTE = 34; // "\""
454
+ const CH_HASH = 35; // "#"
455
+ const CH_QUOTE = 39; // "'"
456
+ const CH_STAR = 42; // "*"
457
+ const CH_DASH = 45; // "-"
458
+ const CH_COMMA = 44; // ","
459
+ const CH_DOT = 46; // "."
460
+ const CH_COLON = 58; // ":"
461
+ const CH_EQUALS = 61; // "="
462
+ const CH_GT = 62; // ">"
463
+ const CH_AT = 64; // "@"
464
+ const CH_BACKSLASH = 92; // "\\"
465
+ const CH_BACKTICK = 96; // "`"
466
+ const CH_LBRACE = 123; // "{"
467
+ const CH_PIPE = 124; // "|"
468
+ const CH_RBRACE = 125; // "}"
469
+ // characters that terminate the current token
470
+ const SPLITS = new Set([
471
+ CH_SPACE, CH_COLON, CH_DOT, CH_COMMA, CH_DASH, 43 /* + */, 40 /* ( */,
472
+ 41 /* ) */, 91 /* [ */, 93 /* ] */, CH_BACKSLASH, CH_TAB, CH_NL
473
+ ]);
474
+ // single characters that are emitted as their own token
475
+ const BUFS = new Set([
476
+ CH_DOT, CH_COMMA, CH_COLON, 40 /* ( */, 41 /* ) */, 91 /* [ */,
477
+ 93 /* ] */, 43 /* + */, CH_AT
478
+ ]);
448
479
  class Lexer {
449
480
  run(file, virtual) {
450
481
  this.virtual = virtual;
@@ -459,15 +490,17 @@ class Lexer {
459
490
  const col = this.stream.getCol();
460
491
  const row = this.stream.getRow();
461
492
  let whiteBefore = false;
462
- if (this.stream.getOffset() - s.length >= 0) {
463
- const prev = this.stream.getRaw().substr(this.stream.getOffset() - s.length, 1);
464
- if (prev === " " || prev === "\n" || prev === "\t" || prev === ":") {
493
+ const beforeOffset = this.stream.getOffset() - s.length;
494
+ if (beforeOffset >= 0) {
495
+ const prev = this.stream.charCodeAt(beforeOffset);
496
+ if (prev === CH_SPACE || prev === CH_NL || prev === CH_TAB || prev === CH_COLON) {
465
497
  whiteBefore = true;
466
498
  }
467
499
  }
468
500
  let whiteAfter = false;
469
501
  const next = this.stream.nextChar();
470
- if (next === " " || next === "\n" || next === "\t" || next === ":" || next === "," || next === "." || next === "" || next === "\"") {
502
+ if (next === CH_SPACE || next === CH_NL || next === CH_TAB || next === CH_COLON
503
+ || next === CH_COMMA || next === CH_DOT || next === EOF || next === CH_DQUOTE) {
471
504
  whiteAfter = true;
472
505
  }
473
506
  let pos = new position_1.Position(row, col - s.length);
@@ -637,10 +670,10 @@ class Lexer {
637
670
  }
638
671
  }
639
672
  if (tok === undefined && this.m === ModeNormal && s.charAt(0) === "\\") {
640
- const adj = this.stream.nextChar() === "" ? 1 : 0;
673
+ const adj = this.stream.nextChar() === EOF ? 1 : 0;
641
674
  const prevOffset = this.stream.getOffset() - s.length - adj;
642
- const prevChar = prevOffset >= 0 ? this.stream.getRaw().substr(prevOffset, 1) : "";
643
- const whiteBeforeBackslash = prevChar === " " || prevChar === "\n" || prevChar === "\t" || prevChar === ":";
675
+ const prevChar = this.stream.charCodeAt(prevOffset);
676
+ const whiteBeforeBackslash = prevChar === CH_SPACE || prevChar === CH_NL || prevChar === CH_TAB || prevChar === CH_COLON;
644
677
  if (!whiteBeforeBackslash) {
645
678
  tok = new tokens_1.AssociationName(pos, s);
646
679
  }
@@ -653,100 +686,77 @@ class Lexer {
653
686
  this.buffer.clear();
654
687
  }
655
688
  process(raw) {
656
- this.stream = new lexer_stream_1.LexerStream(raw.replace(/\r/g, ""));
657
- this.buffer = new lexer_buffer_1.LexerBuffer();
658
- const splits = {};
659
- splits[" "] = true;
660
- splits[":"] = true;
661
- splits["."] = true;
662
- splits[","] = true;
663
- splits["-"] = true;
664
- splits["+"] = true;
665
- splits["("] = true;
666
- splits[")"] = true;
667
- splits["["] = true;
668
- splits["]"] = true;
669
- splits["\\"] = true;
670
- splits["\t"] = true;
671
- splits["\n"] = true;
672
- const bufs = {};
673
- bufs["."] = true;
674
- bufs[","] = true;
675
- bufs[":"] = true;
676
- bufs["("] = true;
677
- bufs[")"] = true;
678
- bufs["["] = true;
679
- bufs["]"] = true;
680
- bufs["+"] = true;
681
- bufs["@"] = true;
689
+ const stream = new lexer_stream_1.LexerStream(raw.replace(/\r/g, ""));
690
+ this.stream = stream;
691
+ this.buffer = new lexer_buffer_1.LexerBuffer(stream.getRaw());
682
692
  for (;;) {
683
- const current = this.stream.currentChar();
684
- const buf = this.buffer.add(current);
685
- const ahead = this.stream.nextChar();
686
- const aahead = this.stream.nextNextChar();
693
+ const current = stream.currentChar();
694
+ this.buffer.add(stream.getOffset());
695
+ const ahead = stream.nextChar();
696
+ const aahead = stream.nextNextChar();
687
697
  if (this.m === ModeNormal) {
688
- if (splits[ahead]) {
698
+ if (SPLITS.has(ahead)) {
689
699
  this.add();
690
700
  }
691
- else if (ahead === "'") {
701
+ else if (ahead === CH_QUOTE) {
692
702
  // start string
693
703
  this.add();
694
704
  this.m = ModeStr;
695
705
  }
696
- else if (ahead === "|" || ahead === "}") {
706
+ else if (ahead === CH_PIPE || ahead === CH_RBRACE) {
697
707
  // start template
698
708
  this.add();
699
709
  this.m = ModeTemplate;
700
710
  }
701
- else if (ahead === "`") {
711
+ else if (ahead === CH_BACKTICK) {
702
712
  // start ping
703
713
  this.add();
704
714
  this.m = ModePing;
705
715
  }
706
- else if (aahead === "##") {
716
+ else if (ahead === CH_HASH && aahead === CH_HASH) {
707
717
  // start pragma
708
718
  this.add();
709
719
  this.m = ModePragma;
710
720
  }
711
- else if (ahead === "\""
712
- || (ahead === "*" && current === "\n")) {
721
+ else if (ahead === CH_DQUOTE
722
+ || (ahead === CH_STAR && current === CH_NL)) {
713
723
  // start comment
714
724
  this.add();
715
725
  this.m = ModeComment;
716
726
  }
717
- else if (ahead === "@" && buf.trim().length === 0) {
727
+ else if (ahead === CH_AT && this.buffer.get().trim().length === 0) {
718
728
  this.add();
719
729
  }
720
- else if (aahead === "->"
721
- || aahead === "=>") {
730
+ else if ((ahead === CH_DASH || ahead === CH_EQUALS) && aahead === CH_GT) {
722
731
  this.add();
723
732
  }
724
- else if (current === ">"
725
- && ahead !== " "
726
- && (this.stream.prevChar() === "-" || this.stream.prevChar() === "=")) {
733
+ else if (current === CH_GT
734
+ && ahead !== CH_SPACE
735
+ && (stream.prevChar() === CH_DASH || stream.prevChar() === CH_EQUALS)) {
727
736
  // arrows
728
737
  this.add();
729
738
  }
730
- else if (buf.length === 1
731
- && (bufs[buf]
732
- || (buf === "-" && ahead !== ">"))) {
739
+ else if (this.buffer.length() === 1
740
+ && (BUFS.has(current)
741
+ || (current === CH_DASH && ahead !== CH_GT))) {
733
742
  this.add();
734
743
  }
735
744
  }
736
- else if (this.m === ModePragma && (ahead === "," || ahead === ":" || ahead === "." || ahead === " " || ahead === "\n")) {
745
+ else if (this.m === ModePragma && (ahead === CH_COMMA || ahead === CH_COLON
746
+ || ahead === CH_DOT || ahead === CH_SPACE || ahead === CH_NL)) {
737
747
  // end of pragma
738
748
  this.add();
739
749
  this.m = ModeNormal;
740
750
  }
741
751
  else if (this.m === ModePing
742
- && buf.length > 1
743
- && current === "`"
744
- && aahead !== "``"
745
- && ahead !== "`"
746
- && this.buffer.countIsEven("`")) {
752
+ && this.buffer.length() > 1
753
+ && current === CH_BACKTICK
754
+ && !(ahead === CH_BACKTICK && aahead === CH_BACKTICK)
755
+ && ahead !== CH_BACKTICK
756
+ && this.buffer.countIsEven(CH_BACKTICK)) {
747
757
  // end of ping
748
758
  this.add();
749
- if (ahead === `"`) {
759
+ if (ahead === CH_DQUOTE) {
750
760
  this.m = ModeComment;
751
761
  }
752
762
  else {
@@ -754,41 +764,41 @@ class Lexer {
754
764
  }
755
765
  }
756
766
  else if (this.m === ModeTemplate
757
- && buf.length > 1
758
- && (current === "|" || current === "{")
759
- && (this.stream.prevChar() !== "\\" || this.stream.prevPrevChar() === "\\\\")) {
767
+ && this.buffer.length() > 1
768
+ && (current === CH_PIPE || current === CH_LBRACE)
769
+ && (stream.prevChar() !== CH_BACKSLASH || (stream.prevPrevChar() === CH_BACKSLASH && stream.prevChar() === CH_BACKSLASH))) {
760
770
  // end of template
761
771
  this.add();
762
772
  this.m = ModeNormal;
763
773
  }
764
774
  else if (this.m === ModeTemplate
765
- && ahead === "}"
766
- && current !== "\\") {
775
+ && ahead === CH_RBRACE
776
+ && current !== CH_BACKSLASH) {
767
777
  this.add();
768
778
  }
769
779
  else if (this.m === ModeStr
770
- && current === "'"
771
- && buf.length > 1
772
- && aahead !== "''"
773
- && ahead !== "'"
774
- && this.buffer.countIsEven("'")) {
780
+ && current === CH_QUOTE
781
+ && this.buffer.length() > 1
782
+ && !(ahead === CH_QUOTE && aahead === CH_QUOTE)
783
+ && ahead !== CH_QUOTE
784
+ && this.buffer.countIsEven(CH_QUOTE)) {
775
785
  // end of string
776
786
  this.add();
777
- if (ahead === "\"") {
787
+ if (ahead === CH_DQUOTE) {
778
788
  this.m = ModeComment;
779
789
  }
780
790
  else {
781
791
  this.m = ModeNormal;
782
792
  }
783
793
  }
784
- else if (ahead === "\n" && this.m !== ModeTemplate) {
794
+ else if (ahead === CH_NL && this.m !== ModeTemplate) {
785
795
  this.add();
786
796
  this.m = ModeNormal;
787
797
  }
788
- else if (this.m === ModeTemplate && current === "\n") {
798
+ else if (this.m === ModeTemplate && current === CH_NL) {
789
799
  this.add();
790
800
  }
791
- if (!this.stream.advance()) {
801
+ if (!stream.advance()) {
792
802
  break;
793
803
  }
794
804
  }
@@ -810,24 +820,38 @@ exports.Lexer = Lexer;
810
820
 
811
821
  Object.defineProperty(exports, "__esModule", ({ value: true }));
812
822
  exports.LexerBuffer = void 0;
823
+ // The buffer holds a reference to the raw input and tracks the [start, end)
824
+ // offset range of the current token, so the token string can be sliced out with
825
+ // a single substring() instead of being concatenated one character at a time.
813
826
  class LexerBuffer {
814
- constructor() {
815
- this.buf = "";
827
+ constructor(raw) {
828
+ this.raw = raw;
829
+ this.start = 0;
830
+ this.end = 0;
831
+ this.empty = true;
816
832
  }
817
- add(s) {
818
- this.buf = this.buf + s;
819
- return this.buf;
833
+ add(offset) {
834
+ if (this.empty === true) {
835
+ this.start = offset < 0 ? 0 : offset;
836
+ this.empty = false;
837
+ }
838
+ this.end = offset + 1;
820
839
  }
821
840
  get() {
822
- return this.buf;
841
+ return this.raw.substring(this.start, this.end);
842
+ }
843
+ length() {
844
+ return this.end - this.start;
823
845
  }
824
846
  clear() {
825
- this.buf = "";
847
+ this.start = 0;
848
+ this.end = 0;
849
+ this.empty = true;
826
850
  }
827
851
  countIsEven(char) {
828
852
  let count = 0;
829
- for (let i = 0; i < this.buf.length; i += 1) {
830
- if (this.buf.charAt(i) === char) {
853
+ for (let i = this.start; i < this.end; i += 1) {
854
+ if (this.raw.charCodeAt(i) === char) {
831
855
  count += 1;
832
856
  }
833
857
  }
@@ -849,6 +873,8 @@ exports.LexerBuffer = LexerBuffer;
849
873
 
850
874
  Object.defineProperty(exports, "__esModule", ({ value: true }));
851
875
  exports.LexerStream = void 0;
876
+ const NL = 10; // "\n"
877
+ const EOF = -1; // no character (start/end of file)
852
878
  class LexerStream {
853
879
  constructor(raw) {
854
880
  this.offset = -1;
@@ -857,7 +883,7 @@ class LexerStream {
857
883
  this.col = 0;
858
884
  }
859
885
  advance() {
860
- if (this.currentChar() === "\n") {
886
+ if (this.currentChar() === NL) {
861
887
  this.col = 1;
862
888
  this.row = this.row + 1;
863
889
  }
@@ -875,38 +901,51 @@ class LexerStream {
875
901
  getRow() {
876
902
  return this.row;
877
903
  }
904
+ // the *Char() accessors return character codes (charCodeAt) rather than
905
+ // single character strings, to avoid allocating a string per input character
906
+ // in the lexer hot loop. EOF (-1) is returned when the offset is out of range.
878
907
  prevChar() {
879
- if (this.offset - 1 < 0) {
880
- return "";
908
+ const o = this.offset - 1;
909
+ if (o < 0) {
910
+ return EOF;
881
911
  }
882
- return this.raw.substr(this.offset - 1, 1);
912
+ return this.raw.charCodeAt(o);
883
913
  }
884
914
  prevPrevChar() {
885
- if (this.offset - 2 < 0) {
886
- return "";
915
+ const o = this.offset - 2;
916
+ if (o < 0) {
917
+ return EOF;
887
918
  }
888
- return this.raw.substr(this.offset - 2, 2);
919
+ return this.raw.charCodeAt(o);
889
920
  }
890
921
  currentChar() {
891
922
  if (this.offset < 0) {
892
- return "\n"; // simulate newline at start of file to handle star(*) comments
923
+ return NL; // simulate newline at start of file to handle star(*) comments
893
924
  }
894
925
  else if (this.offset >= this.raw.length) {
895
- return "";
926
+ return EOF;
896
927
  }
897
- return this.raw.substr(this.offset, 1);
928
+ return this.raw.charCodeAt(this.offset);
898
929
  }
899
930
  nextChar() {
900
- if (this.offset + 2 > this.raw.length) {
901
- return "";
931
+ const o = this.offset + 1;
932
+ if (o >= this.raw.length) {
933
+ return EOF;
902
934
  }
903
- return this.raw.substr(this.offset + 1, 1);
935
+ return this.raw.charCodeAt(o);
904
936
  }
905
937
  nextNextChar() {
906
- if (this.offset + 3 > this.raw.length) {
907
- return this.nextChar();
938
+ const o = this.offset + 2;
939
+ if (o >= this.raw.length) {
940
+ return EOF;
941
+ }
942
+ return this.raw.charCodeAt(o);
943
+ }
944
+ charCodeAt(o) {
945
+ if (o < 0 || o >= this.raw.length) {
946
+ return EOF;
908
947
  }
909
- return this.raw.substr(this.offset + 1, 2);
948
+ return this.raw.charCodeAt(o);
910
949
  }
911
950
  getRaw() {
912
951
  return this.raw;
@@ -2234,6 +2273,7 @@ exports.verNotLang = verNotLang;
2234
2273
  exports.failCombinator = failCombinator;
2235
2274
  exports.failStar = failStar;
2236
2275
  exports.stopBefore = stopBefore;
2276
+ exports.stopBefore1 = stopBefore1;
2237
2277
  const Tokens = __importStar(__webpack_require__(/*! ../1_lexer/tokens */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/index.js"));
2238
2278
  const nodes_1 = __webpack_require__(/*! ../nodes */ "./node_modules/@abaplint/core/build/src/abap/nodes/index.js");
2239
2279
  const version_1 = __webpack_require__(/*! ../../version */ "./node_modules/@abaplint/core/build/src/version.js");
@@ -2303,8 +2343,9 @@ class Word {
2303
2343
  }
2304
2344
  }
2305
2345
  class Token {
2306
- constructor(s) {
2307
- this.name = s;
2346
+ constructor(t) {
2347
+ this.tokenType = t;
2348
+ this.name = t.name;
2308
2349
  }
2309
2350
  listKeywords() {
2310
2351
  return [];
@@ -2316,7 +2357,7 @@ class Token {
2316
2357
  const result = [];
2317
2358
  for (const input of r) {
2318
2359
  if (input.remainingLength() !== 0
2319
- && input.peek().constructor.name === this.name) {
2360
+ && input.peek().constructor === this.tokenType) {
2320
2361
  result.push(input.shift(new nodes_1.TokenNode(input.peek())));
2321
2362
  }
2322
2363
  }
@@ -2512,7 +2553,12 @@ class Optional {
2512
2553
  for (const input of r) {
2513
2554
  result.push(input);
2514
2555
  const res = this.optional.run([input]);
2515
- result.push(...res);
2556
+ if (res.length === 1) {
2557
+ result.push(res[0]);
2558
+ }
2559
+ else {
2560
+ result.push(...res);
2561
+ }
2516
2562
  }
2517
2563
  return result;
2518
2564
  }
@@ -2551,6 +2597,9 @@ class Star {
2551
2597
  // avoid stack overflow
2552
2598
  result = result.concat(res);
2553
2599
  }
2600
+ else if (res.length === 1) {
2601
+ result.push(res[0]);
2602
+ }
2554
2603
  else {
2555
2604
  result.push(...res);
2556
2605
  }
@@ -2702,6 +2751,9 @@ class Sequence {
2702
2751
  // avoid stack overflow
2703
2752
  result = result.concat(temp);
2704
2753
  }
2754
+ else if (temp.length === 1) {
2755
+ result.push(temp[0]);
2756
+ }
2705
2757
  else {
2706
2758
  result.push(...temp);
2707
2759
  }
@@ -2767,24 +2819,14 @@ class Expression {
2767
2819
  for (const input of r) {
2768
2820
  const temp = this.runnable.run([input]);
2769
2821
  for (const t of temp) {
2770
- let consumed = input.remainingLength() - t.remainingLength();
2822
+ const consumed = input.remainingLength() - t.remainingLength();
2771
2823
  if (consumed > 0) {
2772
- const originalLength = t.getNodes().length;
2773
- const children = [];
2774
- while (consumed > 0) {
2775
- const sub = t.popNode();
2776
- if (sub) {
2777
- children.push(sub);
2778
- consumed = consumed - sub.countTokens();
2779
- }
2780
- }
2781
2824
  const re = new nodes_1.ExpressionNode(this);
2782
- re.setChildren(children.reverse());
2783
- const n = t.getNodes().slice(0, originalLength - consumed);
2784
- n.push(re);
2785
- t.setNodes(n);
2825
+ results.push(t.wrapConsumed(consumed, re));
2826
+ }
2827
+ else {
2828
+ results.push(t);
2786
2829
  }
2787
- results.push(t);
2788
2830
  }
2789
2831
  }
2790
2832
  // console.dir(results);
@@ -2926,7 +2968,12 @@ class Alternative {
2926
2968
  const result = [];
2927
2969
  for (const sequ of this.list) {
2928
2970
  const temp = sequ.run(r);
2929
- result.push(...temp);
2971
+ if (temp.length === 1) {
2972
+ result.push(temp[0]);
2973
+ }
2974
+ else {
2975
+ result.push(...temp);
2976
+ }
2930
2977
  }
2931
2978
  return result;
2932
2979
  }
@@ -2984,7 +3031,12 @@ class AlternativePriority {
2984
3031
  // console.log(seq.toStr());
2985
3032
  const temp = sequ.run(r);
2986
3033
  if (temp.length > 0) {
2987
- result.push(...temp);
3034
+ if (temp.length === 1) {
3035
+ result.push(temp[0]);
3036
+ }
3037
+ else {
3038
+ result.push(...temp);
3039
+ }
2988
3040
  break;
2989
3041
  }
2990
3042
  }
@@ -3100,7 +3152,7 @@ function regex(r) {
3100
3152
  return new Regex(r);
3101
3153
  }
3102
3154
  function tok(t) {
3103
- return new Token(t.name);
3155
+ return new Token(t);
3104
3156
  }
3105
3157
  const expressionSingletons = {};
3106
3158
  const stringSingletons = {};
@@ -3214,6 +3266,29 @@ class StopBefore2 {
3214
3266
  function stopBefore(t1, t2) {
3215
3267
  return new StopBefore2(t1, t2);
3216
3268
  }
3269
+ class StopBefore1 {
3270
+ constructor(words) { this.words = words.map(w => w.toUpperCase()); }
3271
+ listKeywords() { return []; }
3272
+ getUsing() { return []; }
3273
+ run(r) {
3274
+ var _a;
3275
+ const result = [];
3276
+ for (const input of r) {
3277
+ const next = (_a = input.peek()) === null || _a === void 0 ? void 0 : _a.getUpperStr();
3278
+ if (next !== undefined && this.words.includes(next)) {
3279
+ continue;
3280
+ }
3281
+ result.push(input);
3282
+ }
3283
+ return result;
3284
+ }
3285
+ railroad() { return "Railroad.Terminal('stopBefore(" + this.words.join("|") + ")')"; }
3286
+ toStr() { return "stopBefore(" + this.words.join(",") + ")"; }
3287
+ first() { return [""]; }
3288
+ }
3289
+ function stopBefore1(...words) {
3290
+ return new StopBefore1(words);
3291
+ }
3217
3292
  //# sourceMappingURL=combi.js.map
3218
3293
 
3219
3294
  /***/ },
@@ -4243,8 +4318,8 @@ const combi_1 = __webpack_require__(/*! ../combi */ "./node_modules/@abaplint/co
4243
4318
  const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
4244
4319
  class ComponentChainSimple extends combi_1.Expression {
4245
4320
  getRunnable() {
4246
- const chain = (0, combi_1.seq)(_1.ComponentName, (0, combi_1.starPrio)((0, combi_1.seq)(_1.ArrowOrDash, _1.ComponentName)));
4247
- const ret = (0, combi_1.seq)(chain, (0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength));
4321
+ const chain = (0, combi_1.starPrio)((0, combi_1.altPrio)(_1.Dereference, (0, combi_1.seq)(_1.ArrowOrDash, _1.ComponentName)));
4322
+ const ret = (0, combi_1.seq)(_1.ComponentName, chain, (0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength));
4248
4323
  return ret;
4249
4324
  }
4250
4325
  }
@@ -7186,7 +7261,7 @@ const combi_1 = __webpack_require__(/*! ../combi */ "./node_modules/@abaplint/co
7186
7261
  const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
7187
7262
  class ParameterListS extends combi_1.Expression {
7188
7263
  getRunnable() {
7189
- return (0, combi_1.plus)(_1.ParameterS);
7264
+ return (0, combi_1.plusPrio)(_1.ParameterS);
7190
7265
  }
7191
7266
  }
7192
7267
  exports.ParameterListS = ParameterListS;
@@ -11277,10 +11352,10 @@ class TypeTableKey extends combi_1.Expression {
11277
11352
  const uniqueness = (0, combi_1.alt)("NON-UNIQUE", "UNIQUE");
11278
11353
  const defaultKey = "DEFAULT KEY";
11279
11354
  const emptyKey = (0, combi_1.ver)(version_1.Release.v740sp02, "EMPTY KEY", { also: combi_1.AlsoIn.OpenABAP });
11280
- const components = (0, combi_1.plus)((0, combi_1.alt)((0, combi_1.seq)("WITH", (0, combi_1.failStar)()), _1.FieldSub));
11355
+ const components = (0, combi_1.plusPrio)((0, combi_1.seq)((0, combi_1.stopBefore1)("WITH", "INITIAL", "WITHOUT"), (0, combi_1.stopBefore)("READ", "-"), _1.FieldSub));
11281
11356
  const further = (0, combi_1.seq)((0, combi_1.alt)("WITHOUT", "WITH"), "FURTHER SECONDARY KEYS");
11282
11357
  const alias = (0, combi_1.seq)("ALIAS", _1.Field);
11283
- const key = (0, combi_1.seq)("WITH", (0, combi_1.opt)(uniqueness), (0, combi_1.altPrio)(defaultKey, emptyKey, (0, combi_1.seq)((0, combi_1.opt)((0, combi_1.alt)("SORTED", "HASHED")), "KEY", (0, combi_1.alt)((0, combi_1.seq)(_1.Field, (0, combi_1.opt)(alias), "COMPONENTS", components), components))), (0, combi_1.optPrio)(further), (0, combi_1.optPrio)("READ-ONLY"));
11358
+ const key = (0, combi_1.seq)("WITH", (0, combi_1.optPrio)(uniqueness), (0, combi_1.altPrio)(defaultKey, emptyKey, (0, combi_1.seq)((0, combi_1.opt)((0, combi_1.alt)("SORTED", "HASHED")), "KEY", (0, combi_1.altPrio)((0, combi_1.seq)(_1.Field, (0, combi_1.opt)(alias), "COMPONENTS", components), components))), (0, combi_1.optPrio)(further), (0, combi_1.optPrio)("READ-ONLY"));
11284
11359
  return key;
11285
11360
  }
11286
11361
  }
@@ -11349,7 +11424,7 @@ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src
11349
11424
  const version_1 = __webpack_require__(/*! ../../../version */ "./node_modules/@abaplint/core/build/src/version.js");
11350
11425
  class ValueBody extends combi_1.Expression {
11351
11426
  getRunnable() {
11352
- const strucOrTab = (0, combi_1.seq)((0, combi_1.optPrio)(_1.Let), (0, combi_1.optPrio)(_1.ValueBase), (0, combi_1.star)(_1.For), (0, combi_1.plusPrio)((0, combi_1.altPrio)(_1.FieldAssignment, _1.ValueBodyLine)));
11427
+ const strucOrTab = (0, combi_1.seq)((0, combi_1.optPrio)(_1.Let), (0, combi_1.optPrio)(_1.ValueBase), (0, combi_1.starPrio)(_1.For), (0, combi_1.plusPrio)((0, combi_1.altPrio)(_1.FieldAssignment, _1.ValueBodyLine)));
11353
11428
  const tabdef = (0, combi_1.ver)(version_1.Release.v740sp08, (0, combi_1.altPrio)("OPTIONAL", (0, combi_1.seq)("DEFAULT", _1.Source)), { also: combi_1.AlsoIn.OpenABAP });
11354
11429
  return (0, combi_1.optPrio)((0, combi_1.altPrio)(strucOrTab, (0, combi_1.seq)(_1.Source, (0, combi_1.optPrio)(tabdef))));
11355
11430
  }
@@ -11478,11 +11553,17 @@ class Result {
11478
11553
  // nodes: matched tokens
11479
11554
  this.tokens = tokens;
11480
11555
  this.tokenIndex = tokenIndex;
11481
- this.nodes = nodes;
11482
- if (this.nodes === undefined) {
11483
- this.nodes = [];
11556
+ this.nodeCount = 0;
11557
+ if (nodes !== undefined) {
11558
+ this.setNodes(nodes);
11484
11559
  }
11485
11560
  }
11561
+ static fromChain(tokens, tokenIndex, nodes, nodeCount) {
11562
+ const ret = new Result(tokens, tokenIndex);
11563
+ ret.nodes = nodes;
11564
+ ret.nodeCount = nodeCount;
11565
+ return ret;
11566
+ }
11486
11567
  peek() {
11487
11568
  return this.tokens[this.tokenIndex];
11488
11569
  }
@@ -11490,18 +11571,54 @@ class Result {
11490
11571
  return this.tokens[this.tokenIndex + offset];
11491
11572
  }
11492
11573
  shift(node) {
11493
- const cp = this.nodes.slice();
11494
- cp.push(node);
11495
- return new Result(this.tokens, this.tokenIndex + 1, cp);
11574
+ return Result.fromChain(this.tokens, this.tokenIndex + 1, { node, previous: this.nodes }, this.nodeCount + 1);
11575
+ }
11576
+ wrapConsumed(consumedTokens, node) {
11577
+ let current = this.nodes;
11578
+ let currentCount = this.nodeCount;
11579
+ const children = [];
11580
+ while (consumedTokens > 0) {
11581
+ if (current === undefined) {
11582
+ break;
11583
+ }
11584
+ children.push(current.node);
11585
+ consumedTokens = consumedTokens - current.node.countTokens();
11586
+ current = current.previous;
11587
+ currentCount--;
11588
+ }
11589
+ node.setChildren(children.reverse());
11590
+ this.nodes = { node, previous: current };
11591
+ this.nodeCount = currentCount + 1;
11592
+ return this;
11496
11593
  }
11497
11594
  popNode() {
11498
- return this.nodes.pop();
11595
+ if (this.nodes === undefined) {
11596
+ return undefined;
11597
+ }
11598
+ const ret = this.nodes.node;
11599
+ this.nodes = this.nodes.previous;
11600
+ this.nodeCount--;
11601
+ return ret;
11499
11602
  }
11500
11603
  getNodes() {
11501
- return this.nodes;
11604
+ const ret = new Array(this.nodeCount);
11605
+ let current = this.nodes;
11606
+ for (let index = this.nodeCount - 1; index >= 0; index--) {
11607
+ if (current === undefined) {
11608
+ break;
11609
+ }
11610
+ ret[index] = current.node;
11611
+ current = current.previous;
11612
+ }
11613
+ return ret;
11502
11614
  }
11503
11615
  setNodes(n) {
11504
- this.nodes = n;
11616
+ this.nodes = undefined;
11617
+ this.nodeCount = 0;
11618
+ for (const node of n) {
11619
+ this.nodes = { node, previous: this.nodes };
11620
+ this.nodeCount++;
11621
+ }
11505
11622
  }
11506
11623
  getTokens() {
11507
11624
  return this.tokens;
@@ -11573,6 +11690,7 @@ const expand_macros_1 = __webpack_require__(/*! ./expand_macros */ "./node_modul
11573
11690
  const tokens_1 = __webpack_require__(/*! ../1_lexer/tokens */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/index.js");
11574
11691
  const _select_reclassify_1 = __webpack_require__(/*! ./_select_reclassify */ "./node_modules/@abaplint/core/build/src/abap/2_statements/_select_reclassify.js");
11575
11692
  exports.STATEMENT_MAX_TOKENS = 20000;
11693
+ const EMPTY_PRAGMAS = Object.freeze([]);
11576
11694
  class StatementMap {
11577
11695
  constructor() {
11578
11696
  this.map = {};
@@ -11765,15 +11883,27 @@ class StatementParser {
11765
11883
  statement = input;
11766
11884
  }
11767
11885
  else if (length === 1 && lastToken instanceof tokens_1.Pragma) {
11768
- statement = new nodes_1.StatementNode(new _statement_1.Empty(), undefined, [lastToken]);
11886
+ // special case, everything crashes if StatementNodes doesnt have children
11887
+ statement = new nodes_1.StatementNode(new _statement_1.Empty(), undefined, [lastToken])
11888
+ .setChildren(this.tokensToNodes([lastToken]));
11769
11889
  }
11770
11890
  }
11771
11891
  return statement;
11772
11892
  }
11773
11893
  removePragma(tokens) {
11894
+ let hasPragma = false;
11895
+ // skip the last token as it is the punctuation
11896
+ for (let i = 0; i < tokens.length - 1; i++) {
11897
+ if (tokens[i] instanceof Tokens.Pragma) {
11898
+ hasPragma = true;
11899
+ break;
11900
+ }
11901
+ }
11902
+ if (hasPragma === false) {
11903
+ return { tokens: tokens.slice(0, tokens.length - 1), pragmas: EMPTY_PRAGMAS };
11904
+ }
11774
11905
  const result = [];
11775
11906
  const pragmas = [];
11776
- // skip the last token as it is the punctuation
11777
11907
  for (let i = 0; i < tokens.length - 1; i++) {
11778
11908
  const t = tokens[i];
11779
11909
  if (t instanceof Tokens.Pragma) {
@@ -20144,7 +20274,7 @@ class TypeMesh {
20144
20274
  const on = (0, combi_1.seq)("ON", expressions_1.NamespaceSimpleName, "=", expressions_1.NamespaceSimpleName, (0, combi_1.star)((0, combi_1.seq)("AND", expressions_1.NamespaceSimpleName, "=", expressions_1.NamespaceSimpleName)));
20145
20275
  const using = (0, combi_1.seq)("USING KEY", expressions_1.NamespaceSimpleName);
20146
20276
  const association = (0, combi_1.seq)("ASSOCIATION", expressions_1.NamespaceSimpleName, "TO", expressions_1.NamespaceSimpleName, (0, combi_1.plus)(on));
20147
- const ret = (0, combi_1.ver)(version_1.Release.v751, (0, combi_1.seq)("TYPES", expressions_1.NamespaceSimpleName, "TYPE", (0, combi_1.opt)("REF TO"), expressions_1.TypeName, (0, combi_1.plus)(association), (0, combi_1.opt)(using)));
20277
+ const ret = (0, combi_1.ver)(version_1.Release.v740sp05, (0, combi_1.seq)("TYPES", expressions_1.NamespaceSimpleName, "TYPE", (0, combi_1.opt)("REF TO"), expressions_1.TypeName, (0, combi_1.plus)(association), (0, combi_1.opt)(using)));
20148
20278
  return ret;
20149
20279
  }
20150
20280
  }
@@ -25147,16 +25277,20 @@ class BuiltIn {
25147
25277
  return def.predicate;
25148
25278
  }
25149
25279
  getTypes() {
25150
- const ret = this.buildSY();
25151
- {
25152
- const id = new tokens_1.Identifier(new position_1.Position(1, 1), "abap_bool");
25153
- ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, new basic_1.CharacterType(1, { qualifiedName: "ABAP_BOOL", ddicName: "ABAP_BOOL" })));
25154
- }
25155
- {
25156
- const id = new tokens_1.Identifier(new position_1.Position(1, 1), "cursor");
25157
- ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.IntegerType.get({ qualifiedName: "CURSOR", ddicName: "CURSOR" })));
25280
+ // the identifiers are identical for every object, share them to reduce memory usage
25281
+ if (BuiltIn.typesCache === undefined) {
25282
+ const ret = this.buildSY();
25283
+ {
25284
+ const id = new tokens_1.Identifier(new position_1.Position(1, 1), "abap_bool");
25285
+ ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, new basic_1.CharacterType(1, { qualifiedName: "ABAP_BOOL", ddicName: "ABAP_BOOL" })));
25286
+ }
25287
+ {
25288
+ const id = new tokens_1.Identifier(new position_1.Position(1, 1), "cursor");
25289
+ ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.IntegerType.get({ qualifiedName: "CURSOR", ddicName: "CURSOR" })));
25290
+ }
25291
+ BuiltIn.typesCache = ret;
25158
25292
  }
25159
- return ret;
25293
+ return BuiltIn.typesCache;
25160
25294
  }
25161
25295
  get(extras) {
25162
25296
  const ret = [];
@@ -25189,10 +25323,17 @@ class BuiltIn {
25189
25323
  BuiltIn.getCache.push(this.buildConstant("space", new basic_1.CharacterType(1, { derivedFromConstant: true }), "' '"));
25190
25324
  }
25191
25325
  ret.push(...BuiltIn.getCache);
25192
- for (const e of extras) {
25193
- const id = new tokens_1.Identifier(new position_1.Position(this.row++, 1), e);
25194
- ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.VoidType.get(e), ["read_only" /* IdentifierMeta.ReadOnly */, "built-in" /* IdentifierMeta.BuiltIn */], "'?'"));
25326
+ // the extras are identical for every object, share them to reduce memory usage
25327
+ const key = extras.join("|");
25328
+ if (key !== BuiltIn.extrasCacheKey) {
25329
+ BuiltIn.extrasCacheKey = key;
25330
+ BuiltIn.extrasCache = [];
25331
+ for (const e of extras) {
25332
+ const id = new tokens_1.Identifier(new position_1.Position(this.row++, 1), e);
25333
+ BuiltIn.extrasCache.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.VoidType.get(e), ["read_only" /* IdentifierMeta.ReadOnly */, "built-in" /* IdentifierMeta.BuiltIn */], "'?'"));
25334
+ }
25195
25335
  }
25336
+ ret.push(...BuiltIn.extrasCache);
25196
25337
  return ret;
25197
25338
  }
25198
25339
  /////////////////////////////
@@ -25401,6 +25542,9 @@ exports.BuiltIn = BuiltIn;
25401
25542
  BuiltIn.filename = "_builtin.prog.abap";
25402
25543
  BuiltIn.counter = 1;
25403
25544
  BuiltIn.getCache = [];
25545
+ BuiltIn.typesCache = undefined;
25546
+ BuiltIn.extrasCacheKey = undefined;
25547
+ BuiltIn.extrasCache = [];
25404
25548
  // todo: "pcre" vs "regex", only one of these parameters are allowed
25405
25549
  // todo: "pcre", only possible from 755
25406
25550
  BuiltIn.methods = {
@@ -26532,7 +26676,7 @@ class CurrentScope {
26532
26676
  }
26533
26677
  findTypePoolConstant(name) {
26534
26678
  var _a;
26535
- if (name === undefined || name.includes("_") === undefined) {
26679
+ if (name === undefined || name.includes("_") === false) {
26536
26680
  return undefined;
26537
26681
  }
26538
26682
  const typePoolName = name.split("_")[0];
@@ -26554,7 +26698,7 @@ class CurrentScope {
26554
26698
  }
26555
26699
  findTypePoolType(name) {
26556
26700
  var _a;
26557
- if (name.includes("_") === undefined) {
26701
+ if (name.includes("_") === false) {
26558
26702
  return undefined;
26559
26703
  }
26560
26704
  const typePoolName = name.split("_")[0];
@@ -26868,11 +27012,9 @@ class ObjectOriented {
26868
27012
  findMethodInInterface(interfaceName, methodName) {
26869
27013
  const idef = this.scope.findInterfaceDefinition(interfaceName);
26870
27014
  if (idef) {
26871
- const methods = idef.getMethodDefinitions().getAll();
26872
- for (const method of methods) {
26873
- if (method.getName().toUpperCase() === methodName.toUpperCase()) {
26874
- return { method, def: idef };
26875
- }
27015
+ const method = idef.getMethodDefinitions().getByName(methodName);
27016
+ if (method) {
27017
+ return { method, def: idef };
26876
27018
  }
26877
27019
  return this.findMethodViaAlias(methodName, idef);
26878
27020
  }
@@ -27094,17 +27236,14 @@ class ObjectOriented {
27094
27236
  if (defs === undefined) {
27095
27237
  return undefined;
27096
27238
  }
27097
- for (const method of defs.getAll()) {
27098
- if (method.getName().toUpperCase() === methodName.toUpperCase()) {
27099
- if (method.isRedefinition()) {
27100
- return this.findMethodInSuper(def, methodName);
27101
- }
27102
- else {
27103
- return method;
27104
- }
27105
- }
27239
+ const method = defs.getByName(methodName);
27240
+ if (method === undefined) {
27241
+ return undefined;
27106
27242
  }
27107
- return undefined;
27243
+ if (method.isRedefinition()) {
27244
+ return this.findMethodInSuper(def, methodName);
27245
+ }
27246
+ return method;
27108
27247
  }
27109
27248
  findMethodInSuper(child, methodName) {
27110
27249
  let sup = child.getSuperClass();
@@ -29690,6 +29829,15 @@ class ComponentChain {
29690
29829
  if (i === 0 && child.concatTokens().toUpperCase() === "TABLE_LINE") {
29691
29830
  continue;
29692
29831
  }
29832
+ else if (child.get() instanceof Expressions.Dereference) {
29833
+ if (!(context instanceof basic_1.DataReference)) {
29834
+ const message = "Not a data reference, cannot be dereferenced";
29835
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, child.getFirstToken(), message));
29836
+ return void_type_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
29837
+ }
29838
+ context = context.getType();
29839
+ continue;
29840
+ }
29693
29841
  else if (child.get() instanceof Expressions.ArrowOrDash) {
29694
29842
  const concat = child.concatTokens();
29695
29843
  if (concat === "-") {
@@ -34465,6 +34613,9 @@ class Source {
34465
34613
  if (context instanceof basic_1.FloatType && found instanceof basic_1.IntegerType) {
34466
34614
  return context;
34467
34615
  }
34616
+ else if (context instanceof basic_1.IntegerType && found instanceof basic_1.HexType) {
34617
+ return context;
34618
+ }
34468
34619
  else if ((context instanceof basic_1.IntegerType || context instanceof basic_1.FloatType) && (found === null || found === void 0 ? void 0 : found.isGeneric())) {
34469
34620
  return context;
34470
34621
  }
@@ -39259,18 +39410,25 @@ class DeleteInternal {
39259
39410
  let targetType = undefined;
39260
39411
  const target = node.findDirectExpression(Expressions.Target);
39261
39412
  if (target) {
39413
+ const targetName = target.concatTokens();
39262
39414
  let tabl = undefined;
39263
- const localVariable = input.scope.findVariable(target.concatTokens());
39415
+ const localVariable = input.scope.findVariable(targetName);
39264
39416
  if (localVariable === undefined && node.getChildren().length === 5 && node.getChildren()[2].concatTokens().toUpperCase() === "FROM") {
39265
39417
  // it might be a database table
39266
- const found = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(target.concatTokens());
39418
+ const found = (_a = input.scope.getDDIC()) === null || _a === void 0 ? void 0 : _a.lookupTableOrView(targetName);
39267
39419
  if ((found === null || found === void 0 ? void 0 : found.object) !== undefined) {
39268
39420
  tabl = found;
39269
39421
  input.scope.getDDICReferences().addUsing(input.scope.getParentObj(), { object: tabl.object });
39270
39422
  }
39271
39423
  }
39272
39424
  if (tabl === undefined) {
39273
- targetType = target_1.Target.runSyntax(target, input);
39425
+ const ambigiousVoids = input.scope.getRegistry().getConfig().getSyntaxSetttings().ambigiousVoids || [];
39426
+ if (ambigiousVoids.some(name => name.toUpperCase() === targetName.toUpperCase())) {
39427
+ targetType = basic_1.VoidType.get(targetName);
39428
+ }
39429
+ else {
39430
+ targetType = target_1.Target.runSyntax(target, input);
39431
+ }
39274
39432
  if (node.findDirectTokenByText("TABLE") === undefined
39275
39433
  && node.findDirectTokenByText("ADJACENT") === undefined
39276
39434
  && (node.findDirectTokenByText("FROM") || node.findDirectTokenByText("INDEX"))
@@ -48257,15 +48415,21 @@ exports.CrossIncludeMacros = CrossIncludeMacros;
48257
48415
 
48258
48416
  Object.defineProperty(exports, "__esModule", ({ value: true }));
48259
48417
  exports.AbstractNode = void 0;
48418
+ // shared constant, so nodes without children don't waste memory on empty arrays
48419
+ const EMPTY = Object.freeze([]);
48260
48420
  class AbstractNode {
48261
48421
  constructor() {
48262
- this.children = [];
48422
+ this.children = EMPTY;
48263
48423
  }
48264
48424
  addChild(n) {
48425
+ if (this.children === EMPTY) {
48426
+ this.children = [];
48427
+ }
48265
48428
  this.children.push(n);
48266
48429
  }
48267
48430
  setChildren(children) {
48268
- this.children = children;
48431
+ // copy, input arrays are built via push() and carry over-allocated backing stores
48432
+ this.children = children.slice();
48269
48433
  }
48270
48434
  getChildren() {
48271
48435
  return this.children;
@@ -48298,6 +48462,7 @@ const _abstract_node_1 = __webpack_require__(/*! ./_abstract_node */ "./node_mod
48298
48462
  class ExpressionNode extends _abstract_node_1.AbstractNode {
48299
48463
  constructor(expression) {
48300
48464
  super();
48465
+ this.tokenCount = 0;
48301
48466
  this.expression = expression;
48302
48467
  }
48303
48468
  addChild(_n) {
@@ -48306,12 +48471,15 @@ class ExpressionNode extends _abstract_node_1.AbstractNode {
48306
48471
  get() {
48307
48472
  return this.expression;
48308
48473
  }
48309
- countTokens() {
48310
- let ret = 0;
48311
- for (const c of this.getChildren()) {
48312
- ret = ret + c.countTokens();
48474
+ setChildren(children) {
48475
+ super.setChildren(children);
48476
+ for (const child of this.getChildren()) {
48477
+ this.tokenCount = this.tokenCount + child.countTokens();
48313
48478
  }
48314
- return ret;
48479
+ return this;
48480
+ }
48481
+ countTokens() {
48482
+ return this.tokenCount;
48315
48483
  }
48316
48484
  getFirstToken() {
48317
48485
  for (const child of this.getChildren()) {
@@ -48621,17 +48789,13 @@ const string_template_middle_1 = __webpack_require__(/*! ../1_lexer/tokens/strin
48621
48789
  const string_template_end_1 = __webpack_require__(/*! ../1_lexer/tokens/string_template_end */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/string_template_end.js");
48622
48790
  const string_template_begin_1 = __webpack_require__(/*! ../1_lexer/tokens/string_template_begin */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/string_template_begin.js");
48623
48791
  const string_template_1 = __webpack_require__(/*! ../1_lexer/tokens/string_template */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/string_template.js");
48792
+ const EMPTY_PRAGMAS = Object.freeze([]);
48624
48793
  class StatementNode extends _abstract_node_1.AbstractNode {
48625
48794
  constructor(statement, colon, pragmas) {
48626
48795
  super();
48627
48796
  this.statement = statement;
48628
48797
  this.colon = colon;
48629
- if (pragmas) {
48630
- this.pragmas = pragmas;
48631
- }
48632
- else {
48633
- this.pragmas = [];
48634
- }
48798
+ this.pragmas = pragmas !== null && pragmas !== void 0 ? pragmas : EMPTY_PRAGMAS;
48635
48799
  }
48636
48800
  get() {
48637
48801
  return this.statement;
@@ -48646,7 +48810,7 @@ class StatementNode extends _abstract_node_1.AbstractNode {
48646
48810
  if (children.length === 0) {
48647
48811
  throw new Error("statement: zero children");
48648
48812
  }
48649
- this.children = children;
48813
+ super.setChildren(children);
48650
48814
  return this;
48651
48815
  }
48652
48816
  getStart() {
@@ -49227,6 +49391,7 @@ exports.StructureNode = StructureNode;
49227
49391
 
49228
49392
  Object.defineProperty(exports, "__esModule", ({ value: true }));
49229
49393
  exports.TokenNode = void 0;
49394
+ const EMPTY_CHILDREN = Object.freeze([]);
49230
49395
  class TokenNode {
49231
49396
  constructor(token) {
49232
49397
  this.token = token;
@@ -49238,7 +49403,7 @@ class TokenNode {
49238
49403
  throw new Error("TokenNode, Method not implemented.");
49239
49404
  }
49240
49405
  getChildren() {
49241
- return [];
49406
+ return EMPTY_CHILDREN;
49242
49407
  }
49243
49408
  concatTokens() {
49244
49409
  return this.token.getStr();
@@ -50952,6 +51117,8 @@ class Attributes {
50952
51117
  this.tlist = [];
50953
51118
  this.filename = input.filename;
50954
51119
  this.parse(node, input);
51120
+ this.all = this.static.concat(this.instance);
51121
+ this.byName = this.buildByName();
50955
51122
  this.types = new type_definitions_1.TypeDefinitions(this.tlist);
50956
51123
  }
50957
51124
  getTypes() {
@@ -50964,10 +51131,7 @@ class Attributes {
50964
51131
  return this.aliases;
50965
51132
  }
50966
51133
  getAll() {
50967
- let res = [];
50968
- res = res.concat(this.static);
50969
- res = res.concat(this.instance);
50970
- return res;
51134
+ return this.all;
50971
51135
  }
50972
51136
  getStaticsByVisibility(visibility) {
50973
51137
  const attributes = [];
@@ -51002,27 +51166,29 @@ class Attributes {
51002
51166
  }
51003
51167
  return attributes;
51004
51168
  }
51005
- // todo, optimize
51006
51169
  findByName(name) {
51007
- const upper = name.toUpperCase();
51008
- for (const a of this.getStatic()) {
51009
- if (a.getName().toUpperCase() === upper) {
51010
- return a;
51011
- }
51170
+ return this.byName[name.toUpperCase()];
51171
+ }
51172
+ /////////////////////////////
51173
+ buildByName() {
51174
+ const ret = {};
51175
+ for (const a of this.static) {
51176
+ ret[a.getName().toUpperCase()] = a;
51012
51177
  }
51013
- for (const a of this.getInstance()) {
51014
- if (a.getName().toUpperCase() === upper) {
51015
- return a;
51178
+ for (const a of this.instance) {
51179
+ const name = a.getName().toUpperCase();
51180
+ if (ret[name] === undefined) {
51181
+ ret[name] = a;
51016
51182
  }
51017
51183
  }
51018
- for (const a of this.getConstants()) {
51019
- if (a.getName().toUpperCase() === upper) {
51020
- return a;
51184
+ for (const a of this.constants) {
51185
+ const name = a.getName().toUpperCase();
51186
+ if (ret[name] === undefined) {
51187
+ ret[name] = a;
51021
51188
  }
51022
51189
  }
51023
- return undefined;
51190
+ return ret;
51024
51191
  }
51025
- /////////////////////////////
51026
51192
  parse(node, input) {
51027
51193
  var _a, _b;
51028
51194
  const cdef = node.findDirectStructure(Structures.ClassDefinition);
@@ -51317,6 +51483,7 @@ class ClassDefinition extends _identifier_1.Identifier {
51317
51483
  // perform checks after everything has been initialized
51318
51484
  this.checkMethodsFromSuperClasses(input);
51319
51485
  this.checkMethodNameLength(input);
51486
+ this.checkClassConstructorStatic(input);
51320
51487
  }
51321
51488
  getFriends() {
51322
51489
  return this.friends;
@@ -51380,6 +51547,13 @@ class ClassDefinition extends _identifier_1.Identifier {
51380
51547
  }
51381
51548
  }
51382
51549
  }
51550
+ checkClassConstructorStatic(input) {
51551
+ for (const m of this.methodDefs.getAll()) {
51552
+ if (m.getName().toUpperCase() === "CLASS_CONSTRUCTOR" && m.isStatic() === false) {
51553
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, m.getToken(), "CLASS_CONSTRUCTOR must be static"));
51554
+ }
51555
+ }
51556
+ }
51383
51557
  checkMethodsFromSuperClasses(input) {
51384
51558
  var _a;
51385
51559
  const scope = input.scope;
@@ -53087,8 +53261,9 @@ var Mode;
53087
53261
  (function (Mode) {
53088
53262
  Mode[Mode["Default"] = 0] = "Default";
53089
53263
  Mode[Mode["String"] = 1] = "String";
53090
- Mode[Mode["SingleLineComment"] = 2] = "SingleLineComment";
53091
- Mode[Mode["MultiLineComment"] = 3] = "MultiLineComment";
53264
+ Mode[Mode["DoubleQuoteString"] = 2] = "DoubleQuoteString";
53265
+ Mode[Mode["SingleLineComment"] = 3] = "SingleLineComment";
53266
+ Mode[Mode["MultiLineComment"] = 4] = "MultiLineComment";
53092
53267
  })(Mode || (Mode = {}));
53093
53268
  class Result {
53094
53269
  constructor() {
@@ -53148,6 +53323,23 @@ class CDSLexer {
53148
53323
  }
53149
53324
  continue;
53150
53325
  }
53326
+ // double-quote string handling
53327
+ if (mode === Mode.DoubleQuoteString) {
53328
+ build += next;
53329
+ if (next === "\\" && nextNext === "\"") {
53330
+ build += stream.takeNext();
53331
+ col++;
53332
+ }
53333
+ else if (next === "\"" && nextNext === "\"") {
53334
+ build += stream.takeNext();
53335
+ col++;
53336
+ }
53337
+ else if (next === "\"") {
53338
+ build = result.add(build, row, col, mode);
53339
+ mode = Mode.Default;
53340
+ }
53341
+ continue;
53342
+ }
53151
53343
  // single line comment handling
53152
53344
  if (mode === Mode.SingleLineComment) {
53153
53345
  if (next === "\n") {
@@ -53194,6 +53386,11 @@ class CDSLexer {
53194
53386
  mode = Mode.String;
53195
53387
  build += next;
53196
53388
  break;
53389
+ case "\"":
53390
+ build = result.add(build, row, col, mode);
53391
+ mode = Mode.DoubleQuoteString;
53392
+ build += next;
53393
+ break;
53197
53394
  case " ":
53198
53395
  case "\t":
53199
53396
  build = result.add(build, row, col, mode);
@@ -53608,7 +53805,9 @@ class CDSAs extends combi_1.Expression {
53608
53805
  getRunnable() {
53609
53806
  const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
53610
53807
  const colonType = (0, combi_1.seq)(":", (0, combi_1.altPrio)(_1.CDSType, _1.CDSName, "LOCALIZED"));
53611
- return (0, combi_1.seq)("AS", _1.CDSName, (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonType)));
53808
+ const ident = (0, combi_1.regex)(/^\w+$/);
53809
+ const namespacedAlias = (0, combi_1.seq)(ident, "/", ident, "/", ident);
53810
+ return (0, combi_1.seq)("AS", (0, combi_1.altPrio)(namespacedAlias, _1.CDSName), (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonType)));
53612
53811
  }
53613
53812
  }
53614
53813
  exports.CDSAs = CDSAs;
@@ -53642,8 +53841,9 @@ class CDSAssociation extends combi_1.Expression {
53642
53841
  // Numeric OF form: "association of [0..1] to Target on ..."
53643
53842
  const ofNumericForm = (0, combi_1.seq)("ASSOCIATION", "OF", numericCardinality, "TO", _1.CDSRelation, "ON", _1.CDSCondition);
53644
53843
  // "association [0..1] to Target as _Alias on condition" — standard form
53844
+ const parentForm = (0, combi_1.seq)("ASSOCIATION", "TO", "PARENT", _1.CDSRelation);
53645
53845
  const standardForm = (0, combi_1.seq)("ASSOCIATION", (0, combi_1.optPrio)(cds_cardinality_1.CDSCardinality), "TO", (0, combi_1.opt)((0, combi_1.altPrio)(textCardinality, "PARENT")), _1.CDSRelation, "ON", _1.CDSCondition, (0, combi_1.opt)((0, combi_1.seq)("WITH", "DEFAULT", "FILTER", _1.CDSCondition)));
53646
- return (0, combi_1.altPrio)(ofTextForm, ofNumericForm, standardForm);
53846
+ return (0, combi_1.altPrio)(ofTextForm, ofNumericForm, standardForm, parentForm);
53647
53847
  }
53648
53848
  }
53649
53849
  exports.CDSAssociation = CDSAssociation;
@@ -53900,11 +54100,9 @@ class CDSDefineHierarchy extends combi_1.Expression {
53900
54100
  const directory = (0, combi_1.seq)("DIRECTORY", _1.CDSName, "FILTER", "BY", _1.CDSCondition);
53901
54101
  // DATE PERIOD: period from <field> to <field> [valid from :p to :p]
53902
54102
  const datePeriod = (0, combi_1.seq)("PERIOD", "FROM", _1.CDSName, "TO", _1.CDSName, (0, combi_1.opt)((0, combi_1.seq)("VALID", "FROM", _1.CDSPrefixedName, "TO", _1.CDSPrefixedName)));
53903
- // DEPTH accepts an integer literal or a parameter reference (:param)
53904
- const depthValue = (0, combi_1.altPrio)(_1.CDSInteger, _1.CDSPrefixedName);
53905
- // LOAD mode: BULK, INCREMENTAL, or a parameter reference ($parameters.p_load)
54103
+ const depthValue = (0, combi_1.altPrio)(_1.CDSString, _1.CDSInteger, _1.CDSPrefixedName);
53906
54104
  const loadMode = (0, combi_1.altPrio)("BULK", "INCREMENTAL", _1.CDSPrefixedName);
53907
- const hierarchyBody = (0, combi_1.seq)("SOURCE", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), "CHILD", "TO", "PARENT", "ASSOCIATION", _1.CDSName, (0, combi_1.opt)(directory), (0, combi_1.opt)(datePeriod), (0, combi_1.opt)((0, combi_1.seq)("START", "WHERE", _1.CDSCondition)), (0, combi_1.opt)(siblingsOrder), (0, combi_1.opt)((0, combi_1.seq)("LOAD", loadMode)), (0, combi_1.opt)((0, combi_1.seq)("NODETYPE", _1.CDSName)), (0, combi_1.opt)((0, combi_1.seq)("DEPTH", depthValue)), (0, combi_1.opt)((0, combi_1.seq)("MULTIPLE", "PARENTS", (0, combi_1.altPrio)("NOT ALLOWED", "ALLOWED", (0, combi_1.seq)("LEAVES", (0, combi_1.optPrio)("ONLY"))))), (0, combi_1.opt)((0, combi_1.seq)("ORPHANS", (0, combi_1.altPrio)("IGNORE", "ROOT", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("CYCLES", (0, combi_1.altPrio)("BREAKUP", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("GENERATE", "SPANTREE")), (0, combi_1.opt)((0, combi_1.seq)("CACHE", (0, combi_1.altPrio)("ON", "OFF", "FORCE"))));
54105
+ const hierarchyBody = (0, combi_1.seq)("SOURCE", _1.CDSName, (0, combi_1.opt)(_1.CDSParametersSelect), "CHILD", "TO", "PARENT", "ASSOCIATION", _1.CDSName, (0, combi_1.opt)(directory), (0, combi_1.opt)(datePeriod), (0, combi_1.opt)((0, combi_1.seq)("START", "WHERE", _1.CDSCondition)), (0, combi_1.opt)(siblingsOrder), (0, combi_1.opt)((0, combi_1.seq)("LOAD", loadMode)), (0, combi_1.opt)((0, combi_1.seq)("DEPTH", depthValue)), (0, combi_1.opt)((0, combi_1.seq)("NODETYPE", _1.CDSName)), (0, combi_1.opt)((0, combi_1.seq)("MULTIPLE", "PARENTS", (0, combi_1.altPrio)("NOT ALLOWED", "ALLOWED", (0, combi_1.seq)("LEAVES", (0, combi_1.optPrio)("ONLY"))))), (0, combi_1.opt)((0, combi_1.seq)("ORPHANS", (0, combi_1.altPrio)("IGNORE", "ROOT", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("CYCLES", (0, combi_1.altPrio)("BREAKUP", "ERROR"))), (0, combi_1.opt)((0, combi_1.seq)("GENERATE", "SPANTREE")), (0, combi_1.opt)((0, combi_1.seq)("CACHE", (0, combi_1.altPrio)("ON", "OFF", "FORCE"))));
53908
54106
  return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), "DEFINE", "HIERARCHY", _1.CDSName, (0, combi_1.opt)(_1.CDSWithParameters), "AS", "PARENT", "CHILD", "HIERARCHY", "(", hierarchyBody, ")", "{", (0, combi_1.seq)(field, (0, combi_1.star)((0, combi_1.seq)(",", field))), "}", (0, combi_1.opt)(";"));
53909
54107
  }
53910
54108
  }
@@ -53952,10 +54150,10 @@ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src
53952
54150
  const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node_modules/@abaplint/core/build/src/abap/2_statements/combi.js");
53953
54151
  class CDSDefineTableEntity extends combi_1.Expression {
53954
54152
  getRunnable() {
53955
- const nullability = (0, combi_1.optPrio)((0, combi_1.alt)("NOT NULL", "NULL"));
53956
- const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)((0, combi_1.str)("KEY")), _1.CDSName, ":", _1.CDSType, nullability, ";");
53957
- const assocOrComp = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), _1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
53958
- const inlineBody = (0, combi_1.plus)((0, combi_1.alt)(field, assocOrComp));
54153
+ // Inline `{ ... }` body: one or more table-field entries. Each entry is
54154
+ // wrapped in a CDSTableField node so downstream tooling can pair each
54155
+ // field name with its own annotations.
54156
+ const inlineBody = (0, combi_1.plus)(_1.CDSTableField);
53959
54157
  const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
53960
54158
  const elements = (0, combi_1.seq)((0, combi_1.str)("{"), (0, combi_1.altPrio)("*", elementList), (0, combi_1.str)("}"));
53961
54159
  const selectBody = (0, combi_1.seq)("AS", "SELECT", "FROM", _1.CDSSource, (0, combi_1.star)(_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, _1.CDSAssociation)), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere));
@@ -53983,7 +54181,7 @@ const cds_name_1 = __webpack_require__(/*! ./cds_name */ "./node_modules/@abapli
53983
54181
  class CDSDefineTableFunction extends combi_1.Expression {
53984
54182
  getRunnable() {
53985
54183
  const methodName = (0, combi_1.seq)(cds_name_1.CDSName, "=", ">", cds_name_1.CDSName);
53986
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE TABLE FUNCTION"), cds_name_1.CDSName, (0, combi_1.optPrio)(_1.CDSWithParameters), (0, combi_1.str)("RETURNS {"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)("KEY"), cds_name_1.CDSName, ":", _1.CDSType, ";")), (0, combi_1.str)("} IMPLEMENTED BY METHOD"), methodName, (0, combi_1.opt)(";"));
54184
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("DEFINE TABLE FUNCTION"), cds_name_1.CDSName, (0, combi_1.optPrio)(_1.CDSWithParameters), (0, combi_1.str)("RETURNS {"), (0, combi_1.plus)((0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)("KEY"), cds_name_1.CDSName, ":", _1.CDSType, (0, combi_1.star)(_1.CDSAnnotation), ";")), (0, combi_1.str)("} IMPLEMENTED BY METHOD"), methodName, (0, combi_1.opt)(";"));
53987
54185
  }
53988
54186
  }
53989
54187
  exports.CDSDefineTableFunction = CDSDefineTableFunction;
@@ -54010,8 +54208,10 @@ const cds_with_parameters_1 = __webpack_require__(/*! ./cds_with_parameters */ "
54010
54208
  class CDSDefineView extends combi_1.Expression {
54011
54209
  getRunnable() {
54012
54210
  const columnAlias = (0, combi_1.seq)("(", cds_name_1.CDSName, (0, combi_1.star)((0, combi_1.seq)(",", cds_name_1.CDSName)), ")");
54013
- return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), (0, combi_1.opt)("WRITABLE"), "VIEW", (0, combi_1.ver)(__1.Release.v755, (0, combi_1.opt)("ENTITY")), cds_name_1.CDSName, (0, combi_1.opt)(columnAlias), (0, combi_1.opt)(cds_with_parameters_1.CDSWithParameters), "AS", cds_select_1.CDSSelect, (0, combi_1.opt)((0, combi_1.seq)("WITH", "HIERARCHY", cds_name_1.CDSName)), // post-select WITH HIERARCHY clause
54014
- (0, combi_1.opt)(";"));
54211
+ const parenSelect = (0, combi_1.seq)("(", cds_select_1.CDSSelect, ")");
54212
+ const unionBranch = (0, combi_1.altPrio)(parenSelect, cds_select_1.CDSSelect);
54213
+ const topLevelSelect = (0, combi_1.altPrio)((0, combi_1.seq)(parenSelect, (0, combi_1.star)((0, combi_1.altPrio)((0, combi_1.seq)("UNION", (0, combi_1.opt)("ALL"), unionBranch), (0, combi_1.seq)("EXCEPT", unionBranch), (0, combi_1.seq)("INTERSECT", unionBranch)))), cds_select_1.CDSSelect);
54214
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.opt)("DEFINE"), (0, combi_1.opt)("ROOT"), (0, combi_1.opt)("WRITABLE"), "VIEW", (0, combi_1.ver)(__1.Release.v755, (0, combi_1.opt)("ENTITY")), cds_name_1.CDSName, (0, combi_1.opt)(columnAlias), (0, combi_1.opt)(cds_with_parameters_1.CDSWithParameters), "AS", topLevelSelect, (0, combi_1.opt)((0, combi_1.seq)("WITH", "HIERARCHY", cds_name_1.CDSName)), (0, combi_1.opt)(";"));
54015
54215
  }
54016
54216
  }
54017
54217
  exports.CDSDefineView = CDSDefineView;
@@ -54038,11 +54238,15 @@ class CDSElement extends combi_1.Expression {
54038
54238
  const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
54039
54239
  const colonThing = (0, combi_1.seq)(":", (0, combi_1.altPrio)(_1.CDSType, _1.CDSName, "LOCALIZED"));
54040
54240
  const extensionWildcard = (0, combi_1.seq)("$extension", ".", "*");
54041
- const includeElement = (0, combi_1.seq)("INCLUDE", _1.CDSPrefixedName);
54241
+ const excludingNames = (0, combi_1.seq)(_1.CDSName, (0, combi_1.starPrio)((0, combi_1.seq)(",", _1.CDSName)));
54242
+ const excluding = (0, combi_1.seq)("EXCLUDING", "{", excludingNames, "}");
54243
+ const includeElement = (0, combi_1.seq)("INCLUDE", _1.CDSPrefixedName, (0, combi_1.optPrio)(excluding), (0, combi_1.optPrio)("SIGNATURE ONLY"));
54042
54244
  const typedVirtual = (0, combi_1.seq)("VIRTUAL", _1.CDSName, ":", _1.CDSType);
54043
- const body = (0, combi_1.altPrio)(extensionWildcard, includeElement, _1.CDSArithmetics, _1.CDSAggregate, _1.CDSString, _1.CDSArithParen, _1.CDSFunction, cds_cast_1.CDSCast, _1.CDSCase, (0, combi_1.seq)("(", _1.CDSCase, ")"), (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.optPrio)(cds_as_1.CDSAs), (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonThing))), _1.CDSInteger);
54245
+ const pathSegment = (0, combi_1.seq)(".", (0, combi_1.altPrio)(_1.CDSString, _1.CDSName, "*"), (0, combi_1.optPrio)((0, combi_1.altPrio)(_1.CDSParametersSelect, _1.CDSParameters)));
54246
+ const funcWithPath = (0, combi_1.seq)(_1.CDSFunction, (0, combi_1.plusPrio)(pathSegment));
54247
+ const body = (0, combi_1.altPrio)(extensionWildcard, includeElement, _1.CDSArithmetics, _1.CDSAggregate, _1.CDSString, _1.CDSArithParen, funcWithPath, _1.CDSFunction, cds_cast_1.CDSCast, _1.CDSCase, (0, combi_1.seq)("(", _1.CDSCase, ")"), (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.optPrio)(cds_as_1.CDSAs), (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonThing))), _1.CDSInteger);
54044
54248
  const elementBody = (0, combi_1.altPrio)(typedVirtual, (0, combi_1.seq)((0, combi_1.altPrio)("KEY", "VIRTUAL"), body), body);
54045
- return (0, combi_1.seq)((0, combi_1.starPrio)(_1.CDSAnnotation), elementBody, (0, combi_1.optPrio)(cds_as_1.CDSAs));
54249
+ return (0, combi_1.seq)((0, combi_1.starPrio)(_1.CDSAnnotation), elementBody, (0, combi_1.optPrio)(cds_as_1.CDSAs), (0, combi_1.starPrio)(_1.CDSAnnotation));
54046
54250
  }
54047
54251
  }
54048
54252
  exports.CDSElement = CDSElement;
@@ -54067,7 +54271,9 @@ class CDSExtendView extends combi_1.Expression {
54067
54271
  const namedot = (0, combi_1.seq)(_1.CDSName, (0, combi_1.optPrio)((0, combi_1.seq)(".", _1.CDSName)), (0, combi_1.optPrio)(_1.CDSAs));
54068
54272
  const valueNested = (0, combi_1.seq)("{", namedot, (0, combi_1.star)((0, combi_1.seq)(",", namedot)), "}");
54069
54273
  const redefineAssoc = (0, combi_1.seq)("REDEFINE", "ASSOCIATION", _1.CDSPrefixedName, (0, combi_1.optPrio)((0, combi_1.seq)("[", _1.CDSCondition, "]")), (0, combi_1.opt)(_1.CDSAs), "REDIRECTED", "TO", (0, combi_1.optPrio)((0, combi_1.altPrio)((0, combi_1.seq)("COMPOSITION", "CHILD"), "PARENT")), _1.CDSName);
54070
- const extendView = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("EXTEND VIEW"), (0, combi_1.opt)((0, combi_1.str)("ENTITY")), _1.CDSName, (0, combi_1.str)("WITH"), (0, combi_1.opt)(_1.CDSName), (0, combi_1.star)(redefineAssoc), valueNested, (0, combi_1.opt)(";"));
54274
+ const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
54275
+ const elementNested = (0, combi_1.seq)("{", (0, combi_1.altPrio)("*", elementList), "}");
54276
+ const extendView = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.str)("EXTEND VIEW"), (0, combi_1.opt)((0, combi_1.str)("ENTITY")), _1.CDSName, (0, combi_1.str)("WITH"), (0, combi_1.opt)(_1.CDSName), (0, combi_1.star)(redefineAssoc), (0, combi_1.star)(_1.CDSAssociation), (0, combi_1.altPrio)(elementNested, valueNested), (0, combi_1.opt)(";"));
54071
54277
  const field = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.optPrio)((0, combi_1.str)("KEY")), _1.CDSName, ":", _1.CDSType, ";");
54072
54278
  const assocOrComp = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), _1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
54073
54279
  const entityBody = (0, combi_1.seq)("{", (0, combi_1.plus)((0, combi_1.alt)(field, assocOrComp)), "}");
@@ -54309,7 +54515,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54309
54515
  class CDSName extends combi_1.Expression {
54310
54516
  getRunnable() {
54311
54517
  const pre = (0, combi_1.seq)("/", (0, combi_1.regex)(/^[\w_]+$/), "/");
54312
- return (0, combi_1.seq)((0, combi_1.optPrio)(":"), (0, combi_1.optPrio)(pre), (0, combi_1.regex)(/^\$?#?[\w_]+$/));
54518
+ return (0, combi_1.altPrio)((0, combi_1.regex)(/^"(?:[^"]|"")*"$/), (0, combi_1.seq)((0, combi_1.optPrio)(":"), (0, combi_1.optPrio)(pre), (0, combi_1.regex)(/^\$?#?[\w_]+$/)));
54313
54519
  }
54314
54520
  }
54315
54521
  exports.CDSName = CDSName;
@@ -54357,7 +54563,9 @@ class CDSParametersSelect extends combi_1.Expression {
54357
54563
  getRunnable() {
54358
54564
  const name = (0, combi_1.seq)(_1.CDSName, (0, combi_1.opt)((0, combi_1.seq)(".", _1.CDSName)));
54359
54565
  const value = (0, combi_1.alt)(_1.CDSInteger, name, _1.CDSString);
54360
- const nameValue = (0, combi_1.seq)(name, ":", value);
54566
+ const colonPair = (0, combi_1.seq)(name, ":", value, (0, combi_1.optPrio)("DEFAULT"));
54567
+ const arrowPair = (0, combi_1.seq)(name, "=", ">", value);
54568
+ const nameValue = (0, combi_1.altPrio)(colonPair, arrowPair);
54361
54569
  return (0, combi_1.seq)("(", nameValue, (0, combi_1.star)((0, combi_1.seq)(",", nameValue)), ")");
54362
54570
  }
54363
54571
  }
@@ -54391,13 +54599,13 @@ class CDSPrefixedName extends combi_1.Expression {
54391
54599
  const cardinalityJoin = (0, combi_1.seq)("[", cardSpec, ":", joinType, "]");
54392
54600
  const cardinalityJoinWhere = (0, combi_1.seq)("[", cardSpec, ":", joinType, "WHERE", cds_condition_1.CDSCondition, "]");
54393
54601
  const joinWhere = (0, combi_1.seq)("[", joinType, "WHERE", cds_condition_1.CDSCondition, "]");
54394
- const textCard = (0, combi_1.altPrio)("TO EXACT ONE", "TO ONE", "TO MANY");
54602
+ const textCard = (0, combi_1.altPrio)("MANY TO EXACT ONE", "MANY TO ONE", "ONE TO MANY", "ONE TO ONE", "TO EXACT ONE", "TO ONE", "TO MANY");
54395
54603
  const textCardFilter = (0, combi_1.seq)("[", textCard, (0, combi_1.optPrio)((0, combi_1.seq)(":", (0, combi_1.altPrio)((0, combi_1.seq)(joinType, "WHERE", cds_condition_1.CDSCondition), joinType, cds_condition_1.CDSCondition))), "]");
54396
54604
  const cardNum = (0, combi_1.altPrio)(cds_integer_1.CDSInteger, "*");
54397
54605
  const rangeCard = (0, combi_1.seq)(cds_integer_1.CDSInteger, ".", ".", cardNum);
54398
54606
  const rangeCardFilter = (0, combi_1.seq)("[", rangeCard, ":", cds_condition_1.CDSCondition, "]");
54399
54607
  const pathFilter = (0, combi_1.altPrio)(cardinalityJoinWhere, joinWhere, cardinalityJoin, joinRedirect, textCardFilter, rangeCardFilter, (0, combi_1.seq)("[", cardSpec, ":", cds_condition_1.CDSCondition, "]"), (0, combi_1.seq)("[", cds_condition_1.CDSCondition, "]"));
54400
- const segment = (0, combi_1.seq)(".", (0, combi_1.altPrio)(cds_string_1.CDSString, cds_name_1.CDSName), (0, combi_1.optPrio)((0, combi_1.altPrio)(cds_parameters_select_1.CDSParametersSelect, cds_parameters_1.CDSParameters)), (0, combi_1.optPrio)(pathFilter));
54608
+ const segment = (0, combi_1.seq)(".", (0, combi_1.altPrio)(cds_string_1.CDSString, cds_name_1.CDSName, "*"), (0, combi_1.optPrio)((0, combi_1.altPrio)(cds_parameters_select_1.CDSParametersSelect, cds_parameters_1.CDSParameters)), (0, combi_1.optPrio)(pathFilter));
54401
54609
  return (0, combi_1.seq)(cds_name_1.CDSName, (0, combi_1.optPrio)((0, combi_1.altPrio)(cds_parameters_1.CDSParameters, cds_parameters_select_1.CDSParametersSelect)), (0, combi_1.optPrio)(pathFilter), (0, combi_1.star)(segment));
54402
54610
  }
54403
54611
  }
@@ -54442,7 +54650,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54442
54650
  class CDSRelation extends combi_1.Expression {
54443
54651
  getRunnable() {
54444
54652
  const pre = (0, combi_1.seq)("/", (0, combi_1.regex)(/^[\w_]+$/), "/");
54445
- return (0, combi_1.seq)((0, combi_1.opt)(pre), (0, combi_1.regex)(/^[\w_]+$/), (0, combi_1.opt)(_1.CDSAs));
54653
+ return (0, combi_1.seq)((0, combi_1.opt)(pre), (0, combi_1.regex)(/^[\w_]+$/), (0, combi_1.opt)(_1.CDSParametersSelect), (0, combi_1.opt)(_1.CDSAs));
54446
54654
  }
54447
54655
  }
54448
54656
  exports.CDSRelation = CDSRelation;
@@ -54470,11 +54678,12 @@ class CDSSelect extends combi_1.Expression {
54470
54678
  const distinct = (0, combi_1.str)("DISTINCT");
54471
54679
  const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
54472
54680
  const elements = (0, combi_1.seq)((0, combi_1.str)("{"), (0, combi_1.altPrio)("*", elementList), (0, combi_1.str)("}"));
54473
- const aspectBinding = (0, combi_1.seq)(_1.CDSPrefixedName, "=", ">", _1.CDSPrefixedName);
54474
- const bindAspect = (0, combi_1.seq)("BIND", "ASPECT", _1.CDSName, "(", aspectBinding, (0, combi_1.starPrio)((0, combi_1.seq)(",", aspectBinding)), ")");
54681
+ const aspectValue = (0, combi_1.altPrio)(_1.CDSString, _1.CDSPrefixedName);
54682
+ const aspectBinding = (0, combi_1.seq)(_1.CDSPrefixedName, "=", ">", aspectValue);
54683
+ const bindAspect = (0, combi_1.seq)("BIND", "ASPECT", _1.CDSName, "(", aspectBinding, (0, combi_1.starPrio)((0, combi_1.seq)(",", aspectBinding)), ")", (0, combi_1.optPrio)((0, combi_1.seq)("AS", _1.CDSName)));
54475
54684
  const parenSelect = (0, combi_1.seq)("(", CDSSelect, ")");
54476
54685
  const unionBranch = (0, combi_1.altPrio)(parenSelect, CDSSelect);
54477
- return (0, combi_1.seq)("SELECT", (0, combi_1.optPrio)(distinct), (0, combi_1.opt)((0, combi_1.altPrio)("*", fields)), "FROM", _1.CDSSource, (0, combi_1.star)(cds_join_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, cds_association_1.CDSAssociation)), (0, combi_1.optPrio)(bindAspect), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere), (0, combi_1.optPrio)(_1.CDSGroupBy), (0, combi_1.optPrio)(_1.CDSHaving), (0, combi_1.optPrio)((0, combi_1.altPrio)((0, combi_1.seq)("UNION", (0, combi_1.optPrio)("ALL"), unionBranch), (0, combi_1.seq)("EXCEPT", unionBranch), (0, combi_1.seq)("INTERSECT", unionBranch))));
54686
+ return (0, combi_1.seq)("SELECT", (0, combi_1.optPrio)(distinct), (0, combi_1.opt)((0, combi_1.altPrio)("*", fields)), "FROM", _1.CDSSource, (0, combi_1.star)(cds_join_1.CDSJoin), (0, combi_1.star)((0, combi_1.altPrio)(_1.CDSComposition, cds_association_1.CDSAssociation)), (0, combi_1.starPrio)(bindAspect), (0, combi_1.opt)(elements), (0, combi_1.optPrio)(_1.CDSWhere), (0, combi_1.optPrio)(_1.CDSGroupBy), (0, combi_1.optPrio)(_1.CDSHaving), (0, combi_1.optPrio)((0, combi_1.altPrio)((0, combi_1.seq)("UNION", (0, combi_1.optPrio)("ALL"), unionBranch), (0, combi_1.seq)("EXCEPT", unionBranch), (0, combi_1.seq)("INTERSECT", unionBranch))));
54478
54687
  }
54479
54688
  }
54480
54689
  exports.CDSSelect = CDSSelect;
@@ -54497,10 +54706,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54497
54706
  class CDSSource extends combi_1.Expression {
54498
54707
  getRunnable() {
54499
54708
  const staticFilter = (0, combi_1.seq)("[", _1.CDSCondition, "]");
54500
- // Dotted path: T._Assoc association path as FROM source
54501
- const dottedName = (0, combi_1.seq)(_1.CDSName, ".", _1.CDSName);
54502
- const namedSource = (0, combi_1.altPrio)(dottedName, _1.CDSName);
54503
- const singleSource = (0, combi_1.seq)(namedSource, (0, combi_1.optPrio)(_1.CDSParametersSelect), (0, combi_1.optPrio)(staticFilter), (0, combi_1.opt)((0, combi_1.altPrio)(_1.CDSAs, _1.CDSName)));
54709
+ const singleSource = (0, combi_1.seq)(_1.CDSPrefixedName, (0, combi_1.optPrio)(_1.CDSParametersSelect), (0, combi_1.optPrio)(staticFilter), (0, combi_1.opt)((0, combi_1.altPrio)(_1.CDSAs, _1.CDSName)));
54504
54710
  const funcSingleSource = (0, combi_1.seq)(_1.CDSFunction, (0, combi_1.opt)((0, combi_1.altPrio)(_1.CDSAs, _1.CDSName)));
54505
54711
  const parenSource = (0, combi_1.seq)("(", (0, combi_1.altPrio)(CDSSource, singleSource), (0, combi_1.star)(_1.CDSJoin), ")");
54506
54712
  return (0, combi_1.altPrio)(parenSource, funcSingleSource, singleSource);
@@ -54525,7 +54731,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54525
54731
  class CDSString extends combi_1.Expression {
54526
54732
  getRunnable() {
54527
54733
  const reg = (0, combi_1.regex)(/^'(?:[^'\\]|''|\\'|\\\\|\\(?!'))*'$/);
54528
- const abapTypeName = (0, combi_1.regex)(/^(?:int[1-9]|int8|sstring|char|numc|dats|datn|tims|timn|utcl|utclong|fltp|decfloat\d+|dec|string|rawstring|rstr|raw|xstring|clnt|lang|unit|cuky|curr|quan|geom_ewkb|d34n|d16n|d34d|d16d|d34s|d16s|d34r|d16r|d|t|p|n|c|x|f)$/i);
54734
+ const abapTypeName = (0, combi_1.regex)(/^(?:int[1-9]|int8|sstring|sstr|char|numc|dats|datn|tims|timn|utcl|utclong|fltp|decfloat\d+|dec|string|rawstring|rstr|raw|xstring|clnt|lang|unit|cuky|curr|quan|geom_ewkb|d34n|d16n|d34d|d16d|d34s|d16s|d34r|d16r|d|t|p|n|c|x|f)$/i);
54529
54735
  const abap = (0, combi_1.seq)("abap", ".", abapTypeName, (0, combi_1.optPrio)((0, combi_1.seq)("(", (0, combi_1.regex)(/^\d+$/), ")")), reg);
54530
54736
  return (0, combi_1.altPrio)(abap, reg);
54531
54737
  }
@@ -54535,6 +54741,35 @@ exports.CDSString = CDSString;
54535
54741
 
54536
54742
  /***/ },
54537
54743
 
54744
+ /***/ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js"
54745
+ /*!**********************************************************************************!*\
54746
+ !*** ./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js ***!
54747
+ \**********************************************************************************/
54748
+ (__unused_webpack_module, exports, __webpack_require__) {
54749
+
54750
+ "use strict";
54751
+
54752
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
54753
+ exports.CDSTableField = void 0;
54754
+ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/cds/expressions/index.js");
54755
+ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node_modules/@abaplint/core/build/src/abap/2_statements/combi.js");
54756
+ // A single field or association/composition inside a `define table entity { ... }`
54757
+ // inline body. Wraps annotations + name + type together so tooling can iterate
54758
+ // per-field with associated field-level annotations (matches the CDSElement
54759
+ // shape used for select-list elements).
54760
+ class CDSTableField extends combi_1.Expression {
54761
+ getRunnable() {
54762
+ const nullability = (0, combi_1.optPrio)((0, combi_1.alt)("NOT NULL", "NULL"));
54763
+ const field = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.str)("KEY")), _1.CDSName, ":", _1.CDSType, nullability);
54764
+ const assocOrComp = (0, combi_1.seq)(_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation));
54765
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.alt)(field, assocOrComp), ";");
54766
+ }
54767
+ }
54768
+ exports.CDSTableField = CDSTableField;
54769
+ //# sourceMappingURL=cds_table_field.js.map
54770
+
54771
+ /***/ },
54772
+
54538
54773
  /***/ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js"
54539
54774
  /*!***************************************************************************!*\
54540
54775
  !*** ./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js ***!
@@ -54666,6 +54901,7 @@ __exportStar(__webpack_require__(/*! ./cds_relation */ "./node_modules/@abaplint
54666
54901
  __exportStar(__webpack_require__(/*! ./cds_select */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_select.js"), exports);
54667
54902
  __exportStar(__webpack_require__(/*! ./cds_source */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_source.js"), exports);
54668
54903
  __exportStar(__webpack_require__(/*! ./cds_string */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_string.js"), exports);
54904
+ __exportStar(__webpack_require__(/*! ./cds_table_field */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js"), exports);
54669
54905
  __exportStar(__webpack_require__(/*! ./cds_type */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js"), exports);
54670
54906
  __exportStar(__webpack_require__(/*! ./cds_where */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_where.js"), exports);
54671
54907
  __exportStar(__webpack_require__(/*! ./cds_with_parameters */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_with_parameters.js"), exports);
@@ -54729,10 +54965,19 @@ class Config {
54729
54965
  for (const rule of sorted) {
54730
54966
  rules[rule.getMetadata().key] = rule.getConfig();
54731
54967
  }
54732
- const version = ver !== null && ver !== void 0 ? ver : {
54733
- release: version_1.Release.Newest.name,
54734
- language: langVer !== null && langVer !== void 0 ? langVer : version_1.LanguageVersion.Normal,
54735
- };
54968
+ const version = langVer !== undefined
54969
+ ? {
54970
+ release: ver === undefined || ver === version_1.Version.Cloud
54971
+ ? version_1.Release.Newest.name
54972
+ : typeof ver === "string"
54973
+ ? (0, version_1.versionToABAPRelease)(ver).name
54974
+ : ver.release,
54975
+ language: langVer,
54976
+ }
54977
+ : ver !== null && ver !== void 0 ? ver : {
54978
+ release: version_1.Release.Newest.name,
54979
+ language: version_1.LanguageVersion.Normal,
54980
+ };
54736
54981
  // defaults: dont skip anything, report everything. The user can decide to skip stuff
54737
54982
  // its difficult to debug errors not being reported
54738
54983
  const config = {
@@ -54757,9 +55002,9 @@ class Config {
54757
55002
  }],
54758
55003
  syntax: {
54759
55004
  version,
54760
- languageVersion: langVer,
54761
55005
  errorNamespace: "^(Z|Y|LCL\_|TY\_|LIF\_)",
54762
55006
  globalConstants: [],
55007
+ ambigiousVoids: [],
54763
55008
  globalMacros: [],
54764
55009
  },
54765
55010
  rules: rules,
@@ -54810,6 +55055,12 @@ class Config {
54810
55055
  // remove duplicates,
54811
55056
  this.config.syntax.globalConstants = [...new Set(this.config.syntax.globalConstants)];
54812
55057
  }
55058
+ if (this.config.syntax.ambigiousVoids === undefined) {
55059
+ this.config.syntax.ambigiousVoids = [];
55060
+ }
55061
+ else {
55062
+ this.config.syntax.ambigiousVoids = [...new Set(this.config.syntax.ambigiousVoids)];
55063
+ }
54813
55064
  if (this.config.global.skipIncludesWithoutMain === undefined) {
54814
55065
  this.config.global.skipIncludesWithoutMain = false;
54815
55066
  }
@@ -54859,9 +55110,6 @@ class Config {
54859
55110
  return v;
54860
55111
  }
54861
55112
  getLanguageVersion() {
54862
- if (this.config.syntax.languageVersion !== undefined) {
54863
- return this.config.syntax.languageVersion;
54864
- }
54865
55113
  const v = this.config.syntax.version;
54866
55114
  if (v !== undefined && typeof v !== "string") {
54867
55115
  return v.language;
@@ -54886,7 +55134,10 @@ class Config {
54886
55134
  return;
54887
55135
  }
54888
55136
  if (version === version_1.Version.Cloud) {
54889
- this.config.syntax.languageVersion = version_1.LanguageVersion.Cloud;
55137
+ this.config.syntax.version = {
55138
+ release: version_1.Release.Newest.name,
55139
+ language: version_1.LanguageVersion.Cloud,
55140
+ };
54890
55141
  }
54891
55142
  // OpenABAP keeps its own version identity; open-abap-ness is derived from the
54892
55143
  // release in getOpenABAP() rather than a separate stored flag.
@@ -59814,6 +60065,7 @@ function parseDynpros(parsed) {
59814
60065
  fields.push({
59815
60066
  name: f.NAME,
59816
60067
  type: f.TYPE,
60068
+ contType: f.CONT_TYPE,
59817
60069
  length: parseNumber(f.LENGTH),
59818
60070
  vislength: parseNumber(f.VISLENGTH),
59819
60071
  line: parseNumber(f.LINE),
@@ -61701,9 +61953,8 @@ class DataDefinition extends _abstract_object_1.AbstractObject {
61701
61953
  }
61702
61954
  if (found === undefined) {
61703
61955
  // typed virtual element: VIRTUAL <name> : <type>
61704
- const names = e.findAllExpressions(expressions_1.CDSName);
61705
- if (e.findDirectTokenByText("VIRTUAL") !== undefined && names.length > 0) {
61706
- found = names[0];
61956
+ if (e.findDirectTokenByText("VIRTUAL") !== undefined) {
61957
+ found = e.findFirstExpression(expressions_1.CDSName);
61707
61958
  }
61708
61959
  }
61709
61960
  if (found === undefined) {
@@ -68995,7 +69246,7 @@ class Registry {
68995
69246
  }
68996
69247
  static abaplintVersion() {
68997
69248
  // magic, see build script "version.js"
68998
- return "2.119.56";
69249
+ return "2.119.64";
68999
69250
  }
69000
69251
  getDDICReferences() {
69001
69252
  return this.ddicReferences;
@@ -71166,17 +71417,22 @@ class BeginEndNames extends _abap_rule_1.ABAPRule {
71166
71417
  test(stru, type, b, e, file) {
71167
71418
  const output = [];
71168
71419
  for (const sub of stru.findAllStructuresRecursive(type)) {
71169
- let begin = sub.findDirectStatements(b)[0].findFirstExpression(Expressions.NamespaceSimpleName);
71420
+ const beginStatement = sub.findDirectStatement(b);
71421
+ const endStatement = sub.findDirectStatement(e);
71422
+ if (beginStatement === undefined || endStatement === undefined) {
71423
+ continue;
71424
+ }
71425
+ let begin = beginStatement.findFirstExpression(Expressions.NamespaceSimpleName);
71170
71426
  if (begin === undefined) {
71171
- begin = sub.findDirectStatements(b)[0].findFirstExpression(Expressions.DefinitionName);
71427
+ begin = beginStatement.findFirstExpression(Expressions.DefinitionName);
71172
71428
  }
71173
71429
  if (begin === undefined) {
71174
71430
  continue;
71175
71431
  }
71176
71432
  const first = begin.getFirstToken();
71177
- let end = sub.findDirectStatements(e)[0].findFirstExpression(Expressions.NamespaceSimpleName);
71433
+ let end = endStatement.findFirstExpression(Expressions.NamespaceSimpleName);
71178
71434
  if (end === undefined) {
71179
- end = sub.findDirectStatements(e)[0].findFirstExpression(Expressions.DefinitionName);
71435
+ end = endStatement.findFirstExpression(Expressions.DefinitionName);
71180
71436
  }
71181
71437
  if (end === undefined) {
71182
71438
  continue;
@@ -74655,6 +74911,7 @@ class DangerousStatementConf extends _basic_rule_config_1.BasicRuleConfig {
74655
74911
  this.insertTextpool = true;
74656
74912
  this.deleteDynpro = true;
74657
74913
  this.exportDynpro = true;
74914
+ this.editorCallForReport = true;
74658
74915
  /** Finds instances of dynamic SQL: SELECT, UPDATE, DELETE, INSERT, MODIFY */
74659
74916
  this.dynamicSQL = true;
74660
74917
  /** Ignore dynamic SQL in IF_RAP_QUERY_PROVIDER~SELECT implementations */
@@ -74739,6 +74996,11 @@ dynamic SQL can potentially create SQL injection problems`,
74739
74996
  else if (this.conf.exportDynpro && statement instanceof Statements.ExportDynpro) {
74740
74997
  message = "EXPORT DYNPRO";
74741
74998
  }
74999
+ else if (this.conf.editorCallForReport
75000
+ && statement instanceof Statements.EditorCall
75001
+ && statementNode.findDirectTokenByText("REPORT")) {
75002
+ message = "EDITOR-CALL FOR REPORT";
75003
+ }
74742
75004
  if (message) {
74743
75005
  issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
74744
75006
  }
@@ -75740,6 +76002,7 @@ Make sure to test the downported code, it might not always be completely correct
75740
76002
  const lowConfig = this.lowReg.getConfig().get();
75741
76003
  highConfig.syntax.errorNamespace = lowConfig.syntax.errorNamespace;
75742
76004
  highConfig.syntax.globalConstants = lowConfig.syntax.globalConstants;
76005
+ highConfig.syntax.ambigiousVoids = lowConfig.syntax.ambigiousVoids;
75743
76006
  highConfig.syntax.globalMacros = lowConfig.syntax.globalMacros;
75744
76007
  this.highReg = new registry_1.Registry();
75745
76008
  for (const o of this.lowReg.getObjects()) {
@@ -78381,7 +78644,7 @@ ${indentation} output = ${uniqueName}.\n`;
78381
78644
  }
78382
78645
  }
78383
78646
  }
78384
- if (fix === undefined && high.findAllExpressions(Expressions.NewObject)) {
78647
+ if (fix === undefined) {
78385
78648
  const found = high.findFirstExpression(Expressions.NewObject);
78386
78649
  if (found === undefined) {
78387
78650
  return undefined;
@@ -78555,12 +78818,13 @@ class DynproChecks {
78555
78818
  const ret = [];
78556
78819
  for (let index = 0; index < dynpro.fields.length; index++) {
78557
78820
  const current = dynpro.fields[index];
78558
- if (current.name === undefined || current.type === "FRAME") {
78821
+ if (current.name === undefined || current.type === "FRAME" || this.hasContainerRelativeCoordinates(current)) {
78559
78822
  continue;
78560
78823
  }
78561
78824
  for (let compare = index + 1; compare < dynpro.fields.length; compare++) {
78562
78825
  const other = dynpro.fields[compare];
78563
- if (other.name === undefined || other.type === "FRAME" || this.overlaps(current, other) === false) {
78826
+ if (other.name === undefined || other.type === "FRAME" || this.hasContainerRelativeCoordinates(other)
78827
+ || this.overlaps(current, other) === false) {
78564
78828
  continue;
78565
78829
  }
78566
78830
  const message = `Screen ${dynpro.number}, ${current.type} ${current.name} and ${other.type} ${other.name} are overlapping`;
@@ -78569,6 +78833,9 @@ class DynproChecks {
78569
78833
  }
78570
78834
  return ret;
78571
78835
  }
78836
+ hasContainerRelativeCoordinates(field) {
78837
+ return field.contType === "TABLE_CTRL" || field.contType === "LOOP" || field.contType === "STRIP_CTRL";
78838
+ }
78572
78839
  overlaps(first, second) {
78573
78840
  if (first.line === 0 || second.line === 0 || first.column === 0 || second.column === 0) {
78574
78841
  return false;
@@ -86018,7 +86285,6 @@ const Expressions = __importStar(__webpack_require__(/*! ../abap/2_statements/ex
86018
86285
  const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "./node_modules/@abaplint/core/build/src/rules/_abap_rule.js");
86019
86286
  const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./node_modules/@abaplint/core/build/src/rules/_basic_rule_config.js");
86020
86287
  const issue_1 = __webpack_require__(/*! ../issue */ "./node_modules/@abaplint/core/build/src/issue.js");
86021
- const tokens_1 = __webpack_require__(/*! ../abap/1_lexer/tokens */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/index.js");
86022
86288
  const expressions_1 = __webpack_require__(/*! ../abap/2_statements/expressions */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
86023
86289
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
86024
86290
  class NamesNoDashConf extends _basic_rule_config_1.BasicRuleConfig {
@@ -86058,32 +86324,26 @@ class NamesNoDash extends _abap_rule_1.ABAPRule {
86058
86324
  if (obj.getType() !== "CLAS" && obj.getType() !== "INTF") {
86059
86325
  for (const form of struc.findAllStatements(Statements.Form)) {
86060
86326
  const expr = form.findFirstExpression(expressions_1.FormName);
86061
- for (const token of expr.getTokens()) {
86062
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
86063
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86064
- issues.push(issue);
86065
- break;
86066
- }
86327
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
86328
+ if (token) {
86329
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86330
+ issues.push(issue);
86067
86331
  }
86068
86332
  }
86069
86333
  for (const form of struc.findAllStatements(Statements.Parameter)) {
86070
86334
  const expr = form.findFirstExpression(Expressions.FieldSub);
86071
- for (const token of expr.getTokens()) {
86072
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
86073
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86074
- issues.push(issue);
86075
- break;
86076
- }
86335
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
86336
+ if (token) {
86337
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86338
+ issues.push(issue);
86077
86339
  }
86078
86340
  }
86079
86341
  for (const form of struc.findAllStatements(Statements.SelectOption)) {
86080
86342
  const expr = form.findFirstExpression(Expressions.FieldSub);
86081
- for (const token of expr.getTokens()) {
86082
- if (token instanceof tokens_1.Dash || token instanceof tokens_1.DashW) {
86083
- const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86084
- issues.push(issue);
86085
- break;
86086
- }
86343
+ const token = expr === null || expr === void 0 ? void 0 : expr.findDirectTokenByText("-");
86344
+ if (token) {
86345
+ const issue = issue_1.Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
86346
+ issues.push(issue);
86087
86347
  }
86088
86348
  }
86089
86349
  }
@@ -88185,11 +88445,11 @@ ENDIF.`,
88185
88445
  }
88186
88446
  }
88187
88447
  else {
88188
- const classNameExpression = staNode.findAllExpressions(Expressions.ClassName);
88189
- const methodNameExpression = staNode.findAllExpressions(Expressions.MethodName);
88190
- if (classNameExpression.length !== 0 && methodNameExpression.length !== 0) {
88191
- const className = classNameExpression[0].concatTokens();
88192
- const methodName = methodNameExpression[0].concatTokens();
88448
+ const classNameExpression = staNode.findFirstExpression(Expressions.ClassName);
88449
+ const methodNameExpression = staNode.findFirstExpression(Expressions.MethodName);
88450
+ if (classNameExpression && methodNameExpression) {
88451
+ const className = classNameExpression.concatTokens();
88452
+ const methodName = methodNameExpression.concatTokens();
88193
88453
  if (className === "cl_abap_regex") {
88194
88454
  if (methodName === "create_posix") {
88195
88455
  const issue = issue_1.Issue.atStatement(file, staNode, "create_posix obsolete, use create_pcre", this.getMetadata().key, this.conf.severity);
@@ -92351,12 +92611,12 @@ class ShortCase extends _abap_rule_1.ABAPRule {
92351
92611
  return [];
92352
92612
  }
92353
92613
  for (const c of struc.findAllStructures(Structures.Case)) {
92354
- const clist = c.findDirectStatements(Statements.Case);
92355
- if (clist.length > 0 && this.conf.allow && this.conf.allow.find((e) => { return e === clist[0].getTokens()[1].getStr(); })) {
92614
+ const caseStatement = c.findDirectStatement(Statements.Case);
92615
+ if (caseStatement && this.conf.allow && this.conf.allow.find((e) => { return e === caseStatement.getTokens()[1].getStr(); })) {
92356
92616
  continue;
92357
92617
  }
92358
92618
  if (c.findDirectStructures(Structures.When).length <= this.conf.length) {
92359
- if (c.findAllExpressions(Expressions.Or).length > 0) {
92619
+ if (c.findFirstExpression(Expressions.Or)) {
92360
92620
  continue;
92361
92621
  }
92362
92622
  const issue = issue_1.Issue.atToken(file, c.getFirstToken(), this.getMessage(), this.getMetadata().key, this.conf.severity);
@@ -94180,9 +94440,9 @@ class TryWithoutCatch extends _abap_rule_1.ABAPRule {
94180
94440
  }
94181
94441
  const tries = stru.findAllStructures(structures_1.Try);
94182
94442
  for (const t of tries) {
94183
- const clean = t.findDirectStructures(structures_1.Cleanup);
94184
- const c = t.findDirectStructures(structures_1.Catch);
94185
- if (c.length === 0 && clean.length === 0) {
94443
+ const clean = t.findDirectStructure(structures_1.Cleanup);
94444
+ const c = t.findDirectStructure(structures_1.Catch);
94445
+ if (c === undefined && clean === undefined) {
94186
94446
  const issue = issue_1.Issue.atToken(file, t.getFirstToken(), this.getMessage(), this.getMetadata().key, this.conf.severity);
94187
94447
  issues.push(issue);
94188
94448
  }
@@ -95091,6 +95351,7 @@ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./
95091
95351
  const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
95092
95352
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
95093
95353
  const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
95354
+ const tokens_1 = __webpack_require__(/*! ../abap/1_lexer/tokens */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/index.js");
95094
95355
  class UnnecessaryPragmaConf extends _basic_rule_config_1.BasicRuleConfig {
95095
95356
  constructor() {
95096
95357
  super(...arguments);
@@ -95159,6 +95420,17 @@ DATA: BEGIN OF blah ##NEEDED,
95159
95420
  for (let i = 0; i < statements.length; i++) {
95160
95421
  const statement = statements[i];
95161
95422
  const nextStatement = statements[i + 1];
95423
+ if (statement.get() instanceof _statement_1.Empty
95424
+ && statement.getChildren().length === 1) {
95425
+ const tokens = statement.getTokens();
95426
+ if (tokens.length === 1
95427
+ && tokens[0] instanceof tokens_1.Pragma) {
95428
+ const message = "Pragma without a statement can be removed";
95429
+ const fix = edit_helper_1.EditHelper.deleteToken(file, tokens[0]);
95430
+ issues.push(issue_1.Issue.atToken(file, tokens[0], message, this.getMetadata().key, this.conf.severity, fix));
95431
+ continue;
95432
+ }
95433
+ }
95162
95434
  if (statement.get() instanceof Statements.EndTry) {
95163
95435
  noHandler = false;
95164
95436
  }
@@ -97872,9 +98144,11 @@ const include_graph_1 = __webpack_require__(/*! ./utils/include_graph */ "./node
97872
98144
  class SkipLogic {
97873
98145
  constructor(reg) {
97874
98146
  this.reg = reg;
98147
+ this.includeGraph = undefined;
97875
98148
  this.tobj = undefined;
97876
98149
  }
97877
98150
  skip(obj) {
98151
+ var _a;
97878
98152
  const global = this.reg.getConfig().getGlobal();
97879
98153
  if (global.skipGeneratedGatewayClasses === true
97880
98154
  && obj instanceof objects_1.Class
@@ -97884,9 +98158,9 @@ class SkipLogic {
97884
98158
  else if (global.skipIncludesWithoutMain === true
97885
98159
  && obj instanceof objects_1.Program
97886
98160
  && obj.isInclude() === true) {
97887
- const ig = new include_graph_1.IncludeGraph(this.reg);
98161
+ (_a = this.includeGraph) !== null && _a !== void 0 ? _a : (this.includeGraph = new include_graph_1.IncludeGraph(this.reg));
97888
98162
  const file = obj.getMainABAPFile();
97889
- if (file && ig.listMainForInclude(file.getFilename()).length === 0) {
98163
+ if (file && this.includeGraph.listMainForInclude(file.getFilename()).length === 0) {
97890
98164
  return true;
97891
98165
  }
97892
98166
  }
@@ -114194,7 +114468,7 @@ class SelectTranspiler {
114194
114468
  }
114195
114469
  dynamicSQLClause(keyword, code) {
114196
114470
  return `(${code} instanceof abap.types.Table || ${code} instanceof abap.types.HashedTable`
114197
- + ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(" "))`
114471
+ + ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(", "))`
114198
114472
  + ` : "${keyword} " + ${code}.get())`;
114199
114473
  }
114200
114474
  isWhereExpression(node, expression) {