@sap/cds-compiler 6.7.3 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +70 -0
- package/README.md +4 -0
- package/bin/cdsc.js +5 -5
- package/bin/cdshi.js +1 -0
- package/bin/cdsse.js +1 -1
- package/lib/api/main.js +17 -9
- package/lib/api/options.js +5 -2
- package/lib/api/validate.js +1 -1
- package/lib/base/builtins.js +13 -9
- package/lib/{model → base}/csnRefs.js +8 -10
- package/lib/base/error.js +2 -0
- package/lib/base/message-registry.js +68 -4
- package/lib/base/messages.js +4 -2
- package/lib/{optionProcessor.js → base/optionProcessor.js} +5 -3
- package/lib/base/{model.js → specialOptions.js} +16 -39
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/elements.js +1 -1
- package/lib/checks/enricher.js +2 -2
- package/lib/checks/featureFlags.js +54 -24
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/onConditions.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/validator.js +10 -14
- package/lib/compiler/assert-consistency.js +11 -9
- package/lib/compiler/base.js +5 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +3 -3
- package/lib/compiler/define.js +6 -3
- package/lib/{base → compiler}/dictionaries.js +4 -3
- package/lib/compiler/extend.js +121 -21
- package/lib/compiler/generate.js +2 -2
- package/lib/compiler/index.js +11 -3
- package/lib/compiler/kick-start.js +1 -1
- package/lib/compiler/lsp-api.js +3 -3
- package/lib/compiler/populate.js +6 -7
- package/lib/compiler/resolve.js +53 -36
- package/lib/compiler/shared.js +68 -18
- package/lib/compiler/tweak-assocs.js +2 -2
- package/lib/compiler/utils.js +28 -27
- package/lib/compiler/xpr-rewrite.js +3 -3
- package/lib/edm/EdmPrimitiveTypeDefinitions.js +4 -1
- package/lib/edm/annotations/edmJson.js +2 -4
- package/lib/edm/annotations/genericTranslation.js +51 -7
- package/lib/edm/csn2edm.js +3 -2
- package/lib/edm/edmAnnoPreprocessor.js +1 -1
- package/lib/edm/edmInboundChecks.js +2 -1
- package/lib/edm/edmPreprocessor.js +3 -3
- package/lib/edm/edmUtils.js +2 -2
- package/lib/gen/BaseParser.js +59 -108
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +2052 -1965
- package/lib/gen/Dictionary.json +67 -7
- package/lib/json/from-csn.js +14 -14
- package/lib/json/to-csn.js +77 -38
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +2 -2
- package/lib/modelCompare/compare.js +1 -1
- package/lib/modelCompare/utils/filter.js +1 -0
- package/lib/parsers/AstBuildingParser.js +83 -33
- package/lib/parsers/index.js +1 -1
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +49 -30
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toSql.js +16 -7
- package/lib/render/utils/common.js +11 -3
- package/lib/render/utils/sql.js +14 -5
- package/lib/render/utils/standardDatabaseFunctions.js +108 -99
- package/lib/sql-identifier.js +9 -1
- package/lib/{model → tool-lib}/enrichCsn.js +3 -2
- package/lib/{model → tool-lib}/revealInternalProperties.js +2 -1
- package/lib/transform/addTenantFields.js +1 -1
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +1 -1
- package/lib/transform/db/backlinks.js +2 -2
- package/lib/transform/db/expansion.js +2 -2
- package/lib/transform/db/flattening.js +3 -4
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +2 -1
- package/lib/transform/db/rewriteCalculatedElements.js +2 -2
- package/lib/transform/db/temporal.js +30 -5
- package/lib/transform/db/views.js +16 -20
- package/lib/transform/draft/db.js +1 -2
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +6 -5
- package/lib/transform/effective/main.js +24 -4
- package/lib/transform/effective/types.js +1 -1
- package/lib/transform/{odata/fioriTreeViews.js → fioriTreeViews.js} +48 -25
- package/lib/transform/forOdata.js +25 -7
- package/lib/transform/forRelationalDB.js +48 -12
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/createForeignKeys.js +1 -1
- package/lib/transform/odata/flattening.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +3 -2
- package/lib/transform/odata/typesExposure.js +3 -2
- package/lib/transform/transformUtils.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +2 -1
- package/lib/transform/tupleExpansion.js +44 -4
- package/lib/transform/universalCsn/universalCsnEnricher.js +7 -3
- package/lib/transform/universalCsn/utils.js +1 -1
- package/lib/{base → utils}/lazyload.js +9 -0
- package/lib/{base → utils}/node-helpers.js +2 -0
- package/lib/utils/objectUtils.js +29 -6
- package/lib/{base → utils}/optionProcessorHelper.js +16 -6
- package/package.json +3 -40
- /package/lib/{model → base}/cloneCsn.js +0 -0
- /package/lib/{model/api.js → base/model-api.js} +0 -0
- /package/lib/{api → base}/trace.js +0 -0
- /package/lib/{model → base}/xprAsTree.js +0 -0
- /package/lib/{inspect → tool-lib}/index.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectModelStatistics.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectPropagation.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectUtils.js +0 -0
- /package/lib/{base → utils}/shuffle.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,76 @@ we might not list every change in its behavior here.
|
|
|
13
13
|
Productive code should never require a `beta` flag to be set, and
|
|
14
14
|
might use a deprecated flag only for a limited period of time.
|
|
15
15
|
|
|
16
|
+
## Version 6.9.0 - 2026-04-21
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
- **compiler:**
|
|
21
|
+
+ add support for extending views/projections with several SQL clauses:
|
|
22
|
+
`where`, `group by`, `having`, `order by`, `limit`
|
|
23
|
+
+ allow extending derived enum types/elements by adding enum symbols
|
|
24
|
+
+ inside `extend … with enum {…}`, it is now possible to use `extend existingEnumSymbol with @Anno`,
|
|
25
|
+
like it is already possible inside `extend … with {…}`
|
|
26
|
+
+ when the new options `v7KeyPropagation` is set, the propagation of the `key` property in queries is simplified,
|
|
27
|
+
and the `key` property is not propagated when including structures into types
|
|
28
|
+
- **odata:** set `meta.compilerCsnFlavor` in the OData transformed CSN
|
|
29
|
+
- **seal**: set `meta.compilerCsnFlavor` in the SEAL transformed CSN
|
|
30
|
+
- **effective:** set `meta.compilerCsnFlavor` in the effective CSN
|
|
31
|
+
- **sql:**
|
|
32
|
+
+ set `meta.compilerCsnFlavor` in SQL transformed CSN
|
|
33
|
+
+ allow single-leafed structures within a `list` on the left-hand side of the `IN` operator.
|
|
34
|
+
For example `(author, struct) in (...)` becomes `(author_ID, struct_leaf) in (...)`.
|
|
35
|
+
+ support `cds.Vector` on Postgres and H2
|
|
36
|
+
|
|
37
|
+
### Bug Fixes
|
|
38
|
+
|
|
39
|
+
- **compiler:**
|
|
40
|
+
+ don't introduce a strange `cast` property in the CSN for a column with an expand on a to-many association
|
|
41
|
+
+ while crawling tokens for LSP, allow extensions without name
|
|
42
|
+
- **effective:** don't absolutify paths in filters in annotations
|
|
43
|
+
- **sql:** properly resolve references in annotation values and `on` conditions for a column inside an expand without base reference
|
|
44
|
+
|
|
45
|
+
### Improvements
|
|
46
|
+
|
|
47
|
+
- **compiler:**
|
|
48
|
+
+ add `compilerVersion` to CSN meta
|
|
49
|
+
+ issue a warning if a structure in an annotation value would have the same CSN representation as an expression
|
|
50
|
+
+ issue warnings for extends on built-in types
|
|
51
|
+
+ warn on duplicate members from includes via extend
|
|
52
|
+
- **odata:**
|
|
53
|
+
+ update OData vocabularies: Common, Core, UI
|
|
54
|
+
+ using `@readonly` with an expression value on entities or aspects is no longer silently accepted and now produces an error
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Version 6.8.0 - 2026-03-05
|
|
59
|
+
|
|
60
|
+
### Features
|
|
61
|
+
|
|
62
|
+
- **api:** basic experimental support for code completion in `cds repl`
|
|
63
|
+
- **compiler:**
|
|
64
|
+
+ retain original meta property in CSN
|
|
65
|
+
+ add compilerCsnFlavor to meta property
|
|
66
|
+
- **sql:**
|
|
67
|
+
+ Add support for `cds.Vector`
|
|
68
|
+
+ Allow migration from cds.String to cds.LargeString
|
|
69
|
+
+ Fiori Tree Views in the database backend
|
|
70
|
+
+ For postgres: warning for identifiers that exceed the databases length limit
|
|
71
|
+
|
|
72
|
+
### Bug Fixes
|
|
73
|
+
|
|
74
|
+
- **sql:**
|
|
75
|
+
+ do not report validation errors on entities marked as `@cds.persistence.skip`
|
|
76
|
+
+ normalize named arguments for portable functions
|
|
77
|
+
+ properly flatten associations for temporal unique constraints
|
|
78
|
+
|
|
79
|
+
### Improvements
|
|
80
|
+
|
|
81
|
+
- **compiler:**
|
|
82
|
+
+ improve warning in case of invalid type for key
|
|
83
|
+
+ simplify syntax error text when expecting Comparison and Operator tokens
|
|
84
|
+
+ improve support for code completion with `case` expressions, queries, and subqueries
|
|
85
|
+
|
|
16
86
|
## Version 6.7.3 - 2026-02-11
|
|
17
87
|
|
|
18
88
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
## Installation and Usage
|
|
5
6
|
|
|
6
7
|
Install with npm:
|
|
@@ -20,16 +21,19 @@ Or maintain your package.json dependencies as follows:
|
|
|
20
21
|
If your project already has a dependency to `@sap/cds`, nothing has to be done.
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
|
|
23
25
|
## Documentation
|
|
24
26
|
|
|
25
27
|
Please refer to the [official CDS documentation](https://cap.cloud.sap/docs/cds/).
|
|
26
28
|
|
|
27
29
|
|
|
30
|
+
|
|
28
31
|
## How to Obtain Support
|
|
29
32
|
|
|
30
33
|
In case you find a bug, please report an [incident](https://cap.cloud.sap/docs/resources/#reporting-incidents) on SAP Support Portal.
|
|
31
34
|
|
|
32
35
|
|
|
36
|
+
|
|
33
37
|
## History and License
|
|
34
38
|
|
|
35
39
|
The cds-compiler uses [Semantic Versioning](./doc/Versioning.md) for its version numbers.
|
package/bin/cdsc.js
CHANGED
|
@@ -25,9 +25,9 @@ const { toRename: _toRename } = require('../lib/render/toRename');
|
|
|
25
25
|
const util = require('util');
|
|
26
26
|
const fs = require('fs');
|
|
27
27
|
const path = require('path');
|
|
28
|
-
const { reveal } = require('../lib/
|
|
29
|
-
const enrichCsn = require('../lib/
|
|
30
|
-
const { optionProcessor } = require('../lib/optionProcessor');
|
|
28
|
+
const { reveal } = require('../lib/tool-lib/revealInternalProperties');
|
|
29
|
+
const enrichCsn = require('../lib/tool-lib/enrichCsn');
|
|
30
|
+
const { optionProcessor } = require('../lib/base/optionProcessor');
|
|
31
31
|
const {
|
|
32
32
|
explainMessage, hasMessageExplanation, sortMessages,
|
|
33
33
|
messageIdsWithExplanation, makeMessageFunction,
|
|
@@ -35,7 +35,7 @@ const {
|
|
|
35
35
|
const { term } = require('../lib/utils/term');
|
|
36
36
|
const { addLocalizationViews } = require('../lib/transform/localized');
|
|
37
37
|
const { addTenantFields } = require('../lib/transform/addTenantFields');
|
|
38
|
-
const { availableBetaFlags } = require('../lib/base/
|
|
38
|
+
const { availableBetaFlags } = require('../lib/base/specialOptions');
|
|
39
39
|
const { alterConstraintsWithCsn } = require('../lib/render/manageConstraints');
|
|
40
40
|
const { tmpFilePath, readStream } = require('../lib/utils/file');
|
|
41
41
|
|
|
@@ -548,7 +548,7 @@ async function executeCommandLine( command, options, args ) {
|
|
|
548
548
|
}
|
|
549
549
|
|
|
550
550
|
function inspect( model ) {
|
|
551
|
-
const inspectModel = require('../lib/
|
|
551
|
+
const inspectModel = require('../lib/tool-lib');
|
|
552
552
|
|
|
553
553
|
if (options.statistics) {
|
|
554
554
|
const result = inspectModel.inspectModelStatistics(model, options);
|
package/bin/cdshi.js
CHANGED
|
@@ -32,6 +32,7 @@ const categoryChars = { // default: first char of category name
|
|
|
32
32
|
ExtService: 'S', // highlight like service definition
|
|
33
33
|
ExtContext: 'C', // highlight like context definition
|
|
34
34
|
// ExtElement: 'E', // using the first letter is the default
|
|
35
|
+
ExtEnum: 'H', // highlight like enum symbol definition
|
|
35
36
|
ExtBoundAction: 'B', // highlight like bound action definition
|
|
36
37
|
ExtParam: 'P', // highlight like entity/action parameter definition
|
|
37
38
|
FromImplicit: 'W',
|
package/bin/cdsse.js
CHANGED
|
@@ -25,7 +25,7 @@ const path = require('path');
|
|
|
25
25
|
const compiler = require('../lib/compiler');
|
|
26
26
|
const main = require('../lib/main');
|
|
27
27
|
const { locationString } = require('../lib/base/messages');
|
|
28
|
-
const { availableBetaFlags: beta } = require('../lib/base/
|
|
28
|
+
const { availableBetaFlags: beta } = require('../lib/base/specialOptions');
|
|
29
29
|
|
|
30
30
|
const { argv } = process;
|
|
31
31
|
const cmd = commands[argv[2]];
|
package/lib/api/main.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const lazyload = require('../
|
|
5
|
+
const lazyload = require('../utils/lazyload')( module );
|
|
6
6
|
|
|
7
7
|
const prepareOptions = lazyload('./options');
|
|
8
|
-
const
|
|
8
|
+
const specialOptions = lazyload('../base/specialOptions');
|
|
9
9
|
const location = lazyload('../base/location');
|
|
10
10
|
const messages = lazyload('../base/messages');
|
|
11
11
|
const compiler = lazyload('../compiler/index');
|
|
@@ -27,8 +27,8 @@ const effective = lazyload('../transform/effective/main');
|
|
|
27
27
|
const toHdbcds = lazyload('../render/toHdbcds');
|
|
28
28
|
const baseError = lazyload('../base/error');
|
|
29
29
|
const csnToEdm = lazyload('../edm/csn2edm');
|
|
30
|
-
const trace = lazyload('
|
|
31
|
-
const cloneCsn = lazyload('../
|
|
30
|
+
const trace = lazyload('../base/trace');
|
|
31
|
+
const cloneCsn = lazyload('../base/cloneCsn');
|
|
32
32
|
const objectUtils = lazyload('../utils/objectUtils');
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -56,6 +56,7 @@ const warnAboutMismatchOdata = [ 'odataVersion' ];
|
|
|
56
56
|
* @param {string[]} relevantOptionNames Option names that are defining characteristics
|
|
57
57
|
* @param {string[]} [optionalOptionNames] Option names that should be attached as a fyi
|
|
58
58
|
*/
|
|
59
|
+
// TODO: move this function to some other place
|
|
59
60
|
function attachTransformerCharacteristics( csn, transformation, options,
|
|
60
61
|
relevantOptionNames, optionalOptionNames = [] ) {
|
|
61
62
|
const relevant = {};
|
|
@@ -75,10 +76,10 @@ function attachTransformerCharacteristics( csn, transformation, options,
|
|
|
75
76
|
relevant[name] = options[name];
|
|
76
77
|
}
|
|
77
78
|
if (!csn.meta)
|
|
78
|
-
|
|
79
|
+
objectUtils.setProp(csn, 'meta', {});
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
objectUtils.setProp(csn.meta, 'options', relevant);
|
|
82
|
+
objectUtils.setProp(csn.meta, 'transformation', transformation);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
/**
|
|
@@ -306,7 +307,14 @@ function forEffectiveInternal( csn, options, internalOptions, messageFunctions )
|
|
|
306
307
|
function forSeal( csn, options, messageFunctions ) {
|
|
307
308
|
const internalOptions = prepareOptions.for.seal(options);
|
|
308
309
|
internalOptions.transformation = 'effective';
|
|
309
|
-
|
|
310
|
+
const result = forEffectiveInternal(csn, options, internalOptions, messageFunctions);
|
|
311
|
+
|
|
312
|
+
if (!options.testMode) {
|
|
313
|
+
result.meta ??= {};
|
|
314
|
+
result.meta.compilerCsnFlavor = 'seal';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return result;
|
|
310
318
|
}
|
|
311
319
|
|
|
312
320
|
/**
|
|
@@ -1166,7 +1174,7 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1166
1174
|
try {
|
|
1167
1175
|
const messageFunctions = messages.makeMessageFunction(csn, options, _name);
|
|
1168
1176
|
if (options.deprecated)
|
|
1169
|
-
|
|
1177
|
+
specialOptions.checkRemovedDeprecatedFlags( options, messageFunctions );
|
|
1170
1178
|
|
|
1171
1179
|
checkOutdatedOptions( options, messageFunctions );
|
|
1172
1180
|
csn = ensureClientCsn( csn, options, messageFunctions, _name );
|
package/lib/api/options.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// The options are specified in ../optionProcessor.js (and some other files).
|
|
3
|
+
// The options are specified in ../base/optionProcessor.js (and some other files).
|
|
4
4
|
// Some backends feel the need to "translate" option, which require to list
|
|
5
|
-
// all options also here (as
|
|
5
|
+
// all options also here (as "public" or "private" option).
|
|
6
|
+
// Parser and core compiler options might not have been listed here.
|
|
6
7
|
|
|
7
8
|
const { validate, generateStringValidator } = require('./validate');
|
|
8
9
|
const { makeMessageFunction } = require('../base/messages');
|
|
@@ -25,6 +26,7 @@ const publicOptionsNewAPI = [
|
|
|
25
26
|
'defaultStringLength',
|
|
26
27
|
'csnFlavor',
|
|
27
28
|
'noDollarCalc',
|
|
29
|
+
'v7KeyPropagation',
|
|
28
30
|
// DB
|
|
29
31
|
'sqlDialect',
|
|
30
32
|
'sqlMapping',
|
|
@@ -36,6 +38,7 @@ const publicOptionsNewAPI = [
|
|
|
36
38
|
'pre2134ReferentialConstraintNames',
|
|
37
39
|
'betterSqliteSessionVariables',
|
|
38
40
|
'fewerLocalizedViews',
|
|
41
|
+
'sqliteRealAffinityForDecimal',
|
|
39
42
|
'withHanaAssociations',
|
|
40
43
|
'standardDatabaseFunctions',
|
|
41
44
|
'booleanEquality',
|
package/lib/api/validate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// The options are specified in ../optionProcessor.js (and some other files).
|
|
3
|
+
// The options are specified in ../base/optionProcessor.js (and some other files).
|
|
4
4
|
// Options with non-boolean values must also be listed in this file.
|
|
5
5
|
|
|
6
6
|
const { forEach } = require('../utils/objectUtils');
|
package/lib/base/builtins.js
CHANGED
|
@@ -89,29 +89,33 @@ function isMagicVariable( name ) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* Properties
|
|
93
|
-
* and not some foreign structure.
|
|
92
|
+
* Properties (without those from CSN v0.1.0) that make an annotation object value
|
|
93
|
+
* an actual expression and not some foreign structure.
|
|
94
94
|
*
|
|
95
95
|
* @type {string[]}
|
|
96
96
|
*/
|
|
97
|
-
const
|
|
98
|
-
'ref', 'xpr', 'list', '
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
const primaryExprProperties = [
|
|
98
|
+
'ref', 'xpr', 'list', 'val', '#', 'func', 'SELECT', 'SET',
|
|
99
|
+
];
|
|
100
|
+
// only with 'ref'/'val'/'func'/misc:
|
|
101
|
+
const exprProperties = [
|
|
102
|
+
...primaryExprProperties,
|
|
103
|
+
'param', 'literal', 'args', 'cast',
|
|
101
104
|
];
|
|
102
|
-
|
|
103
105
|
|
|
104
106
|
/**
|
|
105
107
|
* Return whether JSON object `val` is a representation for an annotation expression
|
|
106
108
|
*/
|
|
107
109
|
function isAnnotationExpression( val ) {
|
|
108
|
-
return val?.['='] !== undefined &&
|
|
110
|
+
return val?.['='] !== undefined && // TODO: truthy
|
|
111
|
+
primaryExprProperties.some( prop => val[prop] !== undefined );
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
module.exports = {
|
|
112
115
|
propagationRules,
|
|
113
116
|
acceptsExprValues,
|
|
114
|
-
|
|
117
|
+
primaryExprProperties,
|
|
118
|
+
exprProperties,
|
|
115
119
|
isInReservedNamespace,
|
|
116
120
|
isBuiltinType,
|
|
117
121
|
isMagicVariable,
|
|
@@ -784,14 +784,15 @@ function csnRefs( csn, universalReady ) {
|
|
|
784
784
|
const target = assocTarget( parent, refCtx );
|
|
785
785
|
return resolvePath( path, target.elements[head], target, 'target' );
|
|
786
786
|
}
|
|
787
|
-
if (
|
|
788
|
-
|
|
789
|
-
return resolvePath( path, baseEnv.elements[head], baseEnv, semantics.dynamic );
|
|
790
|
-
// in an ON condition of an association inside inner expand/inline:
|
|
787
|
+
if (semantics.dynamic === 'query') {
|
|
788
|
+
// in an anno, or an ON condition of an association inside inner expand/inline:
|
|
791
789
|
const elemParent = getCache( parent, '_element' );
|
|
792
|
-
if (elemParent)
|
|
790
|
+
if (elemParent?.elements) // expand in expand
|
|
793
791
|
return resolvePath( path, elemParent.elements[head], null, 'query' );
|
|
794
792
|
}
|
|
793
|
+
else if (baseEnv) { // ref-target (filter condition), expand, inline
|
|
794
|
+
return resolvePath( path, baseEnv.elements[head], baseEnv, semantics.dynamic );
|
|
795
|
+
}
|
|
795
796
|
if (!query) { // outside queries - TODO: items?
|
|
796
797
|
// refs in annos on foreign keys use fk name, not fk ref name:
|
|
797
798
|
const dict = parent.elements ?? getCache( parent, '_keys' );
|
|
@@ -810,11 +811,9 @@ function csnRefs( csn, universalReady ) {
|
|
|
810
811
|
if (!qcache)
|
|
811
812
|
throw new CompilerAssertion( `For semantics '${ refCtx }', query not in cache at: ${ locationString(query.$location) }` );
|
|
812
813
|
|
|
813
|
-
if (semantics.dynamic === 'query')
|
|
814
|
-
// TODO: for ON condition in expand, would need to use cached _element
|
|
815
|
-
// TODO: test and implement - Issue #11792!
|
|
814
|
+
if (semantics.dynamic === 'query')
|
|
816
815
|
return resolvePath( path, qcache.elements[head], null, 'query' );
|
|
817
|
-
|
|
816
|
+
|
|
818
817
|
for (const name in qcache.$aliases) {
|
|
819
818
|
const alias = qcache.$aliases[name];
|
|
820
819
|
const found = alias.elements[head];
|
|
@@ -1144,7 +1143,6 @@ function analyseCsnPath( csnPath, csn, resolve ) {
|
|
|
1144
1143
|
baseEnv = resolve.expandInline( obj, baseCtx, main, query, parent, baseEnv );
|
|
1145
1144
|
refCtx = prop;
|
|
1146
1145
|
}
|
|
1147
|
-
// TODO: for on condition in expand, also set an environment
|
|
1148
1146
|
isName = prop;
|
|
1149
1147
|
}
|
|
1150
1148
|
else if (prop === 'on') {
|
package/lib/base/error.js
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
'use strict';
|
|
37
37
|
|
|
38
38
|
const { CompilerAssertion } = require( './error' );
|
|
39
|
-
const { isDeprecatedEnabled } = require( './
|
|
39
|
+
const { isDeprecatedEnabled } = require( './specialOptions' );
|
|
40
40
|
|
|
41
41
|
const configurableForValidValues = {
|
|
42
42
|
__proto__: null,
|
|
@@ -89,6 +89,7 @@ const centralMessages = {
|
|
|
89
89
|
'anno-invalid-sql-kind': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
90
90
|
'anno-invalid-sql-view': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
91
91
|
'anno-invalid-sql-view-element': { severity: 'Error', configurableFor: true }, // @sql.prepend/append - configurable for "I know what I'm doing"
|
|
92
|
+
'ext-duplicate-include': { severity: 'Warning', errorFor: [ 'v7' ] },
|
|
92
93
|
'ext-undefined-action': { severity: 'Warning' },
|
|
93
94
|
'ext-undefined-art': { severity: 'Warning' }, // for annotate statement (for CDL path root)
|
|
94
95
|
'ext-undefined-def': { severity: 'Warning' }, // for annotate statement (for CSN or CDL path cont)
|
|
@@ -100,6 +101,7 @@ const centralMessages = {
|
|
|
100
101
|
'ext-undefined-element-sec': { severity: 'Error', configurableFor: true }, // for security-relevant…
|
|
101
102
|
'ext-undefined-action-sec': { severity: 'Error', configurableFor: true }, // for security-relevant…
|
|
102
103
|
'ext-undefined-param-sec': { severity: 'Error', configurableFor: true }, // … annotate statement
|
|
104
|
+
'ext-unexpected-type-property': { severity: 'Warning', errorFor: [ 'v7' ] },
|
|
103
105
|
'ext-unexpected-returns': { severity: 'Warning' },
|
|
104
106
|
'ext-unexpected-returns-sec': { severity: 'Error', configurableFor: true }, // … annotate statement
|
|
105
107
|
'anno-unexpected-ellipsis': { severity: 'Error', configurableFor: 'deprecated' },
|
|
@@ -125,8 +127,11 @@ const centralMessages = {
|
|
|
125
127
|
'empty-type': { severity: 'Info' }, // only still an error in old transformers
|
|
126
128
|
|
|
127
129
|
'ref-deprecated-orderby': { severity: 'Error', configurableFor: true },
|
|
128
|
-
'ref-deprecated-self-element': { severity: 'Error', configurableFor:
|
|
130
|
+
'ref-deprecated-self-element': { severity: 'Error', configurableFor: 'v7' },
|
|
129
131
|
'ref-deprecated-variable': { severity: 'Warning' },
|
|
132
|
+
'ref-deprecated-in-extend': { severity: 'Warning' },
|
|
133
|
+
'ref-special-in-extend': { severity: 'Warning' },
|
|
134
|
+
'ref-unexpected-in-extend': { severity: 'Error' },
|
|
130
135
|
'ref-invalid-type': { severity: 'Error' },
|
|
131
136
|
'ref-unexpected-self': { severity: 'Error' },
|
|
132
137
|
'ref-invalid-include': { severity: 'Error' },
|
|
@@ -135,6 +140,7 @@ const centralMessages = {
|
|
|
135
140
|
'type-ignoring-argument': { severity: 'Error', configurableFor: true },
|
|
136
141
|
'type-expected-builtin': { severity: 'Error', configurableFor: true },
|
|
137
142
|
'type-expecting-service-target': { severity: 'Error', configurableFor: true },
|
|
143
|
+
'type-invalid-for-key': { severity: 'Warning' },
|
|
138
144
|
'ref-expecting-const': { severity: 'Error' },
|
|
139
145
|
'ref-expecting-foreign-key': { severity: 'Error' },
|
|
140
146
|
'ref-invalid-source': { severity: 'Error' },
|
|
@@ -154,6 +160,7 @@ const centralMessages = {
|
|
|
154
160
|
'query-unexpected-structure-hdbcds': { severity: 'Error' },
|
|
155
161
|
'query-ignoring-param-nullability': { severity: 'Info' },
|
|
156
162
|
'query-expected-identifier': { severity: 'Error' },
|
|
163
|
+
'query-invalid-identifier': { severity: 'Warning' },
|
|
157
164
|
|
|
158
165
|
'recalculated-localized': { severity: 'Info' }, // KEEP: Downgrade in lib/transform/translateAssocsToJoins.js
|
|
159
166
|
'redirected-implicitly-ambiguous': { severity: 'Error', configurableFor: true }, // does not hurt us - TODO: ref-ambiguous-target
|
|
@@ -202,6 +209,8 @@ const centralMessages = {
|
|
|
202
209
|
// remark: a hard syntax error in new parser for `null` together with `not null`
|
|
203
210
|
'syntax-duplicate-equal-clause': { severity: 'Warning' },
|
|
204
211
|
'syntax-invalid-name': { severity: 'Error' },
|
|
212
|
+
'syntax-invalid-anno-struct': { severity: 'Warning', errorFor: [ 'v7' ] },
|
|
213
|
+
'syntax-invalid-nested-proj': { severity: 'Warning', errorFor: [ 'v7' ] },
|
|
205
214
|
'syntax-missing-as': { severity: 'Error', configurableFor: true },
|
|
206
215
|
'syntax-missing-proj-semicolon': { severity: 'Warning' },
|
|
207
216
|
'syntax-unexpected-after': { severity: 'Error' },
|
|
@@ -246,6 +255,7 @@ const centralMessages = {
|
|
|
246
255
|
'odata-unexpected-nullable-key': { severity: 'Error', configurableFor: true },
|
|
247
256
|
'odata-invalid-key-type': { severity: 'Warning' },
|
|
248
257
|
'odata-invalid-property-name': { severity: 'Warning' },
|
|
258
|
+
'odata-unexpected-xpr-anno': { severity: 'Error', configurableFor: true },
|
|
249
259
|
'odata-anno-preproc': { severity: 'Warning' },
|
|
250
260
|
'odata-anno-dict': { severity: 'Warning' },
|
|
251
261
|
'odata-anno-vocref': { severity: 'Warning' },
|
|
@@ -533,6 +543,10 @@ const centralMessageTexts = {
|
|
|
533
543
|
dot: 'Use a $(NEWCODE), not a $(CODE) after the arguments or filter on an entity',
|
|
534
544
|
colon: 'Use a $(NEWCODE), not a $(CODE) between the element names in a reference',
|
|
535
545
|
},
|
|
546
|
+
'syntax-invalid-anno-struct': {
|
|
547
|
+
std: 'Most CSN processors interpret a structure with property $(PROP) as expression',
|
|
548
|
+
ref: 'Most CSN processors interpret a structure with property $(PROP) as reference',
|
|
549
|
+
},
|
|
536
550
|
// 'syntax-ignoring-doc-comment' (Info)
|
|
537
551
|
'syntax-unexpected-reserved-word': '$(CODE) is a reserved word - write $(DELIMITED) instead if you want to use it as name',
|
|
538
552
|
'syntax-invalid-text-block': 'Missing newline in text block',
|
|
@@ -708,6 +722,14 @@ const centralMessageTexts = {
|
|
|
708
722
|
type: 'Illegal recursive type definition to $(TYPE)',
|
|
709
723
|
},
|
|
710
724
|
'ref-deprecated-orderby': 'Replace source element reference $(ID) by $(NEWCODE); auto-corrected',
|
|
725
|
+
'ref-deprecated-in-extend': {
|
|
726
|
+
std: 'In an extension, do not use the table alias $(ID) to refer to source elements',
|
|
727
|
+
columns: 'In an added column, do not use the table alias $(ID) to refer to source elements',
|
|
728
|
+
where: 'In an added WHERE, do not use the table alias $(ID) to refer to source elements',
|
|
729
|
+
groupBy: 'In an added GROUP BY, do not use the table alias $(ID) to refer to source elements',
|
|
730
|
+
having: 'In an added HAVING, do not use the table alias $(ID) to refer to source elements',
|
|
731
|
+
orderBy: 'In an added ORDER BY, do not use the table alias $(ID) to refer to source elements',
|
|
732
|
+
},
|
|
711
733
|
'ref-missing-self-counterpart' : {
|
|
712
734
|
std: 'Expected to find a matching element in $self-comparison for foreign key $(PROP) of association $(NAME)',
|
|
713
735
|
unmanaged: 'Expected to find a matching element in $self-comparison for $(PROP) of association $(NAME)',
|
|
@@ -728,6 +750,7 @@ const centralMessageTexts = {
|
|
|
728
750
|
'ref-undefined-def': {
|
|
729
751
|
std: 'Artifact $(ART) has not been found',
|
|
730
752
|
// TODO: proposal 'No definition of $(NAME) found',
|
|
753
|
+
hint: 'Artifact $(ART) has not been found. Did you mean to write $(CODE)?',
|
|
731
754
|
element: 'Artifact $(ART) has no element $(MEMBER)',
|
|
732
755
|
},
|
|
733
756
|
'ref-undefined-param': 'Entity $(ART) has no parameter $(ID)',
|
|
@@ -866,6 +889,7 @@ const centralMessageTexts = {
|
|
|
866
889
|
std: 'Unexpected arguments in path $(ELEMREF)', // unused
|
|
867
890
|
'on-condition': 'ON-conditions must not contain parameters, step $(ID) of path $(ELEMREF)',
|
|
868
891
|
calc: 'Unexpected arguments in path $(ELEMREF) of stored calculated element; only simple paths can be used here',
|
|
892
|
+
vector_length: 'Unexpected length of vector $(ELEMREF). The length must be divisble by 4',
|
|
869
893
|
},
|
|
870
894
|
'ref-unsupported-type': {
|
|
871
895
|
std: 'Type $(TYPE) is not supported',
|
|
@@ -955,6 +979,7 @@ const centralMessageTexts = {
|
|
|
955
979
|
missing: 'Expecting service entity $(TARGET); it does not have the key element $(ID) of the provided model target',
|
|
956
980
|
order: 'Expecting service entity $(TARGET); its key elements are in a different order than those of the provided model target',
|
|
957
981
|
},
|
|
982
|
+
'type-invalid-for-key': 'Type $(TYPE) is not supported for key elements',
|
|
958
983
|
|
|
959
984
|
'anno-builtin': 'Builtin types should not be annotated nor extended. Use custom type instead',
|
|
960
985
|
'ext-undefined-def': 'Artifact $(ART) has not been found',
|
|
@@ -1025,7 +1050,6 @@ const centralMessageTexts = {
|
|
|
1025
1050
|
std: '$(KEYWORD) is not supported here', // unused variant
|
|
1026
1051
|
kind: '$(KEYWORD) is only supported for elements in an entity or an aspect',
|
|
1027
1052
|
sub: '$(KEYWORD) is only supported for top-level elements',
|
|
1028
|
-
type: '$(KEYWORD) is not supported for elements of type $(TYPE)',
|
|
1029
1053
|
},
|
|
1030
1054
|
'def-unexpected-localized': {
|
|
1031
1055
|
std: 'Unexpected $(KEYWORD)',
|
|
@@ -1076,6 +1100,12 @@ const centralMessageTexts = {
|
|
|
1076
1100
|
|
|
1077
1101
|
'def-expected-structured': 'Events must either be structured or be projections',
|
|
1078
1102
|
|
|
1103
|
+
'ext-duplicate-include': {
|
|
1104
|
+
std: 'Duplicate $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
1105
|
+
elements: 'Duplicate element $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
1106
|
+
actions: 'Duplicate action or function $(NAME) through multiple includes $(SORTED_ARTS)',
|
|
1107
|
+
},
|
|
1108
|
+
|
|
1079
1109
|
'duplicate-definition': {
|
|
1080
1110
|
std: 'Duplicate definition of $(NAME)',
|
|
1081
1111
|
absolute: 'Duplicate definition of artifact $(NAME)',
|
|
@@ -1153,6 +1183,32 @@ const centralMessageTexts = {
|
|
|
1153
1183
|
join: 'Artifact $(ART) can\'t be extended with columns, because it contains a JOIN',
|
|
1154
1184
|
union: 'Artifact $(ART) can\'t be extended with columns, because it contains a UNION',
|
|
1155
1185
|
},
|
|
1186
|
+
'extend-where': {
|
|
1187
|
+
std: 'Artifact $(ART) can\'t be extended with WHERE, only simple views/projections without JOINs and UNIONs can',
|
|
1188
|
+
join: 'Artifact $(ART) can\'t be extended with WHERE, because it contains a JOIN',
|
|
1189
|
+
union: 'Artifact $(ART) can\'t be extended with WHERE, because it contains a UNION',
|
|
1190
|
+
},
|
|
1191
|
+
'extend-groupby': {
|
|
1192
|
+
std: 'Artifact $(ART) can\'t be extended with GROUP BY, only simple views/projections without JOINs and UNIONs can',
|
|
1193
|
+
join: 'Artifact $(ART) can\'t be extended with GROUP BY, because it contains a JOIN',
|
|
1194
|
+
union: 'Artifact $(ART) can\'t be extended with GROUP BY, because it contains a UNION',
|
|
1195
|
+
},
|
|
1196
|
+
'extend-having': {
|
|
1197
|
+
std: 'Artifact $(ART) can\'t be extended with HAVING, only simple views/projections without JOINs and UNIONs can',
|
|
1198
|
+
join: 'Artifact $(ART) can\'t be extended with HAVING, because it contains a JOIN',
|
|
1199
|
+
union: 'Artifact $(ART) can\'t be extended with HAVING, because it contains a UNION',
|
|
1200
|
+
},
|
|
1201
|
+
'extend-orderby': {
|
|
1202
|
+
std: 'Artifact $(ART) can\'t be extended with ORDER BY, only simple views/projections without JOINs and UNIONs can',
|
|
1203
|
+
join: 'Artifact $(ART) can\'t be extended with ORDER BY, because it contains a JOIN',
|
|
1204
|
+
union: 'Artifact $(ART) can\'t be extended with ORDER BY, because it contains a UNION',
|
|
1205
|
+
},
|
|
1206
|
+
'extend-limit': {
|
|
1207
|
+
std: 'Artifact $(ART) can\'t be extended with LIMIT, only simple views/projections without JOINs and UNIONs can',
|
|
1208
|
+
join: 'Artifact $(ART) can\'t be extended with LIMIT, because it contains a JOIN',
|
|
1209
|
+
union: 'Artifact $(ART) can\'t be extended with LIMIT, because it contains a UNION',
|
|
1210
|
+
},
|
|
1211
|
+
'ext-unexpected-sql-clause': 'Artifact $(ART) can\'t be extended with a $(KEYWORD) clause, because it already exists',
|
|
1156
1212
|
'extend-repeated-intralayer': 'Unstable element order due to repeated extensions in same layer',
|
|
1157
1213
|
'extend-unexpected-include': 'Can\'t extend $(META) with includes',
|
|
1158
1214
|
|
|
@@ -1199,6 +1255,7 @@ const centralMessageTexts = {
|
|
|
1199
1255
|
std: 'Expected identifier for select item',
|
|
1200
1256
|
assoc: 'Expected identifier as the association\'s name',
|
|
1201
1257
|
},
|
|
1258
|
+
'query-invalid-identifier': 'Expected identifier for SQL dialect $(NAME) to not exceed $(NUMBER) characters',
|
|
1202
1259
|
'query-unsupported-calc': {
|
|
1203
1260
|
std: 'Using nested projections next to calculated elements is not supported, yet',
|
|
1204
1261
|
inside: 'Using calculated elements in nested projections is not supported, yet',
|
|
@@ -1252,11 +1309,17 @@ const centralMessageTexts = {
|
|
|
1252
1309
|
},
|
|
1253
1310
|
|
|
1254
1311
|
'ref-special-in-extend': {
|
|
1255
|
-
std: 'In an
|
|
1312
|
+
std: 'In an extension, $(ID) refers to the element of the projection source $(ART), not the table alias or mixin',
|
|
1256
1313
|
alias: 'In an added column, $(ID) refers to the element of the projection source $(ART), not the table alias',
|
|
1257
1314
|
mixin: 'In an added column, $(ID) refers to the element of the projection source $(ART), not the mixin',
|
|
1258
1315
|
},
|
|
1259
1316
|
|
|
1317
|
+
'ref-unexpected-in-extend': {
|
|
1318
|
+
std: 'Unexpected $(ID) in an extension; it matches both a source element of $(ART) and the table alias or mixin',
|
|
1319
|
+
alias: 'Unexpected $(ID) in an added $(KEYWORD); it matches both a source element of $(ART) and the table alias',
|
|
1320
|
+
mixin: 'Unexpected $(ID) in an added $(KEYWORD); it matches both a source element of $(ART) and the mixin',
|
|
1321
|
+
},
|
|
1322
|
+
|
|
1260
1323
|
'type-managed-composition': {
|
|
1261
1324
|
std: 'Managed compositions can\'t be used in types', // yet
|
|
1262
1325
|
sub: 'Managed compositions can\'t be used in sub elements',
|
|
@@ -1396,6 +1459,7 @@ const centralMessageTexts = {
|
|
|
1396
1459
|
xpr: 'Ignoring unexpected expression as default value',
|
|
1397
1460
|
colitem: 'Ignoring unexpected default value for a structured or collection like parameter',
|
|
1398
1461
|
},
|
|
1462
|
+
'odata-unexpected-xpr-anno': 'Annotation $(ANNO) with expression value is not allowed for kind $(KIND)',
|
|
1399
1463
|
// -----------------------------------------------------------------------------------
|
|
1400
1464
|
// All odata-anno MUST have a '$(ANNO)' parameter to indicate error location
|
|
1401
1465
|
// -----------------------------------------------------------------------------------
|
package/lib/base/messages.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const { term } = require('../utils/term');
|
|
8
8
|
const { Location, locationString } = require('./location');
|
|
9
|
-
const { isBetaEnabled } = require('./
|
|
9
|
+
const { isBetaEnabled } = require('./specialOptions');
|
|
10
10
|
const {
|
|
11
11
|
centralMessages,
|
|
12
12
|
configurableForValidValues,
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
oldMessageIds,
|
|
15
15
|
} = require('./message-registry');
|
|
16
16
|
const _messageIdsWithExplanation = require('../../share/messages/message-explanations.json').messages;
|
|
17
|
-
const { analyseCsnPath, traverseQuery } = require('../
|
|
17
|
+
const { analyseCsnPath, traverseQuery } = require('../base/csnRefs');
|
|
18
18
|
const { CompilerAssertion } = require('./error');
|
|
19
19
|
const { getArtifactName } = require('../compiler/base');
|
|
20
20
|
const { cdlNewLineRegEx } = require('../language/textUtils');
|
|
@@ -854,6 +854,8 @@ function value( val ) {
|
|
|
854
854
|
const keywordRepresentations = {
|
|
855
855
|
association: 'Association',
|
|
856
856
|
composition: 'Composition',
|
|
857
|
+
groupby: 'group by',
|
|
858
|
+
orderby: 'order by',
|
|
857
859
|
};
|
|
858
860
|
function keyword( val ) {
|
|
859
861
|
const v = val.toLowerCase();
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
// - Also list the option in the `help` text, used with `cdsc -h`.
|
|
9
9
|
// - All options must also be added to ./api/options.js.
|
|
10
10
|
// - Specify valid values for non-boolean options in ./api/validate.js.
|
|
11
|
-
// - Beta and deprecated options are specified in ./base/
|
|
11
|
+
// - Beta and deprecated options are specified in ./base/specialOptions.js.
|
|
12
12
|
|
|
13
13
|
'use strict';
|
|
14
14
|
|
|
15
|
-
const { createOptionProcessor } = require('
|
|
16
|
-
const { availableBetaFlags } = require('./
|
|
15
|
+
const { createOptionProcessor } = require('../utils/optionProcessorHelper');
|
|
16
|
+
const { availableBetaFlags } = require('./specialOptions');
|
|
17
17
|
|
|
18
18
|
// This option processor is used both by the command line parser (to translate cmd line options
|
|
19
19
|
// into an options object) and by the API functions (to verify options)
|
|
@@ -53,6 +53,7 @@ optionProcessor
|
|
|
53
53
|
.option(' --test-sort-csn')
|
|
54
54
|
.option(' --doc-comment')
|
|
55
55
|
.option(' --propagate-doc-comments')
|
|
56
|
+
.option(' --v7-key-propagation')
|
|
56
57
|
.option(' --add-texts-language-assoc')
|
|
57
58
|
.option(' --localized-without-coalesce')
|
|
58
59
|
.option(' --tenant-discriminator')
|
|
@@ -156,6 +157,7 @@ optionProcessor
|
|
|
156
157
|
option is implicitly enabled as well.
|
|
157
158
|
--doc-comment Preserve /** */ comments at annotation positions as doc property in CSN
|
|
158
159
|
--propagate-doc-comments Propagate doc comments ('--doc-comment')
|
|
160
|
+
--v7-key-propagation Use simplified propagation of 'key' in query entities
|
|
159
161
|
--add-texts-language-assoc In generated texts entities, add association "language"
|
|
160
162
|
to "sap.common.Languages" if it exists
|
|
161
163
|
--localized-without-coalesce Omit coalesce in localized convenience views
|