@sap/cds-compiler 4.9.4 → 5.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/bin/cds_remove_invalid_whitespace.js +2 -1
  3. package/bin/cdsc.js +15 -11
  4. package/bin/cdshi.js +1 -0
  5. package/doc/CHANGELOG_BETA.md +7 -0
  6. package/lib/api/main.js +6 -18
  7. package/lib/api/options.js +3 -11
  8. package/lib/api/trace.js +0 -1
  9. package/lib/base/builtins.js +1 -0
  10. package/lib/base/location.js +4 -1
  11. package/lib/base/message-registry.js +29 -29
  12. package/lib/base/messages.js +22 -26
  13. package/lib/base/model.js +0 -2
  14. package/lib/base/node-helpers.js +0 -1
  15. package/lib/checks/enricher.js +1 -5
  16. package/lib/checks/structuredAnnoExpressions.js +30 -0
  17. package/lib/checks/validator.js +8 -0
  18. package/lib/compiler/assert-consistency.js +4 -1
  19. package/lib/compiler/base.js +1 -1
  20. package/lib/compiler/builtins.js +18 -2
  21. package/lib/compiler/checks.js +2 -5
  22. package/lib/compiler/define.js +7 -7
  23. package/lib/compiler/extend.js +68 -33
  24. package/lib/compiler/generate.js +1 -1
  25. package/lib/compiler/index.js +23 -6
  26. package/lib/compiler/lsp-api.js +501 -2
  27. package/lib/compiler/populate.js +2 -2
  28. package/lib/compiler/propagator.js +1 -4
  29. package/lib/compiler/resolve.js +2 -15
  30. package/lib/compiler/shared.js +112 -31
  31. package/lib/compiler/tweak-assocs.js +2 -16
  32. package/lib/compiler/utils.js +2 -1
  33. package/lib/compiler/xsn-model.js +4 -0
  34. package/lib/edm/annotations/genericTranslation.js +95 -42
  35. package/lib/edm/csn2edm.js +16 -4
  36. package/lib/edm/edm.js +2 -3
  37. package/lib/edm/edmAnnoPreprocessor.js +1 -2
  38. package/lib/edm/edmPreprocessor.js +1 -7
  39. package/lib/gen/Dictionary.json +29 -2
  40. package/lib/gen/language.checksum +1 -1
  41. package/lib/gen/language.interp +2 -1
  42. package/lib/gen/languageParser.js +4995 -4817
  43. package/lib/json/csnVersion.js +1 -1
  44. package/lib/json/from-csn.js +4 -7
  45. package/lib/json/to-csn.js +23 -12
  46. package/lib/language/antlrParser.js +2 -2
  47. package/lib/language/errorStrategy.js +0 -1
  48. package/lib/language/genericAntlrParser.js +35 -12
  49. package/lib/language/multiLineStringParser.js +3 -2
  50. package/lib/language/textUtils.js +1 -0
  51. package/lib/main.d.ts +28 -9
  52. package/lib/main.js +7 -4
  53. package/lib/model/csnRefs.js +20 -4
  54. package/lib/model/csnUtils.js +0 -2
  55. package/lib/model/revealInternalProperties.js +1 -1
  56. package/lib/modelCompare/compare.js +1 -1
  57. package/lib/optionProcessor.js +28 -9
  58. package/lib/render/manageConstraints.js +1 -1
  59. package/lib/render/toCdl.js +36 -7
  60. package/lib/render/toSql.js +1 -0
  61. package/lib/render/utils/common.js +12 -9
  62. package/lib/render/utils/stringEscapes.js +1 -0
  63. package/lib/transform/db/applyTransformations.js +13 -8
  64. package/lib/transform/db/associations.js +62 -54
  65. package/lib/transform/db/expansion.js +1 -6
  66. package/lib/transform/db/flattening.js +89 -111
  67. package/lib/transform/db/temporal.js +3 -4
  68. package/lib/transform/db/views.js +0 -1
  69. package/lib/transform/draft/odata.js +51 -3
  70. package/lib/transform/effective/annotations.js +3 -2
  71. package/lib/transform/effective/flattening.js +135 -0
  72. package/lib/transform/effective/main.js +6 -6
  73. package/lib/transform/effective/types.js +13 -9
  74. package/lib/transform/forOdata.js +0 -2
  75. package/lib/transform/forRelationalDB.js +0 -19
  76. package/lib/transform/localized.js +7 -8
  77. package/lib/transform/odata/flattening.js +39 -31
  78. package/lib/transform/odata/typesExposure.js +5 -17
  79. package/lib/transform/transformUtils.js +1 -1
  80. package/lib/transform/translateAssocsToJoins.js +21 -3
  81. package/lib/utils/file.js +13 -7
  82. package/lib/utils/moduleResolve.js +59 -8
  83. package/lib/utils/term.js +3 -2
  84. package/package.json +7 -3
  85. package/share/messages/message-explanations.json +2 -0
  86. package/share/messages/type-unexpected-foreign-keys.md +52 -0
  87. package/share/messages/type-unexpected-on-condition.md +52 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,72 @@
7
7
  Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
8
8
  The compiler behavior concerning `beta` features can change at any time without notice.
9
9
 
