@sap/cds-compiler 6.9.3 → 7.0.1

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 (69) hide show
  1. package/CHANGELOG.md +76 -2
  2. package/bin/cdsc.js +4 -33
  3. package/doc/IncompatibleChanges_v7.md +639 -0
  4. package/lib/api/main.js +4 -56
  5. package/lib/api/options.js +5 -15
  6. package/lib/api/validate.js +1 -0
  7. package/lib/base/builtins.js +1 -2
  8. package/lib/base/csnRefs.js +2 -6
  9. package/lib/base/message-registry.js +82 -76
  10. package/lib/base/messages.js +8 -5
  11. package/lib/base/optionProcessor.js +2 -72
  12. package/lib/base/specialOptions.js +20 -17
  13. package/lib/checks/defaultValues.js +1 -39
  14. package/lib/checks/hasPersistedElements.js +19 -3
  15. package/lib/checks/parameters.js +0 -34
  16. package/lib/checks/selectItems.js +2 -38
  17. package/lib/checks/typeParameters.js +162 -0
  18. package/lib/checks/validator.js +5 -8
  19. package/lib/compiler/assert-consistency.js +19 -5
  20. package/lib/compiler/checks.js +47 -43
  21. package/lib/compiler/define.js +6 -6
  22. package/lib/compiler/extend.js +102 -111
  23. package/lib/compiler/generate.js +4 -8
  24. package/lib/compiler/populate.js +4 -7
  25. package/lib/compiler/propagator.js +9 -9
  26. package/lib/compiler/resolve.js +205 -7
  27. package/lib/compiler/shared.js +76 -82
  28. package/lib/compiler/tweak-assocs.js +102 -22
  29. package/lib/compiler/utils.js +57 -12
  30. package/lib/compiler/xpr-rewrite.js +2 -15
  31. package/lib/edm/annotations/edmJson.js +14 -10
  32. package/lib/edm/annotations/genericTranslation.js +3 -1
  33. package/lib/edm/annotations/preprocessAnnotations.js +9 -26
  34. package/lib/edm/csn2edm.js +27 -20
  35. package/lib/edm/edmUtils.js +25 -0
  36. package/lib/gen/CdlGrammar.checksum +1 -1
  37. package/lib/gen/CdlParser.js +2237 -2241
  38. package/lib/gen/Dictionary.json +17 -2
  39. package/lib/json/from-csn.js +67 -52
  40. package/lib/json/to-csn.js +28 -25
  41. package/lib/language/textUtils.js +0 -13
  42. package/lib/main.d.ts +22 -59
  43. package/lib/main.js +1 -1
  44. package/lib/model/csnUtils.js +9 -8
  45. package/lib/parsers/AstBuildingParser.js +45 -55
  46. package/lib/parsers/Lexer.js +2 -0
  47. package/lib/parsers/identifiers.js +0 -9
  48. package/lib/render/toCdl.js +41 -40
  49. package/lib/render/toSql.js +8 -1
  50. package/lib/render/utils/common.js +1 -1
  51. package/lib/render/utils/sql.js +2 -3
  52. package/lib/tool-lib/enrichCsn.js +1 -2
  53. package/lib/transform/db/applyTransformations.js +7 -5
  54. package/lib/transform/db/assertUnique.js +8 -51
  55. package/lib/transform/db/associations.js +1 -1
  56. package/lib/transform/db/cdsPersistence.js +1 -15
  57. package/lib/transform/db/expansion.js +9 -12
  58. package/lib/transform/db/flattening.js +1 -1
  59. package/lib/transform/db/groupByOrderBy.js +0 -16
  60. package/lib/transform/db/views.js +57 -161
  61. package/lib/transform/draft/db.js +2 -2
  62. package/lib/transform/forOdata.js +25 -14
  63. package/lib/transform/forRelationalDB.js +93 -301
  64. package/lib/transform/localized.js +33 -102
  65. package/lib/transform/odata/flattening.js +11 -2
  66. package/lib/transform/transformUtils.js +25 -3
  67. package/lib/transform/universalCsn/universalCsnEnricher.js +1 -2
  68. package/package.json +2 -2
  69. package/lib/render/toHdbcds.js +0 -1810
package/lib/api/main.js CHANGED
@@ -24,7 +24,6 @@ const timetrace = lazyload('../utils/timetrace');
24
24
  const forRelationalDB = lazyload('../transform/forRelationalDB');
25
25
  const sqlUtils = lazyload('../render/utils/sql');
26
26
  const effective = lazyload('../transform/effective/main');
27
- const toHdbcds = lazyload('../render/toHdbcds');
28
27
  const baseError = lazyload('../base/error');
29
28
  const csnToEdm = lazyload('../edm/csn2edm');
30
29
  const trace = lazyload('../base/trace');
@@ -251,24 +250,6 @@ function forHdi( csn, options, messageFunctions ) {
251
250
  );
252
251
  return cloneCsn.sortCsnForTests(transformedCsn, internalOptions);
253
252
  }
254
- /**
255
- * Transform a CSN like to.hdbcds
256
- *
257
- * @param {CSN.Model} csn Plain input CSN
258
- * @param {HdbcdsOptions} options Options
259
- * @param {object} messageFunctions Message functions such as `error()`, `info()`, …
260
- * @returns {CSN.Model} CSN transformed like to.hdbcds
261
- * @private
262
- */
263
- function forHdbcds( csn, options, messageFunctions ) {
264
- const internalOptions = prepareOptions.to.hdbcds(options);
265
- internalOptions.transformation = 'hdbcds';
266
- messageFunctions.setOptions( internalOptions );
267
- const hanaCsn = forRelationalDB.transformForRelationalDBWithCsn(
268
- csn, internalOptions, messageFunctions
269
- );
270
- return cloneCsn.sortCsnForTests(hanaCsn, internalOptions);
271
- }
272
253
 
