@sap/cds-compiler 6.1.0 → 6.3.0

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 (90) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/bin/cdsc.js +17 -6
  3. package/bin/cdsse.js +1 -1
  4. package/bin/cdsv2m.js +1 -1
  5. package/lib/api/main.js +29 -7
  6. package/lib/api/options.js +1 -1
  7. package/lib/base/builtins.js +9 -0
  8. package/lib/base/keywords.js +1 -1
  9. package/lib/base/message-registry.js +41 -10
  10. package/lib/base/messages.js +13 -6
  11. package/lib/base/model.js +1 -1
  12. package/lib/base/optionProcessorHelper.js +7 -2
  13. package/lib/checks/assocOutsideService.js +17 -30
  14. package/lib/checks/checkForTypes.js +0 -18
  15. package/lib/checks/checkPathsInStoredCalcElement.js +2 -1
  16. package/lib/checks/featureFlags.js +4 -1
  17. package/lib/checks/onConditions.js +2 -2
  18. package/lib/checks/queryNoDbArtifacts.js +16 -15
  19. package/lib/checks/types.js +1 -1
  20. package/lib/checks/utils.js +30 -6
  21. package/lib/checks/validator.js +4 -5
  22. package/lib/compiler/assert-consistency.js +3 -1
  23. package/lib/compiler/base.js +1 -1
  24. package/lib/compiler/builtins.js +1 -1
  25. package/lib/compiler/checks.js +85 -39
  26. package/lib/compiler/define.js +24 -5
  27. package/lib/compiler/extend.js +1 -1
  28. package/lib/compiler/finalize-parse-cdl.js +9 -1
  29. package/lib/compiler/generate.js +4 -4
  30. package/lib/compiler/index.js +88 -6
  31. package/lib/compiler/lsp-api.js +2 -0
  32. package/lib/compiler/populate.js +8 -8
  33. package/lib/compiler/propagator.js +1 -1
  34. package/lib/compiler/resolve.js +22 -21
  35. package/lib/compiler/shared.js +6 -6
  36. package/lib/compiler/tweak-assocs.js +53 -31
  37. package/lib/compiler/utils.js +9 -16
  38. package/lib/compiler/xpr-rewrite.js +2 -2
  39. package/lib/gen/BaseParser.js +35 -29
  40. package/lib/gen/CdlGrammar.checksum +1 -1
  41. package/lib/gen/CdlParser.js +1424 -1430
  42. package/lib/gen/Dictionary.json +1 -2
  43. package/lib/gen/cdlKeywords.json +26 -0
  44. package/lib/inspect/inspectPropagation.js +1 -1
  45. package/lib/json/from-csn.js +2 -2
  46. package/lib/json/to-csn.js +1 -1
  47. package/lib/language/multiLineStringParser.js +1 -1
  48. package/lib/model/cloneCsn.js +1 -0
  49. package/lib/model/csnRefs.js +9 -4
  50. package/lib/model/csnUtils.js +67 -2
  51. package/lib/optionProcessor.js +9 -9
  52. package/lib/parsers/AstBuildingParser.js +28 -26
  53. package/lib/parsers/identifiers.js +2 -30
  54. package/lib/render/toCdl.js +73 -13
  55. package/lib/render/toSql.js +127 -108
  56. package/lib/render/utils/common.js +4 -2
  57. package/lib/render/utils/sql.js +67 -0
  58. package/lib/transform/addTenantFields.js +4 -4
  59. package/lib/transform/db/assertUnique.js +2 -1
  60. package/lib/transform/db/associations.js +37 -1
  61. package/lib/transform/db/assocsToQueries/transformExists.js +21 -32
  62. package/lib/transform/db/assocsToQueries/utils.js +1 -1
  63. package/lib/transform/db/cdsPersistence.js +1 -1
  64. package/lib/transform/db/expansion.js +37 -36
  65. package/lib/transform/db/killAnnotations.js +1 -0
  66. package/lib/transform/db/processSqlServices.js +20 -2
  67. package/lib/transform/draft/db.js +20 -20
  68. package/lib/transform/draft/odata.js +38 -40
  69. package/lib/transform/effective/associations.js +1 -1
  70. package/lib/transform/effective/flattening.js +40 -47
  71. package/lib/transform/effective/main.js +6 -4
  72. package/lib/transform/forOdata.js +201 -92
  73. package/lib/transform/forRelationalDB.js +151 -142
  74. package/lib/transform/localized.js +116 -109
  75. package/lib/transform/odata/adaptAnnotationRefs.js +21 -16
  76. package/lib/transform/odata/createForeignKeys.js +73 -70
  77. package/lib/transform/odata/flattening.js +216 -200
  78. package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +47 -45
  79. package/lib/transform/odata/toFinalBaseType.js +40 -39
  80. package/lib/transform/odata/typesExposure.js +151 -133
  81. package/lib/transform/odata/utils.js +7 -6
  82. package/lib/transform/parseExpr.js +165 -162
  83. package/lib/transform/transformUtils.js +184 -551
  84. package/lib/transform/translateAssocsToJoins.js +511 -596
  85. package/lib/transform/tupleExpansion.js +495 -0
  86. package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
  87. package/lib/utils/moduleResolve.js +1 -1
  88. package/package.json +2 -2
  89. package/lib/base/cleanSymbols.js +0 -17
  90. package/lib/checks/nonexpandableStructured.js +0 -39