10
+ ## Version 5.0.6 - 2024-07-10
11
+
12
+ ### Fixed
13
+
14
+ - for.seal: Don't generate DRAFT artifacts.
15
+
16
+ ## Version 5.0.4 - 2024-06-26
17
+
18
+ ### Fixed
19
+
20
+ - CDL parser: an `extend entity` and `extend aspect` with an extensions for the
21
+ same element now correctly leads to an error, because it resulted in part of the
22
+ extension being simply dropped. Remark: an `extend type` and the recommended
23
+ plain `extend` led to an error in that situation already before.
24
+ - to.sql: Conditions inside filters in combination with foreign key aliases were
25
+ not properly translated in rare cases.
26
+ - Update OData Vocabularies: 'PDF', 'UI'.
27
+
28
+ ## Version 5.0.2 - 2024-06-14
29
+
30
+ ### Changed
31
+
32
+ - API `CompilationError` will serialize the first compiler error in `e.message`
33
+ - cdsc: `--without-hana-associations` is changed to `--with-hana-associations`
34
+
35
+ ### Fixed
36
+
37
+ - to.edm(x):
38
+ + Respect `AppliesTo` specification in term definitions for actions and functions.
39
+ + Make message `odata-spec-violation-namespace` a warning again.
40
+
41
+ ## Version 5.0.0 - Pre-release version - 2024-05-29
42
+
43
+ This is a preview version for the major release and contains breaking changes. It should not be used for production.
44
+
45
+ ### Changed
46
+
47
+ - Node 18 is now the minimum required version.
48
+ - API `CompilationError`s will no longer serialize all compiler messages into `e.message`.
49
+ Use `e.messages[]` instead or `e.toString()` to serialize errors into a string.
50
+ - CDL parser: Annotations that can't be applied are now rejected.
51
+ - compiler:
52
+ + `extend` statements on "namespaces" (paths that are not definitions) are now always errors.
53
+ + non-structured events are rejected
54
+ + `$self` references in JOINs are rejected if they could lead to issues in SQL rendering.
55
+ + non-string enum definitions must have a value.
56
+ + A top-level definition `$self` is rejected. `$self` is considered a reserved name.
57
+ + `$at.from`/`$at.to` are deprecated; use `$valid.from`/`$valid.to` instead.
58
+ - to.hdbcds: The HDBCDS backend is now considered deprecated.
59
+ - to.edm(x):
60
+ + Set default nullability to `true` for collection like properties (was `false` before).
61
+ + Raise message ids `odata-spec-violation-namespace`, `odata-spec-violation-no-key` from warning to error.
62
+ - to.sql:
63
+ + `@cds.persistence.exists` is _not_ propagated to generated localization views (`localized.*`)
64
+ + Option `fewerLocalizedViews` is now enabled by default.
65
+ + Option `betterSqliteSessionVariables` is now enabled by default.
66
+
67
+ ### Fixed
68
+
69
+ - for.odata: Propagate all `@odata { Type, MaxLength, Precision, Scale, SRID }` to generated foreign keys.
70
+
71
+ ### Removed
72
+
73
+ - API: Deprecated functions `preparedCsnToEdmx` and `preparedCsnToEdm` were removed.
74
+ Use `to.edm(x)` instead.
75
+
10
76
  ## Version 4.9.4 - 2024-05-21
11
77
 
12
78
  ### Fixed