273
254
  /**
274
255
  * Effective CSN transformation
@@ -769,37 +750,11 @@ hdi.migration = hdiMigration;
769
750
 
770
751
  sql.migration = sqlMigration;
771
752
 
772
- /**
773
- * Process the given CSN into HDBCDS artifacts.
774
- *
775
- * @param {any} csn A clean input CSN
776
- * @param {HdbcdsOptions} options Options
777
- * @param {object} messageFunctions Message functions such as `error()`, `info()`, …
778
- * @returns {HDBCDS} { <filename>:<content>, ...}
779
- */
780
- function hdbcds( csn, options, messageFunctions ) {
781
- const internalOptions = prepareOptions.to.hdbcds(options);
782
- internalOptions.transformation = 'hdbcds';
783
- messageFunctions.setOptions( internalOptions );
784
-
785
- // Since v5, the HDBCDS backend is considered deprecated.
786
- // Since v6, it is a configurable error.
787
- messageFunctions.message('api-deprecated-hdbcds', null, null);
788
-
789
- if (options.tenantDiscriminator) {
790
- messageFunctions.error('api-invalid-option', null, {
791
- '#': 'forbidden',
792
- option: 'tenantDiscriminator',
793
- module: 'to.hdbcds',
794
- });
795
- messageFunctions.throwWithAnyError();
796
- }
797
-
798
- const hanaCsn = forHdbcds(csn, internalOptions, messageFunctions);
799
- messageFunctions.setModel(hanaCsn);
800
- const result = toHdbcds.toHdbcdsSource(hanaCsn, internalOptions, messageFunctions);
801
- return flattenResultStructure(result);
753
+ function hdbcds( _csn, _options, messageFunctions ) {
754
+ messageFunctions.error('api-deprecated-hdbcds', null, null);
755
+ messageFunctions.throwWithAnyError();
802
756
  }
757
+
803
758
  /**
804
759
  * Generate an edm document for the given service
805
760
  *
@@ -1138,7 +1093,6 @@ module.exports = {
1138
1093
  /** Internal only */
1139
1094
  for_sql: publishCsnProcessor(forSql, 'for.sql'),
1140
1095
  for_hdi: publishCsnProcessor(forHdi, 'for.hdi'),
1141
- for_hdbcds: publishCsnProcessor(forHdbcds, 'for.hdbcds'),
1142
1096
  for_effective: publishCsnProcessor(forEffective, 'for.effective'),
1143
1097
  for_seal: publishCsnProcessor(forSeal, 'for.seal'),
1144
1098
  };
@@ -1408,12 +1362,6 @@ function handleTenantDiscriminator( options, internalOptions, messageFunctions )
1408
1362
  * @typedef {object} CDL
1409
1363
  */
1410
1364
 
1411
- /**
1412
- * A map of { <file.hdbcds|hdbconstraint>:<content> }.
1413
- *
1414
- * @typedef {object} HDBCDS
1415
- */
1416
-
1417
1365
  /**
1418
1366
  * A map of { <file.hdbtable|hdbview|hdbprojectionview|hdbconstraint...>:<content> }.
1419
1367
  *
@@ -27,7 +27,7 @@ const publicOptionsNewAPI = [
27
27
  'defaultStringLength',
28
28
  'csnFlavor',
29
29
  'noDollarCalc',
30
- 'v7KeyPropagation',
30
+ 'v6KeyPropagation',
31
31
  // DB
32
32
  'sqlDialect',
33
33
  'sqlMapping',
@@ -38,8 +38,7 @@ const publicOptionsNewAPI = [
38
38
  'variableReplacements',
39
39
  'pre2134ReferentialConstraintNames',
40
40
  'betterSqliteSessionVariables',
41
- 'fewerLocalizedViews',
42
- 'sqliteRealAffinityForDecimal',
41
+ 'decimal_affinity',
43
42
  'withHanaAssociations',
44
43
  'standardDatabaseFunctions',
45
44
  'booleanEquality',
@@ -98,6 +97,7 @@ const privateOptions = [
98
97
  'disableHanaComments', // in case of issues with hana comment rendering
99
98
  'tenantDiscriminator', // not published yet
100
99
  'localizedWithoutCoalesce', // deprecated version of 'localizedLanguageFallback', TODO(v7): Remove option
100
+ 'sqliteRealAffinityForDecimal', // deprecated in favor of decimal_affinity, TODO(v7): Remove option
101
101
  ];
102
102
 
103
103
  const overallOptions = publicOptionsNewAPI.concat(privateOptions);
@@ -189,8 +189,9 @@ module.exports = {
189
189
  withHanaAssociations: false,
190
190
  booleanEquality: true,
191
191
  dollarNowAsTimestamp: false,
192
+ decimal_affinity: 'real',
192
193
  };
193
- const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ], 'to.sql');
194
+ const processed = translateOptions(options, defaultOptions, hardOptions, {}, [ 'sql-dialect-and-naming' ], 'to.sql');
194
195
 
195
196
  return Object.assign({}, processed);
196
197
  },
@@ -206,17 +207,6 @@ module.exports = {
206
207
  };
207
208
  return translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
208
209
  },
209
- hdbcds: (options) => {
210
- const hardOptions = { forHana: true };
211
- // TODO: sqlDialect should be a hard option!
212
- const defaultOptions = {
213
- sqlMapping: 'plain',
214
- sqlDialect: 'hana',
215
- booleanEquality: false,
216
- dollarNowAsTimestamp: true, // Keep v5 behavior; backend is deprecated
217
- };
218
- return translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdbcds');
219
- },
220
210
  edm: (options) => {
221
211
  const hardOptions = { json: true, combined: true, toOdata: true };
222
212
  const defaultOptions = { odataVersion: 'v4', odataFormat: 'flat' };
@@ -146,6 +146,7 @@ const validators = {
146
146
  },
147
147
  assertIntegrityType: generateStringValidator([ 'DB', 'RT' ]),
148
148
  tenantDiscriminator: { validate: () => true }, // do it ourselves
149
+ decimal_affinity: generateStringValidator([ 'numeric', 'real' ]),
149
150
  };
150
151
 
151
152
  // Note: if `validate()` returns true, it means the option is _invalid_!
@@ -107,8 +107,7 @@ const exprProperties = [
107
107
  * Return whether JSON object `val` is a representation for an annotation expression
108
108
  */
