@sap/cds-compiler 4.7.6 → 4.9.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 (129) hide show
  1. package/CHANGELOG.md +63 -3
  2. package/bin/cds_remove_invalid_whitespace.js +135 -0
  3. package/bin/cds_update_annotations.js +180 -0
  4. package/bin/cds_update_identifiers.js +3 -4
  5. package/bin/cdsc.js +28 -1
  6. package/bin/cdshi.js +13 -3
  7. package/doc/CHANGELOG_BETA.md +24 -1
  8. package/lib/api/main.js +119 -46
  9. package/lib/api/options.js +51 -0
  10. package/lib/api/validate.js +1 -5
  11. package/lib/base/builtins.js +116 -0
  12. package/lib/base/keywords.js +5 -1
  13. package/lib/base/location.js +91 -14
  14. package/lib/base/message-registry.js +76 -46
  15. package/lib/base/messages.js +121 -35
  16. package/lib/base/model.js +4 -7
  17. package/lib/checks/actionsFunctions.js +3 -3
  18. package/lib/checks/annotationsOData.js +3 -0
  19. package/lib/checks/defaultValues.js +5 -2
  20. package/lib/checks/elements.js +2 -1
  21. package/lib/checks/enricher.js +2 -2
  22. package/lib/checks/queryNoDbArtifacts.js +5 -3
  23. package/lib/checks/utils.js +1 -1
  24. package/lib/checks/validator.js +8 -56
  25. package/lib/compiler/assert-consistency.js +11 -7
  26. package/lib/compiler/builtins.js +0 -74
  27. package/lib/compiler/checks.js +105 -29
  28. package/lib/compiler/define.js +37 -25
  29. package/lib/compiler/extend.js +35 -12
  30. package/lib/compiler/index.js +9 -10
  31. package/lib/compiler/lsp-api.js +5 -0
  32. package/lib/compiler/populate.js +13 -5
  33. package/lib/compiler/propagator.js +24 -18
  34. package/lib/compiler/resolve.js +47 -45
  35. package/lib/compiler/shared.js +61 -21
  36. package/lib/compiler/tweak-assocs.js +15 -90
  37. package/lib/compiler/utils.js +3 -3
  38. package/lib/compiler/xpr-rewrite.js +689 -0
  39. package/lib/compiler/{classes.js → xsn-model.js} +0 -16
  40. package/lib/edm/annotations/edmJson.js +7 -5
  41. package/lib/edm/annotations/genericTranslation.js +149 -71
  42. package/lib/edm/csn2edm.js +25 -9
  43. package/lib/edm/edm.js +7 -7
  44. package/lib/edm/edmInboundChecks.js +57 -5
  45. package/lib/edm/edmPreprocessor.js +54 -25
  46. package/lib/edm/edmUtils.js +3 -16
  47. package/lib/gen/Dictionary.json +138 -14
  48. package/lib/gen/language.checksum +1 -1
  49. package/lib/gen/language.interp +1 -1
  50. package/lib/gen/languageParser.js +2085 -1989
  51. package/lib/json/csnVersion.js +7 -4
  52. package/lib/json/from-csn.js +21 -11
  53. package/lib/json/to-csn.js +8 -4
  54. package/lib/language/antlrParser.js +1 -1
  55. package/lib/language/genericAntlrParser.js +23 -16
  56. package/lib/language/multiLineStringParser.js +2 -2
  57. package/lib/language/textUtils.js +1 -1
  58. package/lib/main.d.ts +90 -14
  59. package/lib/main.js +9 -1
  60. package/lib/model/cloneCsn.js +21 -9
  61. package/lib/model/csnRefs.js +153 -42
  62. package/lib/model/csnUtils.js +14 -11
  63. package/lib/model/enrichCsn.js +4 -2
  64. package/lib/model/revealInternalProperties.js +2 -1
  65. package/lib/model/sortViews.js +14 -6
  66. package/lib/modelCompare/compare.js +135 -122
  67. package/lib/optionProcessor.js +49 -2
  68. package/lib/render/DuplicateChecker.js +6 -6
  69. package/lib/render/manageConstraints.js +1 -0
  70. package/lib/render/toCdl.js +6 -3
  71. package/lib/render/toHdbcds.js +4 -48
  72. package/lib/render/toSql.js +6 -3
  73. package/lib/transform/addTenantFields.js +58 -35
  74. package/lib/transform/db/applyTransformations.js +34 -1
  75. package/lib/transform/db/constraints.js +1 -1
  76. package/lib/transform/db/expansion.js +11 -3
  77. package/lib/transform/db/flattening.js +71 -46
  78. package/lib/transform/db/groupByOrderBy.js +2 -2
  79. package/lib/transform/db/temporal.js +6 -3
  80. package/lib/transform/db/transformExists.js +2 -2
  81. package/lib/transform/db/views.js +1 -4
  82. package/lib/transform/effective/annotations.js +194 -0
  83. package/lib/transform/effective/main.js +11 -10
  84. package/lib/transform/effective/misc.js +45 -14
  85. package/lib/transform/effective/types.js +4 -3
  86. package/lib/transform/forOdata.js +29 -12
  87. package/lib/transform/forRelationalDB.js +104 -113
  88. package/lib/transform/localized.js +7 -6
  89. package/lib/transform/odata/flattening.js +228 -107
  90. package/lib/transform/odata/toFinalBaseType.js +10 -26
  91. package/lib/transform/odata/typesExposure.js +41 -25
  92. package/lib/transform/parseExpr.js +4 -7
  93. package/lib/transform/transformUtils.js +50 -43
  94. package/lib/transform/translateAssocsToJoins.js +48 -48
  95. package/lib/transform/universalCsn/coreComputed.js +2 -1
  96. package/lib/transform/universalCsn/universalCsnEnricher.js +12 -16
  97. package/package.json +2 -2
  98. package/share/messages/README.md +4 -0
  99. package/share/messages/anno-duplicate-unrelated-layer.md +1 -1
  100. package/share/messages/anno-missing-rewrite.md +45 -0
  101. package/share/messages/check-proper-type-of.md +1 -1
  102. package/share/messages/def-duplicate-autoexposed.md +1 -1
  103. package/share/messages/extend-repeated-intralayer.md +3 -16
  104. package/share/messages/extend-unrelated-layer.md +1 -1
  105. package/share/messages/message-explanations.json +2 -0
  106. package/share/messages/redirected-to-ambiguous.md +1 -1
  107. package/share/messages/redirected-to-complex.md +1 -1
  108. package/share/messages/redirected-to-unrelated.md +1 -1
  109. package/share/messages/rewrite-not-supported.md +1 -1
  110. package/share/messages/syntax-expecting-unsigned-int.md +2 -2
  111. package/share/messages/type-missing-enum-value.md +59 -0
  112. package/share/messages/wildcard-excluding-one.md +1 -1
  113. package/bin/.eslintrc.json +0 -17
  114. package/lib/api/.eslintrc.json +0 -37
  115. package/lib/checks/.eslintrc.json +0 -31
  116. package/lib/compiler/.eslintrc.json +0 -8
  117. package/lib/edm/.eslintrc.json +0 -46
  118. package/lib/inspect/.eslintrc.json +0 -4
  119. package/lib/json/.eslintrc.json +0 -4
  120. package/lib/language/.eslintrc.json +0 -4
  121. package/lib/model/.eslintrc.json +0 -13
  122. package/lib/modelCompare/utils/.eslintrc.json +0 -22
  123. package/lib/render/.eslintrc.json +0 -22
  124. package/lib/transform/.eslintrc.json +0 -13
  125. package/lib/transform/db/.eslintrc.json +0 -41
  126. package/lib/transform/draft/.eslintrc.json +0 -4
  127. package/lib/transform/effective/.eslintrc.json +0 -4
  128. package/lib/transform/universalCsn/.eslintrc.json +0 -37
  129. package/lib/utils/.eslintrc.json +0 -7
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ // Model agnostic builtins.
4
+ // It should not contain any specific to XSN, i.e. neither XSN structures
5
+ // nor any other XSN properties.
6
+
7
+ /**
8
+ * Map of propagation rules for annotations.
9
+ * Does not include rules for standard propagation of annotations or other properties.
10
+ *
11
+ * @type {Record<string, string>}
12
+ */
13
+ const propagationRules = {
14
+ __proto__: null,
15
+ '@Analytics.hidden': 'never',
16
+ '@Analytics.visible': 'never',
17
+ '@cds.autoexpose': 'onlyViaArtifact',
18
+ '@cds.autoexposed': 'never',
19
+ '@cds.external': 'never',
20
+ '@cds.persistence.calcview': 'never',
21
+ '@cds.persistence.exists': 'never',
22
+ '@cds.persistence.skip': 'notWithPersistenceTable',
23
+ '@cds.persistence.table': 'never',
24
+ '@cds.persistence.udf': 'never',
25
+ '@cds.redirection.target': 'never',
26
+ '@com.sap.gtt.core.CoreModel.Indexable': 'never',
27
+ '@fiori.draft.enabled': 'onlyViaArtifact',
28
+ '@sql.append': 'never',
29
+ '@sql.prepend': 'never',
30
+ '@sql.replace': 'never',
31
+ }
32
+
33
+ /**
34
+ * Checks whether the given absolute path is inside a reserved namespace.
35
+ *
36
+ * @param {string} absolute
37
+ * @returns {boolean}
38
+ */
39
+ function isInReservedNamespace( absolute ) {
40
+ return absolute === 'cds' || absolute.startsWith( 'cds.' ) &&
41
+ !absolute.match( /^cds\.foundation(\.|$)/ ) &&
42
+ !absolute.match( /^cds\.outbox(\.|$)/ ) && // Requested by Node runtime
43
+ !absolute.match( /^cds\.xt(\.|$)/ ); // Requested by Mtx
44
+ }
45
+
46
+ /**
47
+ * Tell if a type is (directly) a builtin type
48
+ * Note that in CSN builtins are not in the definition of the model, so we can only
49
+ * check against their absolute names. Builtin types are "cds.<something>", i.e. they
50
+ * are directly in 'cds', but not for example in 'cds.foundation'.
51
+ *
52
+ * @param {string|object} type
53
+ * @returns {boolean}
54
+ */
55
+ function isBuiltinType( type ) {
56
+ type = typeof type === 'string' ? type : type?.ref?.[0];
57
+ return type && isInReservedNamespace( type );
58
+ }
59
+
60
+ const magicVariables = [
61
+ '$user',
62
+ '$at',
63
+ '$valid',
64
+ '$now',
65
+ '$tenant',
66
+ '$session',
67
+ ];
68
+
69
+ /**
70
+ * Tell if a name is a magic variable
71
+ *
72
+ * @param {string} name
73
+ * @returns {boolean}
74
+ */
75
+ function isMagicVariable( name ) {
76
+ return typeof name === 'string' && magicVariables.includes(name);
77
+ }
78
+
79
+ /**
80
+ * Properties that are required next to `=` to make an annotation value an actual expression
81
+ * and not some foreign structure.
82
+ *
83
+ * @type {string[]}
84
+ */
85
+ const xprInAnnoProperties = [
86
+ 'ref', 'xpr', 'list', 'literal', 'val',
87
+ '#', 'func', 'args', 'SELECT', 'SET',
88
+ 'cast',
89
+ ];
90
+
91
+ /**
92
+ * Functions without parentheses in CDL (common standard SQL-92 functions)
93
+ * (do not add more - make it part of the SQL renderer to remove parentheses for
94
+ * other funny SQL functions like CURRENT_UTCTIMESTAMP).
95
+ */
96
+ const functionsWithoutParens = [
97
+ 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP',
98
+ 'CURRENT_USER', 'SESSION_USER', 'SYSTEM_USER',
99
+ ];
100
+
101
+ /**
102
+ * Return whether JSON object `val` is a representation for an annotation expression
103
+ */
104
+ function isAnnotationExpression( val ) {
105
+ return val?.['='] !== undefined && xprInAnnoProperties.some( prop => val[prop] !== undefined );
106
+ }
107
+
108
+ module.exports = {
109
+ propagationRules,
110
+ xprInAnnoProperties,
111
+ functionsWithoutParens,
112
+ isInReservedNamespace,
113
+ isBuiltinType,
114
+ isMagicVariable,
115
+ isAnnotationExpression,
116
+ }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { functionsWithoutParens } = require('../compiler/builtins');
3
+ const { functionsWithoutParens } = require('./builtins');
4
4
 
