@sap/cds-compiler 5.9.4 → 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 +117 -319
- package/README.md +1 -1
- package/bin/cds_update_identifiers.js +3 -5
- package/bin/cdsc.js +24 -9
- package/bin/cdshi.js +1 -1
- package/bin/cdsse.js +4 -4
- package/doc/CHANGELOG_BETA.md +11 -0
- package/doc/CHANGELOG_DEPRECATED.md +29 -0
- package/lib/api/main.js +8 -5
- package/lib/api/options.js +12 -10
- package/lib/base/builtins.js +1 -0
- package/lib/base/message-registry.js +191 -99
- package/lib/base/messages.js +35 -21
- package/lib/base/model.js +14 -24
- package/lib/checks/actionsFunctions.js +10 -20
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/elements.js +35 -10
- package/lib/checks/enums.js +31 -0
- package/lib/checks/foreignKeys.js +2 -2
- package/lib/checks/hasPersistedElements.js +5 -0
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/managedWithoutKeys.js +5 -4
- package/lib/checks/queryNoDbArtifacts.js +10 -8
- package/lib/checks/types.js +5 -5
- package/lib/checks/validator.js +6 -4
- package/lib/compiler/assert-consistency.js +13 -9
- package/lib/compiler/checks.js +20 -52
- package/lib/compiler/define.js +31 -6
- package/lib/compiler/extend.js +5 -1
- package/lib/compiler/generate.js +14 -17
- package/lib/compiler/populate.js +8 -31
- package/lib/compiler/propagator.js +21 -35
- package/lib/compiler/resolve.js +64 -29
- package/lib/compiler/shared.js +16 -4
- package/lib/compiler/tweak-assocs.js +1 -1
- package/lib/compiler/utils.js +1 -1
- package/lib/edm/annotations/edmJson.js +23 -20
- package/lib/edm/annotations/genericTranslation.js +12 -10
- package/lib/edm/csn2edm.js +50 -56
- package/lib/edm/edm.js +33 -28
- package/lib/edm/edmInboundChecks.js +2 -2
- package/lib/edm/edmPreprocessor.js +54 -88
- package/lib/edm/edmUtils.js +9 -12
- package/lib/gen/BaseParser.js +63 -52
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +1153 -1165
- package/lib/gen/Dictionary.json +21 -1
- package/lib/json/from-csn.js +70 -43
- package/lib/json/to-csn.js +6 -8
- package/lib/language/multiLineStringParser.js +3 -2
- package/lib/main.d.ts +58 -24
- package/lib/model/cloneCsn.js +3 -0
- package/lib/model/csnUtils.js +28 -39
- package/lib/model/xprAsTree.js +23 -9
- package/lib/modelCompare/compare.js +5 -4
- package/lib/optionProcessor.js +24 -17
- package/lib/parsers/AstBuildingParser.js +81 -25
- package/lib/parsers/XprTree.js +57 -3
- package/lib/parsers/identifiers.js +1 -1
- package/lib/parsers/index.js +0 -3
- package/lib/render/manageConstraints.js +25 -25
- package/lib/render/toCdl.js +173 -170
- package/lib/render/toHdbcds.js +126 -128
- package/lib/render/toRename.js +7 -7
- package/lib/render/toSql.js +128 -125
- package/lib/render/utils/common.js +47 -22
- package/lib/render/utils/delta.js +25 -25
- package/lib/render/utils/operators.js +2 -2
- package/lib/render/utils/pretty.js +5 -5
- package/lib/render/utils/sql.js +13 -13
- package/lib/render/utils/standardDatabaseFunctions.js +115 -103
- package/lib/render/utils/unique.js +4 -4
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/assertUnique.js +2 -2
- package/lib/transform/db/associations.js +6 -7
- package/lib/transform/db/assocsToQueries/utils.js +4 -5
- package/lib/transform/db/backlinks.js +12 -9
- package/lib/transform/db/cdsPersistence.js +8 -7
- package/lib/transform/db/constraints.js +13 -10
- package/lib/transform/db/expansion.js +7 -3
- package/lib/transform/db/flattening.js +4 -14
- package/lib/transform/db/processSqlServices.js +2 -1
- package/lib/transform/db/temporal.js +5 -7
- package/lib/transform/db/views.js +2 -4
- package/lib/transform/draft/db.js +8 -8
- package/lib/transform/draft/odata.js +10 -7
- package/lib/transform/forOdata.js +10 -5
- package/lib/transform/forRelationalDB.js +5 -75
- package/lib/transform/localized.js +1 -1
- package/lib/transform/odata/createForeignKeys.js +11 -10
- package/lib/transform/odata/flattening.js +8 -4
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +96 -0
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/transformUtils.js +4 -8
- package/lib/transform/translateAssocsToJoins.js +14 -7
- package/lib/transform/universalCsn/universalCsnEnricher.js +10 -4
- package/lib/utils/objectUtils.js +0 -17
- package/package.json +10 -13
- package/share/messages/def-upcoming-virtual-change.md +1 -1
- package/LICENSE +0 -37
- package/bin/cds_remove_invalid_whitespace.js +0 -138
- package/doc/CHANGELOG_ARCHIVE.md +0 -3604
- package/lib/gen/genericAntlrParser.js +0 -3
- package/lib/gen/language.checksum +0 -1
- package/lib/gen/language.interp +0 -456
- package/lib/gen/language.tokens +0 -180
- package/lib/gen/languageLexer.interp +0 -439
- package/lib/gen/languageLexer.js +0 -1483
- package/lib/gen/languageLexer.tokens +0 -167
- package/lib/gen/languageParser.js +0 -24941
- package/lib/language/antlrParser.js +0 -205
- package/lib/language/errorStrategy.js +0 -646
- package/lib/language/genericAntlrParser.js +0 -1572
- package/lib/parsers/CdlGrammar.g4 +0 -2070
package/lib/compiler/resolve.js
CHANGED
|
@@ -143,10 +143,6 @@ function resolve( model ) {
|
|
|
143
143
|
const msg = semanticLoc && 'target';
|
|
144
144
|
error( 'ref-cyclic', [ location, semanticLoc || user ], {
|
|
145
145
|
art, '#': msg,
|
|
146
|
-
}, {
|
|
147
|
-
std: 'Illegal circular reference to $(ART)',
|
|
148
|
-
element: 'Illegal circular reference to element $(MEMBER) of $(ART)',
|
|
149
|
-
target: 'Illegal circular reference to target $(ART)',
|
|
150
146
|
} );
|
|
151
147
|
}
|
|
152
148
|
} );
|
|
@@ -1172,12 +1168,24 @@ function resolve( model ) {
|
|
|
1172
1168
|
return [ null, '$navElement', '$tableAlias' ][path.length] === (kind || true) && elem._origin;
|
|
1173
1169
|
}
|
|
1174
1170
|
|
|
1175
|
-
function
|
|
1171
|
+
function isQuasiVirtualAssociation( art ) {
|
|
1172
|
+
if (art.on)
|
|
1173
|
+
return false;
|
|
1174
|
+
if (art.foreignKeys != null)
|
|
1175
|
+
return !art.foreignKeys;
|
|
1176
1176
|
const max = art.cardinality?.targetMax;
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1177
|
+
return max && (typeof max.val !== 'number' || max.val > 1);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function addImplicitForeignKeys( art, obj, target ) {
|
|
1181
|
+
if (!art.$inferred && !art.virtual?.val && isQuasiVirtualAssociation( obj )) {
|
|
1182
|
+
if (!isDeprecatedEnabled( options, 'noQuasiVirtualAssocs' )) {
|
|
1183
|
+
// TODO: set `foreignKeys`, `ON` or `virtual` to false or similar to
|
|
1184
|
+
// indicate that it is already handled (and that we might not be able to
|
|
1185
|
+
// follow the assoc)? Let us set foreignKeys to false
|
|
1186
|
+
obj.foreignKeys = false;
|
|
1187
|
+
return; // no foreign keys for `Association to many Target`;
|
|
1188
|
+
}
|
|
1181
1189
|
}
|
|
1182
1190
|
obj.foreignKeys = Object.create( null );
|
|
1183
1191
|
forEachInOrder( target, 'elements', ( elem, name ) => {
|
|
@@ -1306,6 +1314,8 @@ function resolve( model ) {
|
|
|
1306
1314
|
'The redirected target is the original $(ART)' );
|
|
1307
1315
|
}
|
|
1308
1316
|
|
|
1317
|
+
// No check with user-provided ON/fKeys (remark: compiler deduceds ON/fKeys
|
|
1318
|
+
// _after_ redirecting the target = no $inferred test necessary):
|
|
1309
1319
|
if (elem.foreignKeys || elem.on)
|
|
1310
1320
|
return; // TODO: or should we still bring an msg if nothing in common?
|
|
1311
1321
|
|
|
@@ -1456,19 +1466,35 @@ function resolve( model ) {
|
|
|
1456
1466
|
}
|
|
1457
1467
|
}
|
|
1458
1468
|
|
|
1459
|
-
function resolveAnnoExpr( expr, art, anno = expr ) {
|
|
1469
|
+
function resolveAnnoExpr( expr, art, anno = expr, topItem = false ) {
|
|
1460
1470
|
if (expr.$tokenTexts) {
|
|
1461
|
-
if (
|
|
1471
|
+
if (anno === expr) {
|
|
1462
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
|
+
|
|
1463
1479
|
const type = anno === expr && anno.name;
|
|
1464
1480
|
// TODO: it might be best to set an _artifact link also for property values
|
|
1465
1481
|
// like in `@Anno: [ { foo: #EnumSymbol }]
|
|
1466
1482
|
resolveExpr( expr, 'annotation', anno, type );
|
|
1467
1483
|
}
|
|
1468
1484
|
else if (expr.literal === 'array') {
|
|
1469
|
-
|
|
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 ) );
|
|
1470
1492
|
}
|
|
1471
1493
|
else if (expr.literal === 'struct') {
|
|
1494
|
+
if (topItem) { // item of top-level array annotation
|
|
1495
|
+
setLink( expr, '_outer', anno );
|
|
1496
|
+
anno = expr;
|
|
1497
|
+
}
|
|
1472
1498
|
Object.values( expr.struct ).forEach( val => resolveAnnoExpr( val, art, anno ) );
|
|
1473
1499
|
}
|
|
1474
1500
|
}
|
|
@@ -1480,10 +1506,9 @@ function resolve( model ) {
|
|
|
1480
1506
|
* @param {XSN.Artifact} art
|
|
1481
1507
|
*/
|
|
1482
1508
|
function initAnnotationForExpression( anno, art ) {
|
|
1483
|
-
anno.kind = '$annotation';
|
|
1484
1509
|
setLink( anno, '_outer', art );
|
|
1485
1510
|
art.$contains ??= {};
|
|
1486
|
-
art.$contains.$annotation
|
|
1511
|
+
art.$contains.$annotation ??= { // set in resolveExprPath
|
|
1487
1512
|
$path: false,
|
|
1488
1513
|
$self: false,
|
|
1489
1514
|
};
|
|
@@ -1491,6 +1516,9 @@ function resolve( model ) {
|
|
|
1491
1516
|
// Might be useful for future recursive types.
|
|
1492
1517
|
}
|
|
1493
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
|
|
1494
1522
|
function resolveExpr( expr, exprCtx, art, type = null ) {
|
|
1495
1523
|
traverseTypedExpr( expr, exprCtx, art, type, resolveExprNode );
|
|
1496
1524
|
}
|
|
@@ -1543,8 +1571,12 @@ function resolve( model ) {
|
|
|
1543
1571
|
const ref = resolvePath( expr, expected, user );
|
|
1544
1572
|
|
|
1545
1573
|
if (expected === 'annotation') {
|
|
1546
|
-
user._outer
|
|
1547
|
-
|
|
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';
|
|
1548
1580
|
}
|
|
1549
1581
|
|
|
1550
1582
|
// check whether arguments and filters are allowed on last path item;
|
|
@@ -1562,9 +1594,10 @@ function resolve( model ) {
|
|
|
1562
1594
|
const art = type && (type.kind === 'entity' ? type : type.target?._artifact);
|
|
1563
1595
|
if (!art)
|
|
1564
1596
|
return ref; // error already reported via resolvePathItem()
|
|
1565
|
-
const unexpectedFilter = expected !== 'column' && expected !== 'calc'
|
|
1597
|
+
const unexpectedFilter = expected !== 'column' && expected !== 'calc' && 'std' ||
|
|
1598
|
+
isQuasiVirtualAssociation( type ) && 'model-only';
|
|
1566
1599
|
if (last.args || last.where || last.cardinality)
|
|
1567
|
-
reportUnexpectedArgsAndFilter( last, expected, user, art, unexpectedFilter
|
|
1600
|
+
reportUnexpectedArgsAndFilter( last, expected, user, art, unexpectedFilter );
|
|
1568
1601
|
// TODO: we should have different message-ids for the "last" stuff: adding
|
|
1569
1602
|
// `.item` likely corrects the ref, probably with location at end of ref
|
|
1570
1603
|
return ref;
|
|
@@ -1622,12 +1655,12 @@ function resolve( model ) {
|
|
|
1622
1655
|
function resolveEnumSymbol( expr, expected, user, type ) {
|
|
1623
1656
|
const { sym } = expr;
|
|
1624
1657
|
// CSN input with both '#'+val (recompilation) → do not resolve
|
|
1625
|
-
if (!sym || expr.val !== undefined
|
|
1658
|
+
if (!sym || expr.val !== undefined)
|
|
1626
1659
|
return;
|
|
1627
1660
|
// The parameter def for an argument, and the annotation def for an assignment
|
|
1628
1661
|
// is in `type._artifact`, it is not `type` itself:
|
|
1629
|
-
type = effectiveType( type.id ? type._artifact : type );
|
|
1630
|
-
// Remark:
|
|
1662
|
+
type = type && effectiveType( type.id ? type._artifact : type );
|
|
1663
|
+
// Remark: type could be 0 for cyclic parameter type
|
|
1631
1664
|
if (type && type.foreignKeys) {
|
|
1632
1665
|
const keys = Object.values( type.foreignKeys );
|
|
1633
1666
|
if (keys.length === 1) {
|
|
@@ -1636,11 +1669,14 @@ function resolve( model ) {
|
|
|
1636
1669
|
}
|
|
1637
1670
|
}
|
|
1638
1671
|
const symbols = type && type.enum;
|
|
1639
|
-
if (!symbols)
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1672
|
+
if (!symbols) {
|
|
1673
|
+
if (user.kind !== '$annotation') { // TODO: better type deduction for annotations
|
|
1674
|
+
const msg = (user.kind === 'enum') ? 'symbolDef' : type && 'invalidType';
|
|
1675
|
+
warning( 'ref-unexpected-enum', [ expr.location, user ],
|
|
1676
|
+
{ '#': msg || 'untyped', enum: sym.id, type: type || '' } );
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
else if (symbols[sym.id]) {
|
|
1644
1680
|
setLink( sym, '_artifact', symbols[sym.id] );
|
|
1645
1681
|
}
|
|
1646
1682
|
else {
|
|
@@ -1649,8 +1685,7 @@ function resolve( model ) {
|
|
|
1649
1685
|
type = getOrigin( type );
|
|
1650
1686
|
const err = message( 'ref-undefined-enum', [ sym.location, user ],
|
|
1651
1687
|
{ id: sym.id, type } );
|
|
1652
|
-
|
|
1653
|
-
attachAndEmitValidNames( err, symbols );
|
|
1688
|
+
attachAndEmitValidNames( err, symbols );
|
|
1654
1689
|
}
|
|
1655
1690
|
}
|
|
1656
1691
|
|
|
@@ -1662,7 +1697,7 @@ function resolve( model ) {
|
|
|
1662
1697
|
if ((step.where || step.cardinality) && variant) {
|
|
1663
1698
|
const location = combinedLocation( step.where, step.cardinality );
|
|
1664
1699
|
// XSN TODO: filter$location including […]
|
|
1665
|
-
|
|
1700
|
+
error( 'expr-unexpected-filter', [ location, user ], { '#': variant } );
|
|
1666
1701
|
}
|
|
1667
1702
|
return variant && traverseExpr.SKIP;
|
|
1668
1703
|
}
|
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)' );
|
|
@@ -1286,6 +1292,8 @@ function fns( model ) {
|
|
|
1286
1292
|
if (!user.elements && !user.actions && !user.enum && !user.params &&
|
|
1287
1293
|
couldBeDraftsEntity( item.id, valid, prev, path ))
|
|
1288
1294
|
return;
|
|
1295
|
+
if (couldBeDraftAdminDataEntity( item ) )
|
|
1296
|
+
return;
|
|
1289
1297
|
signalNotFound( (valid.length > 1 ? 'ext-undefined-art' : 'ext-undefined-def'),
|
|
1290
1298
|
// TODO: ext-undefined-xyz
|
|
1291
1299
|
[ item.location, user ], valid, { art } );
|
|
@@ -1293,11 +1301,15 @@ function fns( model ) {
|
|
|
1293
1301
|
|
|
1294
1302
|
function couldBeDraftsEntity( id, valid, prev, path ) {
|
|
1295
1303
|
const entity = prev
|
|
1296
|
-
? prev === path[path.length - 2]._artifact && prev
|
|
1304
|
+
? prev === path[path.length - 2]._artifact && prev // TODO: Should check for '.drafts'?
|
|
1297
1305
|
: path.length === 1 && id.endsWith( '.drafts' ) && model.definitions[id.slice( 0, -7 )];
|
|
1298
1306
|
return entity?.kind === 'entity' && !!entity._service;
|
|
1299
1307
|
}
|
|
1300
1308
|
|
|
1309
|
+
function couldBeDraftAdminDataEntity( item ) {
|
|
1310
|
+
return item.id === 'DraftAdministrativeData' && !item._artifact;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1301
1313
|
function undefinedParam( user, head, valid, _dict, _art, _path, semantics ) {
|
|
1302
1314
|
// TODO: text variant if there are no parameters, or in artifactParameters()
|
|
1303
1315
|
// TODO: use prepared message variants
|
|
@@ -274,7 +274,7 @@ function tweakAssocs( model ) {
|
|
|
274
274
|
// target -> avoid infloop ourselves with _status.
|
|
275
275
|
// TODO: this should be good now
|
|
276
276
|
const chain = [];
|
|
277
|
-
while (!elem.on &&
|
|
277
|
+
while (!elem.on && elem.foreignKeys == null) {
|
|
278
278
|
chain.push( elem );
|
|
279
279
|
if (elem._status === 'rewrite') { // circular dependency (already reported)
|
|
280
280
|
for (const e of chain)
|
package/lib/compiler/utils.js
CHANGED
|
@@ -126,7 +126,7 @@ function proxyCopyMembers( art, dictProp, originDict, location, kind, tmpDepreca
|
|
|
126
126
|
if (kind)
|
|
127
127
|
member.kind = kind;
|
|
128
128
|
else if (origin.key && !tmpDeprecated)
|
|
129
|
-
// TODO(v6): remove tmpDeprecated once `
|
|
129
|
+
// TODO(v6): remove tmpDeprecated once `_noKeyPropagationWithExpansions` is removed
|
|
130
130
|
member.key = Object.assign( { $inferred: 'expanded' }, origin.key );
|
|
131
131
|
if (kind && origin.masked) // TODO: remove!
|
|
132
132
|
member.masked = Object.assign( { $inferred: 'nav' }, origin.masked );
|
|
@@ -83,7 +83,7 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
83
83
|
});
|
|
84
84
|
delete parent[op];
|
|
85
85
|
};
|
|
86
|
-
const noOp = () =>
|
|
86
|
+
const noOp = () => {};
|
|
87
87
|
//----------------------------------
|
|
88
88
|
// Create the transformer dictionary
|
|
89
89
|
const transform = {
|
|
@@ -96,7 +96,6 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
96
96
|
isNull: (p, o) => notADynExpr(p, o, null, null, null, null, 'is null'),
|
|
97
97
|
isNotNull: (p, o) => notADynExpr(p, o, null, null, null, null, 'is not null'),
|
|
98
98
|
exists: notADynExpr,
|
|
99
|
-
'#': notADynExpr,
|
|
100
99
|
SELECT: notADynExpr,
|
|
101
100
|
SET: (p, o) => notADynExpr(p, o, null, null, null, null, 'UNION'),
|
|
102
101
|
like: notADynExpr,
|
|
@@ -312,8 +311,16 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
312
311
|
else
|
|
313
312
|
parentparent[parentprop] = xpr;
|
|
314
313
|
};
|
|
314
|
+
transform['#'] = (parent, prop, xpr, csnPath, parentParent, parentprop, txt) => {
|
|
315
|
+
if (parent['#'] && parent.val) // enum reference that was resolved by the compiler
|
|
316
|
+
delete parent['#'];
|
|
317
|
+
else
|
|
318
|
+
notADynExpr(parent, prop, xpr, csnPath, parentParent, parentprop, txt);
|
|
319
|
+
};
|
|
315
320
|
transform.ref = (parent, prop, xpr, csnPath, parentparent, parentprop) => {
|
|
316
|
-
|
|
321
|
+
// until empty filter syntax is introduced for the annotation expressions,
|
|
322
|
+
// we ignore the filters in order to generate EDMX
|
|
323
|
+
if (xpr.some(ps => ps.args/* || ps.where */)) {
|
|
317
324
|
error('odata-anno-xpr-ref', location, {
|
|
318
325
|
anno, elemref: parent, '#': 'args',
|
|
319
326
|
});
|
|
@@ -492,23 +499,21 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
492
499
|
const td = EdmPrimitiveTypeMap[typeDef];
|
|
493
500
|
if (td) {
|
|
494
501
|
if (td.v2 !== options.isV2() && td.v4 !== options.isV4()) {
|
|
495
|
-
message('odata-
|
|
502
|
+
message('odata-unexpected-edm-type', location,
|
|
496
503
|
{
|
|
497
504
|
anno,
|
|
498
505
|
type: typeDef,
|
|
499
506
|
version: (options.isV4() ? '4.0' : '2.0'),
|
|
500
|
-
'#': '
|
|
507
|
+
'#': 'anno',
|
|
501
508
|
});
|
|
502
509
|
}
|
|
503
510
|
evalArgs(td, typeFacets, typeDef);
|
|
504
511
|
EdmTypeFacetNames.forEach((facetName) => {
|
|
505
512
|
const facetDef = EdmTypeFacetMap[facetName];
|
|
506
|
-
const optional
|
|
507
|
-
|
|
508
|
-
? (Array.isArray(facetDef.optional)
|
|
513
|
+
const optional = (facetDef.optional !== undefined) &&
|
|
514
|
+
(Array.isArray(facetDef.optional)
|
|
509
515
|
? facetDef.optional.includes(typeDef)
|
|
510
|
-
: facetDef.optional)
|
|
511
|
-
: false;
|
|
516
|
+
: facetDef.optional);
|
|
512
517
|
|
|
513
518
|
if (td[facetName]) {
|
|
514
519
|
// ignore facets that are not type relevant
|
|
@@ -516,13 +521,13 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
516
521
|
const facetArgs = typeFacets.filter(arg => arg.func === facetName || arg.func === `$${ facetName }`);
|
|
517
522
|
|
|
518
523
|
if (facetArgs.length === 0 && !optional && (options.isV2() === facetDef.v2 || options.isV4() === facetDef.v4)) {
|
|
519
|
-
message('odata-
|
|
524
|
+
message('odata-unexpected-edm-facet', location,
|
|
520
525
|
{
|
|
521
526
|
anno,
|
|
522
527
|
type: typeDef,
|
|
523
528
|
name: facetName,
|
|
524
529
|
version: (options.isV4() ? '4.0' : '2.0'),
|
|
525
|
-
'#': '
|
|
530
|
+
'#': 'anno',
|
|
526
531
|
});
|
|
527
532
|
}
|
|
528
533
|
else if (facetArgs.length > 1) {
|
|
@@ -566,14 +571,12 @@ function xpr2edmJson( carrier, anno, location, options, messageFunctions ) {
|
|
|
566
571
|
const precision = Number.parseInt(parent.$Precision, 10);
|
|
567
572
|
const scale = Number.parseInt(parent.$Scale, 10);
|
|
568
573
|
if (!Number.isNaN(precision) && !Number.isNaN(scale) && scale > precision) {
|
|
569
|
-
message('odata-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
'#': 'scale_anno',
|
|
576
|
-
});
|
|
574
|
+
message('odata-invalid-scale', location, {
|
|
575
|
+
'#': 'anno',
|
|
576
|
+
anno,
|
|
577
|
+
number: scale,
|
|
578
|
+
rawvalue: precision,
|
|
579
|
+
});
|
|
577
580
|
}
|
|
578
581
|
}
|
|
579
582
|
if (options.isV2() && parent.$Scale === 'variable') {
|
|
@@ -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
|
}
|
|
@@ -852,14 +853,13 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
852
853
|
|
|
853
854
|
termNameWithoutQualifiers.split('.').forEach((id) => {
|
|
854
855
|
if (!edmUtils.isODataSimpleIdentifier(id))
|
|
855
|
-
message('odata-
|
|
856
|
+
message('odata-invalid-name', msg.location, { id });
|
|
856
857
|
});
|
|
857
858
|
newAnno = new Edm.Annotation(v, termNameWithoutQualifiers);
|
|
858
859
|
if (qualifier?.length) {
|
|
859
|
-
if (!edmUtils.isODataSimpleIdentifier(qualifier))
|
|
860
|
-
message('odata-
|
|
861
|
-
|
|
862
|
-
}
|
|
860
|
+
if (!edmUtils.isODataSimpleIdentifier(qualifier))
|
|
861
|
+
message('odata-invalid-qualifier', msg.location, { id: qualifier });
|
|
862
|
+
|
|
863
863
|
newAnno.setEdmAttribute('Term', termNameWithoutQualifiers);
|
|
864
864
|
newAnno.setEdmAttribute('Qualifier', qualifier);
|
|
865
865
|
}
|
|
@@ -1428,7 +1428,7 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
1428
1428
|
// in a record or term
|
|
1429
1429
|
if (Array.isArray(value)) {
|
|
1430
1430
|
message('odata-anno-value', msg.location,
|
|
1431
|
-
{ anno: msg.anno(), '#': '
|
|
1431
|
+
{ anno: msg.anno(), '#': 'nestedCollection' });
|
|
1432
1432
|
}
|
|
1433
1433
|
else if (value && typeof value === 'object') {
|
|
1434
1434
|
if (value['=']) {
|
|
@@ -1439,7 +1439,7 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
1439
1439
|
}
|
|
1440
1440
|
else if (value['#']) {
|
|
1441
1441
|
message('odata-anno-value', msg.location,
|
|
1442
|
-
{ anno: msg.anno(), '#': '
|
|
1442
|
+
{ anno: msg.anno(), '#': 'enuminCollection' });
|
|
1443
1443
|
}
|
|
1444
1444
|
else if (value.$edmJson) {
|
|
1445
1445
|
newCollection.append(handleEdmJson(value.$edmJson, msg));
|
|
@@ -1663,7 +1663,9 @@ function csn2annotationEdm( reqDefs, reqDefsUtils, csnVocabularies, serviceName,
|
|
|
1663
1663
|
message('odata-anno-dict', msg.location, { anno: msg.anno(), '#': 'experimental' });
|
|
1664
1664
|
usedExperimentalTerms[termName] = true;
|
|
1665
1665
|
}
|
|
1666
|
-
|
|
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') {
|
|
1667
1669
|
message('odata-anno-def', msg.location,
|
|
1668
1670
|
{ anno: msg.anno(), depr: dictTerm.$deprecationText, '#': 'deprecated' });
|
|
1669
1671
|
usedDeprecatedTerms[termName] = true;
|
|
@@ -1774,7 +1776,7 @@ function mergeOdataVocabularies( options, message ) {
|
|
|
1774
1776
|
defOk = false;
|
|
1775
1777
|
}
|
|
1776
1778
|
else if (name === 'Alias' && !edmUtils.isODataSimpleIdentifier(def[name])) {
|
|
1777
|
-
message('odata-
|
|
1779
|
+
message('odata-invalid-vocabulary-alias', null, { id: name, value: def[name] });
|
|
1778
1780
|
defOk = false;
|
|
1779
1781
|
}
|
|
1780
1782
|
});
|