@sap/cds-compiler 3.3.2 → 3.4.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 (74) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/bin/cdsc.js +3 -1
  3. package/doc/CHANGELOG_BETA.md +17 -0
  4. package/lib/api/main.js +147 -18
  5. package/lib/api/validate.js +8 -3
  6. package/lib/base/dictionaries.js +6 -6
  7. package/lib/base/keywords.js +104 -0
  8. package/lib/base/message-registry.js +136 -67
  9. package/lib/base/messages.js +59 -48
  10. package/lib/base/model.js +1 -0
  11. package/lib/checks/actionsFunctions.js +1 -1
  12. package/lib/checks/cdsPersistence.js +1 -1
  13. package/lib/checks/checkForTypes.js +13 -8
  14. package/lib/checks/defaultValues.js +3 -1
  15. package/lib/checks/elements.js +1 -1
  16. package/lib/checks/parameters.js +4 -2
  17. package/lib/checks/queryNoDbArtifacts.js +1 -1
  18. package/lib/checks/sql-snippets.js +12 -10
  19. package/lib/checks/validator.js +14 -4
  20. package/lib/compiler/assert-consistency.js +8 -7
  21. package/lib/compiler/checks.js +30 -20
  22. package/lib/compiler/define.js +89 -25
  23. package/lib/compiler/extend.js +21 -18
  24. package/lib/compiler/finalize-parse-cdl.js +14 -9
  25. package/lib/compiler/populate.js +30 -8
  26. package/lib/compiler/propagator.js +4 -2
  27. package/lib/compiler/resolve.js +11 -5
  28. package/lib/compiler/shared.js +66 -48
  29. package/lib/compiler/tweak-assocs.js +2 -3
  30. package/lib/compiler/utils.js +11 -0
  31. package/lib/edm/annotations/genericTranslation.js +7 -4
  32. package/lib/edm/csn2edm.js +1 -1
  33. package/lib/gen/language.checksum +1 -1
  34. package/lib/gen/language.interp +1 -1
  35. package/lib/gen/languageParser.js +3565 -3544
  36. package/lib/json/csnVersion.js +13 -13
  37. package/lib/json/from-csn.js +140 -158
  38. package/lib/json/to-csn.js +23 -5
  39. package/lib/language/.eslintrc.json +4 -0
  40. package/lib/language/antlrParser.js +7 -10
  41. package/lib/language/docCommentParser.js +1 -2
  42. package/lib/language/errorStrategy.js +54 -27
  43. package/lib/language/genericAntlrParser.js +115 -84
  44. package/lib/language/language.g4 +29 -25
  45. package/lib/language/multiLineStringParser.js +75 -63
  46. package/lib/main.js +1 -0
  47. package/lib/model/csnRefs.js +4 -3
  48. package/lib/model/csnUtils.js +39 -7
  49. package/lib/model/sortViews.js +7 -3
  50. package/lib/modelCompare/compare.js +49 -15
  51. package/lib/modelCompare/filter.js +83 -0
  52. package/lib/optionProcessor.js +5 -1
  53. package/lib/render/manageConstraints.js +9 -5
  54. package/lib/render/toCdl.js +120 -62
  55. package/lib/render/toHdbcds.js +1 -1
  56. package/lib/render/toSql.js +6 -2
  57. package/lib/render/utils/common.js +7 -0
  58. package/lib/sql-identifier.js +7 -0
  59. package/lib/transform/db/assertUnique.js +27 -38
  60. package/lib/transform/db/expansion.js +11 -4
  61. package/lib/transform/db/temporal.js +3 -1
  62. package/lib/transform/db/transformExists.js +7 -1
  63. package/lib/transform/db/views.js +42 -13
  64. package/lib/transform/draft/db.js +2 -2
  65. package/lib/transform/forRelationalDB.js +12 -6
  66. package/lib/transform/localized.js +1 -1
  67. package/lib/transform/odata/typesExposure.js +2 -1
  68. package/lib/transform/parseExpr.js +245 -0
  69. package/lib/transform/transformUtilsNew.js +23 -14
  70. package/lib/transform/translateAssocsToJoins.js +12 -12
  71. package/lib/utils/term.js +5 -5
  72. package/package.json +2 -2
  73. package/share/messages/message-explanations.json +1 -1
  74. package/share/messages/{syntax-expected-integer.md → syntax-expecting-integer.md} +1 -1
