@sap/cds-compiler 4.9.6 → 5.1.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 +92 -0
- package/bin/cds_remove_invalid_whitespace.js +2 -1
- package/bin/cdsc.js +49 -19
- package/bin/cdshi.js +3 -1
- package/doc/CHANGELOG_BETA.md +7 -0
- package/lib/api/main.js +16 -19
- package/lib/api/options.js +5 -14
- package/lib/api/trace.js +0 -1
- package/lib/base/builtins.js +1 -0
- package/lib/base/location.js +4 -1
- package/lib/base/message-registry.js +43 -29
- package/lib/base/messages.js +23 -26
- package/lib/base/meta.js +10 -0
- package/lib/base/model.js +0 -2
- package/lib/base/node-helpers.js +0 -1
- package/lib/base/optionProcessorHelper.js +11 -0
- package/lib/checks/dbFeatureFlags.js +5 -0
- package/lib/checks/enricher.js +1 -5
- package/lib/checks/structuredAnnoExpressions.js +30 -0
- package/lib/checks/validator.js +8 -0
- package/lib/compiler/assert-consistency.js +5 -1
- package/lib/compiler/base.js +1 -1
- package/lib/compiler/builtins.js +18 -2
- package/lib/compiler/checks.js +2 -5
- package/lib/compiler/define.js +8 -8
- package/lib/compiler/extend.js +108 -37
- package/lib/compiler/generate.js +1 -1
- package/lib/compiler/index.js +27 -10
- package/lib/compiler/lsp-api.js +501 -2
- package/lib/compiler/populate.js +60 -13
- package/lib/compiler/propagator.js +10 -8
- package/lib/compiler/resolve.js +117 -94
- package/lib/compiler/shared.js +114 -32
- package/lib/compiler/tweak-assocs.js +31 -21
- package/lib/compiler/utils.js +2 -1
- package/lib/compiler/xsn-model.js +4 -0
- package/lib/edm/annotations/genericTranslation.js +69 -35
- package/lib/edm/csn2edm.js +16 -4
- package/lib/edm/edm.js +10 -3
- package/lib/edm/edmAnnoPreprocessor.js +1 -2
- package/lib/edm/edmPreprocessor.js +8 -10
- package/lib/gen/Dictionary.json +66 -2
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +2 -1
- package/lib/gen/languageParser.js +4995 -4817
- package/lib/json/csnVersion.js +1 -1
- package/lib/json/from-csn.js +4 -7
- package/lib/json/to-csn.js +25 -12
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/errorStrategy.js +0 -1
- package/lib/language/genericAntlrParser.js +35 -12
- package/lib/language/multiLineStringParser.js +3 -2
- package/lib/language/textUtils.js +1 -0
- package/lib/main.d.ts +28 -9
- package/lib/main.js +9 -9
- package/lib/model/cloneCsn.js +1 -0
- package/lib/model/csnRefs.js +22 -5
- package/lib/model/csnUtils.js +0 -14
- package/lib/model/revealInternalProperties.js +1 -2
- package/lib/modelCompare/compare.js +13 -11
- package/lib/optionProcessor.js +30 -9
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +44 -14
- package/lib/render/toHdbcds.js +1 -2
- package/lib/render/toSql.js +45 -8
- package/lib/render/utils/common.js +12 -9
- package/lib/render/utils/stringEscapes.js +1 -0
- package/lib/transform/db/applyTransformations.js +13 -8
- package/lib/transform/db/associations.js +62 -54
- package/lib/transform/db/backlinks.js +20 -5
- package/lib/transform/db/expansion.js +1 -6
- package/lib/transform/db/flattening.js +86 -109
- package/lib/transform/db/killAnnotations.js +3 -0
- package/lib/transform/db/processSqlServices.js +63 -0
- package/lib/transform/db/temporal.js +3 -4
- package/lib/transform/db/views.js +0 -1
- package/lib/transform/draft/odata.js +56 -3
- package/lib/transform/effective/annotations.js +3 -2
- package/lib/transform/effective/flattening.js +135 -0
- package/lib/transform/effective/main.js +6 -4
- package/lib/transform/effective/types.js +13 -9
- package/lib/transform/forOdata.js +0 -2
- package/lib/transform/forRelationalDB.js +9 -19
- package/lib/transform/localized.js +7 -8
- package/lib/transform/odata/flattening.js +39 -31
- package/lib/transform/odata/typesExposure.js +5 -17
- package/lib/transform/transformUtils.js +1 -1
- package/lib/transform/translateAssocsToJoins.js +0 -1
- package/lib/utils/file.js +87 -8
- package/lib/utils/moduleResolve.js +59 -8
- package/lib/utils/term.js +3 -2
- package/package.json +7 -3
- package/share/messages/message-explanations.json +2 -0
- package/share/messages/type-unexpected-foreign-keys.md +52 -0
- package/share/messages/type-unexpected-on-condition.md +52 -0
|
@@ -70,7 +70,7 @@ function makeModuleResolver( options, fileCache, messageFunctions ) {
|
|
|
70
70
|
extensions,
|
|
71
71
|
isFile: _fs.isFile,
|
|
72
72
|
readFile: _fs.readFile,
|
|
73
|
-
realpath: _fs.
|
|
73
|
+
realpath: _fs.realpathNative,
|
|
74
74
|
lookupDirs: _getLookupDirectories( options, messageFunctions ),
|
|
75
75
|
};
|
|
76
76
|
|
|
@@ -90,7 +90,20 @@ function makeModuleResolver( options, fileCache, messageFunctions ) {
|
|
|
90
90
|
const body = fileCache[res];
|
|
91
91
|
if (body === undefined || body === true) { // use fs if no or just temp entry
|
|
92
92
|
dep.absname = res;
|
|
93
|
-
_fs.realpath( res,
|
|
93
|
+
_fs.realpath( res, function realPathResult(realpathErr, modulePath) {
|
|
94
|
+
if (realpathErr) {
|
|
95
|
+
cb(realpathErr, modulePath);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
_fs.realpathNative( res, function nativeRealPathResult(nativeErr, nativePath) {
|
|
99
|
+
if (!nativeErr)
|
|
100
|
+
checkFileCase( dep, modulePath, nativePath, messageFunctions );
|
|
101
|
+
// Pass the _native_ path to ensure that we use the actual
|
|
102
|
+
// file's path (include case-differences)
|
|
103
|
+
cb(realpathErr, nativePath);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
} );
|
|
94
107
|
}
|
|
95
108
|
else if (body && typeof body === 'object' && body.realname) {
|
|
96
109
|
// dep.absname = body.realname;
|
|
@@ -138,7 +151,7 @@ function makeModuleResolverSync( options, fileCache, messageFunctions ) {
|
|
|
138
151
|
extensions,
|
|
139
152
|
isFile: _fs.isFileSync,
|
|
140
153
|
readFile: _fs.readFileSync,
|
|
141
|
-
realpath: _fs.
|
|
154
|
+
realpath: _fs.realpathSyncNative,
|
|
142
155
|
lookupDirs: _getLookupDirectories( options, messageFunctions ),
|
|
143
156
|
};
|
|
144
157
|
|
|
@@ -166,11 +179,23 @@ function makeModuleResolverSync( options, fileCache, messageFunctions ) {
|
|
|
166
179
|
const body = result ? fileCache[result] : undefined;
|
|
167
180
|
if (body === undefined || body === true) { // use fs if no or just temp entry
|
|
168
181
|
dep.absname = result;
|
|
169
|
-
_fs.realpathSync( result, (
|
|
170
|
-
if (
|
|
171
|
-
error =
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
_fs.realpathSync( result, function realPathResult(realpathErr, modulePath) {
|
|
183
|
+
if (realpathErr) {
|
|
184
|
+
error = realpathErr;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
_fs.realpathSyncNative( result, function nativeRealPathResult(nativeErr, nativePath) {
|
|
188
|
+
if (nativeErr) {
|
|
189
|
+
error = nativeErr;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
checkFileCase(dep, modulePath, nativePath, messageFunctions);
|
|
193
|
+
// Use the _native_ path to ensure that we use the actual
|
|
194
|
+
// file's path (include case-differences)
|
|
195
|
+
result = nativePath;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
174
199
|
});
|
|
175
200
|
}
|
|
176
201
|
else if (body && typeof body === 'object' && body.realname) {
|
|
@@ -533,6 +558,32 @@ function packageCdsMain( pkg ) {
|
|
|
533
558
|
return null;
|
|
534
559
|
}
|
|
535
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Check if the given paths for case-differences. If there are case differences
|
|
563
|
+
* emit a warning. This can happen on systems with case-insensitive file
|
|
564
|
+
* systems. As that is a hard-to-debug issue, we help the user by emitting
|
|
565
|
+
* a corresponding warning.
|
|
566
|
+
*
|
|
567
|
+
* @param {object} dep
|
|
568
|
+
* @param {string} realpath
|
|
569
|
+
* @param {string} nativeRealpath
|
|
570
|
+
* @param {Function} warning
|
|
571
|
+
*/
|
|
572
|
+
function checkFileCase( dep, realpath, nativeRealpath, { warning } ) {
|
|
573
|
+
if (realpath === nativeRealpath)
|
|
574
|
+
return;
|
|
575
|
+
if (realpath.toLowerCase() !== nativeRealpath.toLowerCase()) {
|
|
576
|
+
// safe-guard: in case realpath() resolved symlinks more deeply or sockets/pipes were used,
|
|
577
|
+
// which realpath.native() handles differently, don't report a possible false positive.
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
for (const using of dep.usingFroms) {
|
|
581
|
+
warning('file-unexpected-case-mismatch', [ using.location, using ], {},
|
|
582
|
+
// eslint-disable-next-line max-len
|
|
583
|
+
'The imported filename differs on the filesystem; ensure that capitalization matches the actual file\'s name');
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
536
587
|
/**
|
|
537
588
|
* @typedef {object} ResolveConfig
|
|
538
589
|
* @property {string[]} lookupDirs
|
package/lib/utils/term.js
CHANGED
|
@@ -57,8 +57,9 @@ function term( useColor = 'auto' ) {
|
|
|
57
57
|
// > that, when present (regardless of its value), prevents the addition
|
|
58
58
|
// > of ANSI color.
|
|
59
59
|
// Note: To be able to disable colors in tests, we check the environment
|
|
60
|
-
//
|
|
61
|
-
hasColor =
|
|
60
|
+
// variables again.
|
|
61
|
+
hasColor = (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== '0') ||
|
|
62
|
+
(hasColorShell && process.env.NO_COLOR === undefined);
|
|
62
63
|
break;
|
|
63
64
|
}
|
|
64
65
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-compiler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "CDS (Core Data Services) compiler and backends",
|
|
5
5
|
"homepage": "https://cap.cloud.sap/",
|
|
6
6
|
"author": "SAP SE (https://www.sap.com)",
|
|
@@ -24,11 +24,15 @@
|
|
|
24
24
|
"test3": "node scripts/verifyGrammarChecksum.js && mocha --reporter-option maxDiffSize=0 test3/",
|
|
25
25
|
"deployHanaSql": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.hana-sql.js",
|
|
26
26
|
"deployHdiHdbcds": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.hdi.hdbcds.js",
|
|
27
|
+
"deployHdi": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 --extensions .hdi test3/test.deploy.hdi.hdbcds.js",
|
|
28
|
+
"deployHdbcds": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 --extensions .hdbcds test3/test.deploy.hdi.hdbcds.js",
|
|
27
29
|
"deployGitDiffs": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.git-diffs.js",
|
|
30
|
+
"deployHdbcdsGitDiffs": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 --extensions .hdbcds test3/test.deploy.git-diffs.js",
|
|
31
|
+
"deployHdiGitDiffs": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 --extensions .hdi test3/test.deploy.git-diffs.js",
|
|
28
32
|
"gentest3": "cross-env MAKEREFS=${MAKEREFS:-'true'} mocha --reporter-option maxDiffSize=0 test3/testRefFiles.js",
|
|
29
33
|
"coverage": "cross-env nyc mocha --reporter-option maxDiffSize=0 test/ test3/testRefFiles.js && nyc report --reporter=lcov",
|
|
30
34
|
"coverage:piper": "cross-env nyc mocha --reporter test/TestMochaReporter.js --reporter-options mochaFile=./coverage/TEST-results.xml --reporter-option maxDiffSize=0 --timeout 10000 test/ test3/ && nyc report --reporter=cobertura && nyc report --reporter=lcov",
|
|
31
|
-
"lint": "eslint bin/ benchmark/ lib/ test/ test3/ scripts/
|
|
35
|
+
"lint": "eslint bin/ benchmark/ lib/ test/ test3/ scripts/ && node scripts/linter/lintGrammar.js && node scripts/linter/lintTests.js test3/ && node scripts/linter/lintMessages.js && node scripts/linter/lintMessageIdCoverage.js lib/ && markdownlint README.md CHANGELOG.md doc/ internalDoc/ && cd share/messages && markdownlint . && cd ../../ && node scripts/check-changelog.js",
|
|
32
36
|
"tslint": "tsc --pretty -p .",
|
|
33
37
|
"updateVocs": "node scripts/odataAnnotations/generateDictMain.js && npm run generateAllRefs",
|
|
34
38
|
"updateTocs": "node scripts/update-toc.js",
|
|
@@ -60,6 +64,6 @@
|
|
|
60
64
|
"LICENSE"
|
|
61
65
|
],
|
|
62
66
|
"engines": {
|
|
63
|
-
"node": ">=
|
|
67
|
+
"node": ">=18"
|
|
64
68
|
}
|
|
65
69
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# type-unexpected-foreign-keys
|
|
2
|
+
|
|
3
|
+
Foreign keys were specified in a composition-of-aspect.
|
|
4
|
+
|
|
5
|
+
Compositions of aspects are managed by the compiler.
|
|
6
|
+
Specifying a foreign key list is not supported.
|
|
7
|
+
If you need to specify foreign keys, use a composition
|
|
8
|
+
of an entity instead.
|
|
9
|
+
|
|
10
|
+
The message's severity is `Error`.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+
Erroneous code example:
|
|
15
|
+
|
|
16
|
+
```cds
|
|
17
|
+
aspect Item {
|
|
18
|
+
key ID : UUID;
|
|
19
|
+
field : String;
|
|
20
|
+
};
|
|
21
|
+
entity Model {
|
|
22
|
+
key ID : UUID;
|
|
23
|
+
Item : Composition of Item { ID }; // ❌
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`Item` is an aspect. Because an explicit list of foreign keys is specified,
|
|
28
|
+
the compiler rejects this CDS snippet. With an explicit foreign key list,
|
|
29
|
+
only entities can be used, but not aspects.
|
|
30
|
+
|
|
31
|
+
## How to Fix
|
|
32
|
+
|
|
33
|
+
Either remove the explicit list of foreign keys and let the compiler handle
|
|
34
|
+
the composition, or use a composition of entity instead.
|
|
35
|
+
|
|
36
|
+
```cds
|
|
37
|
+
aspect Item {
|
|
38
|
+
key ID : UUID;
|
|
39
|
+
field : String;
|
|
40
|
+
};
|
|
41
|
+
entity Model {
|
|
42
|
+
key ID : UUID;
|
|
43
|
+
Item : Composition of Model.Item { ID }; // ok
|
|
44
|
+
};
|
|
45
|
+
entity Model.Item : Item { };
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The snippet uses a user-defined entity, that includes the aspects.
|
|
49
|
+
|
|
50
|
+
## Related Messages
|
|
51
|
+
|
|
52
|
+
- `type-unexpected-on-condition`
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# type-unexpected-on-condition
|
|
2
|
+
|
|
3
|
+
An ON-condition was specified in a composition-of-aspect.
|
|
4
|
+
|
|
5
|
+
Compositions of aspects are managed by the compiler.
|
|
6
|
+
Specifying an ON-condition is not supported.
|
|
7
|
+
If you need to specify an ON-condition, use a composition
|
|
8
|
+
of an entity instead.
|
|
9
|
+
|
|
10
|
+
The message's severity is `Error`.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+
Erroneous code example:
|
|
15
|
+
|
|
16
|
+
```cds
|
|
17
|
+
aspect Item {
|
|
18
|
+
key ID : UUID;
|
|
19
|
+
field : String;
|
|
20
|
+
};
|
|
21
|
+
entity Model {
|
|
22
|
+
key ID : UUID;
|
|
23
|
+
Item : Composition of Item on Item.ID = ID; // ❌
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`Item` is an aspect. Because an ON-condition is specified, the compiler
|
|
28
|
+
rejects this CDS snippet. With an ON-condition, only entities can be used,
|
|
29
|
+
but not aspects.
|
|
30
|
+
|
|
31
|
+
## How to Fix
|
|
32
|
+
|
|
33
|
+
Either remove the ON-condition and let the compiler handle
|
|
34
|
+
the composition, or use a composition of entity instead.
|
|
35
|
+
|
|
36
|
+
```cds
|
|
37
|
+
aspect Item {
|
|
38
|
+
key ID : UUID;
|
|
39
|
+
field : String;
|
|
40
|
+
};
|
|
41
|
+
entity Model {
|
|
42
|
+
key ID : UUID;
|
|
43
|
+
Item : Composition of Model.Item on Item.ID = ID; // ok
|
|
44
|
+
};
|
|
45
|
+
entity Model.Item : Item { };
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The snippet uses a user-defined entity, that includes the aspects.
|
|
49
|
+
|
|
50
|
+
## Related Messages
|
|
51
|
+
|
|
52
|
+
- `type-unexpected-foreign-keys`
|