@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.
- package/CHANGELOG.md +78 -0
- package/bin/cdsc.js +17 -6
- package/bin/cdsse.js +1 -1
- package/bin/cdsv2m.js +1 -1
- package/lib/api/main.js +29 -7
- package/lib/api/options.js +1 -1
- package/lib/base/builtins.js +9 -0
- package/lib/base/keywords.js +1 -1
- package/lib/base/message-registry.js +41 -10
- package/lib/base/messages.js +13 -6
- package/lib/base/model.js +1 -1
- package/lib/base/optionProcessorHelper.js +7 -2
- package/lib/checks/assocOutsideService.js +17 -30
- package/lib/checks/checkForTypes.js +0 -18
- package/lib/checks/checkPathsInStoredCalcElement.js +2 -1
- package/lib/checks/featureFlags.js +4 -1
- package/lib/checks/onConditions.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +16 -15
- package/lib/checks/types.js +1 -1
- package/lib/checks/utils.js +30 -6
- package/lib/checks/validator.js +4 -5
- package/lib/compiler/assert-consistency.js +3 -1
- package/lib/compiler/base.js +1 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +85 -39
- package/lib/compiler/define.js +24 -5
- package/lib/compiler/extend.js +1 -1
- package/lib/compiler/finalize-parse-cdl.js +9 -1
- package/lib/compiler/generate.js +4 -4
- package/lib/compiler/index.js +88 -6
- package/lib/compiler/lsp-api.js +2 -0
- package/lib/compiler/populate.js +8 -8
- package/lib/compiler/propagator.js +1 -1
- package/lib/compiler/resolve.js +22 -21
- package/lib/compiler/shared.js +6 -6
- package/lib/compiler/tweak-assocs.js +53 -31
- package/lib/compiler/utils.js +9 -16
- package/lib/compiler/xpr-rewrite.js +2 -2
- package/lib/gen/BaseParser.js +35 -29
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +1424 -1430
- package/lib/gen/Dictionary.json +1 -2
- package/lib/gen/cdlKeywords.json +26 -0
- package/lib/inspect/inspectPropagation.js +1 -1
- package/lib/json/from-csn.js +2 -2
- package/lib/json/to-csn.js +1 -1
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/model/cloneCsn.js +1 -0
- package/lib/model/csnRefs.js +9 -4
- package/lib/model/csnUtils.js +67 -2
- package/lib/optionProcessor.js +9 -9
- package/lib/parsers/AstBuildingParser.js +28 -26
- package/lib/parsers/identifiers.js +2 -30
- package/lib/render/toCdl.js +73 -13
- package/lib/render/toSql.js +127 -108
- package/lib/render/utils/common.js +4 -2
- package/lib/render/utils/sql.js +67 -0
- package/lib/transform/addTenantFields.js +4 -4
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/associations.js +37 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +21 -32
- package/lib/transform/db/assocsToQueries/utils.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +37 -36
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +20 -2
- package/lib/transform/draft/db.js +20 -20
- package/lib/transform/draft/odata.js +38 -40
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +40 -47
- package/lib/transform/effective/main.js +6 -4
- package/lib/transform/forOdata.js +201 -92
- package/lib/transform/forRelationalDB.js +151 -142
- package/lib/transform/localized.js +116 -109
- package/lib/transform/odata/adaptAnnotationRefs.js +21 -16
- package/lib/transform/odata/createForeignKeys.js +73 -70
- package/lib/transform/odata/flattening.js +216 -200
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +47 -45
- package/lib/transform/odata/toFinalBaseType.js +40 -39
- package/lib/transform/odata/typesExposure.js +151 -133
- package/lib/transform/odata/utils.js +7 -6
- package/lib/transform/parseExpr.js +165 -162
- package/lib/transform/transformUtils.js +184 -551
- package/lib/transform/translateAssocsToJoins.js +511 -596
- package/lib/transform/tupleExpansion.js +495 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/lib/utils/moduleResolve.js +1 -1
- package/package.json +2 -2
- package/lib/base/cleanSymbols.js +0 -17
- package/lib/checks/nonexpandableStructured.js +0 -39
package/lib/gen/BaseParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Base class for generated parser, for redepage v0.
|
|
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_
|
|
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() {
|
|
89
|
-
return this.tokens[this.tokenIdx -
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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=
|
|
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
|
|
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
|
|
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
|
-
|
|
1
|
+
1f3bba2acb882f5120a55a01eb9a7bdc
|