@@ -1,4 +1,4 @@
1
- // Base class for generated parser, for redepage v0.2.5
1
+ // Base class for generated parser, for redepage v0.3.0
2
2
 
3
3
  'use strict';
4
4
 
@@ -17,7 +17,6 @@ class BaseParser {
17
17
  lexer;
18
18
 
19
19
  tokens = undefined;
20
- eofIndex = undefined;
21
20
  tokenIdx = 0;
22
21
  recoverTokenIdx = -1;
23
22
  conditionTokenIdx = -1; // TODO: can we use recoverTokenIdx ?
@@ -44,7 +43,6 @@ class BaseParser {
44
43
 
45
44
  init() {
46
45
  this.lexer.tokenize( this );
47
- this.eofIndex = this.tokens.length - 1;
48
46
  return this;
49
47
  }
50
48
 
@@ -53,7 +51,7 @@ class BaseParser {
53
51
  s: this.s,
54
52
  stack: this.stack,
55
53
  dynamic_: this.dynamic_,
56
- prec_: this.prec_ // TODO: necessary?
54
+ prec_: this.prec_, // TODO: necessary?
57
55
  };
58
56
  }
59
57
 
@@ -85,8 +83,8 @@ class BaseParser {
85
83
  la() { // lookahead: complete token
86
84
  return this.tokens[this.tokenIdx];
87
85
  }
88
- lb() { // look back: complete token
89
- return this.tokens[this.tokenIdx - 1];
86
+ lb( k = 1 ) { // look back: complete token
87
+ return this.tokens[this.tokenIdx - k];
90
88
  }
91
89
  lr() { // return the first token matched by current rule
92
90
  return this.tokens[this.stack[this.stack.length - 1].tokenIdx];
@@ -95,12 +93,12 @@ class BaseParser {
95
93
  // lookahead, error: ----------------------------------------------------------
96
94
 
97
95
  l() { // lookahead: token type
98
- return this.tokens[this.tokenIdx].type;
96
+ return this.la().type;
99
97
  }
100
98
 
101
99
  // instead of l() if keyword (reserved and/or unreserved) is in one of the cases
102
100
  lk() { // keyword lookahead
103
- const la = this.tokens[this.tokenIdx];
101
+ const la = this.la();
104
102
  if (!this.nextTokenAsId)
105
103
  return la.keyword || la.type;
106
104
  // return la.keyword && this.table[this.s][la.keyword] && la.keyword || la.type;
@@ -109,7 +107,7 @@ class BaseParser {
109
107
  }
110
108
 
111
109
  e() { // error: report and recover
112
- const la = this.tokens[this.tokenIdx];
110
+ const la = this.la();
113
111
  this._trace( 'detect parsing error' );
114
112
  if (this.errorTokenIdx === this.tokenIdx)
115
113
  throw Error( `Already reported error for ${ tokenFullName( la ) } at ${ la.location }`);
@@ -141,7 +139,7 @@ class BaseParser {
141
139
 
142
140
  // instead of e() in default if lk() had been used and 'Id' is in a non-default case
143
141
  ei() { // error (after trying to test again as identifier)
144
- if (!this.tokens[this.tokenIdx].keyword) // lk() had directly returned the type
142
+ if (!this.la().keyword) // lk() had directly returned the type
145
143
  return this.e();
146
144
  this.nextTokenAsId = true;
147
145
  return false; // do not execute action after it
@@ -200,18 +198,6 @@ class BaseParser {
200
198
  return false; // do not execute action after it
201
199
  }
202
200
 
203
- // instead of gi() at rule end (RuleEnd_ in follow-set) for `Id<weak>`, TODO: delete
204
- giR( state, follow ) { // go to state (after trying to test again as identifier)
205
- const { keyword } = this.tokens[this.tokenIdx];
206
- if (!keyword || this.keywords[keyword])
207
- return this.g( state, follow );
208
- this._tracePush( [ 'R', 0 ] );
209
- if (this._matchesInFollow( 'Id', keyword, 'R' ))
210
- return this.g( state, follow );
211
- this.nextTokenAsId = true;
212
- return false; // do not execute action after it
213
- }
214
-
215
201
  // instead of g() in a non-default case if there is a LL1 conflict
216
202
  gP( state, follow ) { // goto state with standard weak-conflict prediction
217
203
  return this.lP( follow ) && this.g( state );
@@ -303,7 +289,8 @@ class BaseParser {
303
289
  // “go if user condition fails”
304
290
  gc( state, cond, arg ) {
305
291
  if (this.conditionTokenIdx === this.tokenIdx && // tested on same
306
- this.conditionStackLength == null) { // after error recovery
292
+ this.conditionStackLength == null && // after error recovery
293
+ !this[cond].afterError) {
307
294
  this._tracePush( [ 'C' ] );
308
295
  return true;
309
296
  }
@@ -314,12 +301,11 @@ class BaseParser {
314
301
  }
315
302
  // calling the condition might have side effects (precendence conditions have)
316
303
  // → call tracing “name” before
317
- const fail = this[cond]( arg, true ); // TODO: use single-letter for run?
304
+ const fail = this[cond]( arg, true ); // TODO: use single-letter for run! → 'X'
318
305
  if (this.constructor.tracingParser)
319
306
  this._traceSubPush( !fail );
320
307
  // The default case must not have actions. If written in grammar with action,
321
- // the default must have <default=fallback>
322
-
308
+ // the default must currently have <default=true>
323
309
 
324
310
  if (fail) { // TODO: extra gcK() method instead of check below
325
311
  // TODO: probably remove the following (and `conditionStackLength` tests)
@@ -346,6 +332,23 @@ class BaseParser {
346
332
  return this.gc( null, cond, arg );
347
333
  }
348
334
 
335
+ // predefined guard:
336
+ isNoKeywordInRuleFollow( _arg, mode ) {
337
+ const { keyword } = this.la();
338
+ if (this.constructor.tracingParser && (mode === true || mode === 'M')) {
339
+ // TODO: mode === 'X' || mode === 'M'
340
+ --this.trace.at(-1).length; // do not show guard name in trace
341
+ if (!keyword || this.keywords[keyword] == null)
342
+ return false; // ok
343
+ const r = this._matchesInFollow( 'Id', keyword, 'R' );
344
+ --this.trace.at(-1).length; // this.gc() also traces result
345
+ return r;
346
+ }
347
+ if (!keyword || this.keywords[keyword] == null)
348
+ return false; // ok
349
+ return this._matchesInFollow( 'Id', keyword, 'R' );
350
+ }
351
+
349
352
  // rule start, end and call: --------------------------------------------------
350
353
 
351
354
  rule_( state, followState = -1 ) { // start rule
@@ -762,12 +765,13 @@ class BaseParser {
762
765
  const { keyword, type } = token;
763
766
  if (keyword && set[keyword] === true)
764
767
  delete set[keyword];
765
- else if (set[type] === true && !(keyword && this.keywords[keyword]))
766
- delete set[type]; // delete Id if Id token or non-reserved keyword
768
+ else if (set[type] === true && !(keyword && this.keywords[keyword] != null))
769
+ delete set[type]; // delete if not keyword
767
770
 
768
771
  this._trace( 'collect tokens for message' );
769
772
  const { trace } = this;
770
773
  const saved = this._saveForWalk();
774
+ saved.fixKeywordTokenIdx = this.fixKeywordTokenIdx; // changed by confirmExpected
771
775
  const expecting = Object.keys( set )
772
776
  .filter( tok => this._confirmExpected( tok, saved ) );
773
777
  token.type = type; // overwritten by _confirmExpected
@@ -780,7 +784,7 @@ class BaseParser {
780
784
  _findSyncToken( syncSet ) {
781
785
  const rewindDepth = this.stack.length
782
786
  this.recoverTokenIdx = this.tokenIdx;
783
- while (this.recoverTokenIdx <= this.eofIndex) {
787
+ while (this.recoverTokenIdx < this.tokens.length) {
784
788
  const { keyword, type } = this.tokens[this.recoverTokenIdx];
785
789
  let recoverDepth = keyword ? syncSet[keyword] : null;
786
790
  if (recoverDepth != null)
@@ -971,6 +975,8 @@ class BaseParser {
971
975
  const members = BaseParser.prototype;
972
976
  // functions below are to be called with `call` to set `this`
973
977
 
978
+ members.isNoKeywordInRuleFollow.afterError = true;
979
+
974
980
  members.precLeft_.traceName = function( prec ) {
975
981
  const parentPrec = this.stack.at( -1 ).prec;
976
982
  return `${ parentPrec ?? '-∞' }<${ prec }`;
@@ -1 +1 @@
1
- 7cfe4871a952fbc999cd1e8b06300f7f
1
+ 1f3bba2acb882f5120a55a01eb9a7bdc