@sap/cds-compiler 6.0.10 → 6.0.12
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 +13 -0
- package/bin/cdsc.js +2 -1
- package/lib/base/message-registry.js +1 -3
- package/lib/base/messages.js +6 -1
- package/lib/checks/elements.js +6 -1
- package/lib/compiler/assert-consistency.js +1 -0
- package/lib/compiler/checks.js +2 -2
- package/lib/compiler/define.js +25 -0
- package/lib/compiler/extend.js +3 -0
- package/lib/compiler/resolve.js +29 -7
- package/lib/compiler/shared.js +9 -3
- package/lib/edm/annotations/edmJson.js +3 -5
- package/lib/edm/annotations/genericTranslation.js +5 -2
- package/lib/edm/csn2edm.js +4 -6
- package/lib/edm/edm.js +25 -21
- package/lib/edm/edmInboundChecks.js +2 -2
- package/lib/edm/edmPreprocessor.js +21 -5
- package/lib/edm/edmUtils.js +7 -10
- package/lib/gen/BaseParser.js +10 -10
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +38 -33
- package/lib/gen/Dictionary.json +21 -1
- package/lib/model/cloneCsn.js +3 -0
- package/lib/optionProcessor.js +3 -0
- package/lib/parsers/AstBuildingParser.js +19 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,19 @@ Note: `beta` fixes, changes and features are usually not listed in this ChangeLo
|
|
|
8
8
|
but in [doc/CHANGELOG_BETA.md](doc/CHANGELOG_BETA.md).
|
|
9
9
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
10
10
|
|
|
11
|
+
## Version 6.0.12 - 2025-06-06
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Update OData vocabularies: 'Common', 'Hierarchy'
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- compiler: Fix artifact refs in annotated annotation expressions,
|
|
20
|
+
i.e. the `Type` inside `annotate … with @SomeAnno: (cast( … as Type ))`.
|
|
21
|
+
- to.sql: Checks around managed associations for mocked entities have been relaxed.
|
|
22
|
+
- to.edm(x): Resolved a crash caused by references in annotation expressions that were not properly updated.
|
|
23
|
+
|
|
11
24
|
## Version 6.0.10 - 2025-05-28
|
|
12
25
|
|
|
13
26
|
### Fixed
|
package/bin/cdsc.js
CHANGED
|
@@ -349,7 +349,8 @@ async function executeCommandLine( command, options, args ) {
|
|
|
349
349
|
return;
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
options.
|
|
352
|
+
if (!options.directMessages)
|
|
353
|
+
options.messages = [];
|
|
353
354
|
args.files ??= [];
|
|
354
355
|
|
|
355
356
|
// Load a file from stdin if no explicit file is given and stdin is not a TTY.
|
|
@@ -106,7 +106,6 @@ const centralMessages = {
|
|
|
106
106
|
'def-unexpected-nested-proj': { severity: 'Error' },
|
|
107
107
|
'def-unexpected-paramview-assoc': { severity: 'Error' },
|
|
108
108
|
'def-unexpected-calcview-assoc': { severity: 'Error' },
|
|
109
|
-
'chained-array-of': { severity: 'Error' },
|
|
110
109
|
'def-missing-type': { severity: 'Error', configurableFor: [ 'compile' ] },
|
|
111
110
|
'def-missing-argument': { severity: 'Error' },
|
|
112
111
|
'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.hdbcds', 'to.sql', 'to.hdi', 'to.rename', 'for.effective' ] },
|
|
@@ -390,8 +389,6 @@ const centralMessageTexts = {
|
|
|
390
389
|
param: 'Assign a value for $(ANNO); the value inherited from $(ART) can\'t be rewritten due to parameter reference $(ELEMREF)',
|
|
391
390
|
},
|
|
392
391
|
|
|
393
|
-
'chained-array-of': '"Array of"/"many" must not be chained with another "array of"/"many" inside a service',
|
|
394
|
-
|
|
395
392
|
'check-proper-type-of': {
|
|
396
393
|
std: 'Referred element $(NAME) of $(ART) does not contain proper type information',
|
|
397
394
|
derived: 'Referred type of $(ART) does not contain proper type information',
|
|
@@ -908,6 +905,7 @@ const centralMessageTexts = {
|
|
|
908
905
|
nested: 'Unexpected $(PROP) inside $(PROP)',
|
|
909
906
|
assoc: 'Unexpected association inside $(PROP)',
|
|
910
907
|
comp: 'Unexpected composition inside $(PROP)',
|
|
908
|
+
'chained-service': '"Array of"/"many" must not be chained with another "array of"/"many" inside a service',
|
|
911
909
|
},
|
|
912
910
|
|
|
913
911
|
'type-unexpected-default': {
|
package/lib/base/messages.js
CHANGED
|
@@ -1494,12 +1494,17 @@ function homeName( art, absoluteOnly ) {
|
|
|
1494
1494
|
return art;
|
|
1495
1495
|
if (art._user) // when providing a path item with filter as “user”
|
|
1496
1496
|
return homeName( art._user, absoluteOnly );
|
|
1497
|
-
if (art._outer) {
|
|
1497
|
+
if (art._outer) { // in items property, or annotation with path
|
|
1498
|
+
if (art._outer?.kind === '$annotation')
|
|
1499
|
+
art = art._outer;
|
|
1498
1500
|
const outer = homeName( art._outer, absoluteOnly );
|
|
1499
1501
|
if (art.kind === '$annotation') // eslint-disable-next-line sonarjs/no-nested-template-literals
|
|
1500
1502
|
return `${ outer }/${ quoted( `@${ art.name.id }` ) }`;
|
|
1501
1503
|
return outer;
|
|
1502
1504
|
}
|
|
1505
|
+
else if (art.kind === '$annotation') { // in items property, or annotation with path
|
|
1506
|
+
return quoted( `@${ art.name.id }` );
|
|
1507
|
+
}
|
|
1503
1508
|
else if (art.kind === 'source' || !art.name) { // error reported in parser or on source level
|
|
1504
1509
|
return null;
|
|
1505
1510
|
}
|
package/lib/checks/elements.js
CHANGED
|
@@ -126,8 +126,13 @@ function checkManagedAssoc( member ) {
|
|
|
126
126
|
if (targetMax === 1 || member.on)
|
|
127
127
|
return;
|
|
128
128
|
|
|
129
|
+
// Special case for "--with-mocks" of the cds cli: For testing databases such as H2 and SQLite, we allow
|
|
130
|
+
// associations with neither on-condition nor foreign keys if the CSN is mocked.
|
|
131
|
+
// See #13916 for details.
|
|
132
|
+
const allowForMocked = this.csn._mocked && (this.options.sqlDialect === 'h2' || this.options.sqlDialect === 'sqlite');
|
|
133
|
+
|
|
129
134
|
const isPersisted = !hasPersistenceSkipAnnotation(this.artifact) && !this.artifact['@cds.persistence.exists'];
|
|
130
|
-
if (isPersisted && !member.keys && (targetMax === '*' || Number(targetMax) > 1) && this.options.transformation === 'sql') {
|
|
135
|
+
if (isPersisted && !allowForMocked && !member.keys && (targetMax === '*' || Number(targetMax) > 1) && this.options.transformation === 'sql') {
|
|
131
136
|
// Since cds-compiler v6, managed to-many no longer get 'keys'.
|
|
132
137
|
// As this would lead to DROP COLUMNs, emit an error instead.
|
|
133
138
|
this.error('type-missing-on-condition', member.cardinality?.$path || member.$path, {
|
|
@@ -497,6 +497,7 @@ function assertConsistency( model, stage ) {
|
|
|
497
497
|
// expressions as annotation values
|
|
498
498
|
'$tokenTexts', 'op', 'args', 'func', '_artifact', 'type', '$typeArgs',
|
|
499
499
|
'scale', 'srid', 'length', 'precision', 'scope', '$parens',
|
|
500
|
+
'_block', '_outer', // for annotation assignments
|
|
500
501
|
],
|
|
501
502
|
// TODO: restrict path to #simplePath
|
|
502
503
|
},
|
package/lib/compiler/checks.js
CHANGED
|
@@ -972,7 +972,7 @@ function check( model ) {
|
|
|
972
972
|
|
|
973
973
|
function checkAnnotationAssignment1( art, anno ) {
|
|
974
974
|
const name = anno.name?.id;
|
|
975
|
-
if (art.$contains?.$annotation && anno.kind === '$annotation') {
|
|
975
|
+
if (art.$contains?.$annotation && anno.kind === '$annotation' && anno._outer) {
|
|
976
976
|
if (checkAnnotationAcceptsExpressions( anno, art ))
|
|
977
977
|
checkAnnotationExpressions( anno, art );
|
|
978
978
|
}
|
|
@@ -1125,7 +1125,7 @@ function check( model ) {
|
|
|
1125
1125
|
return;
|
|
1126
1126
|
}
|
|
1127
1127
|
|
|
1128
|
-
// Struct expected (can only happen within arrays)?
|
|
1128
|
+
// Struct expected (can only happen within arrays, or CSN input)?
|
|
1129
1129
|
if (elementDecl._effectiveType.elements) {
|
|
1130
1130
|
if (value.literal !== 'struct') {
|
|
1131
1131
|
warning( null, loc, { anno }, 'A struct value is required here for annotation $(ANNO)' );
|
package/lib/compiler/define.js
CHANGED
|
@@ -298,6 +298,7 @@ function define( model ) {
|
|
|
298
298
|
return;
|
|
299
299
|
}
|
|
300
300
|
setLink( art, '_block', block );
|
|
301
|
+
initExprAnnoBlock( art, block );
|
|
301
302
|
// dictAdd might set $duplicates
|
|
302
303
|
dictAdd( model.definitions, absolute, art );
|
|
303
304
|
}
|
|
@@ -393,6 +394,7 @@ function define( model ) {
|
|
|
393
394
|
|
|
394
395
|
function addExtension( ext, block ) {
|
|
395
396
|
setLink( ext, '_block', block );
|
|
397
|
+
initExprAnnoBlock( ext, block );
|
|
396
398
|
const absolute = ext.name && resolveUncheckedPath( ext.name, '_extensions', ext );
|
|
397
399
|
if (!absolute) // broken path
|
|
398
400
|
return;
|
|
@@ -429,6 +431,7 @@ function define( model ) {
|
|
|
429
431
|
if (prop === 'params' && name === '') // RETURNS
|
|
430
432
|
sub.name = { id: '', location: sub.location };
|
|
431
433
|
setLink( sub, '_block', parent._block );
|
|
434
|
+
initExprAnnoBlock( sub, parent._block );
|
|
432
435
|
setLink( sub, '_parent', parent );
|
|
433
436
|
setLink( sub, '_main', parent._main || parent );
|
|
434
437
|
initExtension( sub );
|
|
@@ -446,6 +449,26 @@ function define( model ) {
|
|
|
446
449
|
}
|
|
447
450
|
}
|
|
448
451
|
|
|
452
|
+
function initExprAnnoBlock( art, block ) {
|
|
453
|
+
// remark: `art` could also be the extension
|
|
454
|
+
for (const prop in art) {
|
|
455
|
+
if (prop.charAt(0) !== '@')
|
|
456
|
+
continue;
|
|
457
|
+
const anno = art[prop];
|
|
458
|
+
// _block links needed for `cast( … as Type )`, `[ ..., cast( … as Type ) ]`
|
|
459
|
+
if (anno.literal === 'array') {
|
|
460
|
+
anno.kind = '$annotation';
|
|
461
|
+
for (const item of anno.val)
|
|
462
|
+
setLink( item, '_block', block );
|
|
463
|
+
}
|
|
464
|
+
else if (anno.$tokenTexts) {
|
|
465
|
+
// remark: it wouldn't hurt to set it always...
|
|
466
|
+
anno.kind = '$annotation';
|
|
467
|
+
setLink( anno, '_block', block );
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
449
472
|
function addVocabulary( vocab, block, prefix ) {
|
|
450
473
|
setLink( vocab, '_block', block );
|
|
451
474
|
const { name } = vocab;
|
|
@@ -1009,6 +1032,7 @@ function define( model ) {
|
|
|
1009
1032
|
}
|
|
1010
1033
|
|
|
1011
1034
|
initItemsLinks( col, parent._block );
|
|
1035
|
+
initExprAnnoBlock( col, parent._block );
|
|
1012
1036
|
}
|
|
1013
1037
|
|
|
1014
1038
|
if (hasItems && !wildcard && parent.excludingDict && !options.$recompile) {
|
|
@@ -1069,6 +1093,7 @@ function define( model ) {
|
|
|
1069
1093
|
const main = parent._main || parent;
|
|
1070
1094
|
const isQueryExtension = construct.kind === 'extend' && main.query;
|
|
1071
1095
|
let obj = initItemsLinks( construct, block );
|
|
1096
|
+
initExprAnnoBlock( construct, block );
|
|
1072
1097
|
if (obj.target && targetIsTargetAspect( obj )) {
|
|
1073
1098
|
obj.targetAspect = obj.target;
|
|
1074
1099
|
delete obj.target;
|
package/lib/compiler/extend.js
CHANGED
|
@@ -490,6 +490,7 @@ function extend( model ) {
|
|
|
490
490
|
const location = firstEllipsis.location || anno.name.location;
|
|
491
491
|
message( 'anno-unexpected-ellipsis', [ location, art ], { code: '...' } );
|
|
492
492
|
previousAnno = {
|
|
493
|
+
kind: '$annotation',
|
|
493
494
|
val: [],
|
|
494
495
|
literal: 'array',
|
|
495
496
|
name: { id: annoName.slice( 1 ) },
|
|
@@ -500,6 +501,7 @@ function extend( model ) {
|
|
|
500
501
|
// TODO: If we introduce sub-messages, point to the non-array base value.
|
|
501
502
|
error( 'anno-mismatched-ellipsis', [ anno.name.location, art ], { code: '...' } );
|
|
502
503
|
previousAnno = {
|
|
504
|
+
kind: '$annotation',
|
|
503
505
|
val: [],
|
|
504
506
|
literal: 'array',
|
|
505
507
|
name: previousAnno.name,
|
|
@@ -533,6 +535,7 @@ function extend( model ) {
|
|
|
533
535
|
}
|
|
534
536
|
// console.log('TP:',previousValue.map(se),anno.val.map(se),'->',result.map(se))
|
|
535
537
|
return {
|
|
538
|
+
kind: '$annotation',
|
|
536
539
|
val: result,
|
|
537
540
|
literal: 'array',
|
|
538
541
|
name: previousAnno.name,
|
package/lib/compiler/resolve.js
CHANGED
|
@@ -1466,19 +1466,35 @@ function resolve( model ) {
|
|
|
1466
1466
|
}
|
|
1467
1467
|
}
|
|
1468
1468
|
|
|
1469
|
-
function resolveAnnoExpr( expr, art, anno = expr ) {
|
|
1469
|
+
function resolveAnnoExpr( expr, art, anno = expr, topItem = false ) {
|
|
1470
1470
|
if (expr.$tokenTexts) {
|
|
1471
|
-
if (
|
|
1471
|
+
if (anno === expr) {
|
|
1472
1472
|
initAnnotationForExpression( anno, art );
|
|
1473
|
+
}
|
|
1474
|
+
else if (topItem) { // item of top-level array annotation
|
|
1475
|
+
setLink( expr, '_outer', anno );
|
|
1476
|
+
anno = expr;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1473
1479
|
const type = anno === expr && anno.name;
|
|
1474
1480
|
// TODO: it might be best to set an _artifact link also for property values
|
|
1475
1481
|
// like in `@Anno: [ { foo: #EnumSymbol }]
|
|
1476
1482
|
resolveExpr( expr, 'annotation', anno, type );
|
|
1477
1483
|
}
|
|
1478
1484
|
else if (expr.literal === 'array') {
|
|
1479
|
-
|
|
1485
|
+
const withExpr = anno === expr &&
|
|
1486
|
+
// the following is needed for checkAnnotationAcceptsExpressions(),
|
|
1487
|
+
// otherwise @cds.persistence.skip: [hdi, hdbcds, sql.postgres] fails
|
|
1488
|
+
expr.val.some( item => item.$tokenTexts || item.literal === 'struct');
|
|
1489
|
+
if (withExpr)
|
|
1490
|
+
initAnnotationForExpression( anno, art );
|
|
1491
|
+
expr.val.forEach( val => resolveAnnoExpr( val, art, anno, withExpr ) );
|
|
1480
1492
|
}
|
|
1481
1493
|
else if (expr.literal === 'struct') {
|
|
1494
|
+
if (topItem) { // item of top-level array annotation
|
|
1495
|
+
setLink( expr, '_outer', anno );
|
|
1496
|
+
anno = expr;
|
|
1497
|
+
}
|
|
1482
1498
|
Object.values( expr.struct ).forEach( val => resolveAnnoExpr( val, art, anno ) );
|
|
1483
1499
|
}
|
|
1484
1500
|
}
|
|
@@ -1490,10 +1506,9 @@ function resolve( model ) {
|
|
|
1490
1506
|
* @param {XSN.Artifact} art
|
|
1491
1507
|
*/
|
|
1492
1508
|
function initAnnotationForExpression( anno, art ) {
|
|
1493
|
-
anno.kind = '$annotation';
|
|
1494
1509
|
setLink( anno, '_outer', art );
|
|
1495
1510
|
art.$contains ??= {};
|
|
1496
|
-
art.$contains.$annotation
|
|
1511
|
+
art.$contains.$annotation ??= { // set in resolveExprPath
|
|
1497
1512
|
$path: false,
|
|
1498
1513
|
$self: false,
|
|
1499
1514
|
};
|
|
@@ -1501,6 +1516,9 @@ function resolve( model ) {
|
|
|
1501
1516
|
// Might be useful for future recursive types.
|
|
1502
1517
|
}
|
|
1503
1518
|
|
|
1519
|
+
// Note: for annotation assignments, `art` should be the annotation, not the
|
|
1520
|
+
// assignee (element, ...); otherwise, artifact links could be resolved in the
|
|
1521
|
+
// wrong block
|
|
1504
1522
|
function resolveExpr( expr, exprCtx, art, type = null ) {
|
|
1505
1523
|
traverseTypedExpr( expr, exprCtx, art, type, resolveExprNode );
|
|
1506
1524
|
}
|
|
@@ -1553,8 +1571,12 @@ function resolve( model ) {
|
|
|
1553
1571
|
const ref = resolvePath( expr, expected, user );
|
|
1554
1572
|
|
|
1555
1573
|
if (expected === 'annotation') {
|
|
1556
|
-
user._outer
|
|
1557
|
-
|
|
1574
|
+
const ruser = (user._outer.kind === '$annotation')
|
|
1575
|
+
? user._outer._outer
|
|
1576
|
+
: user._outer;
|
|
1577
|
+
// if (!ruser.$contains) console.log('UO:',!!ruser,!!user._block,user._outer)
|
|
1578
|
+
ruser.$contains.$annotation.$path = true;
|
|
1579
|
+
ruser.$contains.$annotation.$self ||= expr.path[0]?._navigation?.kind === '$self';
|
|
1558
1580
|
}
|
|
1559
1581
|
|
|
1560
1582
|
// check whether arguments and filters are allowed on last path item;
|
package/lib/compiler/shared.js
CHANGED
|
@@ -775,8 +775,13 @@ function fns( model ) {
|
|
|
775
775
|
if (head._artifact !== undefined)
|
|
776
776
|
return head._artifact;
|
|
777
777
|
let ruser = user._user || user; // TODO: nicer name if we keep this
|
|
778
|
-
|
|
779
|
-
|
|
778
|
+
// TODO: re-think _user link
|
|
779
|
+
if (ruser._outer && !semantics.isMainRef) {
|
|
780
|
+
if (ruser.kind === '$annotation')
|
|
781
|
+
ruser = ruser._outer; // for elem refs, use elem as real "user"
|
|
782
|
+
else if (ruser._outer.kind === '$annotation')
|
|
783
|
+
ruser = ruser._outer._outer;
|
|
784
|
+
}
|
|
780
785
|
|
|
781
786
|
// Handle expand/inline, `type of`, :param, global (internally for CDL):
|
|
782
787
|
if (user._columnParent && !semantics.isMainRef) { // in expand/inline
|
|
@@ -1002,7 +1007,8 @@ function fns( model ) {
|
|
|
1002
1007
|
// TODO: remove again, should be easy enough in to-csn without.
|
|
1003
1008
|
if (path.length === 1 && art.kind === '$tableAlias')
|
|
1004
1009
|
(user._user || user).$noOrigin = true;
|
|
1005
|
-
if (head.id === '$projection' &&
|
|
1010
|
+
if (head.id === '$projection' &&
|
|
1011
|
+
(user.kind === '$annotation' || user._outer?.kind === '$annotation')) {
|
|
1006
1012
|
error( 'ref-unsupported-projection', [ head.location, user ],
|
|
1007
1013
|
{ code: '$projection', newcode: '$self' },
|
|
1008
1014
|
'$(CODE) is not supported in annotations; replace by $(NEWCODE)' );
|
|
@@ -510,12 +510,10 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
510
510
|
evalArgs(td, typeFacets, typeDef);
|
|
511
511
|
EdmTypeFacetNames.forEach((facetName) => {
|
|
512
512
|
const facetDef = EdmTypeFacetMap[facetName];
|
|
513
|
-
const optional
|
|
514
|
-
|
|
515
|
-
? (Array.isArray(facetDef.optional)
|
|
513
|
+
const optional = (facetDef.optional !== undefined) &&
|
|
514
|
+
(Array.isArray(facetDef.optional)
|
|
516
515
|
? facetDef.optional.includes(typeDef)
|
|
517
|
-
: facetDef.optional)
|
|
518
|
-
: false;
|
|
516
|
+
: facetDef.optional);
|
|
519
517
|
|
|
520
518
|
if (td[facetName]) {
|
|
521
519
|
// ignore facets that are not type relevant
|
|
@@ -267,7 +267,8 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
267
267
|
|
|
268
268
|
Object.entries(cObject.actions).forEach(([ n, action ]) => {
|
|
269
269
|
setProp(action, '$isBound', true);
|
|
270
|
-
const
|
|
270
|
+
const v2entity = isV2() ? `${ entityName }_` : '';
|
|
271
|
+
const actionName = `${ serviceName }.${ v2entity }${ n }`;
|
|
271
272
|
handleAction(actionName, action, cObjectname, [ ...location, 'actions', n ]);
|
|
272
273
|
});
|
|
273
274
|
}
|
|
@@ -1662,7 +1663,9 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
1662
1663
|
message('odata-anno-dict', msg.location, { anno: msg.anno(), '#': 'experimental' });
|
|
1663
1664
|
usedExperimentalTerms[termName] = true;
|
|
1664
1665
|
}
|
|
1665
|
-
|
|
1666
|
+
// TODO: remove this part "&& termName !== 'Common.DraftNode'" once the annotation is not part
|
|
1667
|
+
// of the dictionaries
|
|
1668
|
+
if (dictTerm.$deprecated && !usedDeprecatedTerms[termName] && termName !== 'Common.DraftNode') {
|
|
1666
1669
|
message('odata-anno-def', msg.location,
|
|
1667
1670
|
{ anno: msg.anno(), depr: dictTerm.$deprecationText, '#': 'deprecated' });
|
|
1668
1671
|
usedDeprecatedTerms[termName] = true;
|
package/lib/edm/csn2edm.js
CHANGED
|
@@ -1172,12 +1172,10 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
|
|
|
1172
1172
|
}
|
|
1173
1173
|
EdmTypeFacetNames.forEach((name) => {
|
|
1174
1174
|
const facet = EdmTypeFacetMap[name];
|
|
1175
|
-
const optional
|
|
1176
|
-
|
|
1177
|
-
?
|
|
1178
|
-
|
|
1179
|
-
: facet.optional)
|
|
1180
|
-
: false;
|
|
1175
|
+
const optional = (facet.optional !== undefined) &&
|
|
1176
|
+
(Array.isArray(facet.optional)
|
|
1177
|
+
? facet.optional.includes(edmType)
|
|
1178
|
+
: facet.optional);
|
|
1181
1179
|
|
|
1182
1180
|
// facet is not in attributes
|
|
1183
1181
|
// facet is member of type definition and mandatory
|
package/lib/edm/edm.js
CHANGED
|
@@ -633,17 +633,17 @@ function getEdm( options ) {
|
|
|
633
633
|
this._typeName = typeName;
|
|
634
634
|
this._scalarType = undefined;
|
|
635
635
|
if (this._edmAttributes[typeName] === undefined) {
|
|
636
|
-
const
|
|
636
|
+
const typeCsn = csn.items?.type ? csn.items : csn;
|
|
637
637
|
// Complex/EntityType are derived from TypeBase
|
|
638
638
|
// but have no type attribute in their CSN
|
|
639
|
-
if (
|
|
639
|
+
if (typeCsn.type) { // this thing has a type
|
|
640
640
|
// check whether this is a scalar type (or array of scalar type) or a named type
|
|
641
|
-
if (
|
|
642
|
-
isBuiltinType(
|
|
643
|
-
this._scalarType =
|
|
641
|
+
if (typeCsn.items?.type &&
|
|
642
|
+
isBuiltinType(typeCsn.items.type))
|
|
643
|
+
this._scalarType = typeCsn.items;
|
|
644
644
|
|
|
645
|
-
else if (isBuiltinType(
|
|
646
|
-
this._scalarType =
|
|
645
|
+
else if (isBuiltinType(typeCsn.type))
|
|
646
|
+
this._scalarType = typeCsn;
|
|
647
647
|
|
|
648
648
|
if (this._scalarType) {
|
|
649
649
|
this._edmAttributes[typeName] = csn._edmType;
|
|
@@ -658,7 +658,7 @@ function getEdm( options ) {
|
|
|
658
658
|
}
|
|
659
659
|
else {
|
|
660
660
|
// it's either _edmType or type (_edmType only used for explicit binding param)
|
|
661
|
-
this._edmAttributes[typeName] =
|
|
661
|
+
this._edmAttributes[typeName] = typeCsn._edmType || typeCsn.type;
|
|
662
662
|
}
|
|
663
663
|
}
|
|
664
664
|
// CDXCORE-245:
|
|
@@ -666,7 +666,7 @@ function getEdm( options ) {
|
|
|
666
666
|
// optionally add @odata { MaxLength, Precision, Scale, SRID }
|
|
667
667
|
// but only in combination with @odata.Type
|
|
668
668
|
// Allow to override type only on scalar and undefined types
|
|
669
|
-
if ((this._scalarType ||
|
|
669
|
+
if ((this._scalarType || typeCsn.type == null) && !csn.elements) {
|
|
670
670
|
const odataType = csn['@odata.Type'];
|
|
671
671
|
if (odataType) {
|
|
672
672
|
const td = EdmPrimitiveTypeMap[odataType];
|
|
@@ -1053,15 +1053,15 @@ function getEdm( options ) {
|
|
|
1053
1053
|
delete this._edmAttributes.Nullable;
|
|
1054
1054
|
}
|
|
1055
1055
|
// we have exactly one selfReference or the default partner
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1056
|
+
|
|
1057
|
+
if ( !csn.$noPartner) {
|
|
1058
|
+
const partner = csn._selfReferences.length === 1
|
|
1059
|
+
? csn._selfReferences[0]
|
|
1060
|
+
: csn._constraints._partnerCsn;
|
|
1061
|
+
if (partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
|
|
1062
|
+
// $abspath[0] is main entity
|
|
1063
|
+
this._edmAttributes.Partner = partner.$abspath.slice(1).join('/');
|
|
1064
|
+
}
|
|
1065
1065
|
}
|
|
1066
1066
|
|
|
1067
1067
|
/*
|
|
@@ -1212,8 +1212,11 @@ function getEdm( options ) {
|
|
|
1212
1212
|
/* short notation for Edm.Boolean, Edm.String and Edm.Float, see internal project:
|
|
1213
1213
|
edmx2csn-npm/edm-converters/blob/835d92a1aa6b0be25c56cef85e260c9188187429/lib/edmxV40ToJsonV40/README.md
|
|
1214
1214
|
*/
|
|
1215
|
-
if (inline[0] === 'Edm.Boolean')
|
|
1216
|
-
|
|
1215
|
+
if (inline[0] === 'Edm.Boolean') {
|
|
1216
|
+
if (v === 'true')
|
|
1217
|
+
return true;
|
|
1218
|
+
return (v === 'false') ? false : v;
|
|
1219
|
+
}
|
|
1217
1220
|
return v;
|
|
1218
1221
|
}
|
|
1219
1222
|
|
|
@@ -1292,7 +1295,8 @@ function getEdm( options ) {
|
|
|
1292
1295
|
}
|
|
1293
1296
|
|
|
1294
1297
|
getJsonFQTermName() {
|
|
1295
|
-
|
|
1298
|
+
const qualifier = this._edmAttributes.Qualifier ? `#${ this._edmAttributes.Qualifier }` : '';
|
|
1299
|
+
return `@${ this._edmAttributes.Term }${ qualifier }`;
|
|
1296
1300
|
}
|
|
1297
1301
|
}
|
|
1298
1302
|
|
|
@@ -117,13 +117,13 @@ function inboundQualificationChecks( csn, options, messageFunctions,
|
|
|
117
117
|
i++;
|
|
118
118
|
}
|
|
119
119
|
if (i > 1) {
|
|
120
|
-
message('
|
|
120
|
+
message('type-invalid-items', path, { '#': 'nested', prop: 'items' });
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
const itemsType = csnUtils.effectiveType(memberType.items);
|
|
125
125
|
if (itemsType.items)
|
|
126
|
-
message('
|
|
126
|
+
message('type-invalid-items', path, { '#': 'chained-service', prop: 'items' });
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -275,7 +275,10 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
275
275
|
// if this definition has a root def and the root def is not the service/schema name
|
|
276
276
|
// => service C { type D.E }, replace the prefix dots with underscores
|
|
277
277
|
if (rootDef && defName !== rootDef && rootDef !== edmUtils.getSchemaPrefix(defName)) {
|
|
278
|
-
const
|
|
278
|
+
const underscoredDefName = defName
|
|
279
|
+
.replace(`${ rootDef }.`, '')
|
|
280
|
+
.replace(/\./g, '_');
|
|
281
|
+
const newDefName = `${ rootDef }.${ underscoredDefName }`;
|
|
279
282
|
// store renamed types in correlation maps for later renaming
|
|
280
283
|
if (def.kind === 'entity')
|
|
281
284
|
dotEntityNameMap[defName] = newDefName;
|
|
@@ -335,8 +338,20 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
335
338
|
rewriteReferencesInActions(node);
|
|
336
339
|
};
|
|
337
340
|
|
|
338
|
-
|
|
341
|
+
const applyOnAnnoXprs = (node) => {
|
|
342
|
+
Object.keys(node).filter(pn => pn[0] === '@').forEach((anno) => {
|
|
343
|
+
transformAnnotationExpression(node, anno, {
|
|
344
|
+
ref: (elemRef, _prop, ref) => {
|
|
345
|
+
if (dotEntityNameMap[ref[0]] || dotTypeNameMap[ref[0]])
|
|
346
|
+
elemRef.ref[0] = dotEntityNameMap[ref[0]] || dotTypeNameMap[ref[0]];
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
forEachMemberRecursively(def, [ applyOnNode, applyOnAnnoXprs ]);
|
|
339
353
|
applyOnNode(def);
|
|
354
|
+
applyOnAnnoXprs(def);
|
|
340
355
|
// handle unbound action/function and params in views
|
|
341
356
|
rewriteReferencesInActions(def);
|
|
342
357
|
};
|
|
@@ -876,7 +891,7 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
876
891
|
// eslint-disable-next-line eqeqeq
|
|
877
892
|
const srcMult = (partnerCsn.cardinality.src == 1) ? '0..1' : '*';
|
|
878
893
|
const newMult
|
|
879
|
-
= (element.cardinality?.min == 1 && element.cardinality?.max == 1) // eslint-disable-line
|
|
894
|
+
= (element.cardinality?.min == 1 && element.cardinality?.max == 1) // eslint-disable-line
|
|
880
895
|
? 1
|
|
881
896
|
: (element.cardinality?.max === '*' || element.cardinality?.max > 1)
|
|
882
897
|
? '*'
|
|
@@ -1082,8 +1097,9 @@ function initializeModel( csn, _options, messageFunctions, requestedServiceNames
|
|
|
1082
1097
|
|
|
1083
1098
|
// 1) construct the proxy definition
|
|
1084
1099
|
// proxyDefinitionName: strip the serviceName and replace '.' with '_'
|
|
1085
|
-
const defName
|
|
1086
|
-
|
|
1100
|
+
const defName = assoc._target.name
|
|
1101
|
+
.replace(`${ proxySchemaName }.`, '')
|
|
1102
|
+
.replace(/\./g, '_');
|
|
1087
1103
|
|
|
1088
1104
|
// fullName: Prepend serviceName and if in same service add '_proxy'
|
|
1089
1105
|
const proxy = isParamProxy
|
package/lib/edm/edmUtils.js
CHANGED
|
@@ -446,23 +446,20 @@ function determineMultiplicity( csn ) {
|
|
|
446
446
|
if (!csn.cardinality)
|
|
447
447
|
csn.cardinality = Object.create(null);
|
|
448
448
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
csn.cardinality.min = 0;
|
|
453
|
-
if (!csn.cardinality.max)
|
|
454
|
-
csn.cardinality.max = 1;
|
|
449
|
+
csn.cardinality.src ??= isAssoc ? '*' : '1';
|
|
450
|
+
csn.cardinality.min ??= 0;
|
|
451
|
+
csn.cardinality.max ??= 1;
|
|
455
452
|
|
|
456
453
|
const srcCardinality
|
|
457
|
-
= (csn.cardinality.src == 1) // eslint-disable-line
|
|
458
|
-
? (!isAssoc || csn.cardinality.srcmin == 1) // eslint-disable-line
|
|
454
|
+
= (csn.cardinality.src == 1) // eslint-disable-line
|
|
455
|
+
? (!isAssoc || csn.cardinality.srcmin == 1) // eslint-disable-line
|
|
459
456
|
? '1'
|
|
460
457
|
: '0..1'
|
|
461
458
|
: '*';
|
|
462
|
-
const tgtCardinality
|
|
459
|
+
const tgtCardinality // eslint-disable-next-line no-nested-ternary
|
|
463
460
|
= (csn.cardinality.max > 1 || csn.cardinality.max === '*')
|
|
464
461
|
? '*'
|
|
465
|
-
: (csn.cardinality.min == 1) // eslint-disable-line
|
|
462
|
+
: (csn.cardinality.min == 1) // eslint-disable-line
|
|
466
463
|
? '1'
|
|
467
464
|
: '0..1';
|
|
468
465
|
|
package/lib/gen/BaseParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Base class for generated parser, for redepage v0.2.
|
|
1
|
+
// Base class for generated parser, for redepage v0.2.4
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// list of predicates which are tested when continue parsing after error starts,
|
|
10
10
|
// i.e. there is a predicate on the first token to match after recover example
|
|
11
11
|
// `afterBrace` or just method which by default just sets this.conditionTokenIdx
|
|
12
|
-
|
|
12
|
+
// and this.conditionStackLength and returns true?
|
|
13
13
|
|
|
14
14
|
class BaseParser {
|
|
15
15
|
keywords;
|
|
@@ -314,7 +314,7 @@ class BaseParser {
|
|
|
314
314
|
}
|
|
315
315
|
// calling the condition might have side effects (precendence conditions have)
|
|
316
316
|
// → call tracing “name” before
|
|
317
|
-
const fail = this[cond](
|
|
317
|
+
const fail = this[cond]( arg, true ); // TODO: use single-letter for run?
|
|
318
318
|
if (this.constructor.tracingParser)
|
|
319
319
|
this._traceSubPush( !fail );
|
|
320
320
|
// The default case must not have actions. If written in grammar with action,
|
|
@@ -580,7 +580,7 @@ class BaseParser {
|
|
|
580
580
|
if (!cond || lean && !this.leanConditions[cond])
|
|
581
581
|
return false;
|
|
582
582
|
if (!this.constructor.tracingParser)
|
|
583
|
-
return !!this[cond](
|
|
583
|
+
return !!this[cond]( cmd[4], mode );
|
|
584
584
|
// TODO: let this[cond]( true ) return recovery badness in error case
|
|
585
585
|
if (!lean) {
|
|
586
586
|
const { traceName } = this[cond];
|
|
@@ -588,7 +588,7 @@ class BaseParser {
|
|
|
588
588
|
// calling the condition might have side effects (precendence conditions have)
|
|
589
589
|
// → call tracing “name” before
|
|
590
590
|
}
|
|
591
|
-
const succeed = !this[cond](
|
|
591
|
+
const succeed = !this[cond]( cmd[4], mode );
|
|
592
592
|
this._traceSubPush( lean ? { true: 'C✔', false: 'C✖' }[succeed] : succeed );
|
|
593
593
|
return !succeed;
|
|
594
594
|
}
|
|
@@ -934,24 +934,24 @@ class BaseParser {
|
|
|
934
934
|
|
|
935
935
|
// Predefined conditions with extra option names:
|
|
936
936
|
|
|
937
|
-
hide_( mode ) {
|
|
937
|
+
hide_( _arg, mode ) {
|
|
938
938
|
return mode === 'M';
|
|
939
939
|
}
|
|
940
|
-
precLeft_(
|
|
940
|
+
precLeft_( prec ) { // <prec=…>, <…,assoc=left>, <…,prefix=once>
|
|
941
941
|
const parentPrec = this.stack.at( -1 ).prec;
|
|
942
942
|
if (parentPrec != null && parentPrec >= prec)
|
|
943
943
|
return true;
|
|
944
944
|
this.prec_ = prec;
|
|
945
945
|
return false;
|
|
946
946
|
}
|
|
947
|
-
precRight_(
|
|
947
|
+
precRight_( prec ) { // <…,assoc=right>, <…,prefix>
|
|
948
948
|
const parentPrec = this.stack.at( -1 ).prec;
|
|
949
949
|
if (parentPrec != null && parentPrec >= prec)
|
|
950
950
|
return true;
|
|
951
951
|
this.prec_ = prec - 1;
|
|
952
952
|
return false;
|
|
953
953
|
}
|
|
954
|
-
precNone_(
|
|
954
|
+
precNone_( prec ) { // <…,assoc=none>, <…,postfix=once>
|
|
955
955
|
const parentPrec = this.stack.at( -1 ).prec;
|
|
956
956
|
if (parentPrec != null && parentPrec >= prec ||
|
|
957
957
|
this.prec_ != null && this.prec_ <= prec)
|
|
@@ -959,7 +959,7 @@ class BaseParser {
|
|
|
959
959
|
this.prec_ = prec;
|
|
960
960
|
return false;
|
|
961
961
|
}
|
|
962
|
-
precPost_(
|
|
962
|
+
precPost_( prec ) { // <…,postfix>
|
|
963
963
|
const parentPrec = this.stack.at( -1 ).prec;
|
|
964
964
|
if (parentPrec != null && parentPrec >= prec ||
|
|
965
965
|
this.prec_ != null && this.prec_ < prec)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
eb778bab22f4006cfcf64e418dcae71c
|
package/lib/gen/CdlParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Parser generated by redepage v0.2.
|
|
1
|
+
// Parser generated by redepage v0.2.4
|
|
2
2
|
'use strict;'
|
|
3
3
|
const { XsnSource, XsnArtifact, XsnName } = require( '../compiler/xsn-model' )
|
|
4
4
|
const AstBuildingParser = require('../parsers/AstBuildingParser')
|
|
@@ -783,7 +783,7 @@ floating:['ck',0],variable:'floating',
|
|
|
783
783
|
{
|
|
784
784
|
'*':['c',430],
|
|
785
785
|
Number:['c',432],
|
|
786
|
-
'':434
|
|
786
|
+
']':434,
|
|
787
787
|
},
|
|
788
788
|
{',':['c',431],'':434},
|
|
789
789
|
[434,436],
|
|
@@ -1259,10 +1259,10 @@ Id:['ciA',720],
|
|
|
1259
1259
|
},
|
|
1260
1260
|
['m',721,'=>'],
|
|
1261
1261
|
[718,644],
|
|
1262
|
-
{Id:[723,731],'#':'Id','(':'Id','*':'Id','+':'Id','-':'Id',':':'Id','?':'Id',
|
|
1262
|
+
{Id:[723,731],'#':'Id','(':'Id','*':'Id','+':'Id','-':'Id',':':'Id','?':'Id',Number:'Id',String:'Id',QuotedLiteral:'Id',DeleteStarFromSet:'Id','':728},
|
|
1263
1263
|
{',':['c',724,,,,'nextFunctionArgument'],'':725},
|
|
1264
1264
|
{
|
|
1265
|
-
Id:[723,731],'#':'Id','(':'Id','*':'Id','+':'Id','-':'Id',':':'Id','?':'Id',not:'Id',case:'Id',cast:'Id',null:'Id',true:'Id',false:'Id',
|
|
1265
|
+
Id:[723,731],'#':'Id','(':'Id','*':'Id','+':'Id','-':'Id',':':'Id','?':'Id',not:'Id',case:'Id',cast:'Id',null:'Id',true:'Id',false:'Id',Number:'Id',String:'Id',exists:'Id',QuotedLiteral:'Id',DeleteStarFromSet:'Id',
|
|
1266
1266
|
')':['g',725,1,'atRightParen'],order:')',
|
|
1267
1267
|
},
|
|
1268
1268
|
{order:['ck',726],'':728},
|
|
@@ -1430,7 +1430,10 @@ Id:[825,815],'#':'Id','(':'Id','+':'Id','-':'Id','@':'Id','[':'Id','{':'Id',Numb
|
|
|
1430
1430
|
'...':['c',822,,'arrayAnno','ellipsis'],
|
|
1431
1431
|
'':826
|
|
1432
1432
|
},
|
|
1433
|
-
{
|
|
1433
|
+
{
|
|
1434
|
+
up:['ck',823],
|
|
1435
|
+
',':825,']':825,
|
|
1436
|
+
},
|
|
1434
1437
|
['mk',824,'to'],
|
|
1435
1438
|
[825,815],
|
|
1436
1439
|
{
|
|
@@ -1447,7 +1450,7 @@ constructor(lexer,...args){super(lexer,keywords,table,...args)}
|
|
|
1447
1450
|
start($,$next){
|
|
1448
1451
|
$.source??=new XsnSource( 'cdl' )
|
|
1449
1452
|
this.rule_(1,$next)
|
|
1450
|
-
{ this.afterBrace(
|
|
1453
|
+
{ this.afterBrace( 'init' ); }
|
|
1451
1454
|
for(;;)switch(this.s){
|
|
1452
1455
|
case 1:switch(this.lk()){
|
|
1453
1456
|
case'namespace':this.gc(3,'namespaceRestriction')&&this.namespaceDeclaration({source:$.source},2);continue
|
|
@@ -1468,7 +1471,7 @@ default:return this.exit_()
|
|
|
1468
1471
|
artifactsBlock($,$next){
|
|
1469
1472
|
this.rule_(5,$next)
|
|
1470
1473
|
for(;;)switch(this.s){
|
|
1471
|
-
case 5:if(this.m(6,'{')){this.afterBrace(
|
|
1474
|
+
case 5:if(this.m(6,'{')){this.afterBrace('init'); $.art.artifacts = this.createDict( $.start ); $.art.extensions = []; }continue
|
|
1472
1475
|
case 6:switch(this.l()){
|
|
1473
1476
|
case'Id':case'@':this.artifactDefOrExtend({outer:$.art},7);continue
|
|
1474
1477
|
default:this.s=8;continue
|
|
@@ -1771,7 +1774,7 @@ default:this.e();continue
|
|
|
1771
1774
|
case 81:this.elementsBlock({art:$.art},87);continue
|
|
1772
1775
|
case 82:switch(this.lk()){
|
|
1773
1776
|
case'(':case'select':if(this.queryExpression(_={},87)){query=_.expr; $.art.query = query; $.art.$syntax = 'entity'; }continue
|
|
1774
|
-
case'projection':this.s=83;{this.afterBrace(
|
|
1777
|
+
case'projection':this.s=83;{this.afterBrace('sloppy')}continue;
|
|
1775
1778
|
default:this.e();continue
|
|
1776
1779
|
}
|
|
1777
1780
|
case 83:if(this.projectionSpec(_={},84)){query=_.query; $.art.query = query; $.art.$syntax = 'projection'; }continue
|
|
@@ -1783,7 +1786,7 @@ case 85:switch(this.lk()){
|
|
|
1783
1786
|
case'limit':case'order':this.orderByLimitOffset({query},86);continue
|
|
1784
1787
|
default:this.s=86;continue
|
|
1785
1788
|
}
|
|
1786
|
-
case 86:this.s=87;{this.afterBrace(
|
|
1789
|
+
case 86:this.s=87;{this.afterBrace('normal'); ; }continue
|
|
1787
1790
|
case 87:switch(this.lk()){
|
|
1788
1791
|
case'actions':this.actionsBlock({art:$.art},0);continue
|
|
1789
1792
|
default:this.gr([';']);continue
|
|
@@ -2021,7 +2024,7 @@ let art=new XsnArtifact()
|
|
|
2021
2024
|
let ret
|
|
2022
2025
|
this.rule_(154,$next)
|
|
2023
2026
|
for(;;)switch(this.s){
|
|
2024
|
-
case 154:if(this.mk(155,'returns')){ret=this.lb();this.elementRestriction(
|
|
2027
|
+
case 154:if(this.mk(155,'returns')){ret=this.lb();this.elementRestriction('default'); art.kind = 'param'; $.outer.returns = art;
|
|
2025
2028
|
this.docComment( art ); }continue
|
|
2026
2029
|
case 155:switch(this.l()){
|
|
2027
2030
|
case'@':this.annoAssignStd({art},155);continue
|
|
@@ -2078,7 +2081,7 @@ case 167:switch(this.lk()){
|
|
|
2078
2081
|
case'element':if(this.ckP(168,['Id'])){ $.art.$syntax = 'element'; }continue
|
|
2079
2082
|
default:this.s=168;continue
|
|
2080
2083
|
}
|
|
2081
|
-
case 168:if(this.mi(169,'Element')){this.elementRestriction(
|
|
2084
|
+
case 168:if(this.mi(169,'Element')){this.elementRestriction('elem'); this.addDef( $.art, $.outer, 'elements', 'element', this.identAst() );
|
|
2082
2085
|
this.docComment( $.art ); }continue
|
|
2083
2086
|
case 169:switch(this.l()){
|
|
2084
2087
|
case'@':this.annoAssignMid({art:$.art},169);continue
|
|
@@ -2811,11 +2814,11 @@ case 358:switch(this.lk()){
|
|
|
2811
2814
|
case'Id':this.typeRefOptArgs({art:$.art},359);continue
|
|
2812
2815
|
case'type':this.lP()&&this.typeTypeOf({art:$.art},359);continue
|
|
2813
2816
|
case'localized':if(this.ckP(368,['Id'])){ $.art.localized = this.valueWithLocation( true ); }continue
|
|
2814
|
-
case'association':if(this.ckP(370,['[','to'])){assoc=this.lb();this.elementRestriction(
|
|
2815
|
-
case'composition':if(this.ckP(374,['[','of'])){assoc=this.lb();this.elementRestriction(
|
|
2816
|
-
case'array':if(this.ckP(378,['of'])){this.elementRestriction(
|
|
2817
|
-
case'many':if(this.ckP(379,['Id','{'])){this.elementRestriction(
|
|
2818
|
-
case'{':if(this.elementsBlock({art:$.art},385)){this.elementRestriction(
|
|
2817
|
+
case'association':if(this.ckP(370,['[','to'])){assoc=this.lb();this.elementRestriction('calc')}continue;
|
|
2818
|
+
case'composition':if(this.ckP(374,['[','of'])){assoc=this.lb();this.elementRestriction('calc')}continue;
|
|
2819
|
+
case'array':if(this.ckP(378,['of'])){this.elementRestriction('calc')}continue;
|
|
2820
|
+
case'many':if(this.ckP(379,['Id','{'])){this.elementRestriction('calc'); $.art.items = { location: this.lb().location }; }continue
|
|
2821
|
+
case'{':if(this.elementsBlock({art:$.art},385)){this.elementRestriction('calc')}continue;
|
|
2819
2822
|
default:this.ei();continue
|
|
2820
2823
|
}
|
|
2821
2824
|
case 359:this.s=360;{ this.docComment( $.art ); }continue
|
|
@@ -2832,7 +2835,7 @@ case'@':this.annoAssignStd({art:$.art},362);continue
|
|
|
2832
2835
|
default:this.s=363;continue
|
|
2833
2836
|
}
|
|
2834
2837
|
case 363:switch(this.lk()){
|
|
2835
|
-
case'enum':if(this.enumSymbolsBlock({art:$.art},364)){this.elementRestriction(
|
|
2838
|
+
case'enum':if(this.enumSymbolsBlock({art:$.art},364)){this.elementRestriction('anno')}continue;
|
|
2836
2839
|
case'@':case'not':case'null':case'default':this.typeProperties({art:$.art},0);continue
|
|
2837
2840
|
default:this.gr([]);continue
|
|
2838
2841
|
}
|
|
@@ -3062,7 +3065,8 @@ case 428:this.m(429,'[');continue
|
|
|
3062
3065
|
case 429:switch(this.l()){
|
|
3063
3066
|
case'*':if(this.c(430)){ card.targetMax = this.valueWithLocation(); }continue
|
|
3064
3067
|
case'Number':if(this.c(432)){ card.targetMax = this.unsignedIntegerLiteral(); }continue
|
|
3065
|
-
|
|
3068
|
+
case']':this.s=434;{ card.targetMax = this.valueWithLocation( '*' ); }continue
|
|
3069
|
+
default:this.e();continue
|
|
3066
3070
|
}
|
|
3067
3071
|
case 430:switch(this.l()){
|
|
3068
3072
|
case',':this.c(431);continue
|
|
@@ -3228,7 +3232,7 @@ case 473:switch(this.lk()){
|
|
|
3228
3232
|
case'excluding':this.excludingClause({query:$.query},480);continue
|
|
3229
3233
|
default:this.s=480;continue
|
|
3230
3234
|
}
|
|
3231
|
-
case 474:this.s=475;{this.inSelectItem(
|
|
3235
|
+
case 474:this.s=475;{this.inSelectItem('sqlStyle'); ; }continue
|
|
3232
3236
|
case 475:switch(this.l()){
|
|
3233
3237
|
case'*':if(this.c(476)){ $.query.columns = [ this.valueWithLocation() ]; }continue
|
|
3234
3238
|
case'Id':case'#':case'(':case'+':case'-':case':':case'?':case'@':case'{':case'Number':case'String':case'QuotedLiteral':this.selectItemDef({columns:($.query.columns = [])},476);continue
|
|
@@ -3324,12 +3328,12 @@ for(;;)switch(this.s){
|
|
|
3324
3328
|
case 500:if(this.m(501,'(')){this.queryOnLeft()}continue;
|
|
3325
3329
|
case 501:switch(this.lk()){
|
|
3326
3330
|
case'(':this.tableOrQueryParens($,502);continue
|
|
3327
|
-
case'Id':if(this.tableExpression($,503)){this.queryOnLeft(
|
|
3331
|
+
case'Id':if(this.tableExpression($,503)){this.queryOnLeft('table')}continue;
|
|
3328
3332
|
case'select':this.queryExpression($,503);continue
|
|
3329
3333
|
default:this.ei();continue
|
|
3330
3334
|
}
|
|
3331
3335
|
case 502:switch(this.lk()){
|
|
3332
|
-
case'full':case'join':case'left':case'cross':case'inner':case'right':if(this.tableExpression($,503,488)){this.queryOnLeft(
|
|
3336
|
+
case'full':case'join':case'left':case'cross':case'inner':case'right':if(this.tableExpression($,503,488)){this.queryOnLeft('table')}continue;
|
|
3333
3337
|
case'limit':case'minus':case'order':case'union':case'except':case'intersect':this.gc(503,'queryOnLeft')&&this.queryExpression($,503,456);continue
|
|
3334
3338
|
default:this.s=503;continue
|
|
3335
3339
|
}
|
|
@@ -3526,7 +3530,7 @@ default:return this.exit_()
|
|
|
3526
3530
|
selectItemsList($,$next){
|
|
3527
3531
|
this.rule_(559,$next)
|
|
3528
3532
|
for(;;)switch(this.s){
|
|
3529
|
-
case 559:if(this.m(560,'{')){this.inSelectItem(
|
|
3533
|
+
case 559:if(this.m(560,'{')){this.inSelectItem('top'); $.query.columns = this.createArray( $.start ); }continue
|
|
3530
3534
|
case 560:switch(this.l()){
|
|
3531
3535
|
case'*':if(this.c(561)){ $.query.columns.push( this.valueWithLocation() ); }continue
|
|
3532
3536
|
case'Id':case'#':case'(':case'+':case'-':case':':case'?':case'@':case'{':case'Number':case'String':case'QuotedLiteral':this.selectItemDef({columns:$.query.columns},561);continue
|
|
@@ -3574,7 +3578,7 @@ case 570:switch(this.lk()){
|
|
|
3574
3578
|
case'virtual':if(this.lP(['Id','#','(','+','-',':','?','{','key','not','case','cast','null','true','false','Number','String','exists','QuotedLiteral'])&&this.gc(571,'modifierRestriction')&&this.ck(571)){ art.virtual = this.valueWithLocation( true ); }continue
|
|
3575
3579
|
default:this.s=571;continue
|
|
3576
3580
|
}
|
|
3577
|
-
case 571:this.s=572;{this.columnExpr(
|
|
3581
|
+
case 571:this.s=572;{this.columnExpr('key'); ; }continue
|
|
3578
3582
|
case 572:switch(this.lk()){
|
|
3579
3583
|
case'key':if(this.gc(573,'modifierRestriction')&&this.ck(573)){ art.key = this.valueWithLocation( true ); }continue
|
|
3580
3584
|
default:this.s=573;continue
|
|
@@ -3588,7 +3592,7 @@ default:this.ei();continue
|
|
|
3588
3592
|
case 574:switch(this.lk()){
|
|
3589
3593
|
case'as':this.ck(575);continue
|
|
3590
3594
|
case'Id':if(this.ci(584,'ItemAlias')){ art.name = this.fragileAlias( true ); }continue
|
|
3591
|
-
default:this.
|
|
3595
|
+
default:this.giR(584);continue
|
|
3592
3596
|
}
|
|
3593
3597
|
case 575:if(this.mi(584,'ItemAlias')){ art.name = this.identAst(); }continue
|
|
3594
3598
|
case 576:switch(this.lk()){
|
|
@@ -3598,7 +3602,7 @@ case'as':this.ck(581);continue
|
|
|
3598
3602
|
case'Id':if(this.ci(584,'ItemAlias')){this.nestedExpand(); art.name = this.fragileAlias( true ); }continue
|
|
3599
3603
|
case'.':if(this.c(582)){ this.reportUnexpectedSpace( this.lb(), this.la().location, true );
|
|
3600
3604
|
this.reportExpandInline( art, true ); }continue
|
|
3601
|
-
default:if(this.
|
|
3605
|
+
default:if(this.giR(584)){this.nestedExpand(); this.virtualOrImplicit( art ); }continue
|
|
3602
3606
|
}
|
|
3603
3607
|
case 577:this.overClause({outer:expr.suffix},578);continue
|
|
3604
3608
|
case 578:switch(this.lk()){
|
|
@@ -3608,7 +3612,7 @@ default:this.s=579;continue
|
|
|
3608
3612
|
case 579:switch(this.lk()){
|
|
3609
3613
|
case'as':this.ck(580);continue
|
|
3610
3614
|
case'Id':if(this.ci(584,'ItemAlias')){ art.name = this.fragileAlias( true ); }continue
|
|
3611
|
-
default:this.
|
|
3615
|
+
default:this.giR(584);continue
|
|
3612
3616
|
}
|
|
3613
3617
|
case 580:if(this.mi(584,'ItemAlias')){ art.name = this.identAst(); }continue
|
|
3614
3618
|
case 581:if(this.mi(584,'ItemAlias')){this.nestedExpand(); art.name = this.identAst(); }continue
|
|
@@ -3622,7 +3626,7 @@ case'excluding':this.excludingClause({query:art},0);continue
|
|
|
3622
3626
|
default:this.gr([',']);continue
|
|
3623
3627
|
}
|
|
3624
3628
|
case 584:switch(this.l()){
|
|
3625
|
-
case'{':if(this.gc(590,'nestedExpand')&&this.g(585)){ if (!this.nestedExpand(true)) this.reportExpandInline( art, false ); }continue
|
|
3629
|
+
case'{':if(this.gc(590,'nestedExpand')&&this.g(585)){ if (!this.nestedExpand(0,true)) this.reportExpandInline( art, false ); }continue
|
|
3626
3630
|
default:this.s=590;continue
|
|
3627
3631
|
}
|
|
3628
3632
|
case 585:this.nestedSelectItemsList({query:art,clause:'expand'},586);continue
|
|
@@ -3929,13 +3933,13 @@ for(;;)switch(this.s){
|
|
|
3929
3933
|
case 679:if(this.m(680,'(')){this.queryOnLeft()}continue;
|
|
3930
3934
|
case 680:switch(this.lk()){
|
|
3931
3935
|
case'(':this.expressionOrQueryParens($,681);continue
|
|
3932
|
-
case'Id':case'#':case'+':case'-':case':':case'?':case'not':case'case':case'cast':case'null':case'true':case'false':case'Number':case'String':case'exists':case'QuotedLiteral':if(this.expression($,683)){this.queryOnLeft(
|
|
3936
|
+
case'Id':case'#':case'+':case'-':case':':case'?':case'not':case'case':case'cast':case'null':case'true':case'false':case'Number':case'String':case'exists':case'QuotedLiteral':if(this.expression($,683)){this.queryOnLeft('expr')}continue;
|
|
3933
3937
|
case'select':this.queryExpression($,684);continue
|
|
3934
3938
|
default:this.ei();continue
|
|
3935
3939
|
}
|
|
3936
3940
|
case 681:switch(this.lk()){
|
|
3937
|
-
case'*':case'+':case'-':case'/':case'<':case'=':case'>':case'?':case'!=':case'<=':case'<>':case'==':case'>=':case'in':case'is':case'or':case'||':case'and':case'not':case'like':case'between':if(this.expression($,682,645)){this.queryOnLeft(
|
|
3938
|
-
case',':if(this.continueExpressionslist($,684)){this.queryOnLeft(
|
|
3941
|
+
case'*':case'+':case'-':case'/':case'<':case'=':case'>':case'?':case'!=':case'<=':case'<>':case'==':case'>=':case'in':case'is':case'or':case'||':case'and':case'not':case'like':case'between':if(this.expression($,682,645)){this.queryOnLeft('expr')}continue;
|
|
3942
|
+
case',':if(this.continueExpressionslist($,684)){this.queryOnLeft('expr')}continue;
|
|
3939
3943
|
case'limit':case'minus':case'order':case'union':case'except':case'intersect':this.gc(684,'queryOnLeft')&&this.queryExpression($,684,456);continue
|
|
3940
3944
|
default:this.s=684;continue
|
|
3941
3945
|
}
|
|
@@ -4063,7 +4067,7 @@ default:this.e();continue
|
|
|
4063
4067
|
case 720:this.m(721,'=>');continue
|
|
4064
4068
|
case 721:if(this.expression(_={},718)){expr=_.expr; this.addNamedArg( $.pathStep, id, expr ); }continue
|
|
4065
4069
|
case 722:switch(this.l()){
|
|
4066
|
-
case'Id':case'#':case'(':case'*':case'+':case'-':case':':case'?':case'
|
|
4070
|
+
case'Id':case'#':case'(':case'*':case'+':case'-':case':':case'?':case'Number':case'String':case'QuotedLiteral':case'DeleteStarFromSet':if(this.funcExpression(_={},723)){expr=_.expr; $.pathStep.args.push( expr ); }continue
|
|
4067
4071
|
default:this.s=728;continue
|
|
4068
4072
|
}
|
|
4069
4073
|
case 723:switch(this.l()){
|
|
@@ -4071,7 +4075,7 @@ case',':if(this.c(724)){this.nextFunctionArgument()}continue;
|
|
|
4071
4075
|
default:this.s=725;continue
|
|
4072
4076
|
}
|
|
4073
4077
|
case 724:switch(this.lk()){
|
|
4074
|
-
case'Id':case'#':case'(':case'*':case'+':case'-':case':':case'?':case'not':case'case':case'cast':case'null':case'true':case'false':case'
|
|
4078
|
+
case'Id':case'#':case'(':case'*':case'+':case'-':case':':case'?':case'not':case'case':case'cast':case'null':case'true':case'false':case'Number':case'String':case'exists':case'QuotedLiteral':case'DeleteStarFromSet':if(this.funcExpression(_={},723)){expr=_.expr; $.pathStep.args.push( expr ); }continue
|
|
4075
4079
|
case')':case'order':this.lP()&&this.ec('atRightParen')&&this.g(725);continue
|
|
4076
4080
|
default:this.ei();continue
|
|
4077
4081
|
}
|
|
@@ -4452,7 +4456,8 @@ default:this.s=826;continue
|
|
|
4452
4456
|
}
|
|
4453
4457
|
case 822:switch(this.lk()){
|
|
4454
4458
|
case'up':this.ck(823);continue
|
|
4455
|
-
|
|
4459
|
+
case',':case']':this.s=825;{ $.value.val.push( { literal: 'token', val: '...', location: ellipsis.location } ); }continue
|
|
4460
|
+
default:this.e();continue
|
|
4456
4461
|
}
|
|
4457
4462
|
case 823:this.mk(824,'to');continue
|
|
4458
4463
|
case 824:if(this.annoValue(_={},825)){upTo=_.value; $.value.val.push( { literal: 'token', val: '...', location: ellipsis.location, upTo: upTo } ); }continue
|
package/lib/gen/Dictionary.json
CHANGED
|
@@ -557,9 +557,11 @@
|
|
|
557
557
|
"AppliesTo": [
|
|
558
558
|
"EntitySet"
|
|
559
559
|
],
|
|
560
|
-
"Type": "
|
|
560
|
+
"Type": "Core.SimpleIdentifier"
|
|
561
561
|
},
|
|
562
562
|
"Common.DraftNode": {
|
|
563
|
+
"$deprecated": true,
|
|
564
|
+
"$deprecationText": "Draft nodes are marked with [`DraftActivationVia`](#DraftActivationVia)",
|
|
563
565
|
"AppliesTo": [
|
|
564
566
|
"EntitySet"
|
|
565
567
|
],
|
|
@@ -879,6 +881,14 @@
|
|
|
879
881
|
],
|
|
880
882
|
"Type": "Core.Tag"
|
|
881
883
|
},
|
|
884
|
+
"Common.OperationTemplate": {
|
|
885
|
+
"$experimental": true,
|
|
886
|
+
"AppliesTo": [
|
|
887
|
+
"Term",
|
|
888
|
+
"Property"
|
|
889
|
+
],
|
|
890
|
+
"Type": "Common.QualifiedName"
|
|
891
|
+
},
|
|
882
892
|
"Common.OriginalProtocolVersion": {
|
|
883
893
|
"AppliesTo": [
|
|
884
894
|
"Schema"
|
|
@@ -3198,6 +3208,8 @@
|
|
|
3198
3208
|
}
|
|
3199
3209
|
},
|
|
3200
3210
|
"Common.DraftNodeType": {
|
|
3211
|
+
"$deprecated": true,
|
|
3212
|
+
"$deprecationText": "The deprecated term [`DraftNode`](#DraftNode) effectively only tags the entity set, its value is an empty record",
|
|
3201
3213
|
"$kind": "ComplexType",
|
|
3202
3214
|
"Properties": {
|
|
3203
3215
|
"PreparationAction": "Common.QualifiedName",
|
|
@@ -3214,10 +3226,18 @@
|
|
|
3214
3226
|
"EditAction": "Common.QualifiedName",
|
|
3215
3227
|
"NewAction": "Common.QualifiedName",
|
|
3216
3228
|
"PreparationAction": "Common.QualifiedName",
|
|
3229
|
+
"ResumeAction": "Common.QualifiedName",
|
|
3217
3230
|
"ShareAction": "Common.QualifiedName",
|
|
3218
3231
|
"ValidationFunction": "Common.QualifiedName"
|
|
3219
3232
|
}
|
|
3220
3233
|
},
|
|
3234
|
+
"Common.DraftUserAccessType": {
|
|
3235
|
+
"$kind": "ComplexType",
|
|
3236
|
+
"Properties": {
|
|
3237
|
+
"UserAccessRole": "Edm.String",
|
|
3238
|
+
"UserID": "Edm.String"
|
|
3239
|
+
}
|
|
3240
|
+
},
|
|
3221
3241
|
"Common.EffectType": {
|
|
3222
3242
|
"$deprecated": true,
|
|
3223
3243
|
"$deprecationText": "All side effects are essentially value changes, differentiation not needed.",
|
package/lib/model/cloneCsn.js
CHANGED
package/lib/optionProcessor.js
CHANGED
|
@@ -44,6 +44,7 @@ optionProcessor
|
|
|
44
44
|
.option(' --beta <list>')
|
|
45
45
|
.option(' --deprecated <list>')
|
|
46
46
|
.option(' --direct-backend')
|
|
47
|
+
.option(' --direct-messages')
|
|
47
48
|
.option(' --fallback-parser <type>', { valid: [ 'auto!', 'cdl', 'csn', 'csn!' ] })
|
|
48
49
|
.option(' --shuffle <seed>') // 0 | 1..4294967296
|
|
49
50
|
.option(' --test-mode')
|
|
@@ -138,6 +139,8 @@ optionProcessor
|
|
|
138
139
|
Can only be used with certain new CSN based backends. Combination with
|
|
139
140
|
other flags is limited, e.g. --test-mode will not run a consistency check.
|
|
140
141
|
No recompilation is triggered in case of errors. cdsc will dump.
|
|
142
|
+
--direct-messages Messages are written directly to console.error when an error/warning/… is detected.
|
|
143
|
+
Useful to see some messages before a compiler dump.
|
|
141
144
|
--shuffle <seed> If provided, some internal processing sequences are changed, most notably by
|
|
142
145
|
using a shuffled version of ‹model›.definitions. <seed> should be a number
|
|
143
146
|
between 1 and 4294967296, the compiler uses a random number in that range if the
|
|
@@ -113,6 +113,8 @@ class AstBuildingParser extends BaseParser {
|
|
|
113
113
|
err.expectedTokens = this.expectingArray();
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
// Guards, Prepare Commands and Lookahead Methods -----------------------------
|
|
117
|
+
|
|
116
118
|
tableWithoutAs() { // not used in <guard=…>, only called by other guard
|
|
117
119
|
// TODO TOOL: if the tool properly creates `default: this.giR()`, this
|
|
118
120
|
// condition method is most likely not necessary
|
|
@@ -135,7 +137,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
135
137
|
* - <guard=queryOnLeft, arg=tableWithoutAs>: …after having checked
|
|
136
138
|
* whether the next token is no (reserved or unreserved) keyword
|
|
137
139
|
*/
|
|
138
|
-
queryOnLeft(
|
|
140
|
+
queryOnLeft( arg, test ) {
|
|
139
141
|
if (arg === 'tableWithoutAs') {
|
|
140
142
|
if (this.tableWithoutAs())
|
|
141
143
|
return true;
|
|
@@ -217,7 +219,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
inSelectItem(
|
|
222
|
+
inSelectItem( arg ) { // <prepare=…>
|
|
221
223
|
this.dynamic_.inSelectItem = arg ||
|
|
222
224
|
(this.tokens[this.tokenIdx - 2].type === '.' ? 'inline' : 'expand');
|
|
223
225
|
}
|
|
@@ -248,7 +250,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
248
250
|
return next === '*' || next === '{';
|
|
249
251
|
}
|
|
250
252
|
|
|
251
|
-
notAfterEntityArgOrFilter( mode ) { // TODO: for <hide>
|
|
253
|
+
notAfterEntityArgOrFilter( _arg, mode ) { // TODO: for <hide>
|
|
252
254
|
if (mode !== 'M')
|
|
253
255
|
return false;
|
|
254
256
|
const { type } = this.lb();
|
|
@@ -260,14 +262,14 @@ class AstBuildingParser extends BaseParser {
|
|
|
260
262
|
|
|
261
263
|
// <prec=10, postfix=once> + test that the next token is not `null`; TODO: code
|
|
262
264
|
// completion for `… default 3 not ~;` → currently just `null` but hey
|
|
263
|
-
isNegatedRelation(
|
|
265
|
+
isNegatedRelation( prec ) {
|
|
264
266
|
return this.tokens[this.tokenIdx + 1]?.keyword === 'null' ||
|
|
265
|
-
this.precNone_(
|
|
267
|
+
this.precNone_( prec );
|
|
266
268
|
}
|
|
267
269
|
|
|
268
270
|
// TODO: as leanCondition ? `order` should probably appear in the message for
|
|
269
271
|
// test3/Compiler/GrammarRobustness/InvalidSelectInWhere.err.cds
|
|
270
|
-
orderByLimitRestriction( mode ) {
|
|
272
|
+
orderByLimitRestriction( _arg, mode ) {
|
|
271
273
|
if (mode && (!this.$allowOrderByLimit || this.precPost_( mode, 0 )))
|
|
272
274
|
return true;
|
|
273
275
|
this.$allowOrderByLimit = !mode;
|
|
@@ -309,7 +311,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
309
311
|
/**
|
|
310
312
|
* `annotation` def is only allowed top-level. TODO: combine with `extensionRestriction`
|
|
311
313
|
*/
|
|
312
|
-
vocabularyRestriction( test ) {
|
|
314
|
+
vocabularyRestriction( _arg, test ) {
|
|
313
315
|
if (!test)
|
|
314
316
|
this.dynamic_.inBlock = this.tokenIdx;
|
|
315
317
|
return this.dynamic_.inBlock ?? this.dynamic_.inExtension;
|
|
@@ -325,7 +327,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
325
327
|
* Currently only to restrict it to a single `Id` for published associations.
|
|
326
328
|
* No extra syntax-unexpected-assoc for failure.
|
|
327
329
|
*/
|
|
328
|
-
columnExpr(
|
|
330
|
+
columnExpr( arg, mode ) {
|
|
329
331
|
if (mode)
|
|
330
332
|
return !this.columnExpr$;
|
|
331
333
|
if (arg)
|
|
@@ -337,7 +339,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
337
339
|
return true;
|
|
338
340
|
}
|
|
339
341
|
|
|
340
|
-
nestedExpand( mode ) {
|
|
342
|
+
nestedExpand( _arg, mode ) {
|
|
341
343
|
if (!mode)
|
|
342
344
|
this.nestedExpand$ = this.tokenIdx;
|
|
343
345
|
return this.nestedExpand$ !== this.tokenIdx;
|
|
@@ -381,7 +383,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
381
383
|
* - DEFAULT: true if `default` had been provided
|
|
382
384
|
* - NOTNULL: true if `null` or `not null` had been provided
|
|
383
385
|
*/
|
|
384
|
-
elementRestriction(
|
|
386
|
+
elementRestriction( arg, test ) {
|
|
385
387
|
let { elementCtx } = this.dynamic_;
|
|
386
388
|
if (test) {
|
|
387
389
|
if (elementCtx?.[0] === arg)
|
|
@@ -424,7 +426,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
424
426
|
'Unexpected $(OFFENDING) after $(KEYWORD) clause, expecting $(EXPECTING)' );
|
|
425
427
|
}
|
|
426
428
|
|
|
427
|
-
noRepeatedCardinality( mode ) {
|
|
429
|
+
noRepeatedCardinality( _arg, mode ) {
|
|
428
430
|
if (this.tokens[this.tokenIdx - 2]?.type !== ']')
|
|
429
431
|
return false;
|
|
430
432
|
if (mode === 'M')
|
|
@@ -449,7 +451,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
449
451
|
*
|
|
450
452
|
* Beware: mentioned in leanConditions, i.e. executed in predictions!
|
|
451
453
|
*/
|
|
452
|
-
afterBrace(
|
|
454
|
+
afterBrace( arg, test ) {
|
|
453
455
|
if (!test) {
|
|
454
456
|
if (arg === 'normal' && this.lb().type !== '}') {
|
|
455
457
|
const { type, keyword } = this.la();
|
|
@@ -493,7 +495,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
493
495
|
/**
|
|
494
496
|
* For annotations at the beginning of columns outside parentheses
|
|
495
497
|
*/
|
|
496
|
-
annoInSameLine( test ) {
|
|
498
|
+
annoInSameLine( _arg, test ) {
|
|
497
499
|
if (!test)
|
|
498
500
|
this.dynamic_.safeAnno = true;
|
|
499
501
|
return !this.dynamic_.safeAnno &&
|
|
@@ -505,7 +507,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
505
507
|
* - `...` can appear in the top-level array value only and not after `...`
|
|
506
508
|
* without `up to`.
|
|
507
509
|
*/
|
|
508
|
-
arrayAnno(
|
|
510
|
+
arrayAnno( arg, test ) {
|
|
509
511
|
if (!test) {
|
|
510
512
|
this.dynamic_.arrayAnno = [ !this.dynamic_.arrayAnno ];
|
|
511
513
|
}
|
|
@@ -538,7 +540,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
538
540
|
return this.tokens[this.tokenIdx + 1]?.text !== ':';
|
|
539
541
|
}
|
|
540
542
|
|
|
541
|
-
fail( mode ) {
|
|
543
|
+
fail( _arg, mode ) {
|
|
542
544
|
// TODO TOOL: the following test belongs to the BaseParser.js:
|
|
543
545
|
if (this.conditionTokenIdx === this.tokenIdx && // tested on same
|
|
544
546
|
this.conditionStackLength == null && // after error recover
|
|
@@ -624,6 +626,8 @@ class AstBuildingParser extends BaseParser {
|
|
|
624
626
|
return prefixLoc;
|
|
625
627
|
}
|
|
626
628
|
|
|
629
|
+
// Locations for ASTs ---------------------------------------------------------
|
|
630
|
+
|
|
627
631
|
startLocation( { location } = this.lr() ) {
|
|
628
632
|
return {
|
|
629
633
|
__proto__: Location.prototype,
|