@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.
Files changed (95) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/bin/cds_remove_invalid_whitespace.js +2 -1
  3. package/bin/cdsc.js +49 -19
  4. package/bin/cdshi.js +3 -1
  5. package/doc/CHANGELOG_BETA.md +7 -0
  6. package/lib/api/main.js +16 -19
  7. package/lib/api/options.js +5 -14
  8. package/lib/api/trace.js +0 -1
  9. package/lib/base/builtins.js +1 -0
  10. package/lib/base/location.js +4 -1
  11. package/lib/base/message-registry.js +43 -29
  12. package/lib/base/messages.js +23 -26
  13. package/lib/base/meta.js +10 -0
  14. package/lib/base/model.js +0 -2
  15. package/lib/base/node-helpers.js +0 -1
  16. package/lib/base/optionProcessorHelper.js +11 -0
  17. package/lib/checks/dbFeatureFlags.js +5 -0
  18. package/lib/checks/enricher.js +1 -5
  19. package/lib/checks/structuredAnnoExpressions.js +30 -0
  20. package/lib/checks/validator.js +8 -0
  21. package/lib/compiler/assert-consistency.js +5 -1
  22. package/lib/compiler/base.js +1 -1
  23. package/lib/compiler/builtins.js +18 -2
  24. package/lib/compiler/checks.js +2 -5
  25. package/lib/compiler/define.js +8 -8
  26. package/lib/compiler/extend.js +108 -37
  27. package/lib/compiler/generate.js +1 -1
  28. package/lib/compiler/index.js +27 -10
  29. package/lib/compiler/lsp-api.js +501 -2
  30. package/lib/compiler/populate.js +60 -13
  31. package/lib/compiler/propagator.js +10 -8
  32. package/lib/compiler/resolve.js +117 -94
  33. package/lib/compiler/shared.js +114 -32
  34. package/lib/compiler/tweak-assocs.js +31 -21
  35. package/lib/compiler/utils.js +2 -1
  36. package/lib/compiler/xsn-model.js +4 -0
  37. package/lib/edm/annotations/genericTranslation.js +69 -35
  38. package/lib/edm/csn2edm.js +16 -4
  39. package/lib/edm/edm.js +10 -3
  40. package/lib/edm/edmAnnoPreprocessor.js +1 -2
  41. package/lib/edm/edmPreprocessor.js +8 -10
  42. package/lib/gen/Dictionary.json +66 -2
  43. package/lib/gen/language.checksum +1 -1
  44. package/lib/gen/language.interp +2 -1
  45. package/lib/gen/languageParser.js +4995 -4817
  46. package/lib/json/csnVersion.js +1 -1
  47. package/lib/json/from-csn.js +4 -7
  48. package/lib/json/to-csn.js +25 -12
  49. package/lib/language/antlrParser.js +2 -2
  50. package/lib/language/errorStrategy.js +0 -1
  51. package/lib/language/genericAntlrParser.js +35 -12
  52. package/lib/language/multiLineStringParser.js +3 -2
  53. package/lib/language/textUtils.js +1 -0
  54. package/lib/main.d.ts +28 -9
  55. package/lib/main.js +9 -9
  56. package/lib/model/cloneCsn.js +1 -0
  57. package/lib/model/csnRefs.js +22 -5
  58. package/lib/model/csnUtils.js +0 -14
  59. package/lib/model/revealInternalProperties.js +1 -2
  60. package/lib/modelCompare/compare.js +13 -11
  61. package/lib/optionProcessor.js +30 -9
  62. package/lib/render/manageConstraints.js +1 -1
  63. package/lib/render/toCdl.js +44 -14
  64. package/lib/render/toHdbcds.js +1 -2
  65. package/lib/render/toSql.js +45 -8
  66. package/lib/render/utils/common.js +12 -9
  67. package/lib/render/utils/stringEscapes.js +1 -0
  68. package/lib/transform/db/applyTransformations.js +13 -8
  69. package/lib/transform/db/associations.js +62 -54
  70. package/lib/transform/db/backlinks.js +20 -5
  71. package/lib/transform/db/expansion.js +1 -6
  72. package/lib/transform/db/flattening.js +86 -109
  73. package/lib/transform/db/killAnnotations.js +3 -0
  74. package/lib/transform/db/processSqlServices.js +63 -0
  75. package/lib/transform/db/temporal.js +3 -4
  76. package/lib/transform/db/views.js +0 -1
  77. package/lib/transform/draft/odata.js +56 -3
  78. package/lib/transform/effective/annotations.js +3 -2
  79. package/lib/transform/effective/flattening.js +135 -0
  80. package/lib/transform/effective/main.js +6 -4
  81. package/lib/transform/effective/types.js +13 -9
  82. package/lib/transform/forOdata.js +0 -2
  83. package/lib/transform/forRelationalDB.js +9 -19
  84. package/lib/transform/localized.js +7 -8
  85. package/lib/transform/odata/flattening.js +39 -31
  86. package/lib/transform/odata/typesExposure.js +5 -17
  87. package/lib/transform/transformUtils.js +1 -1
  88. package/lib/transform/translateAssocsToJoins.js +0 -1
  89. package/lib/utils/file.js +87 -8
  90. package/lib/utils/moduleResolve.js +59 -8
  91. package/lib/utils/term.js +3 -2
  92. package/package.json +7 -3
  93. package/share/messages/message-explanations.json +2 -0
  94. package/share/messages/type-unexpected-foreign-keys.md +52 -0
  95. 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.realpath,
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, cb );
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.realpathSync,
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, (err, modulePath) => {
170
- if (err)
171
- error = err;
172
- else
173
- result = modulePath;
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
- // variable here again.
61
- hasColor = hasColorShell && (process.env.NO_COLOR === undefined);
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": "4.9.6",
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/ types/ && 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",
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": ">=16"
67
+ "node": ">=18"
64
68
  }
65
69
  }
@@ -14,6 +14,8 @@
14
14
  "rewrite-not-supported",
15
15
  "syntax-expecting-unsigned-int",
16
16
  "type-missing-enum-value",
17
+ "type-unexpected-foreign-keys",
18
+ "type-unexpected-on-condition",
17
19
  "wildcard-excluding-one"
18
20
  ]
19
21
  }
@@ -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`