@abaplint/transpiler-cli 2.13.36 → 2.13.38

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 +376 -174
  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;
908
941
  }
909
- return this.raw.substr(this.offset + 1, 2);
942
+ return this.raw.charCodeAt(o);
943
+ }
944
+ charCodeAt(o) {
945
+ if (o < 0 || o >= this.raw.length) {
946
+ return EOF;
947
+ }
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
  }
@@ -2926,7 +2978,12 @@ class Alternative {
2926
2978
  const result = [];
2927
2979
  for (const sequ of this.list) {
2928
2980
  const temp = sequ.run(r);
2929
- result.push(...temp);
2981
+ if (temp.length === 1) {
2982
+ result.push(temp[0]);
2983
+ }
2984
+ else {
2985
+ result.push(...temp);
2986
+ }
2930
2987
  }
2931
2988
  return result;
2932
2989
  }
@@ -2984,7 +3041,12 @@ class AlternativePriority {
2984
3041
  // console.log(seq.toStr());
2985
3042
  const temp = sequ.run(r);
2986
3043
  if (temp.length > 0) {
2987
- result.push(...temp);
3044
+ if (temp.length === 1) {
3045
+ result.push(temp[0]);
3046
+ }
3047
+ else {
3048
+ result.push(...temp);
3049
+ }
2988
3050
  break;
2989
3051
  }
2990
3052
  }
@@ -3100,7 +3162,7 @@ function regex(r) {
3100
3162
  return new Regex(r);
3101
3163
  }
3102
3164
  function tok(t) {
3103
- return new Token(t.name);
3165
+ return new Token(t);
3104
3166
  }
3105
3167
  const expressionSingletons = {};
3106
3168
  const stringSingletons = {};
@@ -3214,6 +3276,29 @@ class StopBefore2 {
3214
3276
  function stopBefore(t1, t2) {
3215
3277
  return new StopBefore2(t1, t2);
3216
3278
  }
3279
+ class StopBefore1 {
3280
+ constructor(words) { this.words = words.map(w => w.toUpperCase()); }
3281
+ listKeywords() { return []; }
3282
+ getUsing() { return []; }
3283
+ run(r) {
3284
+ var _a;
3285
+ const result = [];
3286
+ for (const input of r) {
3287
+ const next = (_a = input.peek()) === null || _a === void 0 ? void 0 : _a.getUpperStr();
3288
+ if (next !== undefined && this.words.includes(next)) {
3289
+ continue;
3290
+ }
3291
+ result.push(input);
3292
+ }
3293
+ return result;
3294
+ }
3295
+ railroad() { return "Railroad.Terminal('stopBefore(" + this.words.join("|") + ")')"; }
3296
+ toStr() { return "stopBefore(" + this.words.join(",") + ")"; }
3297
+ first() { return [""]; }
3298
+ }
3299
+ function stopBefore1(...words) {
3300
+ return new StopBefore1(words);
3301
+ }
3217
3302
  //# sourceMappingURL=combi.js.map
3218
3303
 
3219
3304
  /***/ },
@@ -4243,8 +4328,8 @@ const combi_1 = __webpack_require__(/*! ../combi */ "./node_modules/@abaplint/co
4243
4328
  const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
4244
4329
  class ComponentChainSimple extends combi_1.Expression {
4245
4330
  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));
4331
+ const chain = (0, combi_1.starPrio)((0, combi_1.altPrio)(_1.Dereference, (0, combi_1.seq)(_1.ArrowOrDash, _1.ComponentName)));
4332
+ const ret = (0, combi_1.seq)(_1.ComponentName, chain, (0, combi_1.optPrio)(_1.FieldOffset), (0, combi_1.optPrio)(_1.FieldLength));
4248
4333
  return ret;
4249
4334
  }
4250
4335
  }
@@ -7186,7 +7271,7 @@ const combi_1 = __webpack_require__(/*! ../combi */ "./node_modules/@abaplint/co
7186
7271
  const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/abap/2_statements/expressions/index.js");
7187
7272
  class ParameterListS extends combi_1.Expression {
7188
7273
  getRunnable() {
7189
- return (0, combi_1.plus)(_1.ParameterS);
7274
+ return (0, combi_1.plusPrio)(_1.ParameterS);
7190
7275
  }
7191
7276
  }
7192
7277
  exports.ParameterListS = ParameterListS;
@@ -11277,10 +11362,10 @@ class TypeTableKey extends combi_1.Expression {
11277
11362
  const uniqueness = (0, combi_1.alt)("NON-UNIQUE", "UNIQUE");
11278
11363
  const defaultKey = "DEFAULT KEY";
11279
11364
  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));