@@ -64,7 +64,8 @@ function modernizeWhitespace( source, filename ) {
64
64
 
65
65
  // To avoid spam, only report errors.
66
66
  // Users should use the compiler to get all messages.
67
- const errors = options.messages.filter(msg => (msg.severity === 'Error'));
67
+ const errors = options.messages
68
+ .filter(msg => (msg.severity === 'Error' && msg.messageId !== 'syntax-invalid-space'));
68
69
  if (errors.length > 0) {
69
70
  errors.forEach((msg) => {
70
71
  console.error(msg.toString());
package/bin/cdsc.js CHANGED
@@ -145,6 +145,7 @@ function cdsc_main() {
145
145
  // Internally, parseCdl/parseOnly are options, so we map the command to it.
146
146
  if (cmdLine.command === 'parseCdl') {
147
147
  cmdLine.command = 'toCsn';
148
+ cmdLine.options.toCsn = cmdLine.options.parseCdl;
148
149
  cmdLine.options.parseCdl = true;
149
150
  cmdLine.args.files = [ cmdLine.args.file ];
150
151
  }
@@ -169,12 +170,20 @@ function cdsc_main() {
169
170
  }
170
171
 
171
172
  const to = cmdLine.options.toSql ? 'toSql' : 'toHana';
172
- // remap string values for `assertIntegrity` option to boolean
173
- if (cmdLine.options[to] && cmdLine.options[to].assertIntegrity &&
174
- (cmdLine.options[to].assertIntegrity === 'true' ||
175
- cmdLine.options[to].assertIntegrity === 'false')
176
- )
177
- cmdLine.options[to].assertIntegrity = cmdLine.options[to].assertIntegrity === 'true';
173
+ if (cmdLine.options[to]) {
174
+ // remap string values in options to boolean
175
+ if (cmdLine.options[to].assertIntegrity &&
176
+ (cmdLine.options[to].assertIntegrity === 'true' ||
177
+ cmdLine.options[to].assertIntegrity === 'false')
178
+ )
179
+ cmdLine.options[to].assertIntegrity = cmdLine.options[to].assertIntegrity === 'true';
180
+
181
+ if (cmdLine.options[to].withHanaAssociations)
182
+ cmdLine.options[to].withHanaAssociations = cmdLine.options[to].withHanaAssociations !== 'false';
183
+
184
+ if (cmdLine.options[to].betterSqliteSessionVariables)
185
+ cmdLine.options[to].betterSqliteSessionVariables = cmdLine.options[to].betterSqliteSessionVariables === 'true';
186
+ }
178
187
 
179
188
  // Enable all beta-flags if betaMode is set to true
180
189
  if (cmdLine.options.betaMode)
@@ -446,11 +455,6 @@ function executeCommandLine( command, options, args ) {
446
455
  // Execute the command line option '--to-sql' and display the results.
447
456
  // Return the original model (for chaining)
448
457
  function toSql( model ) {
449
- if (options.withoutHanaAssociations) {
450
- options.withHanaAssociations = false;
451
- delete options.withoutHanaAssociations;
452
- }
453
-
454
458
  const csn = options.directBackend ? model : compactModel(model, options);
455
459
  if (options.src === 'hdi') {
456
460
  if (options.csn) {
package/bin/cdshi.js CHANGED
@@ -34,6 +34,7 @@ const categoryChars = { // default: first char of category name
34
34
  ExtBoundAction: 'B', // highlight like bound action definition
35
35
  ExtParam: 'P', // highlight like entity/action parameter definition
36
36
  Event: 'Y',
37
+ KeyImplicit: 'r', // handle as normal ref
37
38
  // Remark: do not use `x`/`X` (hex literal `x'1e3d'`)
38
39
  };
39
40
 
@@ -8,6 +8,13 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
8
8
  The compiler behavior concerning `beta` features can change at any time without notice.
9
9
  **Don't use `beta` fixes, changes and features in productive mode.**
10
10
 
11
+
12
+ ## Version 5.0.0 - 2024-05-29
13
+
14
+ ## Removed `v5preview`
15
+
16
+ It is now enabled by default.
17
+
11
18
  ## Version 4.9.0 - 2024-04-25
12
19
 
13
20
  ## Removed `odataAnnotationExpressions`
package/lib/api/main.js CHANGED
@@ -712,9 +712,9 @@ function hdbcds( csn, options, messageFunctions ) {
712
712
  internalOptions.transformation = 'hdbcds';
713
713
  messageFunctions.setOptions( internalOptions );
714
714
 
715
- // no "isBetaEnabled", because this warning must also appear with "deprecated" flags
716
- if (internalOptions.betaMode || internalOptions.beta?.v5preview)
717
- messageFunctions.warning('api-deprecated-v5', null, null);
715
+ // Since v5, the HDBCDS backend is considered deprecated.
716
+ // TODO(v6): Make this a configurable error
717
+ messageFunctions.warning('api-deprecated-v5', null, null);
718
718
 
719
719
  if (options.tenantDiscriminator) {
720
720
  messageFunctions.error('api-invalid-option', null, {
@@ -741,7 +741,6 @@ function hdbcds( csn, options, messageFunctions ) {
741
741
  function edm( csn, options, messageFunctions ) {
742
742
  // If not provided at all, set service to 'undefined' to trigger validation
743
743
  const internalOptions = prepareOptions.to.edm(
744
- // eslint-disable-next-line comma-dangle
745
744
  options.service ? options : Object.assign({ service: undefined }, options)
746
745
  );
747
746
  messageFunctions.setOptions( internalOptions );
@@ -810,7 +809,6 @@ function edmall( csn, options, messageFunctions ) {
810
809
  function edmx( csn, options, messageFunctions ) {
811
810
  // If not provided at all, set service to 'undefined' to trigger validation
812
811
  const internalOptions = prepareOptions.to.edmx(
813
- // eslint-disable-next-line comma-dangle
814
812
  options.service ? options : Object.assign({ service: undefined }, options)
815
813
  );
816
814
  messageFunctions.setOptions( internalOptions );
@@ -880,9 +878,8 @@ function edmxall( csn, options, messageFunctions ) {
880
878
  */
881
879
  // @ts-ignore
882
880
  function odata2( csn, options, messageFunctions ) {
883
- // If not provided at all, set service to undefined to trigger validation
881
+ // If not provided at all, set service to 'undefined' to trigger validation
884
882
  const internalOptions = prepareOptions.to.odata(
885
- // eslint-disable-next-line comma-dangle
886
883
  options.service ? options : Object.assign({ service: undefined }, options)
887
884
  );
888
885
  messageFunctions.setOptions( internalOptions );
@@ -1074,15 +1071,6 @@ module.exports = {
1074
1071
  for_hdbcds: publishCsnProcessor(forHdbcds, 'for.hdbcds'),
1075
1072
  for_effective: publishCsnProcessor(forEffective, 'for.effective'),
1076
1073
  for_seal: publishCsnProcessor(forSeal, 'for.seal'),
1077
-
1078
- /* Deprecated, will be removed in cds-compiler@v5 */ // TODO(v5): Remove
1079
- preparedCsnToEdmx(csn, service, options) {
1080
- preparedCsnToEdmx(csn, service, options, messages.makeMessageFunction( csn, options, 'to.edmx' ));
1081
- },
1082
- /* Deprecated, will be removed in cds-compiler@v5 */ // TODO(v5): Remove
1083
- preparedCsnToEdm(csn, service, options) {
1084
- preparedCsnToEdm(csn, service, options, messages.makeMessageFunction( csn, options, 'to.edm' ));
1085
- },
1086
1074
  };
1087
1075
 
1088
1076
 
@@ -1266,7 +1254,7 @@ function ensureClientCsn( csn, options, messageFunctions, module ) {
1266
1254
  function lazyload( moduleName ) {
1267
1255
  let module;
1268
1256
  return new Proxy(((...args) => {
1269
- if (!module) // eslint-disable-next-line global-require
1257
+ if (!module)
1270
1258
  module = require(moduleName);
1271
1259
 
1272
1260
  if (module.apply && typeof module.apply === 'function')
@@ -1274,7 +1262,7 @@ function lazyload( moduleName ) {
1274
1262
  return module; // for destructured calls
1275
1263
  }), {
1276
1264
  get(target, name) {
1277
- if (!module) // eslint-disable-next-line global-require
1265
+ if (!module)
1278
1266
  module = require(moduleName);
1279
1267
 
1280
1268
  return module[name];
@@ -75,7 +75,7 @@ const privateOptions = [
75
75
  'internalMsg',
76
76
  'disableHanaComments', // in case of issues with hana comment rendering
77
77
  'tenantDiscriminator', // not published yet
78
- 'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback', TODO(v5): Remove option
78
+ 'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback', TODO(v6): Remove option
79
79
  ];
80
80
 
81
81
  const overallOptions = publicOptionsNewAPI.concat(privateOptions);
@@ -145,15 +145,7 @@ function reclassifyErrorsForOpenApi( options ) {
145
145
  // shallow clone, so that we can modify severities without changing the user's.
146
146
  options.severities = Object.assign({}, options.severities ?? {});
147
147
 
148
- options.severities['odata-spec-violation-array'] = 'Warning';
149
- options.severities['odata-spec-violation-assoc'] = 'Warning';
150
- options.severities['odata-spec-violation-namespace'] = 'Warning';
151
- options.severities['odata-spec-violation-param'] = 'Warning';
152
- options.severities['odata-spec-violation-returns'] = 'Warning';
153
- options.severities['odata-spec-violation-type-unknown'] = 'Warning';
154
148
  options.severities['odata-spec-violation-no-key'] = 'Warning';
155
- options.severities['odata-spec-violation-key-type'] = 'Warning';
156
- options.severities['odata-spec-violation-property-name'] = 'Warning';
157
149
  }
158
150
  }
159
151
 
@@ -216,7 +208,7 @@ module.exports = {
216
208
  return translateOptions(options, defaultOptions, hardOptions, undefined, undefined, 'for.hana');
217
209
  },
218
210
  effective: (options) => {
219
- const hardOptions = {};
211
+ const hardOptions = { addCdsPersistenceName: false };
220
212
  const defaultOptions = {
221
213
  sqlMapping: 'plain', resolveSimpleTypes: true, resolveProjections: true, remapOdataAnnotations: false, keepLocalized: false,
222
214
  };
@@ -226,7 +218,7 @@ module.exports = {
226
218
  },
227
219
  seal: (options) => {
228
220
  const hardOptions = {
229
- sqlMapping: 'plain', resolveSimpleTypes: true, resolveProjections: true, keepLocalized: false,
221
+ sqlMapping: 'plain', resolveSimpleTypes: true, resolveProjections: true, keepLocalized: false, addCdsPersistenceName: true,
230
222
  };
231
223
  const defaultOptions = { remapOdataAnnotations: true };
232
224
  const processed = translateOptions(options, defaultOptions, hardOptions, null, [ 'sql-dialect-and-naming' ], 'for.effective');
package/lib/api/trace.js CHANGED
@@ -27,7 +27,6 @@ function traceApi( apiName, options, ...args ) {
27
27
  const argsStr = args.map(val => JSON.stringify(val)).join(', ');
28
28
  const rest = args.length > 0 ? ` | ${ argsStr }` : '';
29
29
  // Local require: Only load on-demand, not when tracing is disabled.
30
- // eslint-disable-next-line global-require
31
30
  const { version } = require('../../package.json');
32
31
  // eslint-disable-next-line no-console
33
32
  console.error( `CDSC_TRACE_API | ${ version } | ${ apiName }(…) | options: ${ optStr }${ rest }`);
@@ -64,6 +64,7 @@ const magicVariables = [
64
64
  '$now',
65
65
  '$tenant',
66
66
  '$session',
67
+ '$draft',
67
68
  ];
68
69
 
69
70
  /**
@@ -11,13 +11,16 @@ class Location {
11
11
  col;
12
12
  endLine;
13
13
  endCol;
14
- constructor(file, line, col, endLine, endCol) {
14
+ constructor( file, line, col, endLine, endCol ) {
15
15
  this.file = file;
16
16
  this.line = line;
17
17
  this.col = col;
18
18
  this.endLine = endLine;
19
19
  this.endCol = endCol;
20
20
  }
21
+ toString() {
22
+ return locationString( this );
23
+ }
21
24
  }
22
25
 
23
26
  class SemanticLocation {
@@ -41,7 +41,6 @@ const { createDict } = require('../utils/objectUtils');
41
41
  * - true = can always be downgraded, we do not really care
42
42
  * - [‹module›, …] = can be downgraded in compiler function ‹module›
43
43
  * - 'deprecated' = severity can only be changed with deprecated.downgradableErrors
44
- * - 'v4' = currently like true, but should be 'deprecated' in v5
45
44
  *
46
45
  * @type {Object<string, MessageConfig>}
47
46
  */
@@ -61,13 +60,13 @@ const centralMessages = {
61
60
  'ext-undefined-art': { severity: 'Warning' }, // for annotate statement (for CDL path root)
62
61
  'ext-undefined-def': { severity: 'Warning' }, // for annotate statement (for CSN or CDL path cont)
63
62
  'ext-undefined-element': { severity: 'Warning' },
63
+ 'ext-undefined-key': { severity: 'Warning' },
64
64
  'ext-undefined-param': { severity: 'Warning' },
65
65
  'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' },
66
66
  'anno-unexpected-localized-skip': { severity: 'Error', configurableFor: true },
67
- 'anno-unexpected-mixin': { severity: 'Warning', errorFor: [ 'v5' ] },
68
67
 
69
68
  'name-invalid-dollar-alias': { severity: 'Error', configurableFor: true },
70
- 'name-deprecated-$self': { severity: 'Warning', errorFor: [ 'v5' ], configurableFor: true },
69
+ 'name-deprecated-$self': { severity: 'Error', configurableFor: true },
71
70
 
72
71
  'type-invalid-items': { severity: 'Error' }, // not supported yet
73
72
  'assoc-as-type': { severity: 'Error' }, // TODO: allow more, but not all
@@ -86,7 +85,7 @@ const centralMessages = {
86
85
  'empty-type': { severity: 'Info' }, // only still an error in old transformers
87
86
 
88
87
  'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
89
- 'ref-deprecated-self-element': { severity: 'Warning', configurableFor: true, errorFor: [ 'v5' ] },
88
+ 'ref-deprecated-self-element': { severity: 'Error', configurableFor: true },
90
89
  'ref-invalid-type': { severity: 'Error' },
91
90
  'ref-unexpected-self': { severity: 'Error' },
92
91
  'ref-invalid-include': { severity: 'Error' },
@@ -152,7 +151,7 @@ const centralMessages = {
152
151
  // 'syntax-duplicate-annotate' came late with v3 - make it configurable as
153
152
  // fallback, but then parse.cdl is not supposed to work correctly (it can
154
153
  // then either issue an error or produce a CSN missing some annotations):
155
- 'syntax-duplicate-annotate': { severity: 'Error', configurableFor: 'deprecated' },
154
+ 'syntax-duplicate-annotate': { severity: 'Error' },
156
155
  'syntax-duplicate-clause': { severity: 'Error', configurableFor: true },
157
156
  'syntax-duplicate-equal-clause': { severity: 'Warning' },
158
157
  'syntax-invalid-name': { severity: 'Error', configurableFor: 'deprecated' },
@@ -162,36 +161,38 @@ const centralMessages = {
162
161
  'syntax-unknown-escape': { severity: 'Error', configurableFor: true },
163
162
  'syntax-unsupported-masked': { severity: 'Error', configurableFor: 'deprecated' },
164
163
  'syntax-unexpected-sql-clause': { severity: 'Error' }, // TODO: configurableFor:'tests'?
165
- 'syntax-ignoring-anno': { severity: 'Warning', errorFor: [ 'v5' ] },
164
+ 'syntax-invalid-space': { severity: 'Error', configurableFor: 'test' },
165
+ 'syntax-expecting-space': { severity: 'Error' },
166
+ 'syntax-unexpected-anno': { severity: 'Error' },
166
167
 
167
168
  'type-unsupported-precision-change': { severity: 'Error' },
168
169
  'type-unsupported-key-change': { severity: 'Error', configurableFor: true },
169
- 'type-missing-enum-value': { severity: 'Warning', errorFor: [ 'v5' ] },
170
+ 'type-missing-enum-value': { severity: 'Error', configurableFor: 'test' },
170
171
 
171
172
  'def-missing-element': { severity: 'Error' },
172
- 'def-expected-structured': { severity: 'Warning', configurableFor: true, errorFor: [ 'v5' ] },
173
+ 'def-expected-structured': { severity: 'Error', configurableFor: true },
173
174
  'def-unsupported-calc-elem': { severity: 'Error', configurableFor: true },
174
175
 
175
176
  'def-invalid-key-cardinality': { severity: 'Error' },
176
177
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
177
- 'odata-spec-violation-array': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
178
+ 'odata-spec-violation-array': { severity: 'Warning' }, // more than 30 chars
178
179
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
179
- 'odata-spec-violation-assoc': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
180
+ 'odata-spec-violation-assoc': { severity: 'Warning' }, // more than 30 chars
180
181
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
181
182
  'odata-spec-violation-constraints': { severity: 'Info' }, // more than 30 chars
182
183
  'odata-spec-violation-id': { severity: 'Error', configurableFor: true },
183
- 'odata-spec-violation-namespace': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
184
+ 'odata-spec-violation-namespace': { severity: 'Warning' }, // more than 30 chars
184
185
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
185
- 'odata-spec-violation-param': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
186
+ 'odata-spec-violation-param': { severity: 'Warning' }, // more than 30 chars
186
187
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
187
- 'odata-spec-violation-returns': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
188
+ 'odata-spec-violation-returns': { severity: 'Warning' }, // more than 30 chars
188
189
  'odata-spec-violation-type': { severity: 'Error', configurableFor: true },
189
- 'odata-spec-violation-type-unknown': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] },
190
- 'odata-spec-violation-no-key': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] },
190
+ 'odata-spec-violation-type-unknown': { severity: 'Error', configurableFor: true },
191
+ 'odata-spec-violation-no-key': { severity: 'Error', configurableFor: true },
191
192
  'odata-spec-violation-key-array': { severity: 'Error', configurableFor: true }, // more than 30 chars
192
193
  'odata-spec-violation-key-null': { severity: 'Error', configurableFor: true }, // more than 30 chars
193
- 'odata-spec-violation-key-type': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
194
- 'odata-spec-violation-property-name': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
194
+ 'odata-spec-violation-key-type': { severity: 'Warning' }, // more than 30 chars
195
+ 'odata-spec-violation-property-name': { severity: 'Warning' }, // more than 30 chars
195
196
  'odata-anno-preproc': { severity: 'Warning' },
196
197
  'odata-anno-dict': { severity: 'Warning' },
197
198
  'odata-anno-vocref': { severity: 'Warning' },
@@ -290,7 +291,6 @@ const centralMessageTexts = {
290
291
  'anno-unstable-array': 'Unstable order of array items due to repeated assignments for $(ANNO)',
291
292
  'anno-mismatched-ellipsis': 'An array with $(CODE) can only be used if there is an assignment below with an array value',
292
293
  'anno-unexpected-ellipsis': 'No base annotation available to apply $(CODE)',
293
- 'anno-unexpected-mixin': 'Unexpected annotation on mixin definition',
294
294
 
295
295
  'anno-unexpected-localized-skip': {
296
296
  std: 'Compiler generated entity $(NAME) must not be annotated with $(ANNO) if $(ART) is not skipped',
@@ -351,7 +351,7 @@ const centralMessageTexts = {
351
351
  'syntax-ignoring-decimal': {
352
352
  std: 'Ignoring decimal places, because an integer was expected'
353
353
  },
354
- 'syntax-ignoring-anno': {
354
+ 'syntax-unexpected-anno': {
355
355
  std: 'Annotations can\'t be used in a column with $(CODE)',
356
356
  doc: 'Doc comments can\'t be used in a column with $(CODE)',
357
357
  },
@@ -435,7 +435,6 @@ const centralMessageTexts = {
435
435
  service: 'Annotations can\'t be defined inside services',
436
436
  context: 'Annotations can\'t be defined inside contexts',
437
437
  },
438
- // 'syntax-unexpected-space' (TODO: also use for :param, #variant, @(…) and @Begin),
439
438
  // 'syntax-unexpected-alias' (is 'syntax-unexpected-property' in CSN)
440
439
  'syntax-unsupported-param': {
441
440
  std: 'Parameter not supported', // unused
@@ -642,6 +641,8 @@ const centralMessageTexts = {
642
641
  std: 'Unexpected reference to association $(NAME)', // "std" currently unused
643
642
  unmanaged: 'Unexpected reference to an unmanaged association',
644
643
  'self-unmanaged': 'Unexpected column reference starting with $(ALIAS) to an unmanaged association',
644
+ 'with-filter': 'Unexpected reference to an association with filter',
645
+ 'self-with-filter': 'Unexpected column reference starting with $(ALIAS) to an association with filter',
645
646
  self: 'A reference to an unmanaged association is only valid when compared via $(CODE)',
646
647
  expr: 'Associations can\'t be used as values in expressions',
647
648
  'expr-comp': 'Compositions can\'t be used as values in expressions',
@@ -683,6 +684,10 @@ const centralMessageTexts = {
683
684
  hdbcds:'Type $(TYPE) is not supported in HDBCDS',
684
685
  odata: 'Type $(TYPE) is not supported for OData'
685
686
  },
687
+ 'ref-unexpected-var': {
688
+ std: 'Variable $(NAME) can\'t be used here',
689
+ 'annotation': 'Variable $(NAME) can only be used in annotation values',
690
+ },
686
691
 
687
692
  // TODO: Better text ?
688
693
  'rewrite-not-supported': 'The ON-condition is not rewritten here - provide an explicit ON-condition',
@@ -746,6 +751,7 @@ const centralMessageTexts = {
746
751
  returns: 'Return value of $(ART) has no element $(NAME)',
747
752
  'enum-returns': 'Return value of $(ART) has no enum $(NAME)',
748
753
  },
754
+ 'ext-undefined-key': 'Foreign key $(NAME) has not been found',
749
755
  'ext-undefined-action': {
750
756
  std: 'Action $(ART) has not been found',
751
757
  action: 'Artifact $(ART) has no action $(NAME)'
@@ -837,12 +843,6 @@ const centralMessageTexts = {
837
843
  'include-elements': 'Duplicate element $(NAME) through multiple includes $(SORTED_ARTS)',
838
844
  'include-actions': 'Duplicate action or function $(NAME) through multiple includes $(SORTED_ARTS)',
839
845
  },
840
- // TODO: Remove in v5, use duplicate-definition (or another ID?)
841
- 'ref-duplicate-include-member': {
842
- std: 'Duplicate member $(NAME) through multiple includes $(SORTED_ARTS)',
843
- elements: 'Duplicate element $(NAME) through multiple includes $(SORTED_ARTS)',
844
- actions: 'Duplicate action or function $(NAME) through multiple includes $(SORTED_ARTS)',
845
- },
846
846
  'ref-invalid-element': {
847
847
  std: 'Invalid element reference',
848
848
  $tableAlias: 'Can\'t refer to source elements of table alias $(ID)',
@@ -859,6 +859,7 @@ const centralMessageTexts = {
859
859
  'old-not-target': 'Expected element $(NAME) not to be an association, because it overrides the included element from $(ART)',
860
860
  },
861
861
 
862
+ 'ref-expecting-$self': 'Use $(NEWCODE) instead of $(CODE) here or remove $(CODE) altogether if possible; the compiler has rewritten it to $(NEWCODE) in CSN',
862
863
  'ref-expecting-assoc': 'Expecting path $(ELEMREF) following “EXISTS” predicate to end with association/composition, found $(TYPE)',
863
864
  'ref-expecting-const': 'A constant expression or variable is expected here',
864
865
  'ref-expecting-foreign-key': 'Expecting foreign key access after managed association $(NAME) in filter expression of $(ID), but found $(ALIAS)',
@@ -908,9 +909,7 @@ const centralMessageTexts = {
908
909
  'indirect': 'Type property $(PROP) can only be extended if directly provided at the definition',
909
910
  'new-prop': 'Type property $(PROP) can only be extended, not added',
910
911
  string: 'Only numerical properties can be extended, but found string for $(PROP)',
911
- // eslint-disable-next-line max-len
912
912
  number: 'Value of type property $(PROP) must be $(NUMBER) or higher, it can\'t be smaller than originally provided',
913
- // eslint-disable-next-line max-len
914
913
  scale: 'With the extension for type property $(OTHERPROP), the value of $(PROP) must be $(NUMBER) or higher',
915
914
  },
916
915
  'ext-missing-type-property': 'Type extension with property $(PROP) must also have property $(OTHERPROP) because $(ART) has both',
@@ -1193,7 +1192,8 @@ const centralMessageTexts = {
1193
1192
  'notaneelement': 'EDM Parameter path $(ELEMREF) can\'t be used in $(ANNO) which is applied to a type entity',
1194
1193
  'notrendered': 'EDM Path step $(COUNT) of $(ELEMREF) in $(ANNO) refers to an unrendered property in the OData API',
1195
1194
  'magic': 'Unexpected magic variable $(ELEMREF) in $(ANNO)',
1196
- 'bparam_v2': 'Unexpected explicit binding parameter path $(ELEMREF) for OData $(VERSION) in $(ANNO)',
1195
+ 'bparam_v2_expl': 'Unexpected explicit binding parameter path $(ELEMREF) for OData $(VERSION) in $(ANNO)',
1196
+ 'bparam_v2_impl': 'Unexpected implicit binding parameter path $(ELEMREF) for OData $(VERSION) in $(ANNO)',
1197
1197
  },
1198
1198
  // -----------------------------------------------------------------------------------
1199
1199
  // OData Message section ends here, no messages below this line
@@ -73,8 +73,8 @@ function isDowngradable( messageId, moduleName, options ) {
73
73
  return false;
74
74
  if (msg.severity !== 'Error')
75
75
  return true;
76
- // v5 messages are downgradable (except if errorFor also contains the current module).
77
- if (msg.errorFor && msg.errorFor.includes('v5'))
76
+ // v6 messages are downgradable (except if errorFor also contains the current module).
77
+ if (msg.errorFor && msg.errorFor.includes('v6'))
78
78
  return true;
79
79
  const { configurableFor } = msg;
80
80
  return (Array.isArray( configurableFor ))
@@ -91,9 +91,11 @@ function isDowngradable( messageId, moduleName, options ) {
91
91
  function severityChangeMarker(msg, config) {
92
92
  const severity = msg.severity || 'Error';
93
93
  if (config.moduleForMarker) {
94
- if (severity === 'Error' && isDowngradable(msg.messageId, config.moduleForMarker, {}))
94
+ if (severity === 'Error' &&
95
+ isDowngradable( msg.messageId, config.moduleForMarker,
96
+ { deprecated: { downgradableErrors: true } }))
95
97
  return '‹↓›';
96
- if (msg.messageId && centralMessages[msg.messageId]?.errorFor?.includes('v5'))
98
+ if (msg.messageId && centralMessages[msg.messageId]?.errorFor?.includes('v6'))
97
99
  return '‹↑›';
98
100
  }
99
101
  return '';
@@ -107,12 +109,16 @@ function severityChangeMarker(msg, config) {
107
109
  class CompilationError extends Error {
108
110
  /**
109
111
  * @param {CompileMessage[]} messages
110
- * @param {boolean} [dontSerializeMessages] If true, compiler messages are NOT part of the errors message text.
111
112
  * @param {XSN.Model} [model] the XSN model, only to be set with options.attachValidNames
112
113
  */
113
- constructor(messages, model, dontSerializeMessages) {
114
- const msg = !dontSerializeMessages && messages?.map( m => m.toString() ).join('\n') || '';
115
- super( `CDS compilation failed\n${msg}` );
114
+ constructor(messages, model) {
115
+ // Because test frameworks such as mocha and jest to not call `toString()` on
116
+ // an unhandled CompilationError and instead use `e.stack` directly, there is
117
+ // no proper message about _what_ the root cause of the exception was.
118
+ // To mitigate that, we serialize the first error in the message as well.
119
+ const firstError = messages.find( m => m.severity === 'Error' )?.toString() || '';
120
+ super( `CDS compilation failed\n${firstError}` );
121
+
116
122
  /** @since v4.0.0 */
117
123
  this.code = 'ERR_CDS_COMPILATION_FAILURE';
118
124
  this.messages = [ ...messages ].sort(compareMessageSeverityAware);
@@ -240,7 +246,7 @@ function reclassifiedSeverity( msg, options, moduleName ) {
240
246
  if (errorFor.includes(moduleName))
241
247
  return 'Error';
242
248
 
243
- if (errorFor.includes('v5') && isBetaEnabled(options, 'v5preview')) {
249
+ if (errorFor.includes('v6') && isBetaEnabled(options, 'v6preview')) {
244
250
  severity = 'Error';
245
251
  if (!isDowngradable(msg.messageId, moduleName, options))
246
252
  return severity;
@@ -555,8 +561,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
555
561
 
556
562
  function throwWithError() {
557
563
  if (hasNewError) {
558
- const dontSerializeMessages = isBetaEnabled(options, 'v5preview');
559
- throw new CompilationError(messages, options.attachValidNames && model, dontSerializeMessages);
564
+ throw new CompilationError(messages, options.attachValidNames && model);
560
565
  }
561
566
  }
562
567
 
@@ -573,8 +578,7 @@ function makeMessageFunction( model, options, moduleName = null ) {
573
578
  return;
574
579
  const hasError = options.testMode ? hasNonDowngradableErrors : hasErrors;
575
580
  if (hasError( messages, moduleName, options )) {
576
- const dontSerializeMessages = isBetaEnabled(options, 'v5preview');
577
- throw new CompilationError(messages, options.attachValidNames && model, dontSerializeMessages);
581
+ throw new CompilationError(messages, options.attachValidNames && model);
578
582
  }
579
583
  }
580
584
 
@@ -1018,10 +1022,6 @@ function replaceInString( text, params ) {
1018
1022
  * @param {boolean} [config.noMessageId]
1019
1023
  * If true, will _not_ show the message ID (+ explanation hint) in the output.
1020
1024
  *
1021
- * @param {boolean} [config.idInBrackets]
1022
- * If true, the message ID (if there is one and noMessageId is falsey) will be put in brackets.
1023
- * This will be the default in cds-compiler v5.
1024
- *
1025
1025
  * @param {boolean} [config.noHome]
1026
1026
  * If true, will _not_ show message's semantic location.
1027
1027
  *
@@ -1049,11 +1049,7 @@ function messageString( err, config ) {
1049
1049
  const downgradable = severityChangeMarker(err, config);
1050
1050
  // even with noHome, print err.home if the location is weak
1051
1051
  const home = !err.home || config.noHome && err.$location?.endLine ? '' : ` (in ${ err.home })`;
1052
-
1053
- let msgId = ''; // TODO(v5): Use brackets only
1054
- if (err.messageId && !config.noMessageId)
1055
- msgId = (config.idInBrackets) ? `[${err.messageId}]` : ` ${err.messageId}`;
1056
-
1052
+ const msgId = (err.messageId && !config.noMessageId) ? `[${err.messageId}]` : '';
1057
1053
  return `${ location }${ severity }${ downgradable }${ msgId }: ${ err.message }${ home }`;
1058
1054
  }
1059
1055
 
@@ -1065,7 +1061,7 @@ function messageString( err, config ) {
1065
1061
  * @returns {string} can be used to uniquely identify a message
1066
1062
  */
1067
1063
  function messageHash( msg ) {
1068
- // parser messages do not provide semantic location, therefore we need to use the file location
1064
+ // parser messages do not provide semantic location, therefore$ we need to use the file location
1069
1065
  if (!msg.home)
1070
1066
  return messageString(msg);
1071
1067
  const copy = { ...msg };
@@ -1118,7 +1114,7 @@ function messageHash( msg ) {
1118
1114
  * If true/'always', ANSI escape codes will be used for coloring the severity. If false/'never',
1119
1115
  * no coloring will be used. If 'auto', we will decide based on certain factors such
1120
1116
  * as whether the shell is a TTY and whether the environment variable `NO_COLOR` is
1121
- * unset.
1117
+ * unset or whether `FORCE_COLOR` is set.
1122
1118
  *
1123
1119
  * @returns {string}
1124
1120
  */
@@ -1285,7 +1281,7 @@ function _messageContext( err, config ) {
1285
1281
  * @param {boolean | 'auto'} [config.color] If true, ANSI escape codes will be used for coloring the `^`. If false, no
1286
1282
  * coloring will be used. If 'auto', we will decide based on certain factors such
1287
1283
  * as whether the shell is a TTY and whether the environment variable 'NO_COLOR' is
1288
- * unset.
1284
+ * unset or `FORCE_COLOR` is set.
1289
1285
  * @returns {string}
1290
1286
  *
1291
1287
  * @deprecated Use `messageStringMultiline()` with `config.sourceMap` and `config.sourceLineMap` instead!
@@ -1353,7 +1349,7 @@ function compareMessageSeverityAware( a, b ) {
1353
1349
  /**
1354
1350
  * Return sort-relevant part of semantic location (after the ':').
1355
1351
  * Messages without semantic locations are considered smaller (for syntax errors)
1356
- * and (currently - should not happen in v5) larger for other messages.
1352
+ * and (currently - should not happen in v6) larger for other messages.
1357
1353
  *
1358
1354
  * @param {CompileMessage} msg
1359
1355
  */
package/lib/base/model.js CHANGED
@@ -31,11 +31,9 @@ const availableBetaFlags = {
31
31
  enableUniversalCsn: true,
32
32
  odataTerms: true,
33
33
  optionalActionFunctionParameters: true, // not supported by runtime, yet.
34
- annotateForeignKeys: true,
35
34
  effectiveCsn: true,
36
35
  tenantVariable: true,
37
36
  calcAssoc: true,
38
- v5preview: true,
39
37
  temporalRawProjection: true,
40
38
  // disabled by --beta-mode
41
39
  nestedServices: false,
@@ -28,7 +28,6 @@ class PromiseAllError extends Error {
28
28
  }
29
29
  }
30
30
 
31
-
32
31
  module.exports = {
33
32
  promiseAllDoNotRejectImmediately,
34
33
  };