@sap/cds-compiler 3.4.4 → 3.5.2

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 (129) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
@@ -8,7 +8,7 @@
8
8
  * @param {string} property
9
9
  * @param {object} targetObj
10
10
  */
11
- function copyPropIfExist(sourceObj, property, targetObj) {
11
+ function copyPropIfExist( sourceObj, property, targetObj ) {
12
12
  if (sourceObj && property in sourceObj)
13
13
  targetObj[property] = sourceObj[property];
14
14
  }
@@ -21,7 +21,7 @@ function copyPropIfExist(sourceObj, property, targetObj) {
21
21
  * @param {object} obj Object with prototype.
22
22
  * @return {object} Object without prototype, i.e. a dict.
23
23
  */
24
- function createDict(obj) {
24
+ function createDict( obj ) {
25
25
  const dict = Object.create(null);
26
26
  const keys = Object.keys(obj);
27
27
  for (const key of keys)
@@ -33,9 +33,9 @@ function createDict(obj) {
33
33
  * Loops over all elements in an object and calls the specified callback(key,obj)
34
34
  *
35
35
  * @param {object} obj
36
- * @param {(string, object) => void} callback
36
+ * @param {(key: string, value: object) => void} callback
37
37
  */
38
- function forEach(obj, callback) {
38
+ function forEach( obj, callback ) {
39
39
  for (const key in obj) {
40
40
  if (Object.prototype.hasOwnProperty.call(obj, key))
41
41
  callback(key, obj[key]);
@@ -49,7 +49,7 @@ function forEach(obj, callback) {
49
49
  * @param {object} o the object which values should be iterated
50
50
  * @param {Function} callback
51
51
  */
52
- function forEachValue(o, callback) {
52
+ function forEachValue( o, callback ) {
53
53
  for (const key in o) {
54
54
  if (Object.prototype.hasOwnProperty.call(o, key))
55
55
  callback(o[key]);
@@ -63,7 +63,7 @@ function forEachValue(o, callback) {
63
63
  * @param {object} o the object which keys should be iterated
64
64
  * @param {Function} callback
65
65
  */
66
- function forEachKey(o, callback) {
66
+ function forEachKey( o, callback ) {
67
67
  for (const key in o) {
68
68
  if (Object.prototype.hasOwnProperty.call(o, key))
69
69
  callback(key);
package/lib/utils/term.js CHANGED
@@ -33,11 +33,14 @@ const t = {
33
33
  cyan: '\x1b[36m', // Foreground Cyan
34
34
  };
35
35
 
36
- function term(useColor = 'auto') {
36
+ /**
37
+ * @param {string|boolean} [useColor]
38
+ */
39
+ function term( useColor = 'auto' ) {
37
40
  let hasColor = hasColorShell;
38
41
  changeColorMode(useColor);
39
42
 
40
- function changeColorMode(mode) {
43
+ function changeColorMode( mode ) {
41
44
  switch (mode) {
42
45
  case false:
43
46
  case 'never':
@@ -1,5 +1,14 @@
1
1
  'use strict';
2
2
 
3
+ const { CompilerAssertion } = require('../base/error');
4
+
5
+ function hrtimeToSec( dt ) {
6
+ const sec = (dt / BigInt('1000000000')).toString().padStart(2, ' ');
7
+ // first, get remaining ns, then convert to ms.
8
+ const msec = ((dt % BigInt('1000000000')) / BigInt('1000000')).toString().padStart(3, '0');
9
+ return [ sec, msec ];
10
+ }
11
+
3
12
  /**
4
13
  * A single StopWatch encapsulates the runtime of a selected code frame.
5
14
  *
@@ -71,6 +80,20 @@ class TimeTracer {
71
80
  */
72
81
  constructor() {
73
82
  this.traceStack = [];
83
+ this.lastStop = null;
84
+ }
85
+
86
+ /**
87
+ * Reset the time tracer. Use this if an exception is thrown, because then
88
+ * start/end won't correctly match.
89
+ *
90
+ * @param {string} reason
91
+ */
92
+ reset(reason) {
93
+ // eslint-disable-next-line no-console
94
+ console.error(`Reset TimeTrace: Stopping all timers because: ${ reason }`);
95
+ while (this.traceStack.length)
96
+ this.stop(this.traceStack[this.traceStack.length - 1].id);
74
97
  }
75
98
 
76
99
  /**
@@ -81,46 +104,50 @@ class TimeTracer {
81
104
  * @memberOf TimeTracer
82
105
  */
83
106
  start(id) {
84
- try {
85
- const b = new StopWatch(id);
86
- this.traceStack.push(b);
87
- b.start();
107
+ // Get time between last stop and new start: Those sections were not tracked.
108
+ const [ sec, msec ] = this.lastStop ? hrtimeToSec(this.lastStop.stop()) : [ ' 0', '000' ];
109
+ this.lastStop = null;
110
+ let base = `${ ' '.repeat(this.traceStack.length * 2) }${ id } started:`;
111
+ base += ' '.repeat(60 - base.length);
112
+ if (sec !== ' 0' || msec !== '000')
88
113
  // eslint-disable-next-line no-console
89
- console.error(`${ ' '.repeat((this.traceStack.length - 1) * 2) }${ id } started`);
90
- }
91
- catch (e) {
114
+ console.error( `${ base } ${ sec }s ${ msec }ms (since last stop)` );
115
+ else
92
116
  // eslint-disable-next-line no-console
93
- console.error(`Starting time trace with id ${ id } failed: ${ e }`);
94
- }
117
+ console.error( `${ base }` );
118
+ this.traceStack.push(new StopWatch(id));
95
119
  }
96
120
 
97
121
  /**
98
122
  * Stop the current TimeTrace and log the execution time.
99
123
  *
100
- *
124
+ * @param {string} id
101
125
  * @memberOf TimeTracer
102
126
  */
103
- stop() {
104
- try {
105
- const current = this.traceStack.pop();
106
- const dt = current.stop();
107
- const base = `${ ' '.repeat(this.traceStack.length * 2) }${ current.id } took:`;
108
- const sec = (dt / BigInt(1000000000)).toString();
109
- // first, get remaining ns, then convert to ms.
110
- const msec = ((dt % BigInt(1000000000)) / BigInt(1000000)).toString();
111
- // eslint-disable-next-line no-console
112
- console.error( `${ base }${ ' '.repeat(60 - base.length) } %ds %dms`, sec, msec );
113
- }
114
- catch (e) {
115
- // eslint-disable-next-line no-console
116
- console.error(`Stopping time trace failed: ${ e }`);
127
+ stop(id) {
128
+ if (this.traceStack.length === 0)
129
+ throw new CompilerAssertion('TimeTracer mismatch: called stop() too many times');
130
+ const current = this.traceStack.pop();
131
+ if (current.id !== id)
132
+ throw new CompilerAssertion(`TimeTracer mismatch; expected id: “${ id }”, was “${ current.id }”`);
133
+ let diff = '';
134
+ if (this.lastStop !== null) {
135
+ const [ sec, msec ] = hrtimeToSec(this.lastStop.stop());
136
+ if ( sec !== ' 0' || msec !== '000')
137
+ diff = ` (diff to last stop: ${ sec }s ${ msec }ms)`;
117
138
  }
139
+ const [ sec, msec ] = hrtimeToSec(current.stop());
140
+ const base = `${ ' '.repeat(this.traceStack.length * 2) }${ current.id } took:`;
141
+ // eslint-disable-next-line no-console
142
+ console.error( `${ base }${ ' '.repeat(60 - base.length) } ${ sec }s ${ msec }ms${ diff }` );
143
+ this.lastStop = new StopWatch(id);
118
144
  }
119
145
  }
120
146
 
121
147
  const ignoreTimeTrace = {
122
148
  start: () => { /* ignore */ },
123
149
  stop: () => { /* ignore */ },
150
+ reset: () => { /* ignore */ },
124
151
  };
125
152
 
126
153
  const doTimeTrace = process && process.env && process.env.CDSC_TIMETRACING !== undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "3.4.4",
3
+ "version": "3.5.2",
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)",
@@ -21,16 +21,14 @@
21
21
  "xmakePrepareRelease": "echo \"$(node scripts/stripReadme.js README.md)\" > README.md && node scripts/assertSnapshotVersioning.js && node scripts/assertChangelog.js && node scripts/cleanup.js --remove-dev",
22
22
  "test": "node scripts/verifyGrammarChecksum.js && mocha --reporter min --reporter-option maxDiffSize=0 scripts/testLazyLoading.js && mocha --parallel --reporter min --reporter-option maxDiffSize=0 test/ test3/",
23
23
  "testverbose": "node scripts/verifyGrammarChecksum.js && mocha --parallel test/ test3/",
24
- "test3": "node scripts/verifyGrammarChecksum.js && node scripts/linter/lintTests.js test3/ && mocha --reporter-option maxDiffSize=0 scripts/linter/lintMessages.js test3/",
25
- "deployTest3SQL": "deployRefs=true mocha --reporter-option maxDiffSize=0 test3/testHANASQLDeployment.js",
24
+ "test3": "node scripts/verifyGrammarChecksum.js && mocha --reporter-option maxDiffSize=0 test3/",
25
+ "deployTest3SQL": "deployRefs=true mocha --reporter-option maxDiffSize=0 test3/test.deploy.hana-sql.js",
26
26
  "deployTest3": "deployRefs=true mocha --reporter-option maxDiffSize=0 test3/testDeployment.js",
27
+ "deployHanaDeltaSQL": "CDS_COMPILER_DEPLOY_HANA=1 mocha test3/test.deploy.hana-sql.delta.js",
27
28
  "deployDiffs": "deployRefs=true mocha --reporter-option maxDiffSize=0 test3/deployDiffs.js",
28
29
  "gentest3": "cross-env MAKEREFS=${MAKEREFS:-'true'} mocha --reporter-option maxDiffSize=0 test3/testRefFiles.js",
29
- "testdb": "node scripts/verifyGrammarChecksum.js && cross-env TESTDB='TRUE' mocha",
30
- "testmigration": "npm install --no-save @sap/hana-client@2.3.123 @sap/hdi-deploy@3.10.0 && node scripts/verifyGrammarChecksum.js && cross-env TESTMIGRATION='TRUE' mocha",
31
- "testall": "npm install --no-save @sap/hana-client@2.3.123 @sap/hdi-deploy@3.10.0 && node scripts/verifyGrammarChecksum.js && cross-env TESTDB='TRUE' TESTMIGRATION='TRUE' mocha",
32
30
  "coverage": "cross-env nyc mocha --reporter-option maxDiffSize=0 test/ test3/ && nyc report --reporter=lcov",
33
- "lint": "eslint bin/ benchmark/ lib/ test/ test3/ scripts/ types/ && node scripts/linter/lintGrammar.js && node scripts/linter/lintTests.js test3/ && node scripts/linter/lintMessageIdCoverage.js lib/ && markdownlint README.md CHANGELOG.md doc/ internalDoc/ && cd share/messages && markdownlint .",
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 .",
34
32
  "tslint": "tsc --pretty -p .",
35
33
  "updateVocs": "node scripts/odataAnnotations/generateDictMain.js && npm run generateAllRefs",
36
34
  "generateCompilerRefs": "cross-env MAKEREFS='true' mocha test/testCompiler.js",
@@ -19,7 +19,7 @@ view ViewFoo as select from Foo {
19
19
  };
20
20
  entity Bar {
21
21
  // `e` has no proper type but has the annotation `@anno`.
22
- e : type of ViewFoo:calculatedField;
22
+ e : ViewFoo:calculatedField;
23
23
  };
24
24
  ```
25
25
 
@@ -11,7 +11,7 @@
11
11
  "redirected-to-complex",
12
12
  "redirected-to-unrelated",
13
13
  "rewrite-not-supported",
14
- "syntax-expecting-integer",
14
+ "syntax-expecting-unsigned-int",
15
15
  "wildcard-excluding-one"
16
16
  ]
17
17
  }
@@ -3,7 +3,7 @@
3
3
  The redirected target is a complex view, for example, contains a JOIN or UNION.
4
4
 
5
5
  The message's severity is `Info` and is raised by the compiler.
6
- It is emitted to help developers identify possible modelling issues.
6
+ It is emitted to help developers identify possible modeling issues.
7
7
 
8
8
  ## Example
9
9
 
@@ -33,7 +33,7 @@ The cross join in the view `CrossJoin` results in multiple rows with the same
33
33
  `id`. Following the redirected view now returns multiple results, effectively
34
34
  making the to-one association a to-many association.
35
35
 
36
- Visualizing the tables with a bit of data, this issues becomes obvious:
36
+ Visualizing the tables with a bit of data, this issue becomes obvious:
37
37
 
38
38
  ```markdown
39
39
  Main Secondary
@@ -54,8 +54,8 @@ CrossJoin
54
54
  ## How to Fix
55
55
 
56
56
  Ensure that the redirected association points to an entity that is a reasonable
57
- redirection target. You must ensure that the redirection does not accidentally
58
- result in a to-one association becoming a to-many association.
57
+ redirection target. That means, the redirection target shouldn't accidentally
58
+ make it a to-many association.
59
59
 
60
60
  ## Related Messages
61
61
 
@@ -1,6 +1,6 @@
1
- # syntax-expecting-integer
1
+ # syntax-expecting-unsigned-int
2
2
 
3
- The compiler expects a safe integer here.
3
+ The compiler expects a safe non-negative integer here.
4
4
  The last safe integer is `2^53 - 1` or `9007199254740991`.
5
5
 
6
6
  A safe integer is an integer that fulfills all of the following:
@@ -34,5 +34,8 @@ type LengthIsSafe : String(9007199254740991);
34
34
  type AnInteger : String(42);
35
35
  ```
36
36
 
37
- If it's not feasible to use a safe integer, a string representation of the
38
- number needs to be used, for example, in annotation values.
37
+ At other places, using unsafe integers (or non-integer numbers) is allowed:
38
+
39
+ - Annotation values: The value is then simply a string.
40
+ - Expressions: The `val` property in the CSN contains a string
41
+ having a sibling `literal: 'number'`.