11365
+ 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
11366
  const further = (0, combi_1.seq)((0, combi_1.alt)("WITHOUT", "WITH"), "FURTHER SECONDARY KEYS");
11282
11367
  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"));
11368
+ 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
11369
  return key;
11285
11370
  }
11286
11371
  }
@@ -11349,7 +11434,7 @@ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src
11349
11434
  const version_1 = __webpack_require__(/*! ../../../version */ "./node_modules/@abaplint/core/build/src/version.js");
11350
11435
  class ValueBody extends combi_1.Expression {
11351
11436
  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)));
11437
+ 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
11438
  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
11439
  return (0, combi_1.optPrio)((0, combi_1.altPrio)(strucOrTab, (0, combi_1.seq)(_1.Source, (0, combi_1.optPrio)(tabdef))));
11355
11440
  }
@@ -11573,6 +11658,7 @@ const expand_macros_1 = __webpack_require__(/*! ./expand_macros */ "./node_modul
11573
11658
  const tokens_1 = __webpack_require__(/*! ../1_lexer/tokens */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/index.js");
11574
11659
  const _select_reclassify_1 = __webpack_require__(/*! ./_select_reclassify */ "./node_modules/@abaplint/core/build/src/abap/2_statements/_select_reclassify.js");
11575
11660
  exports.STATEMENT_MAX_TOKENS = 20000;
11661
+ const EMPTY_PRAGMAS = Object.freeze([]);
11576
11662
  class StatementMap {
11577
11663
  constructor() {
11578
11664
  this.map = {};
@@ -11771,9 +11857,19 @@ class StatementParser {
11771
11857
  return statement;
11772
11858
  }
11773
11859
  removePragma(tokens) {
11860
+ let hasPragma = false;
11861
+ // skip the last token as it is the punctuation
11862
+ for (let i = 0; i < tokens.length - 1; i++) {
11863
+ if (tokens[i] instanceof Tokens.Pragma) {
11864
+ hasPragma = true;
11865
+ break;
11866
+ }
11867
+ }
11868
+ if (hasPragma === false) {
11869
+ return { tokens: tokens.slice(0, tokens.length - 1), pragmas: EMPTY_PRAGMAS };
11870
+ }
11774
11871
  const result = [];
11775
11872
  const pragmas = [];
11776
- // skip the last token as it is the punctuation
11777
11873
  for (let i = 0; i < tokens.length - 1; i++) {
11778
11874
  const t = tokens[i];
11779
11875
  if (t instanceof Tokens.Pragma) {
@@ -25147,16 +25243,20 @@ class BuiltIn {
25147
25243
  return def.predicate;
25148
25244
  }
25149
25245
  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" })));
25246
+ // the identifiers are identical for every object, share them to reduce memory usage
25247
+ if (BuiltIn.typesCache === undefined) {
25248
+ const ret = this.buildSY();
25249
+ {
25250
+ const id = new tokens_1.Identifier(new position_1.Position(1, 1), "abap_bool");
25251
+ ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, new basic_1.CharacterType(1, { qualifiedName: "ABAP_BOOL", ddicName: "ABAP_BOOL" })));
25252
+ }
25253
+ {
25254
+ const id = new tokens_1.Identifier(new position_1.Position(1, 1), "cursor");
25255
+ ret.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.IntegerType.get({ qualifiedName: "CURSOR", ddicName: "CURSOR" })));
25256
+ }
25257
+ BuiltIn.typesCache = ret;
25158
25258
  }
25159
- return ret;
25259
+ return BuiltIn.typesCache;
25160
25260
  }
25161
25261
  get(extras) {
25162
25262
  const ret = [];
@@ -25189,10 +25289,17 @@ class BuiltIn {
25189
25289
  BuiltIn.getCache.push(this.buildConstant("space", new basic_1.CharacterType(1, { derivedFromConstant: true }), "' '"));
25190
25290
  }
25191
25291
  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 */], "'?'"));
25292
+ // the extras are identical for every object, share them to reduce memory usage
25293
+ const key = extras.join("|");
25294
+ if (key !== BuiltIn.extrasCacheKey) {
25295
+ BuiltIn.extrasCacheKey = key;
25296
+ BuiltIn.extrasCache = [];
25297
+ for (const e of extras) {
25298
+ const id = new tokens_1.Identifier(new position_1.Position(this.row++, 1), e);
25299
+ BuiltIn.extrasCache.push(new _typed_identifier_1.TypedIdentifier(id, BuiltIn.filename, basic_1.VoidType.get(e), ["read_only" /* IdentifierMeta.ReadOnly */, "built-in" /* IdentifierMeta.BuiltIn */], "'?'"));
25300
+ }
25195
25301
  }
