@sap/cds-compiler 3.4.4 → 3.5.2

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 +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
@@ -15,6 +15,7 @@ const publicOptionsNewAPI = [
15
15
  'severities',
16
16
  'messages',
17
17
  'withLocations',
18
+ 'structXpr',
18
19
  'defaultBinaryLength',
19
20
  'defaultStringLength',
20
21
  'csnFlavor',
@@ -30,6 +31,7 @@ const publicOptionsNewAPI = [
30
31
  'odataVersion',
31
32
  'odataFormat',
32
33
  'odataContainment',
34
+ 'odataCapabilitiesPullup',
33
35
  'odataForeignKeys',
34
36
  'odataProxies',
35
37
  'odataXServiceRefs',
@@ -75,8 +77,8 @@ const overallOptions = publicOptionsNewAPI.concat(privateOptions);
75
77
  * @param {string} moduleName The called module, e.g. 'for.odata', 'to.hdi'. Needed to initialize the message functions
76
78
  * @returns {TranslatedOptions} General cds options
77
79
  */
78
- function translateOptions(input = {}, defaults = {}, hardRequire = {},
79
- customValidators = {}, combinationValidators = [], moduleName = '') {
80
+ function translateOptions( input = {}, defaults = {}, hardRequire = {},
81
+ customValidators = {}, combinationValidators = [], moduleName = '' ) {
80
82
  const options = Object.assign({}, defaults);
81
83
  for (const name of overallOptions) {
82
84
  // Ensure that arrays are not passed as a reference!
@@ -31,7 +31,7 @@ const booleanValidator = {
31
31
  * @param {any} availableValues Available values
32
32
  * @returns {Validator} Return a validator for a string in an expected range
33
33
  */
34
- function generateStringValidator(availableValues) {
34
+ function generateStringValidator( availableValues ) {
35
35
  return {
36
36
  validate: val => typeof val === 'string' && availableValues.some( av => av.toLowerCase() === val.toLowerCase() ),
37
37
  expected: (val) => {
@@ -152,7 +152,7 @@ const allCombinationValidators = {
152
152
  * @returns {void}
153
153
  * @throws {CompilationError} Throws in case of invalid option usage
154
154
  */
155
- function validate(options, moduleName, customValidators = {}, combinationValidators = []) {
155
+ function validate( options, moduleName, customValidators = {}, combinationValidators = [] ) {
156
156
  // TODO: issuing messages in this function looks very strange...
157
157
  {
158
158
  const messageCollector = { messages: [] };
@@ -7,10 +7,9 @@
7
7
  * @param {object} obj
8
8
  * @param {...any} symbols
9
9
  */
10
- function cleanSymbols(obj, ...symbols) {
11
- for (const symbol of symbols) {
10
+ function cleanSymbols( obj, ...symbols ) {
11
+ for (const symbol of symbols)
12
12
  delete obj[symbol];
13
- }
14
13
  }
15
14
 
16
15
  module.exports = {
@@ -20,7 +20,7 @@ function dictAdd( dict, name, entry, duplicateCallback ) {
20
20
  }
21
21
  found.$duplicates.push( entry );
22
22
  if (Array.isArray( entry.$duplicates ))
23
- found.$duplicates.push( ...entry.$duplicates )
23
+ found.$duplicates.push( ...entry.$duplicates );
24
24
  else if (duplicateCallback && name) // do not complain with empty name ''
25
25
  duplicateCallback( name, entry.name.location, entry );
26
26
  entry.$duplicates = true;
@@ -48,7 +48,7 @@ function dictForEach( dict, callback ) {
48
48
  // `entry.name.location`. If this is the first duplicate entry and if the
49
49
  // `filename`s are different, call the callback again on `found.name.location`.
50
50
  function dictAddArray( dict, name, entry, messageCallback ) {
51
- var found = dict[name];
51
+ const found = dict[name];
52
52
  if (!found || found.builtin) { // do not replace a builtin definition
53
53
  dict[name] = entry; // also ok if array (redefined)
54
54
  return entry;
@@ -86,12 +86,12 @@ function pushToDict( dict, name, entry ) {
86
86
  if (dict[name])
87
87
  dict[name].push( entry );
88
88
  else
89
- dict[name] = [entry];
89
+ dict[name] = [ entry ];
90
90
  }
91
91
 
92
92
  module.exports = {
93
- dictAdd, dictForEach,
93
+ dictAdd,
94
+ dictForEach,
94
95
  dictAddArray,
95
96
  pushToDict,
96
- }
97
-
97
+ };
package/lib/base/error.js CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  class CompilerAssertion extends Error {
8
8
  constructor(message) {
9
- super(`cds-compiler assertion failed: ${message}`);
9
+ super(`cds-compiler assertion failed: ${ message }`);
10
10
  }
11
11
  }
12
12
 
@@ -16,7 +16,7 @@ class CompilerAssertion extends Error {
16
16
  */
17
17
  class ModelError extends Error {
18
18
  constructor(message) {
19
- super(`cds-compiler model error: ${message}`);
19
+ super(`cds-compiler model error: ${ message }`);
20
20
  }
21
21
  }
22
22
 
@@ -185,7 +185,7 @@ module.exports = {
185
185
  'WHERE',
186
186
  'WINDOW',
187
187
  'WITH',
188
- 'WITHOUT'
188
+ 'WITHOUT',
189
189
  ],
190
190
  // SAP HANA keywords, used for smart quoting in to-hdi.plain
191
191
  // See './scripts/keywords/hana/generateSqlKeywords.js'
@@ -706,7 +706,7 @@ module.exports = {
706
706
  'WITH',
707
707
  'WITHIN',
708
708
  'XMLTABLE',
709
- 'YEAR'
709
+ 'YEAR',
710
710
  ],
711
711
  // SAP HANA CDS keywords, used for smart quoting in to-hdbcds.plain
712
712
  hdbcds: [
@@ -841,7 +841,7 @@ module.exports = {
841
841
  'WHEN',
842
842
  'WHERE',
843
843
  'WINDOW',
844
- 'WITH'
844
+ 'WITH',
845
845
  ],
846
846
  // H2 keywords, used for smart quoting in to-sql.plain.postgres
847
847
  // Taken from http://www.h2database.com/html/advanced.html#keywords
@@ -945,6 +945,6 @@ module.exports = {
945
945
  'WINDOW',
946
946
  'WITH',
947
947
  'YEAR',
948
- '_ROWID_'
949
- ]
950
- }
948
+ '_ROWID_',
949
+ ],
950
+ };
@@ -39,7 +39,7 @@ function combinedLocation( start, end ) {
39
39
  *
40
40
  * TODO: make this function redundant (XSN sparse locations project)
41
41
  */
42
- function emptyLocation(filename) {
42
+ function emptyLocation( filename ) {
43
43
  return {
44
44
  file: filename,
45
45
  line: 1,
@@ -58,7 +58,7 @@ function emptyLocation(filename) {
58
58
  *
59
59
  * TODO: make this function redundant (XSN sparse locations project)
60
60
  */
61
- function emptyWeakLocation(filename) {
61
+ function emptyWeakLocation( filename ) {
62
62
  return {
63
63
  file: filename,
64
64
  line: 1,
@@ -90,9 +90,9 @@ function locationString( location, normalizeFilename ) {
90
90
  if (!location)
91
91
  return '<???>';
92
92
  const loc = location;
93
- let filename = (loc.file && normalizeFilename)
94
- ? loc.file.replace( /\\/g, '/' )
95
- : loc.file;
93
+ const filename = (loc.file && normalizeFilename)
94
+ ? loc.file.replace( /\\/g, '/' )
95
+ : loc.file;
96
96
  if (!(loc instanceof Object))
97
97
  return loc;
98
98
  if (!loc.line) {
@@ -100,14 +100,13 @@ function locationString( location, normalizeFilename ) {
100
100
  }
101
101
  else if (!loc.endLine) {
102
102
  return (loc.col)
103
- ? `${filename}:${loc.line}:${loc.col}`
104
- : `${filename}:${loc.line}`;
105
- }
106
- else {
107
- return (loc.line === loc.endLine)
108
- ? `${filename}:${loc.line}:${loc.col}-${loc.endCol}`
109
- : `${filename}:${loc.line}.${loc.col}-${loc.endLine}.${loc.endCol}`;
103
+ ? `${ filename }:${ loc.line }:${ loc.col }`
104
+ : `${ filename }:${ loc.line }`;
110
105
  }
106
+
107
+ return (loc.line === loc.endLine)
108
+ ? `${ filename }:${ loc.line }:${ loc.col }-${ loc.endCol }`
109
+ : `${ filename }:${ loc.line }.${ loc.col }-${ loc.endLine }.${ loc.endCol }`;
111
110
  }
112
111
 
113
112
  /**
@@ -30,8 +30,8 @@
30
30
 
31
31
  'use strict';
32
32
 
33
- const { CompilerAssertion } = require("./error");
34
- const { createDict } = require("../utils/objectUtils");
33
+ const { CompilerAssertion } = require('./error');
34
+ const { createDict } = require('../utils/objectUtils');
35
35
 
36
36
  /**
37
37
  * Central register of messages and their configuration.
@@ -179,6 +179,12 @@ const centralMessages = {
179
179
  'odata-spec-violation-key-null': { severity: 'Error', configurableFor: true }, // more than 30 chars
180
180
  'odata-spec-violation-key-type': { severity: 'Warning' }, // more than 30 chars
181
181
  'odata-spec-violation-property-name': { severity: 'Warning' }, // more than 30 chars
182
+ 'odata-anno-preproc': { severity: 'Warning', configurableFor: true },
183
+ 'odata-anno-dict': { severity: 'Warning', configurableFor: true },
184
+ 'odata-anno-dict-enum': { severity: 'Error' },
185
+ 'odata-anno-value': { severity: 'Warning', configurableFor: true },
186
+ 'odata-anno-type': { severity: 'Warning', configurableFor: true },
187
+ 'odata-anno-def': { severity: 'Info', configurableFor: true },
182
188
  };
183
189
 
184
190
  // Old/Deprecated message IDs that we only still use for backwards-compatibility.
@@ -193,9 +199,9 @@ const oldMessageIds = createDict({
193
199
  for (const oldName in oldMessageIds) {
194
200
  const newName = oldMessageIds[oldName];
195
201
  if (centralMessages[oldName])
196
- throw new CompilerAssertion(`Mapping from ${oldName} not possible: ID is still used in message registry.`);
202
+ throw new CompilerAssertion(`Mapping from ${ oldName } not possible: ID is still used in message registry.`);
197
203
  if (!centralMessages[newName])
198
- throw new CompilerAssertion(`Mapping from ${oldName} to new message ID ${newName} does not exist!`);
204
+ throw new CompilerAssertion(`Mapping from ${ oldName } to new message ID ${ newName } does not exist!`);
199
205
 
200
206
  if (!centralMessages[newName].oldNames)
201
207
  centralMessages[newName].oldNames = [ oldName ];
@@ -234,24 +240,27 @@ const centralMessageTexts = {
234
240
  'flatten-fkey-gen': 'Duplicate definition of foreign key element $(NAME) for association $(ART)',
235
241
  'flatten-fkey-exists': 'Generated foreign key element $(NAME) for association $(ART) conflicts with existing element',
236
242
  },
237
-
238
- // Syntax messages, both CDL and CSN parser: ----------------------------------
239
- 'syntax-dollar-ident': { // Warning, TODO: make it name-invalid-alias
240
- std: 'An artifact starting with $(NAME) might shadow a special variable - replace by another name',
243
+ 'name-invalid-dollar-alias': { // Warning
244
+ std: 'An alias name starting with $(NAME) might shadow a special variable - replace by another name',
241
245
  $tableAlias: 'A table alias name starting with $(NAME) might shadow a special variable - replace by another name',
242
246
  $tableImplicit: 'The resulting table alias starts with $(NAME) and might shadow a special variable - specify another name with $(KEYWORD)',
243
247
  mixin: 'A mixin name starting with $(NAME) might shadow a special variable - replace by another name',
244
248
  },
245
249
 
246
- 'syntax-deprecated-abstract': 'Abstract entity definitions are deprecated; use aspect definitions instead', // Warning, TODO: also use for CSN
250
+ // Syntax messages, both CDL and CSN parser: ----------------------------------
251
+ 'syntax-deprecated-abstract': {
252
+ std: 'Abstract entity definitions are deprecated; use aspect definitions instead',
253
+ 'strange-kind': 'The property $(PROP) is deprecated; expecting it only with kind $(KIND) to define an aspect',
254
+ },
247
255
  'syntax-duplicate-excluding': {
248
256
  std: 'Duplicate $(NAME) in the $(KEYWORD) clause',
249
257
  csn: 'Duplicate $(NAME) in property $(PROP)',
250
258
  },
251
- 'syntax-expecting-integer': { // TODO: currently 'syntax-expecting-natnum' in CSN
252
- std: 'A safe integer is expected here',
253
- normal: 'An integer number is expected here',
259
+ 'syntax-expecting-unsigned-int': { // TODO: test all in SyntaxOnly/
260
+ std: 'A safe non-negative integer is expected here',
261
+ normal: 'A non-negative integer number is expected here',
254
262
  unsafe: 'The provided integer is too large',
263
+ csn: 'Expecting a non-negative integer for property $(PROP)'
255
264
  },
256
265
  'syntax-ignoring-anno': {
257
266
  std: 'Annotations can\'t be used in a column with $(CODE)',
@@ -262,13 +271,13 @@ const centralMessageTexts = {
262
271
  csn: 'Property name in dictionary $(PARENTPROP) must not be empty',
263
272
  as: 'String in property $(PROP) must not be empty', // TODO: use
264
273
  },
265
- 'syntax-invalid-literal': { // TODO: write texts less CDL specific
266
- 'std': 'Invalid literal',
274
+ 'syntax-invalid-literal': {
275
+ 'std': 'Invalid literal value',
267
276
  'uneven-hex': 'A binary literal must have an even number of characters',
268
- 'invalid-hex': 'A binary literal must only contain characters 0-9, a-f and A-F',
269
- 'time': 'Expecting time\'hh:mm:ss\' where hh, mm and the optional ss are numbers',
270
- 'date': 'Expecting date\'YYYY-MM-DD\' where YYYY, MM and DD are numbers',
271
- 'timestamp': 'Expecting timestamp\'YYYY-MM-DD hh:mm:ss.u…u\' where YYYY, MM, DD, hh, mm, ss and u are numbers (optional 1-7×u)',
277
+ 'invalid-hex': 'A binary literal must only contain characters 0-9›, a-f and A-F',
278
+ 'time': 'A time literal must look like ‹hh:mm:ss or hh:mm where each letter represents a digit',
279
+ 'date': 'A date literal must look like ‹YYYY-MM-DD where each letter represents a digit',
280
+ 'timestamp': 'A timestamp literal must look like ‹YYYY-MM-DD hh:mm:ss.u…u or YYYY-MM-DD hh:mm where each letter represents a digit, ‹u…u› represents 1 to 7 digits',
272
281
  },
273
282
  'syntax-missing-ellipsis': 'Expecting an array item $(NEWCODE) after an item with $(CODE)',
274
283
  'syntax-unexpected-ellipsis': {
@@ -313,7 +322,7 @@ const centralMessageTexts = {
313
322
  // 'syntax-unexpected-space', 'syntax-unexpected-doc-comment' (TODO is: -ignoring-, Info)
314
323
  // 'syntax-unexpected-alias' (is 'syntax-unexpected-property' in CSN),
315
324
  // 'syntax-unexpected-right-paren'
316
- 'syntax-unsupported-calc-field': 'Calculated fields are not supported',
325
+ 'syntax-unsupported-calc-elem': 'Calculated elements are not supported',
317
326
  'syntax-unsupported-param': {
318
327
  std: 'Parameter not supported', // unused
319
328
  dynamic: 'Dynamic parameter $(CODE) is not supported',
@@ -323,6 +332,11 @@ const centralMessageTexts = {
323
332
 
324
333
  // Syntax messages, CSN parser - default: Error ------------------------------
325
334
  // TODO: use one id with text variants instead of several message ids
335
+ 'syntax-deprecated-dollar-syntax': {
336
+ std: 'The property $(PROP) is deprecated; its value is ignored',
337
+ projection: 'The property $(PROP) is deprecated; use property $(SIBLINGPROP) instead of $(OTHERPROP) for the query',
338
+ aspect: 'The property $(PROP) is deprecated; change the kind of the current definition to $(KIND) instead',
339
+ },
326
340
  'syntax-deprecated-property': { // Warning
327
341
  std: 'Deprecated property $(PROP)', // unused
328
342
  'zero': 'Deprecated CSN v0.1.0 property $(PROP) is ignored',
@@ -337,7 +351,6 @@ const centralMessageTexts = {
337
351
 
338
352
  'syntax-expecting-object': 'Expecting object for property $(PROP)',
339
353
  'syntax-expecting-column': 'Expecting object or string \'*\' for property $(PROP)',
340
- 'syntax-expecting-natnum': 'Expecting non-negative number for property $(PROP)',
341
354
  'syntax-expecting-cardinality': 'Expecting non-negative number or string \'*\' for property $(PROP)',
342
355
  'syntax-expecting-reference': 'Expecting non-empty string or object for property $(PROP)',
343
356
  'syntax-expecting-term': 'Expecting non-empty string or object for property $(PROP)',
@@ -381,7 +394,7 @@ const centralMessageTexts = {
381
394
  whitespace: 'Unknown escape sequence: Can\'t escape whitespace',
382
395
  codepoint: 'Undefined code-point for $(CODE)',
383
396
  'unicode-hex': 'Expecting hexadecimal numbers for unicode escape but found $(CODE)',
384
- 'hex-count': 'Expecting $(NUMBER) hexadecimal numbers for escape sequence but found $(CODE)',
397
+ 'hex-count': 'Expecting $(COUNT) hexadecimal numbers for escape sequence but found $(CODE)',
385
398
  'unicode-brace': 'Missing closing brace for unicode escape sequence',
386
399
  'language-identifier': 'Escape sequences in text-block\'s language identifier are not allowed',
387
400
  },
@@ -390,7 +403,7 @@ const centralMessageTexts = {
390
403
  placeholder: 'Placeholders are not supported. Replace $(CODE) with $(NEWCODE)',
391
404
  },
392
405
 
393
- // Syntax messages for errorneous references ----------------------------------
406
+ // Messages for errorneous references -----------------------------------------
394
407
  // location at errorneous reference (if possible)
395
408
  'ref-unexpected-self': 'Unexpected $(ID) reference; is valid only in ON-conditions',
396
409
  'ref-undefined-def': {
@@ -406,7 +419,10 @@ const centralMessageTexts = {
406
419
  element: 'Artifact $(ART) has no element $(MEMBER)',
407
420
  aspect: 'Element $(ID) has not been found in the anonymous target aspect'
408
421
  },
409
- 'ref-undefined-var': 'Element or variable $(ID) has not been found',
422
+ 'ref-undefined-var': {
423
+ std: 'Variable $(ID) has not been found',
424
+ alias: 'Variable $(ID) has not been found. Use table alias $(ALIAS) to refer an element with the same name',
425
+ },
410
426
  'ref-unknown-var': {
411
427
  std: 'No replacement found for special variable $(ID)'
412
428
  },
@@ -468,12 +484,34 @@ const centralMessageTexts = {
468
484
  'entity-persistence': 'SAP HANA does not allow associations in entities annotated with $(ANNO)',
469
485
  'target-persistence': 'SAP HANA does not allow associations pointing to entities annotated with $(ANNO)',
470
486
  },
487
+ 'def-unexpected-key': {
488
+ std: '$(ART) can\'t have additional keys',
489
+ // TODO: Better message?
490
+ include: '$(ART) can\'t have additional keys (through include)'
491
+ },
492
+ 'def-unexpected-localized': {
493
+ std: '$(ART) can\'t have localized elements',
494
+ // TODO: Better message?
495
+ include: '$(ART) can\'t have localized elements (through include)',
496
+ },
471
497
 
472
498
  'def-missing-element': {
473
499
  std: 'Expecting entity to have at least one non-virtual element',
474
500
  view: 'Expecting view to have at least one non-virtual element'
475
501
  },
476
502
 
503
+ 'def-invalid-texts-aspect': {
504
+ std: '$(ART) is not valid', // unused
505
+ 'no-aspect': '$(ART) must be an aspect',
506
+ key: '$(ART) must be a key',
507
+ 'no-key': '$(ART) must not be key',
508
+ 'missing': '$(ART) must have an element $(NAME)',
509
+ },
510
+ 'def-invalid-element-type': {
511
+ std: 'Element $(ELEMREF) of $(ART) must be of type $(TYPE)',
512
+ 'texts-aspect-locale': 'Element $(ELEMREF) of $(ART) must be of type $(TYPE) or $(OTHERTYPE)',
513
+ },
514
+
477
515
  'duplicate-definition': {
478
516
  std: 'Duplicate definition of $(NAME)',
479
517
  absolute: 'Duplicate definition of artifact $(NAME)',
@@ -499,7 +537,7 @@ const centralMessageTexts = {
499
537
  'expected-target': 'An entity or an aspect is expected here',
500
538
  'extend-columns': 'Artifact $(ART) can\'t be extended with columns, only projections can',
501
539
  'extend-repeated-intralayer': 'Unstable element order due to repeated extensions in same layer',
502
- 'extend-unexpected-include': 'Can\'t extend $(KIND) with includes',
540
+ 'extend-unexpected-include': 'Can\'t extend $(META) with includes',
503
541
  'ref-expecting-bare-aspect': 'An aspect without elements is expected here',
504
542
 
505
543
  'ext-duplicate-extend-type': 'Duplicate type extension for type $(TYPE)',
@@ -580,10 +618,9 @@ const centralMessageTexts = {
580
618
  std: 'Expected element to have a type',
581
619
  incompatible: 'Unexpected EDM Type $(TYPE) for OData $(VERSION)',
582
620
  facet: 'Unexpected EDM Type facet $(NAME) of type $(TYPE) for OData $(VERSION)',
583
- missing: 'Expected referenced type $(TYPE) to be included in service $(NAME)',
584
621
  external: 'Referenced type $(TYPE) marked as $(ANNO) can\'t be rendered as $(CODE) in service $(NAME) for OData $(VERSION)',
585
622
  },
586
- 'odata-spec-violation-property-name': 'Expected element name to be different from declaring $(KIND)',
623
+ 'odata-spec-violation-property-name': 'Expected element name to be different from declaring $(META)',
587
624
  'odata-spec-violation-namespace': {
588
625
  std: 'Expected service name not to be one of the reserved names $(NAMES)',
589
626
  length: 'Expected service name not to exceed 511 characters',
@@ -591,7 +628,9 @@ const centralMessageTexts = {
591
628
  // Other odata/edm errors
592
629
  'odata-definition-exists': {
593
630
  std: 'Entity can\'t be created due to name collision with existing definition $(NAME)',
594
- proxy: 'No proxy entity created due to name collision with existing definition $(NAME) of kind $(KIND)'
631
+ proxy: 'No proxy entity created due to name collision with existing definition $(NAME) of kind $(KIND)',
632
+ anno: 'Name of annotation definition $(ANNO) conflicts with existing service definition',
633
+ termredef: 'Unexpected redefinition of annotation $(ANNO)',
595
634
  },
596
635
  'odata-navigation': {
597
636
  std: 'No OData navigation property generated, target $(TARGET) is outside of service $(SERVICE)',
@@ -599,6 +638,63 @@ const centralMessageTexts = {
599
638
  },
600
639
  'odata-parameter-order': 'Unexpected mandatory after optional parameter',
601
640
  'odata-key-recursive': 'Unexpected recursive key $(NAME)',
641
+ // -----------------------------------------------------------------------------------
642
+ // All odata-anno MUST have a '$(ANNO)' parameter to indicate error location
643
+ // -----------------------------------------------------------------------------------
644
+ // Annotation Preprocessing:
645
+ // -----------------------------------------------------------------------------------
646
+ 'odata-anno-preproc': {
647
+ 'std': 'unused message text',
648
+ 'nokey': 'Expected target $(NAME) to have a key element for $(ANNO)',
649
+ 'multkeys': 'Expected target $(NAME) to have only one key element',
650
+ 'vhlnokey': 'Expected value help list entity $(NAME) to have a key element for $(ANNO)',
651
+ 'vhlmultkeys': 'Expected value help list entity $(NAME) to have only one key element for $(ANNO)',
652
+ 'notforentity': 'Unexpected usage of $(ANNO) for an entity',
653
+ 'viaassoc': 'Expected value to be a path for $(ANNO)',
654
+ 'noassoc': 'Expected association $(ID) to exist for $(ANNO)',
655
+ 'vallistignored': '$(NAME) is ignored for $(ANNO) as $(CODE) is present',
656
+ 'notastring': 'Expected value to be a string for $(ANNO)',
657
+ 'notexist': 'Expect entity $(ID) to exist for $(ANNO)',
658
+ 'txtarr': 'Expect $(ANNO) shortcut to have a $(NAME) annotation'
659
+ },
660
+ // -----------------------------------------------------------------------------------
661
+ // GenericTranslation:
662
+ // -----------------------------------------------------------------------------------
663
+ 'odata-anno-dict': {
664
+ // ANNO w/o sub elements, term qualifiers and context stack
665
+ 'std': 'Vocabulary dictionary inconsistency: Type $(TYPE) not found for $(ANNO)',
666
+ 'experimental': '$(ANNO) is experimental and can be changed or removed at any time, do not use productively!',
667
+ 'redefinition': '$(ANNO) is an official OASIS/SAP annotation and can\'t be redefined'
668
+ },
669
+ 'odata-anno-dict-enum': {
670
+ 'std' : 'Unexpected annotation definition $(NAME) with many enum type',
671
+ 'type': 'Unexpected annotation definition $(NAME) with many enum type $(TYPE)',
672
+ 'value': 'Expected all enum elements of type $(TYPE) to have a value in annotation definition $(NAME)'
673
+ },
674
+ 'odata-anno-value': {
675
+ 'nested': 'Missing $(STR) annotation for $(ANNO)',
676
+ // -----------------------------------------------------------------------------------
677
+ // All mesages of odata-anno-value below here MUST have $(ANNO) filled with msgctx.anno
678
+ // -----------------------------------------------------------------------------------
679
+ 'enum': 'Value $(VALUE) is not one out of $(RAWVALUES) for $(ANNO) of type $(TYPE)',
680
+ 'std': 'Unexpected value $(VALUE) for $(ANNO) of type $(TYPE)',
681
+ 'struct': 'Unexpected $(STR) value for $(ANNO) of type $(TYPE)',
682
+ 'nestedcollection': 'Nested collections are not supported for $(ANNO)',
683
+ 'enumincollection': 'Enum inside collection is not supported for $(ANNO)',
684
+ 'multexpr': 'EDM JSON code contains more than one dynamic expression: $(RAWVALUES) for $(ANNO)',
685
+ },
686
+ 'odata-anno-type': {
687
+ 'std': '$(NAME) is not a known property for $(ANNO) of type $(TYPE)',
688
+ 'unknown': '$(TYPE) is not a known vocabulary type for $(ANNO)',
689
+ 'abstract': 'Unexpected abstract type $(TYPE) for $(ANNO)',
690
+ 'derived': 'Expected specified $(TYPE) to be derived from $(NAME) for $(ANNO)',
691
+ },
692
+ 'odata-anno-def': {
693
+ // All $(ANNO) w/o sub elements, term qualifiers and context stack
694
+ 'std': '$(ANNO) is not a known annotation in an official OASIS/SAP namespace',
695
+ 'deprecated': '$(ANNO) is deprecated. $(DEPR)',
696
+ 'notapplied': '$(ANNO) is not applied (AppliesTo: $(RAWVALUES))',
697
+ },
602
698
  }
603
699
 
604
700
  /**
@@ -620,6 +716,6 @@ const centralMessageTexts = {
620
716
  * Don't set this property directly! Append to object oldMessageIds instead!
621
717
  */
622
718
 
623
- //console.log('FOO')
719
+ // console.log('FOO')
624
720
 
625
721
  module.exports = { centralMessages, centralMessageTexts, oldMessageIds };