@@ -12,6 +12,7 @@ const { cloneCsnNonDict, cloneCsnDictionary, getUtils } = require('../model/csnU
12
12
  const { typeParameters, isBuiltinType } = require('../compiler/builtins');
13
13
  const { ModelError } = require("../base/error");
14
14
  const { forEach } = require('../utils/objectUtils');
15
+ const { pathName } = require("../compiler/utils");
15
16
 
16
17
  const RestrictedOperators = ['<', '>', '>=', '<='];
17
18
  const RelationalOperators = ['=', '!=', '<>', 'is' /*, 'like'*/,...RestrictedOperators];
@@ -711,7 +712,7 @@ function getTransformers(model, options, pathDelimiter = '_') {
711
712
  if (artifactName) {
712
713
  path = ['definitions', artifactName, 'elements', elemName];
713
714
  }
714
- error(null, path, { name: elemName }, `Generated element $(NAME) conflicts with existing element`);
715
+ error(null, path, { name: elemName }, 'Generated element $(NAME) conflicts with existing element');
715
716
  return;
716
717
  }
717
718
 
@@ -865,9 +866,9 @@ function getTransformers(model, options, pathDelimiter = '_') {
865
866
  if (array.length > 1) {
866
867
  const loc = ['definitions', artifactName];
867
868
  if (err === true) {
868
- error(null, loc, { anno: annoName }, `Annotation $(ANNO) must be assigned only once`);
869
+ error(null, loc, { anno: annoName }, 'Annotation $(ANNO) must be assigned only once');
869
870
  } else {
870
- warning(null, loc, { anno: annoName },`Annotation $(ANNO) must be assigned only once`);
871
+ warning(null, loc, { anno: annoName },'Annotation $(ANNO) must be assigned only once');
871
872
  }
872
873
  }
873
874
  }
@@ -958,7 +959,7 @@ function getTransformers(model, options, pathDelimiter = '_') {
958
959
  node[name] = value;
959
960
  if(wasOverwritten)
960
961
  info(null, path, { anno: name, prop: value, otherprop: oldValue },
961
- `Value $(OTHERPROP) of annotation $(ANNO) is overwritten with new value $(PROP)`);
962
+ 'Value $(OTHERPROP) of annotation $(ANNO) is overwritten with new value $(PROP)');
962
963
  return wasOverwritten;
963
964
  }
964
965
 