25302
+ ret.push(...BuiltIn.extrasCache);
25196
25303
  return ret;
25197
25304
  }
25198
25305
  /////////////////////////////
@@ -25401,6 +25508,9 @@ exports.BuiltIn = BuiltIn;
25401
25508
  BuiltIn.filename = "_builtin.prog.abap";
25402
25509
  BuiltIn.counter = 1;
25403
25510
  BuiltIn.getCache = [];
25511
+ BuiltIn.typesCache = undefined;
25512
+ BuiltIn.extrasCacheKey = undefined;
25513
+ BuiltIn.extrasCache = [];
25404
25514
  // todo: "pcre" vs "regex", only one of these parameters are allowed
25405
25515
  // todo: "pcre", only possible from 755
25406
25516
  BuiltIn.methods = {
@@ -29690,6 +29800,15 @@ class ComponentChain {
29690
29800
  if (i === 0 && child.concatTokens().toUpperCase() === "TABLE_LINE") {
29691
29801
  continue;
29692
29802
  }
29803
+ else if (child.get() instanceof Expressions.Dereference) {
29804
+ if (!(context instanceof basic_1.DataReference)) {
29805
+ const message = "Not a data reference, cannot be dereferenced";
29806
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, child.getFirstToken(), message));
29807
+ return void_type_1.VoidType.get(_syntax_input_1.CheckSyntaxKey);
29808
+ }
29809
+ context = context.getType();
29810
+ continue;
29811
+ }
29693
29812
  else if (child.get() instanceof Expressions.ArrowOrDash) {
29694
29813
  const concat = child.concatTokens();
29695
29814
  if (concat === "-") {
@@ -48257,15 +48376,21 @@ exports.CrossIncludeMacros = CrossIncludeMacros;
48257
48376
 
48258
48377
  Object.defineProperty(exports, "__esModule", ({ value: true }));
48259
48378
  exports.AbstractNode = void 0;
48379
+ // shared constant, so nodes without children don't waste memory on empty arrays
48380
+ const EMPTY = Object.freeze([]);
48260
48381
  class AbstractNode {
48261
48382
  constructor() {
48262
- this.children = [];
48383
+ this.children = EMPTY;
48263
48384
  }
48264
48385
  addChild(n) {
48386
+ if (this.children === EMPTY) {
48387
+ this.children = [];
48388
+ }
48265
48389
  this.children.push(n);
48266
48390
  }
48267
48391
  setChildren(children) {
48268
- this.children = children;
48392
+ // copy, input arrays are built via push() and carry over-allocated backing stores
48393
+ this.children = children.slice();
48269
48394
  }
48270
48395
  getChildren() {
48271
48396
  return this.children;
@@ -48298,6 +48423,7 @@ const _abstract_node_1 = __webpack_require__(/*! ./_abstract_node */ "./node_mod
48298
48423
  class ExpressionNode extends _abstract_node_1.AbstractNode {
48299
48424
  constructor(expression) {
48300
48425
  super();
48426
+ this.tokenCount = 0;
48301
48427
  this.expression = expression;
48302
48428
  }
48303
48429
  addChild(_n) {
@@ -48306,12 +48432,15 @@ class ExpressionNode extends _abstract_node_1.AbstractNode {
48306
48432
  get() {
48307
48433
  return this.expression;
48308
48434
  }
48309
- countTokens() {
48310
- let ret = 0;
48311
- for (const c of this.getChildren()) {
48312
- ret = ret + c.countTokens();
48435
+ setChildren(children) {
48436
+ super.setChildren(children);
48437
+ for (const child of this.getChildren()) {
48438
+ this.tokenCount = this.tokenCount + child.countTokens();
48313
48439
  }
48314
- return ret;
48440
+ return this;
48441
+ }
48442
+ countTokens() {
48443
+ return this.tokenCount;
48315
48444
  }
48316
48445
  getFirstToken() {
48317
48446
  for (const child of this.getChildren()) {
@@ -48621,17 +48750,13 @@ const string_template_middle_1 = __webpack_require__(/*! ../1_lexer/tokens/strin
48621
48750
  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
48751
  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
48752
  const string_template_1 = __webpack_require__(/*! ../1_lexer/tokens/string_template */ "./node_modules/@abaplint/core/build/src/abap/1_lexer/tokens/string_template.js");
48753
+ const EMPTY_PRAGMAS = Object.freeze([]);
48624
48754
  class StatementNode extends _abstract_node_1.AbstractNode {
48625
48755
  constructor(statement, colon, pragmas) {
48626
48756
  super();
48627
48757
  this.statement = statement;
48628
48758
  this.colon = colon;
48629
- if (pragmas) {
48630
- this.pragmas = pragmas;
48631
- }
48632
- else {
48633
- this.pragmas = [];
48634
- }
48759
+ this.pragmas = pragmas !== null && pragmas !== void 0 ? pragmas : EMPTY_PRAGMAS;
48635
48760
  }
48636
48761
  get() {
48637
48762
  return this.statement;
@@ -48646,7 +48771,7 @@ class StatementNode extends _abstract_node_1.AbstractNode {
48646
48771
  if (children.length === 0) {
48647
48772
  throw new Error("statement: zero children");
48648
48773
  }
48649
- this.children = children;
48774
+ super.setChildren(children);
48650
48775
  return this;
48651
48776
  }
48652
48777
  getStart() {
@@ -49227,6 +49352,7 @@ exports.StructureNode = StructureNode;
49227
49352
 
49228
49353
  Object.defineProperty(exports, "__esModule", ({ value: true }));
49229
49354
  exports.TokenNode = void 0;
49355
+ const EMPTY_CHILDREN = Object.freeze([]);
49230
49356
  class TokenNode {
49231
49357
  constructor(token) {
49232
49358
  this.token = token;
@@ -49238,7 +49364,7 @@ class TokenNode {
49238
49364
  throw new Error("TokenNode, Method not implemented.");
49239
49365
  }
49240
49366
  getChildren() {
49241
- return [];
49367
+ return EMPTY_CHILDREN;
49242
49368
  }
49243
49369
  concatTokens() {
49244
49370
  return this.token.getStr();
@@ -51317,6 +51443,7 @@ class ClassDefinition extends _identifier_1.Identifier {
51317
51443
  // perform checks after everything has been initialized
51318
51444
  this.checkMethodsFromSuperClasses(input);
51319
51445
  this.checkMethodNameLength(input);
51446
+ this.checkClassConstructorStatic(input);
51320
51447
  }
51321
51448
  getFriends() {
51322
51449
  return this.friends;
@@ -51380,6 +51507,13 @@ class ClassDefinition extends _identifier_1.Identifier {
51380
51507
  }
51381
51508
  }
51382
51509
  }
51510
+ checkClassConstructorStatic(input) {
51511
+ for (const m of this.methodDefs.getAll()) {
51512
+ if (m.getName().toUpperCase() === "CLASS_CONSTRUCTOR" && m.isStatic() === false) {
51513
+ input.issues.push((0, _syntax_input_1.syntaxIssue)(input, m.getToken(), "CLASS_CONSTRUCTOR must be static"));
51514
+ }
51515
+ }
51516
+ }
51383
51517
  checkMethodsFromSuperClasses(input) {
51384
51518
  var _a;
51385
51519
  const scope = input.scope;
@@ -53087,8 +53221,9 @@ var Mode;
53087
53221
  (function (Mode) {
53088
53222
  Mode[Mode["Default"] = 0] = "Default";
53089
53223
  Mode[Mode["String"] = 1] = "String";
53090
- Mode[Mode["SingleLineComment"] = 2] = "SingleLineComment";
53091
- Mode[Mode["MultiLineComment"] = 3] = "MultiLineComment";
53224
+ Mode[Mode["DoubleQuoteString"] = 2] = "DoubleQuoteString";
53225
+ Mode[Mode["SingleLineComment"] = 3] = "SingleLineComment";
53226
+ Mode[Mode["MultiLineComment"] = 4] = "MultiLineComment";
53092
53227
  })(Mode || (Mode = {}));
53093
53228
  class Result {
53094
53229
  constructor() {
@@ -53148,6 +53283,23 @@ class CDSLexer {
53148
53283
  }
53149
53284
  continue;
53150
53285
  }
53286
+ // double-quote string handling
53287
+ if (mode === Mode.DoubleQuoteString) {
53288
+ build += next;
53289
+ if (next === "\\" && nextNext === "\"") {
53290
+ build += stream.takeNext();
53291
+ col++;
53292
+ }
53293
+ else if (next === "\"" && nextNext === "\"") {
53294
+ build += stream.takeNext();
53295
+ col++;
53296
+ }
53297
+ else if (next === "\"") {
53298
+ build = result.add(build, row, col, mode);
53299
+ mode = Mode.Default;
53300
+ }
53301
+ continue;
53302
+ }
53151
53303
  // single line comment handling
53152
53304
  if (mode === Mode.SingleLineComment) {
53153
53305
  if (next === "\n") {
@@ -53194,6 +53346,11 @@ class CDSLexer {
53194
53346
  mode = Mode.String;
53195
53347
  build += next;
53196
53348
  break;
53349
+ case "\"":
53350
+ build = result.add(build, row, col, mode);
53351
+ mode = Mode.DoubleQuoteString;
53352
+ build += next;
53353
+ break;
53197
53354
  case " ":
53198
53355
  case "\t":
53199
53356
  build = result.add(build, row, col, mode);
@@ -53608,7 +53765,9 @@ class CDSAs extends combi_1.Expression {
53608
53765
  getRunnable() {
53609
53766
  const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
53610
53767
  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)));
53768
+ const ident = (0, combi_1.regex)(/^\w+$/);
53769
+ const namespacedAlias = (0, combi_1.seq)(ident, "/", ident, "/", ident);
53770
+ return (0, combi_1.seq)("AS", (0, combi_1.altPrio)(namespacedAlias, _1.CDSName), (0, combi_1.optPrio)((0, combi_1.altPrio)(redirected, colonType)));
53612
53771
  }
53613
53772
  }
53614
53773
  exports.CDSAs = CDSAs;
@@ -53642,8 +53801,9 @@ class CDSAssociation extends combi_1.Expression {
53642
53801
  // Numeric OF form: "association of [0..1] to Target on ..."
53643
53802
  const ofNumericForm = (0, combi_1.seq)("ASSOCIATION", "OF", numericCardinality, "TO", _1.CDSRelation, "ON", _1.CDSCondition);
53644
53803
  // "association [0..1] to Target as _Alias on condition" — standard form
53804
+ const parentForm = (0, combi_1.seq)("ASSOCIATION", "TO", "PARENT", _1.CDSRelation);
53645
53805
  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);
53806
+ return (0, combi_1.altPrio)(ofTextForm, ofNumericForm, standardForm, parentForm);
53647
53807
  }
53648
53808
  }
53649
53809
  exports.CDSAssociation = CDSAssociation;
@@ -53900,11 +54060,9 @@ class CDSDefineHierarchy extends combi_1.Expression {
53900
54060
  const directory = (0, combi_1.seq)("DIRECTORY", _1.CDSName, "FILTER", "BY", _1.CDSCondition);
53901
54061
  // DATE PERIOD: period from <field> to <field> [valid from :p to :p]
53902
54062
  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)
54063
+ const depthValue = (0, combi_1.altPrio)(_1.CDSString, _1.CDSInteger, _1.CDSPrefixedName);
53906
54064
  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"))));
54065
+ 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
54066
  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
54067
  }
53910
54068
  }
@@ -53952,10 +54110,10 @@ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src
53952
54110
  const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node_modules/@abaplint/core/build/src/abap/2_statements/combi.js");
53953
54111
  class CDSDefineTableEntity extends combi_1.Expression {
53954
54112
  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));
54113
+ // Inline `{ ... }` body: one or more table-field entries. Each entry is
54114
+ // wrapped in a CDSTableField node so downstream tooling can pair each
54115
+ // field name with its own annotations.
54116
+ const inlineBody = (0, combi_1.plus)(_1.CDSTableField);
53959
54117
  const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
53960
54118
  const elements = (0, combi_1.seq)((0, combi_1.str)("{"), (0, combi_1.altPrio)("*", elementList), (0, combi_1.str)("}"));
53961
54119
  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 +54141,7 @@ const cds_name_1 = __webpack_require__(/*! ./cds_name */ "./node_modules/@abapli
53983
54141
  class CDSDefineTableFunction extends combi_1.Expression {
53984
54142
  getRunnable() {
53985
54143
  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)(";"));
54144
+ 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
54145
  }
53988
54146
  }
53989
54147
  exports.CDSDefineTableFunction = CDSDefineTableFunction;
@@ -54010,8 +54168,10 @@ const cds_with_parameters_1 = __webpack_require__(/*! ./cds_with_parameters */ "
54010
54168
  class CDSDefineView extends combi_1.Expression {
54011
54169
  getRunnable() {
54012
54170
  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)(";"));
54171
+ const parenSelect = (0, combi_1.seq)("(", cds_select_1.CDSSelect, ")");
54172
+ const unionBranch = (0, combi_1.altPrio)(parenSelect, cds_select_1.CDSSelect);
54173
+ 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);
54174
+ 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
54175
  }
54016
54176
  }
54017
54177
  exports.CDSDefineView = CDSDefineView;
@@ -54038,11 +54198,15 @@ class CDSElement extends combi_1.Expression {
54038
54198
  const redirected = (0, combi_1.seq)(": REDIRECTED TO", (0, combi_1.optPrio)((0, combi_1.altPrio)("PARENT", "COMPOSITION CHILD")), _1.CDSName);
54039
54199
  const colonThing = (0, combi_1.seq)(":", (0, combi_1.altPrio)(_1.CDSType, _1.CDSName, "LOCALIZED"));
54040
54200
  const extensionWildcard = (0, combi_1.seq)("$extension", ".", "*");
54041
- const includeElement = (0, combi_1.seq)("INCLUDE", _1.CDSPrefixedName);
54201
+ const excludingNames = (0, combi_1.seq)(_1.CDSName, (0, combi_1.starPrio)((0, combi_1.seq)(",", _1.CDSName)));
54202
+ const excluding = (0, combi_1.seq)("EXCLUDING", "{", excludingNames, "}");
54203
+ const includeElement = (0, combi_1.seq)("INCLUDE", _1.CDSPrefixedName, (0, combi_1.optPrio)(excluding), (0, combi_1.optPrio)("SIGNATURE ONLY"));
54042
54204
  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);
54205
+ 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)));
54206
+ const funcWithPath = (0, combi_1.seq)(_1.CDSFunction, (0, combi_1.plusPrio)(pathSegment));
54207
+ 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
54208
  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));
54209
+ 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
54210
  }
54047
54211
  }
54048
54212
  exports.CDSElement = CDSElement;
@@ -54067,7 +54231,9 @@ class CDSExtendView extends combi_1.Expression {
54067
54231
  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
54232
  const valueNested = (0, combi_1.seq)("{", namedot, (0, combi_1.star)((0, combi_1.seq)(",", namedot)), "}");
54069
54233
  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)(";"));
54234
+ const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
54235
+ const elementNested = (0, combi_1.seq)("{", (0, combi_1.altPrio)("*", elementList), "}");
54236
+ 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
54237
  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
54238
  const assocOrComp = (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), _1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation), ";");
54073
54239
  const entityBody = (0, combi_1.seq)("{", (0, combi_1.plus)((0, combi_1.alt)(field, assocOrComp)), "}");
@@ -54309,7 +54475,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54309
54475
  class CDSName extends combi_1.Expression {
54310
54476
  getRunnable() {
54311
54477
  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_]+$/));
