@sap/cds-compiler 2.12.0 → 2.13.6
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 +110 -15
- package/bin/cdsc.js +13 -13
- package/bin/cdsse.js +2 -2
- package/doc/CHANGELOG_BETA.md +13 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +28 -63
- package/lib/api/options.js +3 -3
- package/lib/api/validate.js +0 -5
- package/lib/backends.js +15 -23
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +7 -17
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +25 -4
- package/lib/base/messages.js +16 -26
- package/lib/base/model.js +2 -63
- package/lib/base/optionProcessorHelper.js +158 -123
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +27 -26
- package/lib/checks/types.js +1 -1
- package/lib/checks/validator.js +4 -7
- package/lib/compiler/assert-consistency.js +5 -3
- package/lib/compiler/builtins.js +8 -6
- package/lib/compiler/checks.js +14 -3
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1103 -0
- package/lib/compiler/extend.js +983 -0
- package/lib/compiler/finalize-parse-cdl.js +231 -0
- package/lib/compiler/index.js +32 -13
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1226 -0
- package/lib/compiler/propagator.js +111 -46
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +64 -37
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +197 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +5 -9
- package/lib/edm/annotations/preprocessAnnotations.js +2 -2
- package/lib/edm/csn2edm.js +9 -8
- package/lib/edm/edm.js +11 -12
- package/lib/edm/edmPreprocessor.js +137 -73
- package/lib/edm/edmUtils.js +116 -22
- package/lib/gen/Dictionary.json +10 -3
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +9 -1
- package/lib/gen/language.tokens +86 -83
- package/lib/gen/languageLexer.interp +10 -1
- package/lib/gen/languageLexer.js +860 -833
- package/lib/gen/languageLexer.tokens +78 -75
- package/lib/gen/languageParser.js +5282 -4265
- package/lib/json/from-csn.js +12 -1
- package/lib/json/to-csn.js +126 -66
- package/lib/language/docCommentParser.js +2 -2
- package/lib/language/genericAntlrParser.js +76 -3
- package/lib/language/language.g4 +297 -130
- package/lib/language/multiLineStringParser.js +5 -5
- package/lib/main.d.ts +468 -59
- package/lib/main.js +35 -9
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +225 -156
- package/lib/model/csnUtils.js +192 -223
- package/lib/model/enrichCsn.js +70 -29
- package/lib/model/revealInternalProperties.js +27 -6
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +5 -4
- package/lib/render/manageConstraints.js +35 -32
- package/lib/render/toCdl.js +73 -288
- package/lib/render/toHdbcds.js +25 -23
- package/lib/render/toSql.js +98 -41
- package/lib/render/utils/common.js +5 -10
- package/lib/render/utils/sql.js +4 -3
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/db/.eslintrc.json +2 -0
- package/lib/transform/db/applyTransformations.js +35 -12
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +103 -305
- package/lib/transform/db/cdsPersistence.js +2 -2
- package/lib/transform/db/constraints.js +55 -52
- package/lib/transform/db/expansion.js +46 -24
- package/lib/transform/db/flattening.js +553 -102
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/transformExists.js +59 -6
- package/lib/transform/db/views.js +5 -4
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +6 -5
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +67 -183
- package/lib/transform/forOdataNew.js +17 -171
- package/lib/transform/localized.js +34 -19
- package/lib/transform/odata/generateForeignKeyElements.js +1 -1
- package/lib/transform/odata/referenceFlattener.js +95 -89
- package/lib/transform/odata/structureFlattener.js +1 -1
- package/lib/transform/odata/toFinalBaseType.js +86 -12
- package/lib/transform/odata/typesExposure.js +5 -5
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +36 -22
- package/lib/transform/translateAssocsToJoins.js +2 -19
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +170 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/objectUtils.js +30 -0
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2361
- package/lib/compiler/resolver.js +0 -3079
- package/lib/transform/universalCsnEnricher.js +0 -237
package/lib/compiler/shared.js
CHANGED
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
const { searchName } = require('../base/messages');
|
|
7
7
|
const { dictAddArray } = require('../base/dictionaries');
|
|
8
|
-
const { setProp } = require('../base/model');
|
|
9
8
|
|
|
10
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
setLink,
|
|
11
|
+
setArtifactLink,
|
|
12
|
+
dependsOn,
|
|
13
|
+
pathName,
|
|
14
|
+
} = require('./utils');
|
|
11
15
|
|
|
12
16
|
function artifactsEnv( art ) {
|
|
13
17
|
return art._subArtifacts || Object.create(null);
|
|
@@ -161,7 +165,7 @@ function fns( model ) {
|
|
|
161
165
|
return;
|
|
162
166
|
|
|
163
167
|
function checkConstRef( art ) {
|
|
164
|
-
return
|
|
168
|
+
return art.kind !== 'builtin' && art.kind !== 'param';
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
function checkIncludesRef( art ) {
|
|
@@ -265,9 +269,9 @@ function fns( model ) {
|
|
|
265
269
|
return ref._artifact;
|
|
266
270
|
if (!ref.path || ref.path.broken || !ref.path.length) {
|
|
267
271
|
// incomplete type AST or empty env (already reported)
|
|
268
|
-
return
|
|
272
|
+
return setArtifactLink( ref, undefined );
|
|
269
273
|
}
|
|
270
|
-
|
|
274
|
+
setArtifactLink( ref, 0 ); // avoid cycles for type T: association to T.m;
|
|
271
275
|
|
|
272
276
|
let spec = specExpected[expected];
|
|
273
277
|
const { path } = ref;
|
|
@@ -280,7 +284,7 @@ function fns( model ) {
|
|
|
280
284
|
if (!spec.escape) {
|
|
281
285
|
error( 'ref-unexpected-scope', [ ref.location, user ], {},
|
|
282
286
|
'Unexpected parameter reference' );
|
|
283
|
-
return
|
|
287
|
+
return setArtifactLink( ref, null );
|
|
284
288
|
}
|
|
285
289
|
spec = specExpected[spec.escape];
|
|
286
290
|
// In queries and query entities, the first lexical search environment
|
|
@@ -298,7 +302,7 @@ function fns( model ) {
|
|
|
298
302
|
const query = (spec.lexical === 'main') ? user._main : userQuery( user );
|
|
299
303
|
// in path filter, just $magic (and $parameters)
|
|
300
304
|
env = (spec.lexical === 'from') ? query._parent : query || user._main || user;
|
|
301
|
-
// queries: first
|
|
305
|
+
// queries: first table aliases, then $magic - value refs: first $self, then $magic
|
|
302
306
|
if (!extDict && !spec.noExt) {
|
|
303
307
|
// TODO: change to name restriction for $joins, not own environments
|
|
304
308
|
extDict = query && spec.rootEnv !== 'elements' &&
|
|
@@ -314,18 +318,34 @@ function fns( model ) {
|
|
|
314
318
|
? getPathRoot( path, spec, user, {}, model[spec.global || 'definitions'] )
|
|
315
319
|
: getPathRoot( path, spec, user, env, extDict, msgArt || 0 );
|
|
316
320
|
if (!art) {
|
|
317
|
-
return
|
|
321
|
+
return setArtifactLink( ref, art );
|
|
318
322
|
}
|
|
319
323
|
else if (!spec.envFn && user._pathHead) {
|
|
320
324
|
// eslint-disable-next-line no-empty
|
|
321
325
|
}
|
|
322
326
|
else if (art.kind === 'using') {
|
|
323
|
-
|
|
324
|
-
if (!
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
const def = model.definitions[art.name.absolute];
|
|
328
|
+
if (!def) {
|
|
329
|
+
// It could be that the artifact was removed and that the using-proxy needs to be reported.
|
|
330
|
+
// The check for $inferred is required to avoid consequential errors for cases such as:
|
|
331
|
+
// using unknown.abc;
|
|
332
|
+
// entity P as projection on abc; // <-- no consequential error here
|
|
333
|
+
if (art.$inferred === 'path-prefix') {
|
|
334
|
+
// head._artifact referred to the `using`. Remove the reference,
|
|
335
|
+
// so that getPathItem() below emits an error.
|
|
336
|
+
setArtifactLink( head, false );
|
|
337
|
+
setArtifactLink( ref, false );
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
return setArtifactLink( ref, false );
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else if (def.$duplicates) { // redefined art referenced by using proxy
|
|
344
|
+
return setArtifactLink( ref, false );
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
setArtifactLink( head, def ); // we do not want to see the using
|
|
348
|
+
}
|
|
329
349
|
}
|
|
330
350
|
else if (art.kind === 'mixin') {
|
|
331
351
|
if (spec.noAliasOrMixin) {
|
|
@@ -333,14 +353,14 @@ function fns( model ) {
|
|
|
333
353
|
signalNotFound( 'ref-rejected-on', [ head.location, user ], extDict && [ extDict ],
|
|
334
354
|
{ '#': 'mixin', id: head.id } );
|
|
335
355
|
// also set link on head?
|
|
336
|
-
return
|
|
356
|
+
return setArtifactLink( ref, false );
|
|
337
357
|
}
|
|
338
358
|
// console.log(message( null, art.location, art, {}, 'Info','MIX').toString())
|
|
339
|
-
setLink( head,
|
|
359
|
+
setLink( head, '_navigation', art );
|
|
340
360
|
}
|
|
341
361
|
else if (art.kind === '$navElement') {
|
|
342
|
-
setLink( head,
|
|
343
|
-
|
|
362
|
+
setLink( head, '_navigation', art );
|
|
363
|
+
setArtifactLink( head, art._origin );
|
|
344
364
|
// TODO: set art?
|
|
345
365
|
}
|
|
346
366
|
else if (art.kind === '$tableAlias' || art.kind === '$self') {
|
|
@@ -349,13 +369,17 @@ function fns( model ) {
|
|
|
349
369
|
signalNotFound( 'ref-rejected-on', [ head.location, user ], extDict && [ extDict ],
|
|
350
370
|
{ '#': 'alias', id: head.id } );
|
|
351
371
|
// also set link on head?
|
|
352
|
-
return
|
|
372
|
+
return setArtifactLink( ref, false );
|
|
353
373
|
}
|
|
354
|
-
setLink( head,
|
|
355
|
-
|
|
374
|
+
setLink( head, '_navigation', art );
|
|
375
|
+
setArtifactLink( head, art._origin ); // query source or leading query in FROM
|
|
356
376
|
// require('../model/revealInternalProperties').log(model, 'foo.bar.S.V1a')
|
|
357
377
|
if (!art._origin)
|
|
358
|
-
return
|
|
378
|
+
return setArtifactLink( ref, art._origin );
|
|
379
|
+
// if just table alias (with expand), mark `user` with `$noOrigin` to indicate
|
|
380
|
+
// that the corresponding entity should not be put as $origin into the CSN
|
|
381
|
+
if (path.length === 1 && user && art.kind === '$tableAlias')
|
|
382
|
+
user.$noOrigin = true;
|
|
359
383
|
}
|
|
360
384
|
|
|
361
385
|
// how many path items are for artifacts (rest: elements)
|
|
@@ -365,20 +389,20 @@ function fns( model ) {
|
|
|
365
389
|
// console.log(expected, ref.path.map(a=>a.id),artItemsCount)
|
|
366
390
|
art = getPathItem( path, spec, user, artItemsCount, !spec.envFn && user._pathHead && art);
|
|
367
391
|
if (!art)
|
|
368
|
-
return
|
|
392
|
+
return setArtifactLink( ref, art );
|
|
369
393
|
|
|
370
394
|
if (art.$autoElement) {
|
|
371
395
|
const { location } = path[path.length - 1];
|
|
372
396
|
const step = { id: art.$autoElement, $inferred: '$autoElement', location };
|
|
373
397
|
art = art.elements[step.id];
|
|
374
|
-
|
|
398
|
+
setArtifactLink( step, art );
|
|
375
399
|
path.push( step );
|
|
376
400
|
}
|
|
377
401
|
if (spec.check) {
|
|
378
402
|
const fail = spec.check( art, path );
|
|
379
403
|
if (fail === true) {
|
|
380
404
|
signalNotFound( spec.expectedMsgId, [ ref.location, user ], null );
|
|
381
|
-
return
|
|
405
|
+
return setArtifactLink( ref, false );
|
|
382
406
|
}
|
|
383
407
|
else if (fail) {
|
|
384
408
|
signalNotFound( spec.sloppyMsgId, [ ref.location, user ], null );
|
|
@@ -410,7 +434,7 @@ function fns( model ) {
|
|
|
410
434
|
!(env.$frontend && env.$frontend !== 'cdl'))
|
|
411
435
|
deprecateSmart( ref, art, user );
|
|
412
436
|
// TODO: follow FROM here, see csnRef - fromRef
|
|
413
|
-
return
|
|
437
|
+
return setArtifactLink( ref, art );
|
|
414
438
|
}
|
|
415
439
|
|
|
416
440
|
// Issue errors for "smart" element-in-artifact references
|
|
@@ -475,6 +499,8 @@ function fns( model ) {
|
|
|
475
499
|
// TODO: not necessarily for explicit ON condition in expand
|
|
476
500
|
VolatileFns.environment( user._pathHead ); // make sure _origin is set
|
|
477
501
|
return user._pathHead._origin;
|
|
502
|
+
// const { _origin } = user._pathHead;
|
|
503
|
+
// return (_origin && _origin.kind === '$tableAlias') ? _origin._origin : _origin;
|
|
478
504
|
}
|
|
479
505
|
const head = path[0];
|
|
480
506
|
if (!head || !head.id || !env)
|
|
@@ -501,7 +527,7 @@ function fns( model ) {
|
|
|
501
527
|
const r = e[head.id];
|
|
502
528
|
if (r) {
|
|
503
529
|
if (Array.isArray(r)) { // redefinitions
|
|
504
|
-
|
|
530
|
+
setArtifactLink( head, r );
|
|
505
531
|
return false;
|
|
506
532
|
}
|
|
507
533
|
// if (head.$delimited && r.kind !== '$tableAlias' && r.kind !== 'mixin')
|
|
@@ -512,18 +538,18 @@ function fns( model ) {
|
|
|
512
538
|
{ code: `$parameters.${ path[1].id }`, newcode: `:${ path[1].id }` },
|
|
513
539
|
'Obsolete $(CODE) - replace by $(NEWCODE)' );
|
|
514
540
|
// TODO: replace it in to-csn correspondingly
|
|
515
|
-
return
|
|
541
|
+
return setArtifactLink( head, r );
|
|
516
542
|
}
|
|
517
543
|
}
|
|
518
544
|
else if (r.kind === '$self') {
|
|
519
545
|
// TODO: handle $delimited differently
|
|
520
546
|
// TODO: $projection only if not delimited _and_ length > 1
|
|
521
|
-
return
|
|
547
|
+
return setArtifactLink( head, r );
|
|
522
548
|
}
|
|
523
549
|
else if (r.kind !== '$tableAlias' || path.length > 1 || user.expand || user.inline) {
|
|
524
550
|
// except "real" table aliases (not $self) with path len 1
|
|
525
551
|
// TODO: $projection only if not delimited _and_ length > 1
|
|
526
|
-
return
|
|
552
|
+
return setArtifactLink( head, r );
|
|
527
553
|
}
|
|
528
554
|
}
|
|
529
555
|
}
|
|
@@ -540,11 +566,11 @@ function fns( model ) {
|
|
|
540
566
|
'Ambiguous $(ID), replace by $(NAMES)' );
|
|
541
567
|
}
|
|
542
568
|
}
|
|
543
|
-
|
|
569
|
+
setArtifactLink( head, r );
|
|
544
570
|
return false;
|
|
545
571
|
}
|
|
546
572
|
else if (r) {
|
|
547
|
-
return
|
|
573
|
+
return setArtifactLink( head, r );
|
|
548
574
|
}
|
|
549
575
|
}
|
|
550
576
|
if (spec.noMessage || msgArt === true && extDict === model.definitions)
|
|
@@ -598,7 +624,7 @@ function fns( model ) {
|
|
|
598
624
|
signalNotFound( spec.undefinedArt || 'ref-undefined-art', [ head.location, user ],
|
|
599
625
|
valid, { name: head.id } );
|
|
600
626
|
}
|
|
601
|
-
return
|
|
627
|
+
return setArtifactLink( head, null );
|
|
602
628
|
}
|
|
603
629
|
|
|
604
630
|
// Return artifact or element referred by path (array of ids) `tail`. The
|
|
@@ -606,6 +632,7 @@ function fns( model ) {
|
|
|
606
632
|
// missing artifacts (as opposed to elements), provide the `head` (first
|
|
607
633
|
// element item in the path)
|
|
608
634
|
function getPathItem( path, spec, user, artItemsCount, headArt ) {
|
|
635
|
+
// let art = (headArt && headArt.kind === '$tableAlias') ? headArt._origin : headArt;
|
|
609
636
|
let art = headArt;
|
|
610
637
|
let nav = spec.assoc !== '$keys' && null; // false for '$keys'
|
|
611
638
|
const last = path[path.length - 1];
|
|
@@ -622,7 +649,7 @@ function fns( model ) {
|
|
|
622
649
|
|
|
623
650
|
const fn = (spec.envFn && artItemsCount >= 0) ? spec.envFn : VolatileFns.environment;
|
|
624
651
|
const env = fn( art, item.location, user, spec.assoc );
|
|
625
|
-
const sub =
|
|
652
|
+
const sub = setArtifactLink( item, env && env[item.id] );
|
|
626
653
|
|
|
627
654
|
if (!sub) {
|
|
628
655
|
// element was not found in environment
|
|
@@ -684,7 +711,7 @@ function fns( model ) {
|
|
|
684
711
|
if (node._artifact) {
|
|
685
712
|
// set the original(!) foreign key for the assoc - the "right" ones
|
|
686
713
|
// after rewriteKeys() is the one with the same name.id
|
|
687
|
-
setLink( item, node._artifact
|
|
714
|
+
setLink( item, '_navigation', node._artifact );
|
|
688
715
|
if (item === last)
|
|
689
716
|
return;
|
|
690
717
|
}
|
|
@@ -817,7 +844,7 @@ function fns( model ) {
|
|
|
817
844
|
if (!(Array.isArray(annos)))
|
|
818
845
|
annos = [ annos ];
|
|
819
846
|
for (const a of annos) {
|
|
820
|
-
|
|
847
|
+
setLink( a, '_block', block );
|
|
821
848
|
a.$priority = priority;
|
|
822
849
|
if (construct !== art)
|
|
823
850
|
addAnnotation( art, annoProp, a );
|
|
@@ -867,7 +894,7 @@ function fns( model ) {
|
|
|
867
894
|
value.name && value.name.location ||
|
|
868
895
|
value.path && value.path.location,
|
|
869
896
|
};
|
|
870
|
-
|
|
897
|
+
setLink( anno, '_block', block );
|
|
871
898
|
// TODO: _parent, _main is set later (if we have ElementRef), or do we
|
|
872
899
|
// set _artifact?
|
|
873
900
|
anno.$priority = priority;
|