UNPKG

@sap/cds-compiler

Version:

CDS (Core Data Services) compiler and backends

870 lines (810 loc) 88.2 kB
// 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'