54478
+ 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
54479
  }
54314
54480
  }
54315
54481
  exports.CDSName = CDSName;
@@ -54357,7 +54523,9 @@ class CDSParametersSelect extends combi_1.Expression {
54357
54523
  getRunnable() {
54358
54524
  const name = (0, combi_1.seq)(_1.CDSName, (0, combi_1.opt)((0, combi_1.seq)(".", _1.CDSName)));
54359
54525
  const value = (0, combi_1.alt)(_1.CDSInteger, name, _1.CDSString);
54360
- const nameValue = (0, combi_1.seq)(name, ":", value);
54526
+ const colonPair = (0, combi_1.seq)(name, ":", value, (0, combi_1.optPrio)("DEFAULT"));
54527
+ const arrowPair = (0, combi_1.seq)(name, "=", ">", value);
54528
+ const nameValue = (0, combi_1.altPrio)(colonPair, arrowPair);
54361
54529
  return (0, combi_1.seq)("(", nameValue, (0, combi_1.star)((0, combi_1.seq)(",", nameValue)), ")");
54362
54530
  }
54363
54531
  }
@@ -54391,13 +54559,13 @@ class CDSPrefixedName extends combi_1.Expression {
54391
54559
  const cardinalityJoin = (0, combi_1.seq)("[", cardSpec, ":", joinType, "]");
54392
54560
  const cardinalityJoinWhere = (0, combi_1.seq)("[", cardSpec, ":", joinType, "WHERE", cds_condition_1.CDSCondition, "]");
54393
54561
  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");
54562
+ 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
54563
  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
54564
  const cardNum = (0, combi_1.altPrio)(cds_integer_1.CDSInteger, "*");
54397
54565
  const rangeCard = (0, combi_1.seq)(cds_integer_1.CDSInteger, ".", ".", cardNum);
54398
54566
  const rangeCardFilter = (0, combi_1.seq)("[", rangeCard, ":", cds_condition_1.CDSCondition, "]");
54399
54567
  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));