109
109
  function isAnnotationExpression( val ) {
110
- return val?.['='] !== undefined && // TODO: truthy
111
- primaryExprProperties.some( prop => val[prop] !== undefined );
110
+ return val && primaryExprProperties.some( prop => val[prop] !== undefined );
112
111
  }
113
112
 
114
113
  module.exports = {
@@ -617,13 +617,9 @@ function csnRefs( csn, universalReady ) {
617
617
  if (art.type) { // TODO: make robust against "linked" = only direct
618
618
  if (art.type !== '$self')
619
619
  return artifactRef( art.type, BUILTIN_TYPE );
620
+ // binding parameter is typed with `$self` or `many $self`:
620
621
  const action = boundActionOrMain( art );
621
- const binding = action?.params && Object.values( action.params )[0];
622
- // binding parameter must be typed with `$self` or `many $self`:
623
- const entity = binding && (art === binding || art === binding.items) &&
624
- getCache( action, '_parent' );
625
- // if name-deprecated-$self is a non-config error, this could be simplified to:
626
- // const entity = action?.params && getCache( action, '_parent' );
622
+ const entity = action?.params && getCache( action, '_parent' );
627
623
  return entity || artifactRef( art.type, BUILTIN_TYPE );
628
624
  }
629
625
  if (typeof art.$origin === 'object') // null, […], {…}
@@ -38,24 +38,26 @@
38
38
  const { CompilerAssertion } = require( './error' );
39
39
  const { isDeprecatedEnabled } = require( './specialOptions' );
40
40
 
41
- const configurableForValidValues = {
41
+ const configurableForValidValues = { // for configurableFor: …
42
42
  __proto__: null,
43
43
  // can always be downgraded, we do not really care:
44
44
  true: () => true,
45
- // like `true`, but is intended to be removed or made 'deprecated' with v7:
46
- v7: () => true,
45
+ // like `true`, but is intended to be removed or made 'deprecated' with v8:
46
+ before_v8: () => true,
47
47
  // only configurable if option deprecated.downgradableErrors is set:
48
48
  deprecated: options => isDeprecatedEnabled( options, 'downgradableErrors' ),
49
+ // only with option deprecated.downgradableErrors, intended to be removed with v8:
50
+ deprecated_before_v8: options => isDeprecatedEnabled( options, 'downgradableErrors' ),
49
51
  // still allow to produce output in tests:
50
52
  test: options => options.testMode != null,
51
53
  };
52
54
 
53
- const validModules = [ // for configurableFor and errorFor
54
- 'v7', // pseudo module in errorFor: planned as error
55
+ const validModules = [ // for errorFor:
56
+ 'v8', // pseudo module in errorFor: planned as error
57
+ // ./messages.js test for 'v8' to write `Warning‹↑›…` into test3/**/*.err
55
58
  'compile',
56
59
  'for.odata',
57
60
  'to.edmx',
58
- 'to.hdbcds',
59
61
  'to.hdi',
60
62
  'to.sql',
61
63
  'to.sql.migration',
@@ -77,7 +79,7 @@ const validModules = [ // for configurableFor and errorFor
77
79
  * @type {Object<string, MessageConfig>}
78
80
  */
79
81
  const centralMessages = {
80
- 'api-deprecated-hdbcds': { severity: 'Error', configurableFor: true },
82
+ 'api-deprecated-hdbcds': { severity: 'Error' },
81
83
  'anno-definition': { severity: 'Warning' },
82
84
  'anno-duplicate': { severity: 'Error', configurableFor: true }, // does not hurt us
83
85
  'anno-duplicate-unrelated-layer': { severity: 'Error', configurableFor: true }, // does not hurt us
@@ -89,11 +91,9 @@ const centralMessages = {
89
91
  'anno-invalid-sql-kind': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
90
92
  'anno-invalid-sql-view': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
91
93
  'anno-invalid-sql-view-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
92
- 'ext-duplicate-include': { severity: 'Warning', errorFor: [ 'v7' ] },
94
+ 'ext-duplicate-include': { severity: 'Error', configurableFor: 'deprecated_before_v8' },
93
95
  'ext-undefined-action': { severity: 'Warning' },
94
- 'ext-undefined-art': { severity: 'Warning' }, // for annotate statement (for CDL path root)
95
- 'ext-undefined-def': { severity: 'Warning' }, // for annotate statement (for CSN or CDL path cont)
96
- 'ext-undefined-art-sec': { severity: 'Error', configurableFor: true }, // for security-relevant…
96
+ 'ext-undefined-def': { severity: 'Warning' }, // for annotate statement
97
97
  'ext-undefined-def-sec': { severity: 'Error', configurableFor: true }, // … annotate statement
98
98
  'ext-undefined-element': { severity: 'Warning' },
99
99
  'ext-undefined-key': { severity: 'Warning' },
@@ -101,23 +101,21 @@ const centralMessages = {
101
101
  'ext-undefined-element-sec': { severity: 'Error', configurableFor: true }, // for security-relevant…
102
102
  'ext-undefined-action-sec': { severity: 'Error', configurableFor: true }, // for security-relevant…
103
103
  'ext-undefined-param-sec': { severity: 'Error', configurableFor: true }, // … annotate statement
104
- 'ext-unexpected-type-property': { severity: 'Warning', errorFor: [ 'v7' ] },
104
+ 'ext-unexpected-type-property': { severity: 'Error', configurableFor: 'before_v8' },
105
105
  'ext-unexpected-returns': { severity: 'Warning' },
106
106
  'ext-unexpected-returns-sec': { severity: 'Error', configurableFor: true }, // … annotate statement
107
- 'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' },
107
+ 'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' }, // or ok?
108
108
  'anno-unexpected-localized-skip': { severity: 'Error', configurableFor: true },
109
109
 
110
110
  'name-invalid-dollar-alias': { severity: 'Error', configurableFor: true },
111
- 'name-deprecated-$self': { severity: 'Error', configurableFor: true },
111
+ 'name-deprecated-$self': { severity: 'Error' },
112
112
 
113
113
  'type-invalid-items': { severity: 'Error' }, // not supported yet
114
114
  'assoc-as-type': { severity: 'Error' }, // TODO: allow more, but not all
115
115
  'def-unexpected-nested-proj': { severity: 'Error' },
116
- 'def-unexpected-paramview-assoc': { severity: 'Error' },
117
- 'def-unexpected-calcview-assoc': { severity: 'Error' },
118
116
  'def-missing-type': { severity: 'Error', configurableFor: [ 'compile' ] },
119
117
  'def-missing-argument': { severity: 'Error' },
120
- 'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.hdbcds', 'to.sql', 'to.hdi', 'to.rename', 'for.effective' ] },
118
+ 'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.sql', 'to.hdi', 'to.rename', 'for.effective' ] },
121
119
 
122
120
  'def-duplicate-autoexposed': { severity: 'Error' },
123
121
  'def-unexpected-default': { severity: 'Error', configurableFor: 'test' },
@@ -127,15 +125,18 @@ const centralMessages = {
127
125
  'empty-type': { severity: 'Info' }, // only still an error in old transformers
128
126
 
129
127
  'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
130
- 'ref-deprecated-self-element': { severity: 'Error', configurableFor: 'v7' },
128
+ 'ref-deprecated-self-element': { severity: 'Error', configurableFor: 'before_v8' },
131
129
  'ref-deprecated-variable': { severity: 'Warning' },
132
130
  'ref-deprecated-in-extend': { severity: 'Warning' },
133
131
  'ref-special-in-extend': { severity: 'Warning' },
134
132
  'ref-unexpected-in-extend': { severity: 'Error' },
135
133
  'ref-invalid-type': { severity: 'Error' },
136
134
  'ref-unexpected-self': { severity: 'Error' },
135
+ 'ref-duplicate-self-comparison': { severity: 'Error', configurableFor: 'before_v8' },
137
136
  'ref-invalid-include': { severity: 'Error' },
138
137
  'type-unexpected-typeof': { severity: 'Error' },
138
+ 'type-unexpected-default-struct': { severity: 'Error', configurableFor: true },
139
+ 'type-unexpected-default-array': { severity: 'Error', configurableFor: true },
139
140
  'type-unexpected-null': { severity: 'Error', configurableFor: true },
140
141
  'type-ignoring-argument': { severity: 'Error', configurableFor: true },
141
142
  'type-expected-builtin': { severity: 'Error', configurableFor: true },
@@ -145,8 +146,9 @@ const centralMessages = {
145
146
  'ref-expecting-foreign-key': { severity: 'Error' },
146
147
  'ref-invalid-source': { severity: 'Error' },
147
148
  'ref-invalid-target': { severity: 'Error' },
149
+ 'ref-invalid-backlink': { severity: 'Error', configurableFor: 'before_v8' },
148
150
  'ref-missing-self-counterpart': { severity: 'Error', configurableFor: true },
149
- 'ref-sloppy-target': { severity: 'Error', configurableFor: 'deprecated' },
151
+ 'ref-sloppy-target': { severity: 'Error', configurableFor: 'deprecated_before_v8' },
150
152
 
151
153
  'extend-repeated-intralayer': { severity: 'Warning' },
152
154
  'extend-unrelated-layer': { severity: 'Info' },
@@ -156,8 +158,6 @@ const centralMessages = {
156
158
 
157
159
  'param-default': { severity: 'Error' }, // not supported yet
158
160
 
159
- 'query-unexpected-assoc-hdbcds': { severity: 'Error' },
160
- 'query-unexpected-structure-hdbcds': { severity: 'Error' },
161
161
  'query-ignoring-param-nullability': { severity: 'Info' },
162
162
  'query-expected-identifier': { severity: 'Error' },
163
163
  'query-invalid-identifier': { severity: 'Warning' },
@@ -170,7 +170,6 @@ const centralMessages = {
170
170
  'ref-unexpected-many-expand': { severity: 'Error' },
171
171
  'ref-unexpected-many-navigation': { severity: 'Error' },
172
172
  // Published! Used in @sap/cds-lsp; if renamed, add to oldMessageIds and contact colleagues
173
- 'ref-undefined-art': { severity: 'Error' },
174
173
  'ref-undefined-def': { severity: 'Error' },
175
174
  'ref-undefined-using': { severity: 'Warning' },
176
175
  'ref-undefined-var': { severity: 'Error' },
@@ -178,10 +177,10 @@ const centralMessages = {
178
177
  'anno-undefined-element': { severity: 'Error' },
179
178
  'ref-unknown-var': { severity: 'Info' },
180
179
  'ref-obsolete-parameters': { severity: 'Error', configurableFor: 'deprecated' },
181
- // does not hurt us, but makes it tedious to detect parameter refs
180
+ // does not hurt us, but makes it tedious to detect parameter refs (unchecked by csn-refs)
182
181
  'ref-undefined-param': { severity: 'Error' },
183
- 'ref-undefined-enum': { severity: 'Warning', errorFor: [ 'to.sql', 'to.hdbcds', 'to.hdi' ] },
184
- 'ref-unexpected-enum': { severity: 'Warning', errorFor: [ 'to.sql', 'to.hdbcds', 'to.hdi' ] },
182
+ 'ref-undefined-enum': { severity: 'Warning', errorFor: [ 'to.sql', 'to.hdi' ] },
183
+ 'ref-unexpected-enum': { severity: 'Warning', errorFor: [ 'v8', 'to.sql', 'to.hdi' ] },
185
184
  'anno-undefined-param': { severity: 'Error' },
186
185
  'ref-rejected-on': { severity: 'Error' },
187
186
  'ref-expected-element': { severity: 'Error' },
@@ -197,8 +196,8 @@ const centralMessages = {
197
196
  'expr-unexpected-operator': { severity: 'Error' },
198
197
 
199
198
  // Published! Used in @sap/cds-lsp; if renamed, add to oldMessageIds and contact colleagues
200
- // Also used by other projects that rely on double-quotes for delimited identifiers.
201
- 'syntax-deprecated-ident': { severity: 'Error', configurableFor: true },
199
+ // Also used by other projects that rely on double-quotes for delimited identifiers:
200
+ 'syntax-deprecated-ident': { severity: 'Error', configurableFor: true }, // ok for us
202
201
  'syntax-deprecated-property': { severity: 'Error', configurableFor: 'test' }, // v0 prop
203
202
  'syntax-deprecated-value': { severity: 'Error', configurableFor: 'test' }, // v0 prop
204
203
  // 'syntax-duplicate-annotate' came late with v3 - make it configurable as
@@ -209,24 +208,23 @@ const centralMessages = {
209
208
  // remark: a hard syntax error in new parser for `null` together with `not null`
210
209
  'syntax-duplicate-equal-clause': { severity: 'Warning' },
211
210
  'syntax-invalid-name': { severity: 'Error' },
212
- 'syntax-invalid-anno-struct': { severity: 'Warning', errorFor: [ 'v7' ] },
213
- 'syntax-invalid-nested-proj': { severity: 'Warning', errorFor: [ 'v7' ] },
214
- 'syntax-missing-as': { severity: 'Error', configurableFor: true },
211
+ 'syntax-invalid-anno-struct': { severity: 'Error' }, // not configurable with v7
212
+ 'syntax-invalid-nested-proj': { severity: 'Warning', errorFor: [ 'v8' ] },
213
+ 'syntax-missing-as': { severity: 'Error', configurableFor: true }, // ok for us
215
214
  'syntax-missing-proj-semicolon': { severity: 'Warning' },
216
215
  'syntax-unexpected-after': { severity: 'Error' },
217
- 'syntax-unexpected-filter': { severity: 'Error', configurableFor: 'v7' },
216
+ 'syntax-unexpected-filter': { severity: 'Error' }, // TODO v8 - via grammar
218
217
  'syntax-unexpected-many-one': { severity: 'Error' },
219
218
  'syntax-deprecated-ref-virtual': { severity: 'Error' },
220
- 'syntax-unexpected-reserved-word': { severity: 'Error', configurableFor: true },
221
- 'syntax-unexpected-with-returns': { severity: 'Warning' }, // errorFor: [ 'v8' ] }, or v7?
222
- 'syntax-unknown-escape': { severity: 'Error', configurableFor: true },
223
- 'syntax-unsupported-masked': { severity: 'Error', configurableFor: 'deprecated' },
219
+ 'syntax-unexpected-reserved-word': { severity: 'Error', configurableFor: true }, // ok for us
220
+ 'syntax-unexpected-with-returns': { severity: 'Warning', errorFor: [ 'v8' ] },
221
+ 'syntax-unknown-escape': { severity: 'Error', configurableFor: true }, // ok for us
224
222
  'syntax-unexpected-sql-clause': { severity: 'Error' }, // TODO: configurableFor:'tests'?
225
- 'syntax-invalid-space': { severity: 'Error', configurableFor: true },
223
+ 'syntax-invalid-space': { severity: 'Error', configurableFor: true }, // TODO: no error
226
224
  'syntax-expecting-space': { severity: 'Error' },
227
225
  'syntax-unexpected-anno': { severity: 'Error' },
228
226
  'migration-unsupported-key-change': { severity: 'Error', configurableFor: [ 'to.sql.migration', 'to.sql.migration-script' ] },
229
- 'type-missing-enum-value': { severity: 'Error', configurableFor: 'deprecated' },
227
+ 'type-missing-enum-value': { severity: 'Error', configurableFor: 'deprecated_before_v8' },
230
228
 
231
229
  'def-missing-element': { severity: 'Error' },
232
230
  'def-missing-virtual': { severity: 'Error', configurableFor: true },
@@ -239,6 +237,7 @@ const centralMessages = {
239
237
  'odata-unexpected-assoc': { severity: 'Warning' },
240
238
  'odata-incomplete-constraints': { severity: 'Info' },
241
239
  'odata-invalid-name': { severity: 'Error', configurableFor: true },
240
+ 'odata-invalid-name-v2': { severity: 'Warning' },
242
241
  'odata-invalid-vocabulary-alias': { severity: 'Error', configurableFor: true },
243
242
  'odata-invalid-qualifier': { severity: 'Error', configurableFor: true },
244
243
  'odata-invalid-service-name': { severity: 'Warning' },
@@ -330,7 +329,8 @@ for (const oldName in oldMessageIds) {
330
329
  // If you change it, keep in sync with scripts/eslint/rules/message-text.js
331
330
 
332
331
  const centralMessageTexts = {
333
- 'api-deprecated-hdbcds': 'Support for generating hdbcds output is deprecated with @sap/cds-compiler v5 and later',
332
+ 'api-invalid-deprecated': 'Deprecated flag $(NAME) has been removed in CDS compiler $(COMPILER)',
333
+ 'api-deprecated-hdbcds': 'to.hdbcds() has been removed; use to.hdi() instead — see https://cap.cloud.sap/docs/cds/compiler/hdbcds-to-hdbtable',
334
334
  'api-invalid-option': {
335
335
  std: 'Invalid option $(NAME)!',
336
336
  deprecated: 'Option $(NAME) is no longer supported! Use latest API options instead',
@@ -433,7 +433,6 @@ const centralMessageTexts = {
433
433
  'name-missing-alias': {
434
434
  std: 'Missing table alias for this subquery',
435
435
  duplicate: 'Missing table alias for this subquery; add $(CODE) to fix name clash of internal and explicit table alias',
436
- hdbcds: 'Missing table alias for a subquery; SAP HANA CDS requires table aliases',
437
436
  },
438
437
 
439
438
  // Syntax messages, both CDL and CSN parser: ----------------------------------
@@ -504,12 +503,15 @@ const centralMessageTexts = {
504
503
  'syntax-invalid-anno': {
505
504
  std: 'Unexpected $(OFFENDING), invalid annotation value, expecting $(EXPECTING)',
506
505
  empty: 'Unexpected $(OFFENDING), empty structure flattens to nothing, expecting $(EXPECTING)',
506
+ // empty could be part of syntax-invalid-struct
507
+ // rename "rest" to syntax-invalid-ellipsis
507
508
  ellipsis: 'Unexpected $(OFFENDING) in inner array value, expecting $(EXPECTING)',
508
509
  bracket: 'Missing array item $(CODE) before $(OFFENDING), expecting $(EXPECTING)',
509
510
  },
510
- 'syntax-unsupported-masked': { // configurable Error
511
- std: 'The keyword $(KEYWORD) is not supported',
512
- csn: 'The property $(PROP) is not supported',
511
+ 'syntax-invalid-special': { // -> invalid-array
512
+ std: 'Invalid value in property $(PROP)',
513
+ long: 'Too many array items in property $(PROP)',
514
+ sum: 'Sum of numbers in property $(PROP) exceeds number of elements',
513
515
  },
514
516
 
515
517
  // Syntax messages, CDL parser -----------------------------------------------
@@ -545,7 +547,7 @@ const centralMessageTexts = {
545
547
  },
546
548
  'syntax-invalid-anno-struct': {
547
549
  std: 'Most CSN processors interpret a structure with property $(PROP) as expression',
548
- ref: 'Most CSN processors interpret a structure with property $(PROP) as reference',
550
+ ref: 'The value of property $(PROP) must be a non-empty string, which most CSN processors interpret as reference',
549
551
  },
550
552
  // 'syntax-ignoring-doc-comment' (Info)
551
553
  'syntax-unexpected-reserved-word': '$(CODE) is a reserved word - write $(DELIMITED) instead if you want to use it as name',
@@ -609,7 +611,7 @@ const centralMessageTexts = {
609
611
  'syntax-expecting-string': {
610
612
  std: 'Expecting non-empty string for property $(PROP)',
611
613
  'or-object': 'Expecting non-empty string or object for property $(PROP)',
612
- 'or-bool': 'Expecting non-empty string or boolean for property $(PROP)',
614
+ 'or-true': 'Expecting non-empty string or true for property $(PROP)',
613
615
  'or-null': 'Expecting non-empty string or null for property $(PROP)',
614
616
  },
615
617
  // 'syntax-expecting-boolean' (Warning), 'syntax-expecting-scalar',
@@ -675,7 +677,6 @@ const centralMessageTexts = {
675
677
  std: 'Calculated elements are not supported, yet',
676
678
  nested: 'Calculated elements in structures are not supported, yet',
677
679
  'on-write': 'Calculated elements on-write are not supported, yet',
678
- hdbcds: 'Calculated elements on-write are not supported for HDBCDS',
679
680
  },
680
681
  // 'syntax-unknown-property' (Warning? Better configurable Error)
681
682
 
@@ -749,7 +750,8 @@ const centralMessageTexts = {
749
750
  },
750
751
  'ref-undefined-def': {
751
752
  std: 'Artifact $(ART) has not been found',
752
- // TODO: proposal 'No definition of $(NAME) found',
753
+ using: 'Artifact $(ART) can\'t be referred to without a $(KEYWORD) declaration',
754
+ localized: 'Artifact $(ART) has not been found, or it might be a localization view which can\'t be extended',
753
755
  hint: 'Artifact $(ART) has not been found. Did you mean to write $(CODE)?',
754
756
  element: 'Artifact $(ART) has no element $(MEMBER)',
755
757
  },
@@ -759,12 +761,7 @@ const centralMessageTexts = {
759
761
  entity: 'Entity $(ART) has no parameter $(ID)',
760
762
  action: 'Action $(ART) has no parameter $(ID)',
761
763
  },
762
- 'ref-undefined-art': {
763
- std: 'No artifact has been found with name $(ART)',
764
- localized: 'Can\'t extend localized definitions, only annotate them using an $(KEYWORD) statement',
765
- },
766
764
  'ref-undefined-using': 'There is no definition in the model whose name starts with $(ART)',
767
- // TODO: proposal 'No definition found for $(NAME)',
768
765
  'ref-undefined-element': {
769
766
  std: 'Element $(ART) has not been found',
770
767
  element: 'Artifact $(ART) has no element $(MEMBER)',
@@ -895,7 +892,6 @@ const centralMessageTexts = {
895
892
  std: 'Type $(TYPE) is not supported',
896
893
  dialect: 'Type $(TYPE) is not supported for SQL dialect $(VALUE)',
897
894
  hana: 'Type $(TYPE) is only supported for SQL dialect $(VALUE), not $(OTHERVALUE)',
898
- hdbcds:'Type $(TYPE) is not supported in HDBCDS',
899
895
  odata: 'Type $(TYPE) is not supported for OData $(VERSION)',
900
896
  key: 'Type $(TYPE) can\'t be used as primary key in element $(NAME)',
901
897
  },
@@ -918,8 +914,10 @@ const centralMessageTexts = {
918
914
  std: 'Rewriting the ON-condition not supported here', // unused: merge with 'rewrite-not-supported'
919
915
  'sub-element': 'Rewriting the ON-condition of unmanaged association in sub element is not supported',
920
916
  },
921
- 'rewrite-undefined-key': 'Can\'t redirect association $(NAME), as redirection target $(TARGET) does not project element $(ID), which is required to match foreign key of $(NAME)',
922
-
917
+ 'rewrite-undefined-key': {
918
+ std: 'Can\'t redirect association $(NAME), as redirection target $(TARGET) does not project element $(ID), which is required to match foreign key of $(NAME)',
919
+ backlink: 'Can\'t project association, as the current entity does not project element $(ID), which is required to match foreign key of the backlink association',
920
+ },
923
921
  'type-unexpected-typeof': {
924
922
  std: 'Unexpected $(KEYWORD) for the type reference here',
925
923
  type: 'Unexpected $(KEYWORD) for the type of a type definition',
@@ -934,7 +932,6 @@ const centralMessageTexts = {
934
932
  std: 'Missing value for non-string enum element $(NAME)',
935
933
  numeric: 'Missing value for numeric enum element $(NAME)',
936
934
  },
937
- 'type-missing-argument': 'Missing value for argument $(NAME) in reference to type $(ID)',
938
935
  'type-ignoring-argument': 'Too many arguments for type $(ART)',
939
936
  'type-unexpected-argument': {
940
937
  std: 'Too many arguments for type $(ART)', // we use config 'type-ignoring-argument' instead
@@ -983,9 +980,7 @@ const centralMessageTexts = {
983
980
 
984
981
  'anno-builtin': 'Builtin types should not be annotated nor extended. Use custom type instead',
985
982
  'ext-undefined-def': 'Artifact $(ART) has not been found',
986
- 'ext-undefined-art': 'No artifact has been found with name $(ART)',
987
983
  'ext-undefined-def-sec': 'Artifact $(ART) has not been found',
988
- 'ext-undefined-art-sec': 'No artifact has been found with name $(ART)',
989
984
  'ext-undefined-element': {
990
985
  std: 'Element $(NAME) has not been found',
991
986
  enum: 'Enum symbol $(NAME) has not been found',
@@ -1011,6 +1006,18 @@ const centralMessageTexts = {
1011
1006
  'ext-undefined-param-sec': {
1012
1007
  std: 'Parameter $(NAME) has not been found',
1013
1008
  },
1009
+ 'ext-unexpected-returns': {
1010
+ std: 'Unexpected $(KEYWORD); only actions and functions have return parameters',
1011
+ action: 'Unexpected $(KEYWORD) for action without return parameter',
1012
+ // function without `returns` can happen via CSN input! TODO: check in parser
1013
+ function: 'Unexpected $(KEYWORD) for function without return parameter',
1014
+ },
1015
+ 'ext-unexpected-returns-sec': {
1016
+ std: 'Unexpected $(KEYWORD); only actions and functions have return parameters',
1017
+ action: 'Unexpected $(KEYWORD) for action without return parameter',
1018
+ // function without `returns` can happen via CSN input! TODO: check in parser
1019
+ function: 'Unexpected $(KEYWORD) for function without return parameter',
1020
+ },
1014
1021
 
1015
1022
  // annotation checks against their definition
1016
1023
  'anno-expecting-value': {
@@ -1018,22 +1025,12 @@ const centralMessageTexts = {
1018
1025
  type: 'Expecting a value of type $(TYPE) for the annotation',
1019
1026
  },
1020
1027
 
1021
- 'def-unexpected-paramview-assoc': {
1022
- std: 'unused',
1023
- source: 'Unexpected definition of an association in an entity with parameters',
1024
- target: 'Expected association target to have no parameters',
1025
- },
1026
1028
  'def-unexpected-nested-proj': {
1027
1029
  std: 'Unexpected $(CODE)',
1028
1030
  var: 'Unexpected $(CODE) after reference to CDS variable',
1029
1031
  struct: 'Unexpected $(CODE); can only be used after a reference to a structure or association',
1030
1032
  init: 'Unexpected $(CODE); can only be used after a reference to a structure, association or table alias',
1031
1033
  },
1032
- 'def-unexpected-calcview-assoc': {
1033
- std: 'unused',
1034
- source: 'Unexpected definition of an association in an entity annotated with $(ANNO)',
1035
- target: 'Expected association target not to be annotated with $(ANNO)',
1036
- },
1037
1034
  'def-invalid-key': {
1038
1035
  std: 'The current element can\'t be defined as primary key', // (unused)
1039
1036
  unmanaged: 'Unmanaged associations/compositions can\'t be defined as primary key',
@@ -1177,6 +1174,12 @@ const centralMessageTexts = {
1177
1174
  event: 'An event\'s projection source must be an entity, structured type, aspect, event, or an association element',
1178
1175
  type: 'A type\'s projection source must be an entity, structured type, aspect, event, or an association element',
1179
1176
  },
1177
+ 'ref-invalid-backlink': {
1178
+ std: 'The target $(TARGET) of the backlink association is unrelated to the current entity',
1179
+ aspect: 'The target $(TARGET) of the backlink association is unrelated to the current aspect',
1180
+ include: 'The open backlink target $(TARGET) of the aspect is unrelated to the current entity',
1181
+ backlink: 'Can\'t use $(ART) as backlink association, because its ON-condition contains a backlink comparison',
1182
+ },
1180
1183
  'extend-columns': {
1181
1184
  std: 'Artifact $(ART) can\'t be extended with columns, only simple views/projections without JOINs and UNIONs can',
1182
1185
  join: 'Artifact $(ART) can\'t be extended with columns, because it contains a JOIN',
@@ -1234,13 +1237,11 @@ const centralMessageTexts = {
1234
1237
  std: 'Target $(TARGET) of $(NAME) is missing element $(ID); use $(KEYWORD) with an explicit ON-condition',
1235
1238
  redirected: 'Target $(TARGET) of $(NAME) is missing element $(ID); add an ON-condition to $(KEYWORD)',
1236
1239
  },
1237
- 'query-unexpected-assoc-hdbcds': 'Publishing a managed association in a view is not possible for “hdbcds” naming mode', // eslint-disable-line cds-compiler/message-no-quotes
1238
1240
  'query-unexpected-exists': {
1239
1241
  std: 'Unexpected $(PROP) predicate',
1240
1242
  groupBy: 'Unexpected $(PROP) predicate in GROUP BY clause',
1241
1243
  orderBy: 'Unexpected $(PROP) predicate in ORDER BY clause',
1242
1244
  },
1243
- 'query-unexpected-structure-hdbcds': 'Publishing a structured element in a view is not possible for “hdbcds” naming mode', // eslint-disable-line cds-compiler/message-no-quotes
1244
1245
  'query-ignoring-param-nullability': {
1245
1246
  std: 'Ignoring nullability constraint on parameter when generating SAP HANA CDS view',
1246
1247
  sql: 'Ignoring nullability constraint on parameter when generating SQL view',
@@ -1403,10 +1404,8 @@ const centralMessageTexts = {
1403
1404
  'odata-invalid-return-type': 'Expected $(KIND) to return one or many values of scalar, complex, entity or view type for OData $(VERSION)',
1404
1405
  'odata-unexpected-assoc': 'Unexpected association in structured type for OData $(VERSION)',
1405
1406
  'odata-incomplete-constraints': 'Partial referential constraints produced for OData $(VERSION)',
1406
- 'odata-invalid-name': {
1407
- std: 'Expected OData name $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1408
- v2firstChar: 'Unexpected first character $(PROP) of OData name $(ID) for OData $(VERSION)',
1409
- },
1407
+ 'odata-invalid-name': 'Expected OData name $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1408
+ 'odata-invalid-name-v2': 'Expected OData V2 name $(ID) to start with an alphabetic character, followed by a maximum of 479 alphabetic characters, digits, or underscores',
1410
1409
  'odata-invalid-vocabulary-alias': 'Expected value $(VALUE) of OData vocabulary reference attribute $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1411
1410
  'odata-invalid-qualifier': 'Expected OData annotation qualifier $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1412
1411
  // version independent messages
@@ -1458,6 +1457,10 @@ const centralMessageTexts = {
1458
1457
  xpr: 'Ignoring unexpected expression as default value',
1459
1458
  colitem: 'Ignoring unexpected default value for a structured or collection like parameter',
1460
1459
  },
1460
+ 'odata-unexpected-default-struct': 'Default value for structured element $(NAME) is not allowed',
1461
+ 'type-default-ignored-for-struct': {
1462
+ std: 'Ignoring default value for structured element $(NAME) with multiple fields; default values are only supported for single-field structures',
1463
+ },
1461
1464
  'odata-unexpected-xpr-anno': 'Annotation $(ANNO) with expression value is not allowed for kind $(KIND)',
1462
1465
  // -----------------------------------------------------------------------------------
1463
1466
  // All odata-anno MUST have a '$(ANNO)' parameter to indicate error location
@@ -1605,11 +1608,14 @@ const centralMessageTexts = {
1605
1608
  *
1606
1609
  * @typedef {object} MessageConfig
1607
1610
  * @property {MessageSeverity} severity Default severity for the message.
1608
- * @property {string[]|'deprecated'|'v4'|'test'|true} [configurableFor]
1611
+ * @property {string[]|(keyof configurableForValidValues)|true} [configurableFor]
1609
1612
  * Whether the error can be reclassified to a warning or lower.
1610
- * If not `true` then an array is expected with specified modules in which the error is downgradable.
1613
+ * If an array, it contains module names (see validModules) in which the error is downgradable.
1614
+ * If a string, it must be a key of `configurableForValidValues` (e.g. 'deprecated', 'before_v8').
1615
+ * If `true`, always allow downgrade.
1616
+
1617
+
1611
1618
  * Only has an effect if default severity is 'Error'.
1612
- * 'deprecated': severity can only be changed with deprecated.downgradableErrors.
1613
1619
  * @property {string[]} [errorFor] Array of module names where the message shall be reclassified to an error.
1614
1620
  * @property {boolean} [throughMessageCall]
1615
1621
  * If set, it means that a message-id was added to the registry in test-mode through a `message.<severity>()`