@sap/cds-compiler 5.2.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/bin/cdsc.js +5 -0
  3. package/bin/cdshi.js +8 -8
  4. package/doc/CHANGELOG_BETA.md +9 -4
  5. package/lib/api/validate.js +5 -0
  6. package/lib/base/message-registry.js +25 -1
  7. package/lib/base/messages.js +1 -1
  8. package/lib/base/model.js +0 -1
  9. package/lib/compiler/assert-consistency.js +2 -2
  10. package/lib/compiler/builtins.js +1 -1
  11. package/lib/compiler/checks.js +25 -6
  12. package/lib/compiler/define.js +24 -28
  13. package/lib/compiler/extend.js +11 -13
  14. package/lib/compiler/generate.js +3 -3
  15. package/lib/compiler/populate.js +13 -7
  16. package/lib/compiler/propagator.js +2 -2
  17. package/lib/compiler/resolve.js +58 -60
  18. package/lib/compiler/shared.js +5 -5
  19. package/lib/compiler/tweak-assocs.js +247 -34
  20. package/lib/compiler/utils.js +40 -32
  21. package/lib/compiler/xpr-rewrite.js +44 -58
  22. package/lib/edm/annotations/genericTranslation.js +4 -4
  23. package/lib/edm/csn2edm.js +2 -2
  24. package/lib/edm/edm.js +46 -21
  25. package/lib/edm/edmInboundChecks.js +0 -1
  26. package/lib/edm/edmPreprocessor.js +40 -27
  27. package/lib/edm/edmUtils.js +1 -1
  28. package/lib/gen/BaseParser.js +180 -122
  29. package/lib/gen/CdlParser.js +2226 -2170
  30. package/lib/gen/language.checksum +1 -1
  31. package/lib/gen/language.interp +1 -1
  32. package/lib/gen/languageParser.js +3820 -3777
  33. package/lib/inspect/inspectPropagation.js +1 -1
  34. package/lib/json/from-csn.js +5 -3
  35. package/lib/json/to-csn.js +7 -10
  36. package/lib/language/antlrParser.js +38 -4
  37. package/lib/language/errorStrategy.js +1 -1
  38. package/lib/language/genericAntlrParser.js +4 -4
  39. package/lib/language/multiLineStringParser.js +1 -1
  40. package/lib/main.d.ts +23 -0
  41. package/lib/model/cloneCsn.js +22 -13
  42. package/lib/optionProcessor.js +7 -7
  43. package/lib/parsers/AstBuildingParser.js +155 -37
  44. package/lib/parsers/CdlGrammar.g4 +154 -81
  45. package/lib/parsers/Lexer.js +20 -10
  46. package/lib/render/toCdl.js +23 -18
  47. package/lib/transform/addTenantFields.js +4 -4
  48. package/lib/transform/forRelationalDB.js +7 -6
  49. package/lib/utils/moduleResolve.js +1 -1
  50. package/package.json +1 -1
  51. package/share/messages/redirected-to-complex.md +6 -3