54568
+ 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
54569
  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
54570
  }
54403
54571
  }
@@ -54442,7 +54610,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54442
54610
  class CDSRelation extends combi_1.Expression {
54443
54611
  getRunnable() {
54444
54612
  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));
54613
+ 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
54614
  }
54447
54615
  }
54448
54616
  exports.CDSRelation = CDSRelation;
@@ -54470,11 +54638,12 @@ class CDSSelect extends combi_1.Expression {
54470
54638
  const distinct = (0, combi_1.str)("DISTINCT");
54471
54639
  const elementList = (0, combi_1.seq)(_1.CDSElement, (0, combi_1.star)((0, combi_1.seq)(",", _1.CDSElement)), (0, combi_1.opt)(","));
54472
54640
  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)), ")");
54641
+ const aspectValue = (0, combi_1.altPrio)(_1.CDSString, _1.CDSPrefixedName);
54642
+ const aspectBinding = (0, combi_1.seq)(_1.CDSPrefixedName, "=", ">", aspectValue);
54643
+ 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
54644
  const parenSelect = (0, combi_1.seq)("(", CDSSelect, ")");
54476
54645
  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))));
54646
+ 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
54647
  }
54479
54648
  }
54480
54649
  exports.CDSSelect = CDSSelect;
@@ -54497,10 +54666,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54497
54666
  class CDSSource extends combi_1.Expression {
54498
54667
  getRunnable() {
54499
54668
  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)));