@@ -1161,42 +1162,50 @@ function getTransformers(model, options, pathDelimiter = '_') {
1161
1162
  const xrefvalues = Object.values(xref);
1162
1163
  let cont = true;
1163
1164
 
1164
- if(op === 'like' && xrefvalues.reduce((a, v) => {
1165
+ if(op === 'like' && xrefvalues.reduce((a, v) => {
1165
1166
  return (v.lhs && v.rhs) ? a + 1: a;
1166
1167
  }, 0) === 0) {
1167
1168
  // error if intersection of paths is zero
1168
- error(null, location, `Expected compatible types for '${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}'`);
1169
+ error(null, location, { lhs: pathName(lhs.ref), op, rhs: pathName(rhs.ref) },
1170
+ 'Expected compatible types for $(LHS) $(OP) $(RHS)');
1169
1171
  cont = false;
1170
1172
  }
1171
1173
 
1172
1174
  cont && xrefkeys.forEach(xn => {
1173
1175
  const x = xref[xn];
1176
+ const prefix = `${pathName(lhs.ref)} ${op} ${pathName(rhs.ref)}`;
1174
1177
  // do the paths match?
1175
1178
  if(op !== 'like' && !(x.lhs && x.rhs)) {
1176
- if(xn.length)
1177
- error(null, location, `'${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}': Sub path '${xn}' not found in ${((x.lhs ? rhs : lhs).ref.join('.'))}`)
1178
- else
1179
- error(null, location, `'${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}': Path '${((x.lhs ? lhs : rhs).ref.join('.'))}' does not match ${((x.lhs ? rhs : lhs).ref.join('.'))}`)
1179
+ if(xn.length) {
1180
+ error(null, location, { prefix, name: xn, alias: pathName((x.lhs ? rhs : lhs).ref) },
1181
+ '$(PREFIX): Sub path $(NAME) not found in $(ALIAS)');
1182
+ }
1183
+ else {
1184
+ error(null, location, { prefix, name: pathName((x.lhs ? lhs : rhs).ref), alias: pathName((x.lhs ? rhs : lhs).ref) },
1185
+ '$(PREFIX): Path $(NAME) does not match $(ALIAS)');
1186
+ }
1180
1187
  cont = false;
1181
1188
  }
1182
1189
  // lhs && rhs are present, consistency checks that affect both ends
1183
1190
  else {
1184
1191
  // is lhs scalar?
1185
1192
  if(!lhsIsVal && x.lhs && !isScalarOrNoType(x.lhs._art)) {
1186
- error(null, location, `'${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}': Path '${x.lhs.ref.join('.')}${(xn.length ? '.' + xn : '')}' must end on a scalar type`)
1193
+ error(null, location, { prefix, name: `${pathName(x.lhs.ref)}${(xn.length ? '.' + xn : '')}` },
1194
+ '$(PREFIX): Path $(NAME) must end on a scalar type')
1187
1195
  cont = false;
1188
1196
  }
1189
1197
  // is rhs scalar?
1190
1198
  if(!rhsIsVal && x.rhs && !isScalarOrNoType(x.rhs._art)) {
1191
- error(null, location, `'${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}': Path '${x.rhs.ref.join('.')}${(xn.length ? '.' + xn : '')}' must end on a scalar type`)
1199
+ error(null, location, { prefix, name: `${pathName(x.rhs.ref)}${(xn.length ? '.' + xn : '')}` },
1200
+ '$(PREFIX): Path $(NAME) must end on a scalar type');
1192
1201
  cont = false;
1193
1202
  }
1194
- // info about type incompatibility if no other errors occured
1203
+ // info about type incompatibility if no other errors occurred
1195
1204
  if(!(lhsIsVal || rhsIsVal) && x.lhs && x.rhs && xn && cont) {
1196
1205
  const lhst = getType(x.lhs._art);
1197
1206
  const rhst = getType(x.rhs._art);
1198
1207
  if(lhst !== rhst) {
1199
- info(null, location, `'${lhs.ref.join('.')} ${op} ${rhs.ref.join('.')}': Types for sub path '${xn}' don't match`)
1208
+ info(null, location, { prefix, name: xn },'$(PREFIX): Types for sub path $(NAME) don\'t match');
1200
1209
  }
1201
1210
  }
1202
1211
  }
@@ -902,29 +902,29 @@ function translateAssocsToJoins(model, inputOptions = {})
902
902
  // source side from view point of view (target side from forward point of view)
903
903
  path = tail; // pop assoc step
904
904
  let elt = env.lead._combined[path[0].id];
905
- let err = 'Element "' + path[0].id +
906
- '" referred in association "' + assoc.name.id +'" of Artifact "' + assoc.name.absolute +'"';
907
905
 
908
906
  if(elt) {
909
907
  if(Array.isArray(elt)) {
910
- err += ' is available from multiple query sources ' +
911
- elt.map(e => '"' + e._origin.name.absolute + '"').join(', ');
912
- error(null, assocQAT._origin.location, `${err}`);
908
+ const names = elt.map(e => e._origin.name.absolute);
909
+ error(null, [ assocQAT._origin.location, assocQAT._origin ], { elemref: path[0].id, id: assoc.name.id, art: assoc.name.absolute, names },
910
+ 'Element $(ELEMREF) referred in association $(ID) of artifact $(ART) is available from multiple query sources $(NAMES)');
913
911
  return pathNode.path;
914
912
  } else {
915
913
  // check if element has same origin on both ends
916
914
  if(elt._origin._main !== path[0]._artifact._origin._main) {
917
- err += ' originates from "' +
918
- path[0]._artifact._origin._main.name.absolute+'" and from "' +
919
- elt._origin._main.name.absolute +
920
- '" in "' + elt._main.name.absolute + '"';
921
- warning(null, assocQAT._origin.location, `${err}`);
915
+ warning(null, [ assocQAT._origin.location, assocQAT._origin ], {
916
+ elemref: path[0].id,
917
+ id: assoc.name.id, art: assoc.name.absolute,
918
+ name: path[0]._artifact._origin._main.name.absolute,
919
+ alias: elt._origin._main.name.absolute,
920
+ source: elt._main.name.absolute,
921
+ }, 'Element $(ELEMREF) referred in association $(ID) of artifact $(ART) originates from $(NAME) and from $(ALIAS) in $(SOURCE)');
922
922
  }
923
923
  _navigation = elt._parent;
924
924
  }
925
925
  } else {
926
- err += ' has not been found';
927
- error(null, assocQAT._origin.location, `${err}`);
926
+ error(null, [ assocQAT._origin.location, assocQAT._origin ], { elemref: path[0].id, id: assoc.name.id, art: assoc.name.absolute },
927
+ 'Element $(ELEMREF) referred in association $(ID) of artifact $(ART) has not been found');
928
928
  return pathNode.path;
929
929
  }
930
930
  } else {
package/lib/utils/term.js CHANGED
@@ -1,6 +1,6 @@
1
1
  //
2
2
  // This file is used for color output to stderr and stdout.
3
- // Use `term.error`, `term.warn` and `term.info` as they use color output
3
+ // Use `term.asError`, `term.asWarn` and `term.asInfo` as they use color output
4
4
  // per default if the process runs in a TTY, i.e. stdout as well as
5
5
  // stderr are TTYs. stderr/stdout are no TTYs if they are
6
6
  // (for example) piped into another process or written to file:
@@ -88,10 +88,10 @@ function term(useColor = 'auto') {
88
88
  bold,
89
89
 
90
90
  severity: asSeverity,
91
- error: asError,
92
- warn: asWarning,
93
- info: asInfo,
94
- help: asHelp,
91
+ asError,
92
+ asWarning,
93
+ asInfo,
94
+ asHelp,
95
95
  };
96
96
  }
97
97
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "3.3.2",
3
+ "version": "3.4.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)",
@@ -16,7 +16,7 @@
16
16
  "scripts": {
17
17
  "download": "node scripts/downloadANTLR.js",
18
18
  "gen": "node ./scripts/build.js && node scripts/genGrammarChecksum.js",
19
- "xmakeBeforeInstall": "echo \"Due to binary mirror, use sqlite 5.1.1 explicitly\" && npm install --save --save-exact --no-package-lock sqlite3@5.1.1",
19
+ "xmakeBeforeInstall": "echo \"Due to binary mirror, use sqlite 5.1.2 explicitly\" && npm install --save --save-exact --no-package-lock sqlite3@5.1.2",
20
20
  "xmakeAfterInstall": "npm run gen",
21
21
  "xmakePrepareRelease": "echo \"$(node scripts/stripReadme.js README.md)\" > README.md && node scripts/assertSnapshotVersioning.js && node scripts/assertChangelog.js && node scripts/cleanup.js --remove-dev",
22
22
  "test": "node scripts/verifyGrammarChecksum.js && mocha --reporter min --reporter-option maxDiffSize=0 scripts/testLazyLoading.js && mocha --parallel --reporter min --reporter-option maxDiffSize=0 test/ test3/",
@@ -11,7 +11,7 @@
11
11
  "redirected-to-complex",
12
12
  "redirected-to-unrelated",
13
13
  "rewrite-not-supported",
14
- "syntax-expected-integer",
14
+ "syntax-expecting-integer",
15
15
  "wildcard-excluding-one"
16
16
  ]
17
17
  }
@@ -1,4 +1,4 @@
1
- # syntax-expected-integer
1
+ # syntax-expecting-integer
2
2
 
3
3
  The compiler expects a safe integer here.
4
4
  The last safe integer is `2^53 - 1` or `9007199254740991`.