@@ -1331,6 +1331,9 @@ function csnToCdl( csn, options, msg ) {
1331
1331
  if (artifact.localized) // works even for type definitions
1332
1332
  result += 'localized ';
1333
1333
 
1334
+ // Some properties are always "top-level", even for "many", e.g. "default" or
1335
+ // "not null". Keep a reference to the outer artifact.
1336
+ const origArtifact = artifact;
1334
1337
  if (!artifact.type && artifact.items) {
1335
1338
  checkArrayedArtifact(artifact, env);
1336
1339
  result += 'many '; // alternative: 'array of'; but not used
@@ -1342,11 +1345,14 @@ function csnToCdl( csn, options, msg ) {
1342
1345
 
1343
1346
  if (!type && artifact.elements) {
1344
1347
  result += renderElements(artifact, env);
1345
- result += renderNullability(artifact);
1348
+ result += renderNullability(artifact.notNull);
1346
1349
  // structured default not possible at the moment
1347
1350
  return result;
1348
1351
  }
1349
1352
 
1353
+ const defaultValue = origArtifact.default ? origArtifact.default : artifact.default;
1354
+ const notNull = origArtifact.notNull ? origArtifact.notNull : artifact.notNull;
1355
+
1350
1356
  // Association type
1351
1357
  if (isDirectAssocOrComp(type)) {
1352
1358
  const isComp = type === 'cds.Composition';
@@ -1378,11 +1384,11 @@ function csnToCdl( csn, options, msg ) {
1378
1384
  if (artifact.keys && !artifact.on)
1379
1385
  result += ` ${ renderForeignKeys(artifact, env) }`;
1380
1386
 
1381
- if (artifact.notNull !== undefined && !artifact.on) // unmanaged associations can't be followed by "not null"
1382
- result += renderNullability(artifact);
1383
-
1384
- if (artifact.default && !artifact.on)
1385
- result += renderDefaultExpr(artifact, env);
1387
+ if (!artifact.on) {
1388
+ // unmanaged associations can't be followed by "not null" or "default"
1389
+ result += renderNullability(notNull);
1390
+ result += renderDefaultExpr(defaultValue, env.withSubPath([ 'default' ]));
1391
+ }
1386
1392
  return result;
1387
1393
  }
1388
1394
 
@@ -1409,13 +1415,12 @@ function csnToCdl( csn, options, msg ) {
1409
1415
 
1410
1416
  if (artifact.enum && !typeRefOnly)
1411
1417
  result += renderEnum(artifact.enum, env);
1412
- if (artifact.notNull !== undefined)
1413
- result += renderNullability(artifact);
1414
1418
 
1419
+ result += renderNullability(notNull);
1415
1420
  // If there is a default value, and it's a calculated element, do not
1416
1421
  // render the default (because it's not supported for calc elements).
1417
- if (artifact.default !== undefined && !artifact.value)
1418
- result += renderDefaultExpr(artifact, env);
1422
+ if (defaultValue !== undefined && !artifact.value)
1423
+ result += renderDefaultExpr(defaultValue, env.withSubPath([ 'default' ]));
1419
1424
 
1420
1425
  return result;
1421
1426
  }
@@ -1789,24 +1794,24 @@ function csnToCdl( csn, options, msg ) {
1789
1794
  return result;
1790
1795
  }
1791
1796
 
1792
- function renderDefaultExpr( art, env ) {
1793
- if (!art.default)
1797
+ function renderDefaultExpr( defaultValue, env ) {
1798
+ if (!defaultValue)
1794
1799
  return '';
1795
1800
  let result = ' default ';
1796
- if ( art.default.xpr && xprContainsCondition( art.default.xpr))
1797
- result += exprRenderer.renderSubExpr(withoutCast( art.default), env.withSubPath([ 'default' ]));
1801
+ if (defaultValue.xpr && xprContainsCondition( defaultValue.xpr))
1802
+ result += exprRenderer.renderSubExpr(withoutCast(defaultValue), env);
1798
1803
  else
1799
- result += exprRenderer.renderExpr(withoutCast( art.default), env.withSubPath([ 'default' ]));
1804
+ result += exprRenderer.renderExpr(withoutCast(defaultValue), env);
1800
1805
  return result;
1801
1806
  }
1802
1807
 
1803
1808
  // Render the nullability of an element or parameter (can be unset, true, or false)
1804
- function renderNullability( obj /* , env */) {
1805
- if (obj.notNull === undefined) {
1809
+ function renderNullability( notNull /* , env */) {
1810
+ if (notNull === undefined) {
1806
1811
  // Attribute not set at all
1807
1812
  return '';
1808
1813
  }
1809
- return obj.notNull ? ' not null' : ' null';
1814
+ return notNull ? ' not null' : ' null';
1810
1815
  }
1811
1816
 
1812
1817
  /**
@@ -78,7 +78,7 @@ function addTenantFields( csn, options, messageFunctions ) {
78
78
  else if (!independent && independent != null) {
79
79
  error( 'tenant-invalid-anno-value', msgLocations( csnPath ),
80
80
  { anno: annoTenantIndep, value: independent },
81
- // eslint-disable-next-line max-len
81
+ // eslint-disable-next-line @stylistic/js/max-len
82
82
  'Can\'t add $(ANNO) with value $(VALUE) to a non-entity, which is always tenant-independent' );
83
83
  }
84
84
  else if (art.includes) {
@@ -119,9 +119,9 @@ function addTenantFields( csn, options, messageFunctions ) {
119
119
  .filter( name => isTenantDepEntity( csn.definitions[name] ) );
120
120
  if (names.length) {
121
121
  error( 'tenant-invalid-include', msgLocations( csnPath ), { names }, {
122
- // eslint-disable-next-line max-len
122
+ // eslint-disable-next-line @stylistic/js/max-len
123
123
  std: 'Can\'t include the tenant-dependent entities $(NAMES) into a tenant-independent definition',
124
- // eslint-disable-next-line max-len
124
+ // eslint-disable-next-line @stylistic/js/max-len
125
125
  one: 'Can\'t include the tenant-dependent entity $(NAMES) into a tenant-independent definition',
126
126
  } );
127
127
  }
@@ -206,7 +206,7 @@ function addTenantFields( csn, options, messageFunctions ) {
206
206
  if (art[annoTenantIndep]) {
207
207
  error( 'tenant-expecting-tenant-source', msgLocations( csnPath ), { art: query },
208
208
  // TODO: better the final entity name of assoc navigation in FROM
209
- // eslint-disable-next-line max-len
209
+ // eslint-disable-next-line @stylistic/js/max-len
210
210
  'Expecting the query source $(ART) to be tenant-dependent for a tenant-dependent query entity' );
211
211
  }
212
212
  return true;
@@ -817,16 +817,17 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
817
817
  function checkTypeParameters(artifact, artifactName) {
818
818
  forEachMemberRecursively(artifact, (member, memberName, prop, path) => {
819
819
  // Check type parameters (length, precision, scale ...)
820
- if (!member.$ignore && member.type)
821
- _check(member, memberName, csn, path);
822
-
823
- if (!member.$ignore && member.items && member.items.type)
824
- _check(member.items, memberName, csn, path.concat([ 'items' ]));
820
+ if (!member.$ignore) {
821
+ if (member.type)
822
+ _check(member, memberName, csn, path);
823
+ if (member.items?.type)
824
+ _check(member.items, memberName, csn, path.concat([ 'items' ]));
825
+ }
825
826
  }, [ 'definitions', artifactName ]);
826
827
 
827
828
  // Check that required actual parameters on 'node.type' are set, that their values are in the correct range etc.
828
829
  function _check(node, nodeName, model, path) {
829
- if (node.type) {
830
+ if (node.type && !node.virtual) {
830
831
  const absolute = node.type;
831
832
  switch (absolute) {
832
833
  case 'cds.String':
@@ -579,7 +579,7 @@ function checkFileCase( dep, realpath, nativeRealpath, { warning } ) {
579
579
  }
580
580
  for (const using of dep.usingFroms) {
581
581
  warning('file-unexpected-case-mismatch', [ using.location, using ], {},
582
- // eslint-disable-next-line max-len
582
+ // eslint-disable-next-line @stylistic/js/max-len
583
583
  'The imported filename differs on the filesystem; ensure that capitalization matches the actual file\'s name');
584
584
  }
585
585
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "5.2.0",
3
+ "version": "5.3.0",
4
4
  "description": "CDS (Core Data Services) compiler and backends",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -53,9 +53,12 @@ CrossJoin
53
53
 
54
54
  ## How to Fix
55
55
 
56
- Ensure that the redirected association points to an entity that is a reasonable
57
- redirection target. That means, the redirection target shouldn't accidentally
58
- make it a to-many association.
56
+ First, ensure that the redirected association points to an entity that is
57
+ a reasonable redirection target. That means, the redirection target shouldn't
58
+ accidentally make it a to-many association.
59
+
60
+ Then add an explicit ON-condition or explicit foreign keys to the redirected
61
+ association. That will silence the compiler message.
59
62
 
60
63
  ## Related Messages
61
64