@sap/cds-compiler
Version:
CDS (Core Data Services) compiler and backends
870 lines (810 loc) • 88.2 kB
JavaScript
// Central registry for messages.
// `centralMessages` contains all details of a message-id except its standard texts
// (`standardTexts` exists for that). Only `severity` is required, all other
// properties are optional.
// The user can specify "severity wishes" via the option `severities`. Errors
// that don't have a `configurableFor` property cannot be reclassified by
// users. If a module is used that is _not_ listed in `configurableFor` (if it
// is an array) property of the message then the message cannot be
// reclassified.
// We also allow `configurableFor` to have value `true` for errors which are
// always configurable; useful for issues like deprecated syntax variants which
// do not affect the compiler or CSN processors. Temporarily, we also allow
// value `deprecated` for errors which are only configurable if the option
// `deprecated.downgradableErrors` is set. If a string like `v6`, it works like
// `true`, but is meant to be removed with the next major version.
// Messages other than errors can always be reclassified by the user except if
// the module is listed in the message's `errorFor` property.
// __NEW__: If the future `poc` (proof of concept) or `sloppy` option is set,
// the module name `compile` is added to all configurable messages, i.e. to all
// `configurableFor` arrays. (module `compile` includes all parsers and the
// core compiler). This allows creators of _non-productive models_ to
// reclassify errors which usually cannot be reclassified, and continue the
// compilation but has the side effect that the result may be unstable, hence
// "sloppy": with an upcoming _minor_ version of the compiler, the compilation
// might lead to an error anyway or the compiled CSN might look different.
/* eslint @stylistic/no-multi-spaces: 0 */
/* eslint @stylistic/max-len: 0 */
/* eslint @stylistic/key-spacing: 0 */
'use strict';
const { CompilerAssertion } = require( './error' );
const { isDeprecatedEnabled } = require( './model' );
const configurableForValidValues = {
__proto__: null,
// can always be downgraded, we do not really care:
true: () => true,
// like `true`, but is intended to be removed or made 'deprecated' with v7:
v7: () => true,
// only configurable if option deprecated.downgradableErrors is set:
deprecated: options => isDeprecatedEnabled( options, 'downgradableErrors' ),
// still allow to produce output in tests:
test: options => options.testMode != null,
};
const validModules = [ // for configurableFor and errorFor
'v7', // pseudo module in errorFor: planned as error
'compile',
'for.odata',
'to.edmx',
'to.hdbcds',
'to.hdi',
'to.sql',
'to.sql.migration',
'to.sql.migration-script',
'to.rename',
'for.effective',
];
/**
* Central register of messages and their configuration.
* Group by id-category.
*
* Message with severity 'Error' can have a configurableFor property. Its value
* is either array of modules (see validModules) where the error can be
* downgraded, or a value in configurableForValidValues.
*
* Messages with another severity can have an errorFor property. Its value is an
* array of modules (see validModules) where the message is turned into an error.
*
* @type {Object<string, MessageConfig>}
*/
const centralMessages = {
'api-deprecated-hdbcds': { severity: 'Error', configurableFor: true },
'anno-definition': { severity: 'Warning' },
'anno-duplicate': { severity: 'Error', configurableFor: true }, // does not hurt us
'anno-duplicate-unrelated-layer': { severity: 'Error', configurableFor: true }, // does not hurt us
'anno-unstable-array': { severity: 'Warning' },
'anno-invalid-sql-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-struct': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-assoc': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-calc': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-kind': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-view': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'anno-invalid-sql-view-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
'ext-undefined-action': { severity: 'Warning' },
'ext-undefined-art': { severity: 'Warning' }, // for annotate statement (for CDL path root)
'ext-undefined-def': { severity: 'Warning' }, // for annotate statement (for CSN or CDL path cont)
'ext-undefined-element': { severity: 'Warning' },
'ext-undefined-key': { severity: 'Warning' },
'ext-undefined-param': { severity: 'Warning' },
'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' },
'anno-unexpected-localized-skip': { severity: 'Error', configurableFor: true },
'name-invalid-dollar-alias': { severity: 'Error', configurableFor: true },
'name-deprecated-$self': { severity: 'Error', configurableFor: true },
'type-invalid-items': { severity: 'Error' }, // not supported yet
'assoc-as-type': { severity: 'Error' }, // TODO: allow more, but not all
'def-unexpected-nested-proj': { severity: 'Error' },
'def-unexpected-paramview-assoc': { severity: 'Error' },
'def-unexpected-calcview-assoc': { severity: 'Error' },
'def-missing-type': { severity: 'Error', configurableFor: [ 'compile' ] },
'def-missing-argument': { severity: 'Error' },
'check-proper-type-of': { severity: 'Info', errorFor: [ 'for.odata', 'to.edmx', 'to.hdbcds', 'to.sql', 'to.hdi', 'to.rename', 'for.effective' ] },
'def-duplicate-autoexposed': { severity: 'Error' },
'def-unexpected-default': { severity: 'Error', configurableFor: 'test' },
'expr-unexpected-filter': { severity: 'Error' },
'empty-type': { severity: 'Info' }, // only still an error in old transformers
'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
'ref-deprecated-self-element': { severity: 'Error', configurableFor: true },
'ref-deprecated-variable': { severity: 'Warning' },
'ref-invalid-type': { severity: 'Error' },
'ref-unexpected-self': { severity: 'Error' },
'ref-invalid-include': { severity: 'Error' },
'type-unexpected-typeof': { severity: 'Error' },
'type-unexpected-null': { severity: 'Error', configurableFor: true },
'type-ignoring-argument': { severity: 'Error', configurableFor: true },
'type-expected-builtin': { severity: 'Error', configurableFor: true },
'type-expecting-service-target': { severity: 'Error', configurableFor: true },
'ref-expecting-const': { severity: 'Error' },
'ref-expecting-foreign-key': { severity: 'Error' },
'ref-invalid-source': { severity: 'Error' },
'ref-invalid-target': { severity: 'Error' },
'ref-missing-self-counterpart': { severity: 'Error', configurableFor: true },
'ref-sloppy-target': { severity: 'Error', configurableFor: 'deprecated' },
'extend-repeated-intralayer': { severity: 'Warning' },
'extend-unrelated-layer': { severity: 'Info' },
'ext-duplicate-extend-type': { severity: 'Error' },
'ext-duplicate-extend-type-unrelated-layer': { severity: 'Error', configurableFor: true },
'param-default': { severity: 'Error' }, // not supported yet
'query-unexpected-assoc-hdbcds': { severity: 'Error' },
'query-unexpected-structure-hdbcds': { severity: 'Error' },
'query-ignoring-param-nullability': { severity: 'Info' },
'query-expected-identifier': { severity: 'Error' },
'recalculated-localized': { severity: 'Info' }, // KEEP: Downgrade in lib/transform/translateAssocsToJoins.js
'redirected-implicitly-ambiguous': { severity: 'Error', configurableFor: true }, // does not hurt us - TODO: ref-ambiguous-target
'type-ambiguous-target': { severity: 'Warning' },
'ref-unexpected-autoexposed': { severity: 'Error' },
'ref-unexpected-many-navigation': { severity: 'Error' },
// Published! Used in @sap/cds-lsp; if renamed, add to oldMessageIds and contact colleagues
'ref-undefined-art': { severity: 'Error' },
'ref-undefined-def': { severity: 'Error' },
'ref-undefined-var': { severity: 'Error' },
'ref-undefined-element': { severity: 'Error' },
'anno-undefined-element': { severity: 'Error' },
'ref-unknown-var': { severity: 'Info' },
'ref-obsolete-parameters': { severity: 'Error', configurableFor: 'deprecated' },
// does not hurt us, but makes it tedious to detect parameter refs
'ref-undefined-param': { severity: 'Error' },
'ref-undefined-enum': { severity: 'Warning', errorFor: [ 'to.sql', 'to.hdbcds', 'to.hdi' ] },
'ref-unexpected-enum': { severity: 'Warning', errorFor: [ 'to.sql', 'to.hdbcds', 'to.hdi' ] },
'anno-undefined-param': { severity: 'Error' },
'ref-rejected-on': { severity: 'Error' },
'ref-expected-element': { severity: 'Error' },
'rewrite-key-not-covered-explicit': { severity: 'Error' },
'rewrite-key-not-covered-implicit': { severity: 'Error' },
'rewrite-key-not-matched-explicit': { severity: 'Error' },
'rewrite-key-not-matched-implicit': { severity: 'Error' },
'service-nested-context': { severity: 'Error', configurableFor: true }, // does not hurt compile, TODO
'service-nested-service': { severity: 'Error' }, // not supported yet; TODO: configurableFor:'test'?
'expr-unexpected-operator': { severity: 'Error', configurableFor: true },
// Published! Used in @sap/cds-lsp; if renamed, add to oldMessageIds and contact colleagues
// Also used by other projects that rely on double-quotes for delimited identifiers.
'syntax-deprecated-ident': { severity: 'Error', configurableFor: true },
'syntax-deprecated-property': { severity: 'Error', configurableFor: 'test' }, // v0 prop
'syntax-deprecated-value': { severity: 'Error', configurableFor: 'test' }, // v0 prop
// 'syntax-duplicate-annotate' came late with v3 - make it configurable as
// fallback, but then parse.cdl is not supposed to work correctly (it can
// then either issue an error or produce a CSN missing some annotations):
'syntax-duplicate-annotate': { severity: 'Error' },
'syntax-duplicate-clause': { severity: 'Error' },
// remark: a hard syntax error in new parser for `null` together with `not null`
'syntax-duplicate-equal-clause': { severity: 'Warning' },
'syntax-invalid-name': { severity: 'Error' },
'syntax-missing-as': { severity: 'Error', configurableFor: true },
'syntax-missing-proj-semicolon': { severity: 'Warning' },
'syntax-unexpected-after': { severity: 'Error' },
'syntax-unexpected-filter': { severity: 'Error', configurableFor: true },
'syntax-unexpected-many-one': { severity: 'Error' },
'syntax-deprecated-ref-virtual': { severity: 'Error' },
'syntax-unexpected-reserved-word': { severity: 'Error', configurableFor: true },
'syntax-unknown-escape': { severity: 'Error', configurableFor: true },
'syntax-unsupported-masked': { severity: 'Error', configurableFor: 'deprecated' },
'syntax-unexpected-sql-clause': { severity: 'Error' }, // TODO: configurableFor:'tests'?
'syntax-invalid-space': { severity: 'Error', configurableFor: true },
'syntax-expecting-space': { severity: 'Error' },
'syntax-unexpected-anno': { severity: 'Error' },
'migration-unsupported-key-change': { severity: 'Error', configurableFor: [ 'to.sql.migration', 'to.sql.migration-script' ] },
'type-missing-enum-value': { severity: 'Error', configurableFor: 'deprecated' },
'def-missing-element': { severity: 'Error' },
'def-missing-virtual': { severity: 'Error', configurableFor: true },
'def-expected-structured': { severity: 'Error', configurableFor: true },
'def-unsupported-calc-elem': { severity: 'Error', configurableFor: true },
'def-invalid-key-cardinality': { severity: 'Error' },
'odata-unexpected-array': { severity: 'Warning' },
'odata-unexpected-assoc': { severity: 'Warning' },
'odata-incomplete-constraints': { severity: 'Info' },
'odata-invalid-name': { severity: 'Error', configurableFor: true },
'odata-invalid-vocabulary-alias': { severity: 'Error', configurableFor: true },
'odata-invalid-qualifier': { severity: 'Error', configurableFor: true },
'odata-invalid-service-name': { severity: 'Warning' },
'odata-invalid-param-type': { severity: 'Warning' },
'odata-invalid-return-type': { severity: 'Warning' },
'odata-missing-type': { severity: 'Error', configurableFor: true },
'odata-invalid-scale': { severity: 'Error', configurableFor: true },
'odata-unexpected-edm-facet': { severity: 'Error', configurableFor: true },
'odata-invalid-external-type': { severity: 'Error', configurableFor: true },
'odata-unexpected-edm-type': { severity: 'Error', configurableFor: true },
'odata-unknown-edm-type': { severity: 'Error', configurableFor: true },
'odata-missing-key': { severity: 'Error', configurableFor: true },
'odata-unexpected-arrayed-key': { severity: 'Error', configurableFor: true },
'odata-unexpected-nullable-key': { severity: 'Error', configurableFor: true },
'odata-invalid-key-type': { severity: 'Warning' },
'odata-invalid-property-name': { severity: 'Warning' },
'odata-anno-preproc': { severity: 'Warning' },
'odata-anno-dict': { severity: 'Warning' },
'odata-anno-vocref': { severity: 'Warning' },
'odata-anno-dict-enum': { severity: 'Error' },
'odata-anno-value': { severity: 'Warning' },
'odata-anno-type': { severity: 'Warning' },
'odata-anno-def': { severity: 'Info' },
'odata-duplicate-definition': { severity: 'Error' },
'odata-duplicate-proxy': { severity: 'Warning' },
'query-ignoring-assoc-in-union': { severity: 'Info' },
// for to.sql.migration - cannot be supplied by the user!
'migration-unsupported-precision-change': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
'migration-unsupported-element-drop': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
'migration-unsupported-length-change': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
'migration-unsupported-scale-change': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
'migration-unsupported-change': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
'migration-unsupported-table-drop': { severity: 'Error', configurableFor: [ 'to.sql.migration-script' ] },
// end of to.sql.migration specific
};
// Old/Deprecated message IDs that we only still use for backwards-compatibility.
// We keep them in a separate array for easier access. No need to go through all
// existing messages and search for the old one in `oldNames` property.
// The keys will be added to `oldNames` of the new message, which is used for reclassification.
const oldMessageIds = {
__proto__: null,
'old-anno-duplicate': 'anno-duplicate', // Example
'assoc-in-array': 'type-invalid-items',
'duplicate-autoexposed': 'def-duplicate-autoexposed',
'expr-no-filter': 'expr-unexpected-filter',
'check-proper-type': 'def-missing-type',
// All odata messages were renamed in v6. Some were split up into separate ones.
'odata-spec-violation-array': 'odata-unexpected-array',
'odata-spec-violation-assoc': 'odata-unexpected-assoc',
'odata-spec-violation-constraints': 'odata-incomplete-constraints',
'odata-spec-violation-id': [ 'odata-invalid-name', 'odata-invalid-vocabulary-alias', 'odata-invalid-qualifier' ],
'odata-spec-violation-namespace': 'odata-invalid-service-name',
'odata-spec-violation-param': 'odata-invalid-param-type',
'odata-spec-violation-returns': 'odata-invalid-return-type',
'odata-spec-violation-type': [ 'odata-unexpected-edm-facet', 'odata-missing-type', 'odata-invalid-scale', 'odata-unexpected-edm-type', 'odata-invalid-external-type' ],
'odata-spec-violation-type-unknown': 'odata-unknown-edm-type',
'odata-spec-violation-no-key': 'odata-missing-key',
'odata-spec-violation-key-array': 'odata-unexpected-arrayed-key',
'odata-spec-violation-key-type': 'odata-invalid-key-type',
'odata-spec-violation-key-null': 'odata-unexpected-nullable-key',
'odata-spec-violation-property-name': 'odata-invalid-property-name',
'odata-definition-exists': [ 'odata-duplicate-definition', 'odata-duplicate-proxy' ],
};
// Set up the old-to-new message ID mapping in the message registry.
for (const oldName in oldMessageIds) {
if (centralMessages[oldName])
throw new CompilerAssertion(`Mapping from ${ oldName } not possible: ID is still used in message registry.`);
const newNames = Array.isArray(oldMessageIds[oldName]) ? oldMessageIds[oldName] : [ oldMessageIds[oldName] ];
for (const newName of newNames) {
if (!centralMessages[newName])
throw new CompilerAssertion(`Mapping from ${ oldName } to new message ID ${ newName } does not exist!`);
centralMessages[newName].oldNames ??= [ ];
centralMessages[newName].oldNames.push(oldName);
}
}
// For messageIds, where no text has been provided via code (central def).
// DO NOT CHANGE THE VARIABLE NAME!
// If you change it, keep in sync with scripts/eslint/rules/message-text.js
const centralMessageTexts = {
'api-deprecated-hdbcds': 'Support for generating hdbcds output is deprecated with @sap/cds-compiler v5 and later',
'api-invalid-option': {
std: 'Invalid option $(NAME)!',
deprecated: 'Option $(NAME) is no longer supported! Use latest API options instead',
magicVars: 'Option $(PROP) is no longer supported! Use $(OTHERPROP) instead. See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
value: 'Expected option $(PROP) to have $(VALUE). Found: $(OTHERVALUE)',
value2: 'Expected option $(OPTION) to have value $(VALUE) or $(RAWVALUE); found: $(OTHERVALUE)',
type: 'Expected option $(OPTION) to be of type $(VALUE). Found: $(OTHERVALUE)',
forbidden: 'Option $(OPTION) can\'t be used with API function $(MODULE)',
odataV2json: 'OData JSON output is not available for OData V2',
},
'def-upcoming-virtual-change': {
std: 'This select item is a new element in cds-compiler v6, but only supported with the new parser',
},
'query-invalid-virtual-struct': 'For a virtual structure in a query, use a defined structure type, or add $(CODE) when you meant to specify references',
'api-invalid-variable-replacement': {
std: 'Option $(OPTION) does not support $(NAME)',
user: 'Option $(OPTION) expects $(PROP) instead of $(OTHERPROP). See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
locale: 'Option $(OPTION) expects $(PROP) instead of $(OTHERPROP). See <https://cap.cloud.sap/docs/guides/databases#configuring-variables> for details',
noDollar: 'Option $(OPTION) does not know $(NAME). Did you forget a leading $(CODE)?',
},
'api-invalid-version': {
std: 'Invalid CSN version: $(VERSION)',
migrationComparison: 'Incompatible CSN versions: $(VALUE) is a major downgrade from $(OTHERVALUE). Is @sap/cds-compiler version $(VERSION) outdated?',
},
'api-invalid-combination': {
std: 'Invalid option combination found: $(OPTION) and $(PROP)', // unused
'valid-structured': 'Structured OData is only supported with OData version v4',
'sql-dialect-and-naming': 'sqlDialect $(NAME) can\'t be combined with sqlMapping $(PROP)',
'tenant-and-naming': 'Option $(OPTION) can\'t be combined with sqlMapping $(PROP) - expected sqlMapping $(VALUE)',
'dry-and-script': 'script:true must be combined with dry:true, found $(VALUE)',
'hana-migration': 'SQL dialect $(VALUE) is not supported with API function "to.sql.migration" - use HDI via "to.hdi" and "to.hdi.migration"',
'effectiveServiceName-and-type-resolution': 'Option $(NAME) can\'t be used without $(PROP)',
},
'api-unexpected-combination': {
std: 'Unexpected option combination: $(OPTION) and $(PROP)', // unused
'beta-no-test':'Option $(OPTION) was used. This option should not be used in productive scenarios!',
},
'api-unexpected-option': 'Option $(OPTION) can\'t be used in backend $(MODULE)',
'api-invalid-lookup-dir': {
std: '',
slash: 'Expected directory $(VALUE) in option $(OPTION) to end with $(OTHERVALUE)',
relative: 'Expected directory $(VALUE) in option $(OPTION) to not start with $(OTHERVALUE)',
},
'api-unsupported-csn-flavor': {
std: 'Module $(NAME) expects a client/inferred CSN, not $(OPTION)',
'parsed-requires': 'Module $(NAME) expects a client/inferred CSN, or a parsed CSN without dependencies, but found $(PROP) property',
},
'anno-duplicate': {
std: 'Duplicate assignment with $(ANNO)',
doc: 'Duplicate assignment with a doc comment',
},
'anno-duplicate-same-file': {
std: 'Duplicate assignment with $(ANNO), using last',
doc: 'Duplicate assignment with a doc comment, using last',
},
'anno-duplicate-unrelated-layer': {
std: 'Duplicate assignment with $(ANNO)',
doc: 'Duplicate assignment with a doc comment',
},
'anno-unstable-array': 'Unstable order of array items due to repeated assignments for $(ANNO)',
'anno-mismatched-ellipsis': 'An array with $(CODE) can only be used if there is an assignment below with an array value',
'anno-unexpected-ellipsis': 'No base annotation available to apply $(CODE)',
'anno-unexpected-localized-skip': {
std: 'Compiler generated entity $(NAME) must not be annotated with $(ANNO) if $(ART) is not skipped',
view: 'Compiler generated view $(NAME) must not be annotated with $(ANNO) if $(ART) is not skipped',
},
'anno-missing-rewrite': {
std: 'Assign a value for $(ANNO); the value inherited from $(ART) can\'t be rewritten due to $(ELEMREF)',
unsupported: 'Assign a value for $(ANNO); the value inherited from $(ART) can\'t be rewritten due to unsupported $(ELEMREF)',
param: 'Assign a value for $(ANNO); the value inherited from $(ART) can\'t be rewritten due to parameter reference $(ELEMREF)',
},
'check-proper-type-of': {
std: 'Referred element $(NAME) of $(ART) does not contain proper type information',
derived: 'Referred type of $(ART) does not contain proper type information',
managedAssocForeignKey: 'Foreign key $(NAME) of managed association $(ART) must have a type',
managedCompForeignKey: 'Foreign key $(NAME) of managed composition $(ART) must have a type',
},
'name-duplicate-element': {
std: 'Generated element $(NAME) conflicts with another element',
'flatten-element-gen': 'Generated element $(NAME) conflicts with other generated element',
'flatten-element-exist': 'Flattened name of structured element conflicts with existing element $(NAME)',
'flatten-fkey-gen': 'Duplicate definition of foreign key element $(NAME) for association $(ART)',
'flatten-fkey-exists': 'Generated foreign key element $(NAME) for association $(ART) conflicts with existing element',
},
'name-invalid-dollar-alias': {
std: 'An alias name starting with $(NAME) might shadow a special variable; replace by another name',
$tableAlias: 'A table alias name must not start with $(NAME); choose another name',
$tableImplicit: 'The resulting table alias starts with $(NAME); choose another name with $(KEYWORD)',
mixin: 'A mixin name starting with $(NAME) might shadow a special variable; replace by another name',
},
'name-missing-alias': {
std: 'Missing table alias for this subquery',
duplicate: 'Missing table alias for this subquery; add $(CODE) to fix name clash of internal and explicit table alias',
hdbcds: 'Missing table alias for a subquery; SAP HANA CDS requires table aliases',
},
// Syntax messages, both CDL and CSN parser: ----------------------------------
'syntax-deprecated-abstract': {
std: 'Abstract entity definitions are deprecated; use aspect definitions instead',
'strange-kind': 'The property $(PROP) is deprecated; expecting it only with kind $(KIND) to define an aspect',
},
'syntax-duplicate-excluding': {
std: 'Duplicate $(NAME) in the $(KEYWORD) clause',
csn: 'Duplicate $(NAME) in property $(PROP)',
},
'syntax-expecting-unsigned-int': { // TODO: test all in SyntaxOnly/
std: 'A safe non-negative integer is expected here',
normal: 'A non-negative integer number is expected here',
unsafe: 'The provided integer is too large',
csn: 'Expecting a non-negative integer for property $(PROP)',
'or-asterisk': 'Expecting a non-negative integer or string $(OP) for property $(PROP)',
},
'syntax-ignoring-decimal': {
std: 'Ignoring decimal places, because an integer was expected',
},
'syntax-unexpected-anno': {
std: 'Annotations can\'t be used in a column with $(CODE)',
doc: 'Doc comments can\'t be used in a column with $(CODE)',
},
'syntax-unexpected-after': {
std: 'Unexpected $(KEYWORD) after annotation assignment',
many: 'Unexpected $(KEYWORD) after array type',
enum: 'Unexpected annotation assignment after enum type',
},
'syntax-unexpected-filter': 'Unexpected filter on the result of a function call',
'syntax-unexpected-many-one': 'Replace $(CODE) with $(DELIMITED) to avoid an ambiguity with managed compositions of anonymous aspects',
'syntax-deprecated-ref-virtual': {
std: 'Use $(DELIMITED) at the beginning of the column expression',
ref: 'Use $(DELIMITED) to refer to the element $(NAME) at the beginning of the column expression',
func: 'Use $(DELIMITED) when calling the function $(NAME) at the beginning of the column expression',
},
'syntax-invalid-name': {
std: 'Identifier must consist of at least one character', // only via delimited id
// as: 'String in property $(PROP) must not be empty', // expecting non-empty string is ok
'{}': 'Property name in structured value must not be empty', // CSN anno val
dict: 'Property name in dictionary $(PARENTPROP) must not be empty',
'=': 'The dot-separated name parts in property $(PROP) must not be empty',
type: 'The dot-separated element name parts in property $(PROP) must not be empty', // CSN v0
},
'syntax-invalid-literal': {
std: 'Invalid literal value',
'uneven-hex': 'A binary literal must have an even number of characters',
'invalid-hex': 'A binary literal must only contain characters ‹0-9›, ‹a-f› and ‹A-F›',
time: 'A time literal must look like ‹hh:mm:ss› or ‹hh:mm› where each letter represents a digit. A timezone is optional',
date: 'A date literal must look like ‹YYYY-MM-DD› where each letter represents a digit',
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. A timezone is optional',
number: 'The string value in property $(PROP) does not represent a number',
expecting: 'Expecting literal type $(OP) for the value in property $(OTHERPROP)',
typeof: 'String $(RAWVALUE) is no valid literal type for the string value in property $(OTHERPROP)',
},
'syntax-invalid-source': {
std: 'The given source is invalid', // unused
'cdl-stackoverflow': 'The parser ran into a stack overflow. Does your CDS file contain too many nested artifacts?',
},
'syntax-missing-ellipsis': 'Expecting an array item $(NEWCODE) after an item with $(CODE)',
'syntax-unexpected-ellipsis': {
std: 'Unexpected array item $(CODE)',
duplicate: 'Unexpected array item $(CODE) after previous $(CODE) without $(KEYWORD)',
'csn-duplicate': 'Unexpected object with property $(PROP) after previous array item $(CODE)',
'csn-nested': 'Unexpected object with property $(PROP) in nested array',
},
'syntax-invalid-anno': {
std: 'Unexpected $(OFFENDING), invalid annotation value, expecting $(EXPECTING)',
empty: 'Unexpected $(OFFENDING), empty structure flattens to nothing, expecting $(EXPECTING)',
ellipsis: 'Unexpected $(OFFENDING) in inner array value, expecting $(EXPECTING)',
bracket: 'Missing array item $(CODE) before $(OFFENDING), expecting $(EXPECTING)',
},
'syntax-unsupported-masked': { // configurable Error
std: 'The keyword $(KEYWORD) is not supported',
csn: 'The property $(PROP) is not supported',
},
// Syntax messages, CDL parser -----------------------------------------------
// 'syntax-deprecated-auto-as', 'syntax-deprecated-ident'
'syntax-duplicate-annotate': 'You can\'t refer to $(NAME) repeatedly with property $(PROP) in the same annotate statement',
'syntax-duplicate-argument': {
std: 'Duplicate value for parameter $(NAME)',
type: 'Duplicate value for type parameter $(NAME)',
},
'syntax-duplicate-clause': {
std: 'You have already provided this clause',
cardinality: 'You have already provided a target cardinality $(CODE) instead, at line $(LINE), column $(COL)',
notNull: 'You have already provided $(CODE) instead, at line $(LINE), column $(COL) below',
orderByLimit: 'You have already provided $(CODE) before',
setForCsn: 'You have provided property $(PROP)/$(SIBLINGPROP) inside and outside $(PARENTPROP)',
},
'syntax-duplicate-equal-clause': {
std: 'You have already provided the same clause',
cardinality: 'You have already provided the target cardinality $(CODE) at line $(LINE), column $(COL)',
notNull: 'You have already provided $(CODE) at line $(LINE), column $(COL)',
},
'syntax-duplicate-extend': {
std: 'You can\'t define and refer to $(NAME) repeatedly in the same extend statement',
define: 'You can\'t refer to $(NAME) in the same extend statement where it was defined',
extend: 'You can\'t refer to $(NAME) repeatedly in the same extend statement',
},
// 'syntax-duplicate-anno', 'syntax-duplicate-doc-comment', 'syntax-duplicate-property',
// 'syntax-duplicate-wildcard'
'syntax-invalid-path-separator': {
std: 'Invalid reference path separator', // unused
dot: 'Use a $(NEWCODE), not a $(CODE) after the arguments or filter on an entity',
colon: 'Use a $(NEWCODE), not a $(CODE) between the element names in a reference',
},
// 'syntax-ignoring-doc-comment' (Info)
'syntax-unexpected-reserved-word': '$(CODE) is a reserved word - write $(DELIMITED) instead if you want to use it as name',
'syntax-invalid-text-block': 'Missing newline in text block',
// 'syntax-missing-newline' (Warning), 'syntax-missing-as',
// 'syntax-missing-token'
'syntax-unexpected-extension': {
std: 'Unexpected $(KEYWORD) inside $(CODE) block',
'new-parser': 'Unexpected $(OFFENDING) inside $(CODE) block, expecting $(EXPECTING)',
},
'syntax-unexpected-token': {
std: 'Mismatched $(OFFENDING), expecting $(EXPECTING)',
unwanted: 'Extraneous $(OFFENDING), expecting $(EXPECTING)',
noRepeatedCardinality: 'Unexpected $(OFFENDING), cardinality already provided at $(LOCATION) via $(CODE), expecting $(EXPECTING)',
nestedExpand: 'Unexpected $(OFFENDING), nested projections are valid after a reference only, expecting $(EXPECTING)',
},
'syntax-unexpected-vocabulary': {
std: 'Annotations can\'t be defined inside contexts or services', // used inside extensions
service: 'Annotations can\'t be defined inside services',
context: 'Annotations can\'t be defined inside contexts',
'extend-new': 'Unexpected $(OFFENDING) definition inside a context or service, expecting $(EXPECTING)',
'service-new': 'Unexpected $(OFFENDING) definition inside a service, expecting $(EXPECTING)',
'context-new': 'Unexpected $(OFFENDING) definition inside a context, expecting $(EXPECTING)',
},
// 'syntax-unexpected-alias' (is 'syntax-unexpected-property' in CSN)
'syntax-unsupported-param': {
std: 'Parameter not supported', // unused
dynamic: 'Dynamic parameter $(CODE) is not supported',
positional: 'Positional parameter $(CODE) is not supported',
},
'syntax-unexpected-sql-clause': {
std: 'Unexpected $(KEYWORD) clause for path filter',
},
// Syntax messages, CSN parser - default: Error ------------------------------
'syntax-deprecated-dollar-syntax': {
std: 'The property $(PROP) is deprecated; its value is ignored',
projection: 'The property $(PROP) is deprecated; use property $(SIBLINGPROP) instead of $(OTHERPROP) for the query',
aspect: 'The property $(PROP) is deprecated; change the kind of the current definition to $(KIND) instead',
},
'syntax-deprecated-property': { // Configurable error
std: 'Deprecated property $(PROP)', // unused
zero: 'Deprecated CSN v0.1.0 property $(PROP) is ignored',
'zero-replace': 'Replace CSN v0.1.0 property $(PROP) by $(OTHERPROP)',
},
'syntax-deprecated-value': { // Configurable error
std: 'Deprecated representation of the value in property $(PROP)',
'zero-parens': 'Deprecated CSN v0.1.0 representation of expressions in parentheses',
'zero-replace': 'Replace CSN v0.1.0 value in $(PROP) by $(VALUE)',
},
'syntax-deprecated-type-ref': {
std: 'Expecting a string as value for property $(PROP) for a reference to a definition',
'ref-item': 'Expecting a string as value for property $(PROP) for a type reference to an element',
},
'syntax-expecting-object': {
std: 'Expecting object for property $(PROP)',
'or-asterisk': 'Expecting object or string $(OP) for property $(PROP)',
'or-string': 'Expecting object or non-empty string for property $(PROP)',
},
'syntax-expecting-string': {
std: 'Expecting non-empty string for property $(PROP)',
'or-object': 'Expecting non-empty string or object for property $(PROP)',
'or-bool': 'Expecting non-empty string or boolean for property $(PROP)',
'or-null': 'Expecting non-empty string or null for property $(PROP)',
},
// 'syntax-expecting-boolean' (Warning), 'syntax-expecting-scalar',
// 'syntax-expecting-args', 'syntax-expecting-translation', 'syntax-expecting-array'
'syntax-incomplete-array': { // location at ']'
std: 'Expecting array in $(PROP) to have at least $(N) items',
one: 'Expecting array in $(PROP) to have at least one item',
suffix: 'With sibling property $(SIBLINGPROP), expecting array in $(PROP) to have at least one item',
},
'syntax-incomplete-object': { // location at '}'
std: 'Object in $(PROP) must have at least one valid CSN property',
as: 'Object in $(PROP) must have at least one valid CSN property other than $(OTHERPROP)',
},
'syntax-invalid-string': {
std: 'Invalid string value in property $(PROP)',
},
// 'syntax-invalid-ref' (Warning?), 'syntax-invalid-kind', 'syntax-invalid-literal' (Warning)
'syntax-missing-property': { // location at sibling or '}' otherwise
std: 'Object in $(PARENTPROP) must have the property $(PROP)',
sibling: 'Object with property $(SIBLINGPROP) must also have a property $(PROP)',
bothTargets: 'Object with properties $(SIBLINGPROP) and $(OTHERPROP) must also have a property $(PROP)',
columns: 'Object in $(PARENTPROP) must have an expression property like $(PROP)',
extensions: 'Object in $(PARENTPROP) must have the property $(PROP) or $(OTHERPROP)',
},
'syntax-unexpected-property': {
std: 'Unexpected CSN property $(PROP)',
sibling: 'CSN property $(PROP) is not expected in an object with property $(SIBLINGPROP)',
target: 'CSN property $(PROP) with sub property $(SUBPROP) is not expected in an object with property $(SIBLINGPROP)',
targetAspect: 'CSN property $(PROP) is not expected in an object with property $(SIBLINGPROP) having sub property $(SUBPROP)',
prop: 'CSN property $(PROP) is not expected in $(PARENTPROP)',
top: 'CSN property $(PROP) is not expected top-level',
kind: 'CSN property $(PROP) is not expected by a definition of kind $(KIND)',
extend: 'CSN property $(PROP) is not expected by an extend in $(PARENTPROP)',
annotate: 'CSN property $(PROP) is not expected by an annotate in $(PARENTPROP)',
},
'def-invalid-calc-elem': {
std: 'Invalid calculated element',
key: 'A primary key element can\'t be calculated',
virtual: 'A virtual element can\'t be calculated',
localized: 'A localized element can\'t be calculated',
default: 'An element with a default value can\'t be calculated',
event: 'An event can\'t have calculated elements',
type: 'A type can\'t have calculated elements',
action: 'An action can\'t have calculated elements',
function: 'A function can\'t have calculated elements',
annotation: 'Annotation definitions can\'t have calculated elements',
param: 'Parameters can\'t have calculated elements',
},
'def-invalid-name': {
std: 'The character \'.\' is not allowed in identifiers',
element: 'The character \'.\' is not allowed in element names',
param: 'The character \'.\' is not allowed in parameter names',
action: 'The character \'.\' is not allowed in bound action names',
function: 'The character \'.\' is not allowed in bound function names',
},
'ref-invalid-calc-elem': {
std: 'Can\'t include artifact with calculated element',
event: 'An event can\'t include an artifact with calculated elements',
type: 'A type can\'t include an artifact with calculated elements',
annotation: 'An annotation can\'t include an artifact with calculated elements',
},
'def-unsupported-calc-elem': {
std: 'Calculated elements are not supported, yet',
nested: 'Calculated elements in structures are not supported, yet',
'on-write': 'Calculated elements on-write are not supported, yet',
hdbcds: 'Calculated elements on-write are not supported for HDBCDS',
},
// 'syntax-unknown-property' (Warning? Better configurable Error)
'expr-unexpected-argument': {
// TODO: change to `Arguments…`
std: 'Parameters can only be provided when navigating along associations',
from: 'Parameters can only be provided for the source entity or associations',
tableAlias: 'Arguments can\'t be provided for table aliases, only when navigating along associations',
// no-params TODO: extra message id or a variant of expr-undefined-param
'no-params': 'Unexpected arguments for entity $(ART) without parameters',
},
'expr-unexpected-filter': {
std: 'A filter can only be provided when navigating along associations',
// to help users for `… from E:toF { toF[…].x }`
tableAlias: 'A filter can only be provided when navigating along associations, but found table alias',
from: 'A filter can only be provided for the source entity or associations',
'model-only': 'A filter can\'t be provided for a to-many association without ON-condition',
},
// multi-line strings: --------------------------------------------------------
'syntax-unknown-escape': 'Unknown escape sequence $(CODE)',
'syntax-invalid-escape': {
std: 'Invalid escape sequence $(CODE)',
octal: 'Octal escape sequences are not supported. Use unicode escapes instead',
whitespace: 'Unknown escape sequence: Can\'t escape whitespace',
codepoint: 'Undefined code-point for $(CODE)',
'unicode-hex': 'Expecting hexadecimal numbers for unicode escape but found $(CODE)',
'hex-count': 'Expecting $(COUNT) hexadecimal numbers for escape sequence but found $(CODE)',
'unicode-brace': 'Missing closing brace for unicode escape sequence',
'language-identifier': 'Escape sequences in text-block\'s language identifier are not allowed',
},
'syntax-missing-escape': {
std: 'Missing escape. Replace $(CODE) with $(NEWCODE)',
placeholder: 'Placeholders are not supported. Replace $(CODE) with $(NEWCODE)',
},
// Messages for erroneous references -----------------------------------------
// location at erroneous reference (if possible)
'ref-cyclic': {
std: 'Illegal circular reference to $(ART)',
element: 'Illegal circular reference to element $(MEMBER) of $(ART)',
target: 'Illegal circular reference to target $(ART)',
type: 'Illegal recursive type definition to $(TYPE)',
},
'ref-deprecated-orderby': 'Replace source element reference $(ID) by $(NEWCODE); auto-corrected',
'ref-missing-self-counterpart' : {
std: 'Expected to find a matching element in $self-comparison for foreign key $(PROP) of association $(NAME)',
unmanaged: 'Expected to find a matching element in $self-comparison for $(PROP) of association $(NAME)',
},
'ref-unexpected-self': {
std: 'Unexpected $(ID) reference; is valid only in ON-conditions of unmanaged associations',
on: 'Unexpected $(ID) reference; is valid only if compared to be equal to an association of the target side',
subQuery: 'Unexpected $(ID) reference in a sub query',
setQuery: 'Unexpected $(ID) reference in a query on the right side of $(OP)',
exists: 'With $(NAME), path steps must not start with $(ID)',
'exists-filter': 'Unexpected $(ID) reference in filter of path $(ELEMREF) following “EXISTS” predicate',
},
'ref-unexpected-map': {
std: 'Unexpected reference to an element of type $(TYPE)', // unused
keys: 'Unexpected reference to an element of type $(TYPE) in foreign keys',
onCond: 'Unexpected reference to an element of type $(TYPE) in an ON-condition',
},
'ref-undefined-def': {
std: 'Artifact $(ART) has not been found',
// TODO: proposal 'No definition of $(NAME) found',
element: 'Artifact $(ART) has no element $(MEMBER)',
},
'ref-undefined-param': 'Entity $(ART) has no parameter $(ID)',
'anno-undefined-param': {
std: 'Entity $(ART) has no parameter $(ID)',
entity: 'Entity $(ART) has no parameter $(ID)',
action: 'Action $(ART) has no parameter $(ID)',
},
'ref-undefined-art': {
std: 'No artifact has been found with name $(ART)',
namespace: 'No artifact has been found with name $(ART) which can be extended with annotations',
localized: 'Can\'t extend localized definitions, only annotate them using an $(KEYWORD) statement',
},
// TODO: proposal 'No definition found for $(NAME)',
'ref-undefined-element': {
std: 'Element $(ART) has not been found',
element: 'Artifact $(ART) has no element $(MEMBER)',
target: 'Target entity $(ART) has no element $(ID)',
aspect: 'Element $(ID) has not been found in the anonymous target aspect',
query: 'The current query has no element $(ART)',
alias: 'Element $(ART) has not been found in the sub query for alias $(ALIAS)',
virtual: 'Element $(ART) has not been found. Use $(CODE) to add virtual elements in queries',
},
'anno-undefined-element': {
std: 'Element $(ART) has not been found',
element: 'Artifact $(ART) has no element $(MEMBER)',
target: 'Target entity $(ART) has no element $(ID)',
query: 'The current query has no element $(ART)',
alias: 'Element $(ART) has not been found in the sub query for alias $(ALIAS)',
aspect: 'Element $(ID) has not been found in the anonymous target aspect',
},
'ref-undefined-var': {
std: 'Variable $(ID) has not been found',
alias: 'Variable $(ID) has not been found. Use table alias $(ALIAS) to refer an element with the same name',
self: 'Variable $(ID) has not been found. Use $(ALIAS) to refer an element with the same name',
value: 'No value found for variable $(ID). Use option $(OPTION) to specify a value for $(ID)',
},
'ref-undefined-enum': 'Enum symbol $(ID) is not defined in $(TYPE)',
'ref-unexpected-enum': {
std: 'Unexpected enum reference $(ENUM)',
symbolDef: 'References to other values are not allowed as enum values',
untyped: 'Unexpected enum reference $(ENUM); no type can be inferred for it',
invalidType: 'Unexpected enum reference $(ENUM) as value for a non-enum type $(TYPE)',
},
'ref-unknown-var': {
std: 'No replacement found for special variable $(ID)',
},
'ref-unexpected-draft-enabled': 'Composition in draft-enabled entity can\'t lead to another entity with $(ANNO)',
'ref-rejected-on': { // TODO: currently not used - just remove?
std: 'Do not refer to a artefact like $(ID) in the explicit ON of a redirection', // Not used
mixin: 'Do not refer to a mixin like $(ID) in the explicit ON of a redirection',
alias: 'Do not refer to a source element (via table alias $(ID)) in the explicit ON of a redirection',
},
'ref-expected-element': {
std: 'Expected element reference',
magicVar: 'Only elements of variable $(ID) can be selected',
},
'ref-expected-direct-structure': {
std: '$(ART) can\'t be extended because it originates from an include',
elements: '$(ART) can\'t be extended by elements/enums because it originates from an include',
},
'ref-unexpected-many-navigation': {
std: 'Unexpected navigation into arrayed structure',
},
'ref-unexpected-scope': {
std: 'Unexpected parameter reference',
calc: 'Calculated elements can\'t use parameter references',
},
'ref-unexpected-structured': {
std: 'Unexpected usage of structured type $(ELEMREF)',
expr: 'Structured elements can\'t be used in expressions',
},
'ref-unexpected-virtual': {
std: 'Unexpected reference to virtual element $(NAME)', // "std" currently unused
expr: 'Virtual elements can\'t be used in expressions',
fkey: 'Virtual elements can\'t be used as foreign keys for managed associations',
},
'ref-unexpected-assoc': {
std: 'Unexpected reference to association $(NAME)', // "std" currently unused
unmanaged: 'Unexpected reference to an unmanaged association',
'self-unmanaged': 'Unexpected column reference starting with $(ALIAS) to an unmanaged association',
'with-filter': 'Unexpected reference to an association with filter',
'self-with-filter': 'Unexpected column reference starting with $(ALIAS) to an association with filter',
self: 'A reference to an unmanaged association is only valid when compared via $(CODE)',
expr: 'Associations can\'t be used as values in expressions',
'expr-comp': 'Compositions can\'t be used as values in expressions',
'assoc-stored': 'Associations and compositions can\'t be used as values in stored calculated elements',
'managed-filter': 'Unexpected managed association $(NAME) in filter expression of $(ID)',
'unmanaged-filter': 'Unexpected unmanaged association $(NAME) in filter expression of $(ID)',
},
'ref-unexpected-assoc-type': {
std: 'An association is not allowed as this artifact\'s type', // Not used
'action-param': 'An association is not allowed as action\'s parameter type',
'function-param': 'An association is not allowed as function\'s parameter type',
'action-returns': 'An association is not allowed as action\'s return type',
'function-returns': 'An association is not allowed as function\'s return type',
},
'ref-unexpected-calculated': {
std: 'Unexpected reference to calculated element',
on: 'Calculated elements (on-read) can\'t be used in ON-conditions of unmanaged associations',
fkey: 'Calculated elements (on-read) can\'t be used as foreign keys for managed associations',
},
'ref-unexpected-localized': {
std: 'Unexpected reference to localized element $(NAME)', // "std" currently unused
calc: 'Calculated elements "on-write" can\'t refer to localized elements',
},
'ref-unexpected-navigation': {
std: 'Can\'t follow association $(ID) in path $(ELEMREF) in an ON-condition; only foreign keys can be referred to, but not $(NAME)',
unmanaged: 'Can\'t follow association $(ID) in path $(ELEMREF) in an ON-condition',
unmanagedleaf: 'Unexpected unmanaged association as final path step of $(ELEMREF) in an ON-condition',
'calc-non-fk': 'Can\'t follow association $(ID) in path $(ELEMREF) in a stored calculated element; only foreign keys can be referred to, but not $(NAME)',
'calc-unmanaged': 'Can\'t follow association $(ID) in path $(ELEMREF) in a stored calculated element',
},
'ref-unexpected-filter': {
std: 'Unexpected filter in path $(ELEMREF)', // unused
'on-condition': 'ON-conditions must not contain filters, step $(ID) of path $(ELEMREF)',
calc: 'Unexpected filter in path $(ELEMREF) of stored calculated element; only simple paths can be used here',
},
'ref-unexpected-args': {
std: 'Unexpected arguments in path $(ELEMREF)', // unused
'on-condition': 'ON-conditions must not contain parameters, step $(ID) of path $(ELEMREF)',
calc: 'Unexpected arguments in path $(ELEMREF) of stored calculated element; only simple paths can be used here',
},
'ref-unsupported-type': {
std: 'Type $(TYPE) is not supported',
dialect: 'Type $(TYPE) is not supported for SQL dialect $(VALUE)',
hana: 'Type $(TYPE) is only supported for SQL dialect $(VALUE), not $(OTHERVALUE)',
hdbcds:'Type $(TYPE) is not supported in HDBCDS',
odata: 'Type $(TYPE) is not supported for OData $(VERSION)',
key: 'Type $(TYPE) can\'t be used as primary key in element $(NAME)',
},
'ref-unexpected-var': {
std: 'Variable $(NAME) can\'t be used here',
annotation: 'Variable $(NAME) can only be used in annotation values',
},
'rewrite-not-supported': {
// TODO: Better text ?
std: 'The ON-condition is not rewritten here - provide an explicit ON-condition',
'inline-expand': 'The ON-condition is not rewritten in nested projections - provide an explicit ON-condition',
secondary: 'The ON-condition is not rewritten due to multiple associations in this path - provide an explicit ON-condition',
},
'rewrite-not-projected': {
std: 'Projected association $(NAME) uses non-projected element $(ELEMREF)',
element: 'Projected association $(NAME) uses non-projected element $(ELEMREF) of $(ART)',
},
'type-unsupported-rewrite': {
std: 'Rewriting the ON-condition not supported here', // unused: merge with 'rewrite-not-supported'