5
5
  module.exports = {
6
6
  // CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
@@ -207,6 +207,7 @@ module.exports = {
207
207
  'ABAP_TIME',
208
208
  'ABAP_XSTRING',
209
209
  'ABS',
210
+ 'ABSOLUTE',
210
211
  'ACOS',
211
212
  'ADD_DAYS',
212
213
  'ADD_MONTHS',
@@ -529,6 +530,7 @@ module.exports = {
529
530
  'RAW',
530
531
  'RDICT',
531
532
  'REAL',
533
+ 'REAL_VECTOR',
532
534
  'RECORD_COMMIT_TIMESTAMP',
533
535
  'RECORD_COUNT',
534
536
  'RECORD_ID',
@@ -579,6 +581,7 @@ module.exports = {
579
581
  'ST_ALPHASHAPEAGGR',
580
582
  'ST_ALPHASHAPEAREAAGGR',
581
583
  'ST_ALPHASHAPEEDGEAGGR',
584
+ 'ST_ASESRIJSON',
582
585
  'ST_ASGEOJSON',
583
586
  'ST_ASMVT',
584
587
  'ST_ASSVGAGGR',
@@ -828,6 +831,7 @@ module.exports = {
828
831
  'SIMILAR',
829
832
  'SOME',
830
833
  'SYMMETRIC',
834
+ 'SYSTEM_USER',
831
835
  'TABLE',
832
836
  'TABLESAMPLE',
833
837
  'THEN',
@@ -1,10 +1,85 @@
1
1
  'use strict';
2
2
 
3
3
  // This file contains functions related to XSN/CSN-location objects,
4
- // but not semantic locations (which are message-specific),
4
+ // and the class definition for semantic locations
5
5
 
6
6
  const { copyPropIfExist } = require('../utils/objectUtils');
7
- const { CsnLocation } = require('../compiler/classes');
7
+
8
+ class Location {
9
+ file;
10
+ line;
11
+ col;
12
+ endLine;
13
+ endCol;
14
+ constructor(file, line, col, endLine, endCol) {
15
+ this.file = file;
16
+ this.line = line;
17
+ this.col = col;
18
+ this.endLine = endLine;
19
+ this.endCol = endCol;
20
+ }
21
+ }
22
+
23
+ class SemanticLocation {
24
+ mainKind;
25
+ absolute;
26
+ action;
27
+ param;
28
+ select;
29
+ mixin;
30
+ element = [];
31
+ suffix;
32
+ innerKind;
33
+
34
+ toString() {
35
+ return semanticLocationString( this );
36
+ }
37
+ }
38
+
39
+ function semanticLocationString( name, extended = false ) {
40
+ const parts = [ `${ name.mainKind }:“${ name.absolute }”` ];
41
+ if (name.action != null)
42
+ parts.push( `“action:${ name.action }”` );
43
+ if (name.param != null)
44
+ parts.push( name.param ? `param:“${ name.param }”` : 'returns' );
45
+ if (name.select != null)
46
+ parts.push( name.select ? `select:${ name.select }` : 'select' );
47
+ if (name.mixin != null) {
48
+ const prop = (name.innerKind === 'alias') ? 'alias' : 'mixin';
49
+ parts.push( `${ prop }:${ stringOrRaw( name.mixin ) }` );
50
+ }
51
+ const { element, innerKind } = name;
52
+ if (element.length) {
53
+ const append = innerKind === 'item' || innerKind === 'aspect';
54
+ const prop = !append && innerKind || !innerKind && name.select != null && 'column';
55
+ if (!prop || append) {
56
+ parts.push( `element:${ stringOrRaw( element ) }` );
57
+ if (append)
58
+ parts.push( innerKind );
59
+ }
60
+ else if (prop === 'column') {
61
+ const pos = extended ? -1
62
+ : element.findIndex( ( e, idx ) => idx && typeof e !== 'string' );
63
+ parts.push( `column:${ stringOrRaw( pos > 0 ? element.slice( 0, pos ) : element ) }` );
64
+ }
65
+ else {
66
+ if (element.length > 1)
67
+ parts.push( `element:${ stringOrRaw( element.slice( 0, -1 ) ) }` );
68
+ parts.push( `${ innerKind }:“${ element[element.length - 1] }”` );
69
+ }
70
+ }
71
+ if (name.suffix)
72
+ parts.push( name.suffix );
73
+ return parts.join( '/' );
74
+ }
75
+
76
+ function stringOrRaw( val ) {
77
+ if (!Array.isArray( val ))
78
+ return (typeof val === 'string') ? `“${ val }”` : val;
79
+ return val.every( e => typeof e === 'string' ) // && no '.' ?
80
+ ? `“${ val.join( '.' ) }”`
81
+ : val.map( stringOrRaw ).join( '→' ); // for XSN output, is sliced otherwise
82
+ }
8
83
 
9
84
  /**
10
85
  * Create a location with properties `file`, `line` and `col` from argument
@@ -42,7 +117,7 @@ function combinedLocation( start, end ) {
42
117
  */
43
118
  function emptyLocation( filename ) {
44
119
  return {
45
- __proto__: CsnLocation.prototype,
120
+ __proto__: Location.prototype,
46
121
  file: filename,
47
122
  line: 1,
48
123
  col: 1,
@@ -62,7 +137,7 @@ function emptyLocation( filename ) {
62
137
  */
63
138
  function emptyWeakLocation( filename ) {
64
139
  return {
65
- __proto__: CsnLocation.prototype,
140
+ __proto__: Location.prototype,
66
141
  file: filename,
67
142
  line: 1,
68
143
  col: 1,
@@ -72,12 +147,12 @@ function emptyWeakLocation( filename ) {
72
147
  }
73
148
 
74
149
  /**
75
- * @param {CsnLocation} loc
76
- * @returns {CsnLocation}
150
+ * @param {Location} loc
151
+ * @returns {Location}
77
152
  */
78
153
  function weakLocation( loc ) {
79
154
  return (!loc?.endLine) ? loc : {
80
- __proto__: CsnLocation.prototype,
155
+ __proto__: Location.prototype,
81
156
  file: loc.file,
82
157
  line: loc.line,
83
158
  col: loc.col,
@@ -96,8 +171,8 @@ function weakLocation( loc ) {
96
171
  * a double-click on the _last_ identifier token of the reference jumps to the artifact
97
172
  * represented by the complete reference.
98
173
  *
99
- * @param {CsnLocation} loc
100
- * @returns {CsnLocation}
174
+ * @param {Location} loc
175
+ * @returns {Location}
101
176
  */
102
177
  function weakRefLocation( ref ) {
103
178
  if (!ref)
@@ -105,7 +180,7 @@ function weakRefLocation( ref ) {
105
180
  const { path } = ref;
106
181
  const loc = path?.length ? path[path.length - 1].location : ref.location;
107
182
  return (!loc?.endLine) ? loc : {
108
- __proto__: CsnLocation.prototype,
183
+ __proto__: Location.prototype,
109
184
  file: loc.file,
110
185
  line: loc.line,
111
186
  col: loc.col,
@@ -115,12 +190,12 @@ function weakRefLocation( ref ) {
115
190
  }
116
191
 
117
192
  /**
118
- * @param {CsnLocation} loc
119
- * @returns {CsnLocation}
193
+ * @param {Location} loc
194
+ * @returns {Location}
120
195
  */
121
196
  function weakEndLocation( loc ) {
122
197
  return loc && {
123
- __proto__: CsnLocation.prototype,
198
+ __proto__: Location.prototype,
124
199
  file: loc.file,
125
200
  line: loc.endLine,
126
201
  col: loc.endCol && loc.endCol - 1,
@@ -203,7 +278,7 @@ function dictLocation( dict, extraLocation ) {
203
278
  const lineB = (b.endLine || b.line);
204
279
  return (lineA > lineB || (lineA === lineB && (a.endCol || a.col) > (b.endCol || b.col)) ? a : b);
205
280
  });
206
- return new CsnLocation( min.file, min.line, min.col, max.endLine, max.endCol );
281
+ return new Location( min.file, min.line, min.col, max.endLine, max.endCol );
207
282
  }
208
283
 
209
284
  function _objLocations( obj ) {
@@ -211,6 +286,8 @@ function _objLocations( obj ) {
211
286
  }
212
287
 
213
288
  module.exports = {
289
+ Location,
290
+ SemanticLocation,
214
291
  combinedLocation,
215
292
  emptyLocation,
216
293
  emptyWeakLocation,
@@ -64,8 +64,10 @@ const centralMessages = {
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' ] },
67
68
 
68
69
  'name-invalid-dollar-alias': { severity: 'Error', configurableFor: true },
70
+ 'name-deprecated-$self': { severity: 'Warning', errorFor: [ 'v5' ], configurableFor: true },
69
71
 
70
72
  'type-invalid-items': { severity: 'Error' }, // not supported yet
71
73
  'assoc-as-type': { severity: 'Error' }, // TODO: allow more, but not all
@@ -84,6 +86,7 @@ const centralMessages = {
84
86
  'empty-type': { severity: 'Info' }, // only still an error in old transformers
85
87
 
86
88
  'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
89
+ 'ref-deprecated-self-element': { severity: 'Warning', configurableFor: true, errorFor: [ 'v5' ] },
87
90
  'ref-invalid-type': { severity: 'Error' },
88
91
  'ref-unexpected-self': { severity: 'Error' },
89
92
  'ref-invalid-include': { severity: 'Error' },
@@ -159,34 +162,36 @@ const centralMessages = {
159
162
  'syntax-unknown-escape': { severity: 'Error', configurableFor: true },
160
163
  'syntax-unsupported-masked': { severity: 'Error', configurableFor: 'deprecated' },
161
164
  'syntax-unexpected-sql-clause': { severity: 'Error' }, // TODO: configurableFor:'tests'?
165
+ 'syntax-ignoring-anno': { severity: 'Warning', errorFor: [ 'v5' ] },
162
166
 
163
167
  'type-unsupported-precision-change': { severity: 'Error' },
164
168
  'type-unsupported-key-change': { severity: 'Error', configurableFor: true },
169
+ 'type-missing-enum-value': { severity: 'Warning', errorFor: [ 'v5' ] },
165
170
 
166
171
  'def-missing-element': { severity: 'Error' },
167
-
172
+ 'def-expected-structured': { severity: 'Warning', configurableFor: true, errorFor: [ 'v5' ] },
168
173
  'def-unsupported-calc-elem': { severity: 'Error', configurableFor: true },
169
174
 
170
175
  'def-invalid-key-cardinality': { severity: 'Error' },
171
176
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
172
- 'odata-spec-violation-array': { severity: 'Warning' }, // more than 30 chars
177
+ 'odata-spec-violation-array': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
173
178
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
174
- 'odata-spec-violation-assoc': { severity: 'Warning' }, // more than 30 chars
179
+ 'odata-spec-violation-assoc': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
175
180
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
176
181
  'odata-spec-violation-constraints': { severity: 'Info' }, // more than 30 chars
177
182
  'odata-spec-violation-id': { severity: 'Error', configurableFor: true },
178
- 'odata-spec-violation-namespace': { severity: 'Warning' }, // more than 30 chars
183
+ 'odata-spec-violation-namespace': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
179
184
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
180
- 'odata-spec-violation-param': { severity: 'Warning' }, // more than 30 chars
185
+ 'odata-spec-violation-param': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
181
186
  // Published! Used in @cap-js-community/odata-v2-adapter; if renamed, add to oldMessageIds
182
- 'odata-spec-violation-returns': { severity: 'Warning' }, // more than 30 chars
187
+ 'odata-spec-violation-returns': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] }, // more than 30 chars
183
188
  'odata-spec-violation-type': { severity: 'Error', configurableFor: true },
184
- 'odata-spec-violation-type-unknown': { severity: 'Warning' },
185
- 'odata-spec-violation-no-key': { severity: 'Warning' },
189
+ 'odata-spec-violation-type-unknown': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] },
190
+ 'odata-spec-violation-no-key': { severity: 'Warning', configurableFor: true, errorFor: ['v5'] },
186
191
  'odata-spec-violation-key-array': { severity: 'Error', configurableFor: true }, // more than 30 chars
187
192
  'odata-spec-violation-key-null': { severity: 'Error', configurableFor: true }, // more than 30 chars
188
- 'odata-spec-violation-key-type': { severity: 'Warning' }, // more than 30 chars
189
- 'odata-spec-violation-property-name': { severity: 'Warning' }, // 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
190
195
  'odata-anno-preproc': { severity: 'Warning' },
191
196
  'odata-anno-dict': { severity: 'Warning' },
192
197
  'odata-anno-vocref': { severity: 'Warning' },
@@ -229,6 +234,9 @@ for (const oldName in oldMessageIds) {
229
234
  // If you change it, keep in sync with scripts/eslint/rules/message-text.js
230
235
 
231
236
  const centralMessageTexts = {
237
+ 'api-deprecated-v5': {
238
+ std: 'Support for generating hdbcds output is deprecated with @sap/cds-compiler v5 and later'
239
+ },
232
240
  'api-invalid-option': {
233
241
  std: 'Invalid option $(NAME)!',
234
242
  deprecated: 'Option $(NAME) is no longer supported! Use latest API options instead',
@@ -250,7 +258,7 @@ const centralMessageTexts = {
250
258
  std: 'Invalid option combination found: $(OPTION) and $(PROP)', // unused
251
259
  'valid-structured': 'Structured OData is only supported with OData version v4',
252
260
  'sql-dialect-and-naming': 'sqlDialect $(NAME) can\'t be combined with sqlMapping $(PROP)',
253
- 'sql-dialect-and-localized': 'Option $(OPTION) can\'t be combined with SQL dialect $(VALUE) or the to.hdi()/to.hdbcds() backend',
261
+ 'tenant-and-naming': 'Option $(OPTION) can\'t be combined with sqlMapping $(PROP) - expected sqlMapping $(VALUE)'
254
262
  },
255
263
  'api-unexpected-combination': {
256
264
  std: 'Unexpected option combination: $(OPTION) and $(PROP)', // unused
@@ -282,6 +290,7 @@ const centralMessageTexts = {
282
290
  'anno-unstable-array': 'Unstable order of array items due to repeated assignments for $(ANNO)',
283
291
  'anno-mismatched-ellipsis': 'An array with $(CODE) can only be used if there is an assignment below with an array value',
284
292
  'anno-unexpected-ellipsis': 'No base annotation available to apply $(CODE)',
293
+ 'anno-unexpected-mixin': 'Unexpected annotation on mixin definition',
285
294
 
286
295
  'anno-unexpected-localized-skip': {
287
296
  std: 'Compiler generated entity $(NAME) must not be annotated with $(ANNO) if $(ART) is not skipped',
@@ -289,8 +298,8 @@ const centralMessageTexts = {
289
298
  },
290
299
 
291
300
  'anno-missing-rewrite': {
292
- std: 'Assign a value for $(ANNO), the value inherited from $(ART) would contain invalid references like $(ELEMREF)',
293
- unrelated: 'Assign a value for $(ANNO), the value inherited from $(ART) would contain references like $(ELEMREF) to unrelated elements',
301
+ std: 'Assign a value for $(ANNO); the value inherited from $(ART) would contain invalid or unrelated references like $(ELEMREF)',
302
+ unsupported: 'Assign a value for $(ANNO); the value inherited from $(ART) can\'t be rewritten due to unsupported $(ELEMREF)',
294
303
  },
295
304
 
296
305
  'chained-array-of': '"Array of"/"many" must not be chained with another "array of"/"many" inside a service',
@@ -566,13 +575,17 @@ const centralMessageTexts = {
566
575
  entity: 'Entity $(ART) has no parameter $(ID)',
567
576
  action: 'Action $(ART) has no parameter $(ID)',
568
577
  },
569
- 'ref-undefined-art': 'No artifact has been found with name $(ART)',
578
+ 'ref-undefined-art': {
579
+ std: 'No artifact has been found with name $(ART)',
580
+ namespace: 'No artifact has been found with name $(ART) which can be extended with annotations',
581
+ localized: 'Can\'t extend localized definitions, only annotate them using an $(KEYWORD) statement',
582
+ },
570
583
  // TODO: proposal 'No definition found for $(NAME)',
571
584
  'ref-undefined-element': {
572
585
  std: 'Element $(ART) has not been found',
573
586
  element: 'Artifact $(ART) has no element $(MEMBER)',
574
587
  target: 'Target entity $(ART) has no element $(ID)',
575
- aspect: 'Element $(ID) has not been found in the anonymous target aspect', // TODO: still?
588
+ aspect: 'Element $(ID) has not been found in the anonymous target aspect',
576
589
  query: 'The current query has no element $(ART)',
577
590
  alias: 'Element $(ART) has not been found in the sub query for alias $(ALIAS)',
578
591
  virtual: 'Element $(ART) has not been found. Use $(CODE) to add virtual elements in queries'
@@ -583,6 +596,7 @@ const centralMessageTexts = {
583
596
  target: 'Target entity $(ART) has no element $(ID)',
584
597
  query: 'The current query has no element $(ART)',
585
598
  alias: 'Element $(ART) has not been found in the sub query for alias $(ALIAS)',
599
+ aspect: 'Element $(ID) has not been found in the anonymous target aspect',
586
600
  },
587
601
  'ref-undefined-var': {
588
602
  std: 'Variable $(ID) has not been found',
@@ -631,7 +645,6 @@ const centralMessageTexts = {
631
645
  expr: 'Associations can\'t be used as values in expressions',
632
646
  'expr-comp': 'Compositions can\'t be used as values in expressions',
633
647
  'assoc-stored': 'Associations and compositions can\'t be used as values in stored calculated elements',
634
- cast: 'Casting to an association is not supported',
635
648
 
636
649
  'managed-filter': 'Unexpected managed association $(NAME) in filter expression of $(ID)',
637
650
  'unmanaged-filter': 'Unexpected unmanaged association $(NAME) in filter expression of $(ID)'
@@ -688,7 +701,10 @@ const centralMessageTexts = {
688
701
  'type-unexpected-assoc': {
689
702
  std: 'An unmanaged association can\'t be used as type',
690
703
  },
691
-
704
+ 'type-missing-enum-value': {
705
+ std: 'Missing value for non-string enum element $(NAME)',
706
+ numeric: 'Missing value for numeric enum element $(NAME)',
707
+ },
692
708
  'type-missing-argument': 'Missing value for argument $(NAME) in reference to type $(ID)',
693
709
  'type-ignoring-argument': 'Too many arguments for type $(ART)',
694
710
  'type-unexpected-argument': {
@@ -717,7 +733,7 @@ const centralMessageTexts = {
717
733
  'targetAspect': 'Unexpected $(KEYWORD) on composition of aspect'
718
734
  },
719
735
 
720
- 'anno-builtin': 'Builtin types should not be annotated. Use custom type instead',
736
+ 'anno-builtin': 'Builtin types should not be annotated nor extended. Use custom type instead',
721
737
  'ext-undefined-def': 'Artifact $(ART) has not been found',
722
738
  'ext-undefined-art': 'No artifact has been found with name $(ART)',
723
739
  'ext-undefined-element': {
@@ -803,6 +819,8 @@ const centralMessageTexts = {
803
819
  'texts-aspect-locale': 'Element $(ELEMREF) of $(ART) must be of type $(TYPE) or $(OTHERTYPE)',
804
820
  },
805
821
 
822
+ 'def-expected-structured': 'Events must either be structured or be projections',
823
+
806
824
  'duplicate-definition': {
807
825
  std: 'Duplicate definition of $(NAME)',
808
826
  absolute: 'Duplicate definition of artifact $(NAME)',
@@ -829,10 +847,13 @@ const centralMessageTexts = {
829
847
  $self: 'Can\'t refer to the query\'s own elements',
830
848
  },
831
849
  'ref-invalid-override': {
832
- std: 'Overridden element of include must not change element structure', // unused
850
+ std: 'Overridden element of include must not change its type drastically', // unused
833
851
  'new-not-structured': 'Expected element $(NAME) to be structured, because it overrides the included element from $(ART)',
834
852
  'old-not-structured': 'Expected element $(NAME) to be scalar, because it overrides the included element from $(ART)',
835
- missing: 'Expected element $(ID) to have at least all the same sub-elements as included artifacts, but it is missing $(NAME)'
853
+ missing: 'Expected element $(ID) to have at least all the same sub-elements as included artifacts, but it is missing $(NAME)',
854
+
855
+ 'new-not-target': 'Expected element $(NAME) to be an association, because it overrides the included element from $(ART)',
856
+ 'old-not-target': 'Expected element $(NAME) not to be an association, because it overrides the included element from $(ART)',
836
857
  },
837
858
 
838
859
  'ref-expecting-assoc': 'Expecting path $(ELEMREF) following “EXISTS” predicate to end with association/composition, found $(TYPE)',
@@ -898,8 +919,8 @@ const centralMessageTexts = {
898
919
  },
899
920
 
900
921
  'query-undefined-element': {
901
- std: 'Target $(TARGET) of $(NAME) is missing element $(ID); please use $(KEYWORD) with an explicit ON-condition',
902
- redirected: 'Target $(TARGET) of $(NAME) is missing element $(ID); please add an ON-condition to $(KEYWORD)',
922
+ std: 'Target $(TARGET) of $(NAME) is missing element $(ID); use $(KEYWORD) with an explicit ON-condition',
923
+ redirected: 'Target $(TARGET) of $(NAME) is missing element $(ID); add an ON-condition to $(KEYWORD)',
903
924
  },
904
925
  'query-unexpected-assoc-hdbcds': 'Publishing a managed association in a view is not possible for “hdbcds” naming mode',
905
926
  'query-unexpected-structure-hdbcds': 'Publishing a structured element in a view is not possible for “hdbcds” naming mode',
@@ -974,7 +995,8 @@ const centralMessageTexts = {
974
995
  'from-structure': 'Structured elements can\'t be cast to a different type',
975
996
  'expr-to-structure': 'Can\'t cast an expression to a structured type',
976
997
  'val-to-structure': 'Can\'t cast $(VALUE) to a structured type',
977
- 'from-assoc': 'Invalid type cast on an association'
998
+ 'from-assoc': 'Invalid type cast on an association',
999
+ 'assoc': 'Can\'t cast to an association',
978
1000
  },
979
1001
 
980
1002
  // -----------------------------------------------------------------------------------
@@ -997,6 +1019,21 @@ const centralMessageTexts = {
997
1019
  publishingFilter: 'Can\'t publish managed association $(ID) with filter, as it must have at least one foreign key',
998
1020
  },
999
1021
 
1022
+ // tenenat isolation via discriminator column:
1023
+ 'tenant-invalid-alias-name': {
1024
+ std: 'Can\'t have a table alias named $(NAME) in a tenant-dependent entity',
1025
+ implicit: 'Provide an explicit table alias name; do not use $(NAME)',
1026
+ mixin: 'Can\'t define a mixin named $(NAME) in a tenant-dependent entity',
1027
+ },
1028
+ 'tenant-invalid-composition': {
1029
+ std: 'Can\'t define a composition of a tenant-independent entity $(TARGET) in a tenant-dependent entity',
1030
+ type: 'Can\'t use type $(TYPE) with a composition of a tenant-independent entity in a tenant-dependent entity',
1031
+ },
1032
+ 'tenant-invalid-target': {
1033
+ std: 'Can\'t define an association to a tenant-dependent entity $(TARGET) in a tenant-independent entity',
1034
+ type: 'Can\'t use type $(TYPE) with an association to a tenant-dependent entity in a tenant-independent entity',
1035
+ },
1036
+
1000
1037
  // -----------------------------------------------------------------------------------
1001
1038
  // OData Message section starts here
1002
1039
  // -----------------------------------------------------------------------------------
@@ -1007,10 +1044,10 @@ const centralMessageTexts = {
1007
1044
  'odata-spec-violation-assoc': 'Unexpected association in structured type for OData $(VERSION)',
1008
1045
  'odata-spec-violation-constraints': 'Partial referential constraints produced for OData $(VERSION)',
1009
1046
  'odata-spec-violation-id': {
1010
- std: 'Expected EDM name $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits',
1047
+ std: 'Expected EDM name $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1011
1048
  'v2firstchar': 'Unexpected first character $(PROP) of EDM Name $(ID) for OData $(VERSION)',
1012
- 'qualifier': 'Expected annotation qualifier $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits',
1013
- 'vocrefalias': 'Expected value $(VALUE) of vocabulary reference attribute $(ID) to start with a letter or underscore, followed by at most 127 letters, underscores or digits'
1049
+ 'qualifier': 'Expected annotation qualifier $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1050
+ 'vocrefalias': 'Expected value $(VALUE) of vocabulary reference attribute $(ID) to start with an alphabetic character or underscore, followed by a maximum of 127 alphabetic characters, digits, or underscores',
1014
1051
  },
1015
1052
  // version independent messages
1016
1053
  'odata-spec-violation-key-array': {
@@ -1026,7 +1063,7 @@ const centralMessageTexts = {
1026
1063
  scalar: 'Unexpected $(TYPE) mapped to $(ID) as type for key element' // flat
1027
1064
  },
1028
1065
  'odata-spec-violation-no-key': 'Expected entity to have a primary key',
1029
- 'odata-spec-violation-type-unknown': 'Unknown Edm Type $(TYPE)',
1066
+ 'odata-spec-violation-type-unknown': 'Unknown EDM Type $(TYPE)',
1030
1067
  'odata-spec-violation-type': {
1031
1068
  std: 'Expected element to have a type',
1032
1069
  incompatible: 'Unexpected EDM Type $(TYPE) for OData $(VERSION)',
@@ -1123,8 +1160,9 @@ const centralMessageTexts = {
1123
1160
  'odata-anno-xpr': {
1124
1161
  'std': 'unused',
1125
1162
  'notadynexpr': '$(OP) is not a renderable dynamic expression in $(ANNO)',
1126
- 'use': 'Function $(OP) is not a renderable dynamic expression in $(ANNO), please use $(CODE) instead',
1163
+ 'use': 'Function $(OP) is not a renderable dynamic expression in $(ANNO), use $(CODE) instead',
1127
1164
  'canonfuncalias': 'Expected function name $(CODE) to be of the form $(META).$(OTHERMETA) for $(OP) in $(ANNO)',
1165
+ 'unexpected': 'Unexpected expression in $(ANNO)',
1128
1166
  }
1129
1167
  ,
1130
1168
  'odata-anno-xpr-type': {
@@ -1136,30 +1174,22 @@ const centralMessageTexts = {
1136
1174
  'atleast': 'Expected at least $(COUNT) argument(s) for $(OP) in $(ANNO)',
1137
1175
  'atmost': 'Expected at most $(COUNT) argument(s) for $(OP) in $(ANNO)',
1138
1176
  'wrongcount': 'Expected exactly one $(PROP) for $(OP) in $(ANNO)',
1139
- 'wrongref': 'Unexpected arguments or filters in $(ELEMREF) in $(ANNO)',
1140
1177
  'wrongval': 'Unexpected value for $(OP) in $(ANNO)',
1141
1178
  'wrongval_meta': 'Expected value for $(OP) to be a $(META) in $(ANNO)',
1142
1179
  'wrongval_meta_list': 'Expected value for $(OP) to be a $(META) or $(RAWVALUES) in $(ANNO)',
1143
1180
  },
1144
1181
  'odata-anno-xpr-ref': {
1145
1182
  'std': '$(ANNO) can\'t be propagated to $(NAME) because path $(ELEMREF) is not resolvable via type reference $(CODE)',
1146
- 'flatten_builtin': 'Expected path $(ELEMREF) in $(ANNO) to resolve to a builtin type while flattening $(NAME)',
1147
- 'notaparam': 'Unexpected path $(ELEMREF) for parameter entity in $(ANNO)',
1148
- 'notaneelement': 'Unexpected path $(ELEMREF) for type entity in $(ANNO)'
1149
- },
1150
- // tenenat isolation via discriminator column:
1151
- 'tenant-invalid-alias-name': {
1152
- std: 'Can\'t have a table alias named $(NAME) in a tenant-dependent entity',
1153
- implicit: 'Provide an explicit table alias name; do not use $(NAME)',
1154
- mixin: 'Can\'t define a mixin named $(NAME) in a tenant-dependent entity',
1155
- },
1156
- 'tenant-invalid-composition': {
1157
- std: 'Can\'t define a composition of a tenant-independent entity $(TARGET) in a tenant-dependent entity',
1158
- type: 'Can\'t use type $(TYPE) with a composition of a tenant-independent entity in a tenant-dependent entity',
1159
- },
1160
- 'tenant-invalid-target': {
1161
- std: 'Can\'t define an association to a tenant-dependent entity $(TARGET) in a tenant-independent entity',
1162
- type: 'Can\'t use type $(TYPE) with an association to a tenant-dependent entity in a tenant-independent entity',
1183
+ 'args': 'Unexpected arguments or filters in $(ELEMREF) in $(ANNO)',
1184
+ 'flatten_builtin': 'Expected path $(ELEMREF) in $(ANNO) to end in a scalar typed leaf element while flattening $(NAME)',
1185
+ 'flatten_builtin_type': 'Expected path $(ELEMREF) in $(ANNO) to end in a scalar typed leaf element while flattening',
1186
+ 'invalid': 'Invalid path $(ELEMREF) in $(ANNO)',
1187
+ // genericTranslation
1188
+ 'notaparam': 'EDM Element path $(ELEMREF) can\'t be used in $(ANNO) which is applied to a parameter entity',
1189
+ 'notaneelement': 'EDM Parameter path $(ELEMREF) can\'t be used in $(ANNO) which is applied to a type entity',
1190
+ 'notrendered': 'EDM Path step $(COUNT) of $(ELEMREF) in $(ANNO) refers to an unrendered property in the OData API',
1191
+ 'magic': 'Unexpected magic variable $(ELEMREF) in $(ANNO)',
1192
+ 'bparam_v2': 'Unexpected explicit binding parameter path $(ELEMREF) for OData $(VERSION) in $(ANNO)',
1163
1193
  },
1164
1194
  // -----------------------------------------------------------------------------------
1165
1195
  // OData Message section ends here, no messages below this line