54669
+ 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
54670
  const funcSingleSource = (0, combi_1.seq)(_1.CDSFunction, (0, combi_1.opt)((0, combi_1.altPrio)(_1.CDSAs, _1.CDSName)));
54505
54671
  const parenSource = (0, combi_1.seq)("(", (0, combi_1.altPrio)(CDSSource, singleSource), (0, combi_1.star)(_1.CDSJoin), ")");
54506
54672
  return (0, combi_1.altPrio)(parenSource, funcSingleSource, singleSource);
@@ -54525,7 +54691,7 @@ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node
54525
54691
  class CDSString extends combi_1.Expression {
54526
54692
  getRunnable() {
54527
54693
  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);
54694
+ 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
54695
  const abap = (0, combi_1.seq)("abap", ".", abapTypeName, (0, combi_1.optPrio)((0, combi_1.seq)("(", (0, combi_1.regex)(/^\d+$/), ")")), reg);
54530
54696
  return (0, combi_1.altPrio)(abap, reg);
54531
54697
  }
@@ -54535,6 +54701,35 @@ exports.CDSString = CDSString;
54535
54701
 
54536
54702
  /***/ },
54537
54703
 
54704
+ /***/ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js"
54705
+ /*!**********************************************************************************!*\
54706
+ !*** ./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js ***!
54707
+ \**********************************************************************************/
54708
+ (__unused_webpack_module, exports, __webpack_require__) {
54709
+
54710
+ "use strict";
54711
+
54712
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
54713
+ exports.CDSTableField = void 0;
54714
+ const _1 = __webpack_require__(/*! . */ "./node_modules/@abaplint/core/build/src/cds/expressions/index.js");
54715
+ const combi_1 = __webpack_require__(/*! ../../abap/2_statements/combi */ "./node_modules/@abaplint/core/build/src/abap/2_statements/combi.js");
54716
+ // A single field or association/composition inside a `define table entity { ... }`
54717
+ // inline body. Wraps annotations + name + type together so tooling can iterate
54718
+ // per-field with associated field-level annotations (matches the CDSElement
54719
+ // shape used for select-list elements).
54720
+ class CDSTableField extends combi_1.Expression {
54721
+ getRunnable() {
54722
+ const nullability = (0, combi_1.optPrio)((0, combi_1.alt)("NOT NULL", "NULL"));
54723
+ const field = (0, combi_1.seq)((0, combi_1.optPrio)((0, combi_1.str)("KEY")), _1.CDSName, ":", _1.CDSType, nullability);
54724
+ const assocOrComp = (0, combi_1.seq)(_1.CDSName, ":", (0, combi_1.alt)(_1.CDSComposition, _1.CDSAssociation));
54725
+ return (0, combi_1.seq)((0, combi_1.star)(_1.CDSAnnotation), (0, combi_1.alt)(field, assocOrComp), ";");
54726
+ }
54727
+ }
54728
+ exports.CDSTableField = CDSTableField;
54729
+ //# sourceMappingURL=cds_table_field.js.map
54730
+
54731
+ /***/ },
54732
+
54538
54733
  /***/ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js"
54539
54734
  /*!***************************************************************************!*\
54540
54735
  !*** ./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js ***!
@@ -54666,6 +54861,7 @@ __exportStar(__webpack_require__(/*! ./cds_relation */ "./node_modules/@abaplint
54666
54861
  __exportStar(__webpack_require__(/*! ./cds_select */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_select.js"), exports);
54667
54862
  __exportStar(__webpack_require__(/*! ./cds_source */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_source.js"), exports);
54668
54863
  __exportStar(__webpack_require__(/*! ./cds_string */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_string.js"), exports);
54864
+ __exportStar(__webpack_require__(/*! ./cds_table_field */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_table_field.js"), exports);
54669
54865
  __exportStar(__webpack_require__(/*! ./cds_type */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_type.js"), exports);
54670
54866
  __exportStar(__webpack_require__(/*! ./cds_where */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_where.js"), exports);
54671
54867
  __exportStar(__webpack_require__(/*! ./cds_with_parameters */ "./node_modules/@abaplint/core/build/src/cds/expressions/cds_with_parameters.js"), exports);
@@ -68995,7 +69191,7 @@ class Registry {
68995
69191
  }
68996
69192
  static abaplintVersion() {
68997
69193
  // magic, see build script "version.js"
68998
- return "2.119.56";
69194
+ return "2.119.60";
68999
69195
  }
69000
69196
  getDDICReferences() {
69001
69197
  return this.ddicReferences;
@@ -74655,6 +74851,7 @@ class DangerousStatementConf extends _basic_rule_config_1.BasicRuleConfig {
74655
74851
  this.insertTextpool = true;
74656
74852
  this.deleteDynpro = true;
74657
74853
  this.exportDynpro = true;
74854
+ this.editorCallForReport = true;
74658
74855
  /** Finds instances of dynamic SQL: SELECT, UPDATE, DELETE, INSERT, MODIFY */
74659
74856
  this.dynamicSQL = true;
74660
74857
  /** Ignore dynamic SQL in IF_RAP_QUERY_PROVIDER~SELECT implementations */
@@ -74739,6 +74936,11 @@ dynamic SQL can potentially create SQL injection problems`,
74739
74936
  else if (this.conf.exportDynpro && statement instanceof Statements.ExportDynpro) {
74740
74937
  message = "EXPORT DYNPRO";
74741
74938
  }
74939
+ else if (this.conf.editorCallForReport
74940
+ && statement instanceof Statements.EditorCall
74941
+ && statementNode.findDirectTokenByText("REPORT")) {
74942
+ message = "EDITOR-CALL FOR REPORT";
74943
+ }
74742
74944
  if (message) {
74743
74945
  issues.push(issue_1.Issue.atStatement(file, statementNode, this.getDescription(message), this.getMetadata().key, this.conf.severity));
74744
74946
  }
@@ -114194,7 +114396,7 @@ class SelectTranspiler {
114194
114396
  }
114195
114397
  dynamicSQLClause(keyword, code) {
114196
114398
  return `(${code} instanceof abap.types.Table || ${code} instanceof abap.types.HashedTable`
114197
- + ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(" "))`
114399
+ + ` ? (${code}.array().length === 0 ? "" : "${keyword} " + ${code}.array().map(row => row.get()).join(", "))`
114198
114400
  + ` : "${keyword} " + ${code}.get())`;
114199
114401
  }
114200
114402
  isWhereExpression(node, expression) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/transpiler-cli",
3
- "version": "2.13.36",
3
+ "version": "2.13.38",
4
4
  "description": "Transpiler - Command Line Interface",
5
5
  "funding": "https://github.com/sponsors/larshp",
6
6
  "bin": {
@@ -27,8 +27,8 @@
27
27
  "author": "abaplint",
28
28
  "license": "MIT",
29
29
  "devDependencies": {
30
- "@abaplint/core": "^2.119.56",
31
- "@abaplint/transpiler": "^2.13.36",
30
+ "@abaplint/core": "^2.119.60",
31
+ "@abaplint/transpiler": "^2.13.38",
32
32
  "@types/glob": "^8.1.0",
33
33
  "@types/node": "^24.12.2",
34
34
  "@types/progress": "^2.0.7",