@sap/cds-compiler 4.8.0 → 4.9.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 (95) hide show
  1. package/CHANGELOG.md +38 -4
  2. package/bin/cds_remove_invalid_whitespace.js +135 -0
  3. package/bin/cds_update_annotations.js +180 -0
  4. package/bin/cds_update_identifiers.js +3 -4
  5. package/bin/cdsc.js +30 -17
  6. package/doc/CHANGELOG_BETA.md +19 -0
  7. package/lib/api/main.js +59 -24
  8. package/lib/api/options.js +12 -1
  9. package/lib/api/validate.js +1 -5
  10. package/lib/base/builtins.js +27 -0
  11. package/lib/base/message-registry.js +38 -21
  12. package/lib/base/messages.js +51 -20
  13. package/lib/base/model.js +4 -5
  14. package/lib/checks/actionsFunctions.js +2 -2
  15. package/lib/checks/annotationsOData.js +3 -0
  16. package/lib/checks/defaultValues.js +5 -2
  17. package/lib/checks/queryNoDbArtifacts.js +3 -2
  18. package/lib/checks/validator.js +2 -34
  19. package/lib/compiler/assert-consistency.js +10 -3
  20. package/lib/compiler/checks.js +44 -18
  21. package/lib/compiler/define.js +38 -30
  22. package/lib/compiler/extend.js +33 -10
  23. package/lib/compiler/index.js +0 -1
  24. package/lib/compiler/lsp-api.js +5 -0
  25. package/lib/compiler/populate.js +0 -2
  26. package/lib/compiler/propagator.js +23 -19
  27. package/lib/compiler/resolve.js +48 -29
  28. package/lib/compiler/shared.js +60 -20
  29. package/lib/compiler/tweak-assocs.js +72 -116
  30. package/lib/compiler/xpr-rewrite.js +762 -0
  31. package/lib/edm/annotations/edmJson.js +24 -7
  32. package/lib/edm/annotations/genericTranslation.js +81 -61
  33. package/lib/edm/edm.js +4 -4
  34. package/lib/edm/edmInboundChecks.js +33 -0
  35. package/lib/edm/edmPreprocessor.js +9 -6
  36. package/lib/gen/Dictionary.json +129 -14
  37. package/lib/gen/language.checksum +1 -1
  38. package/lib/gen/language.interp +1 -1
  39. package/lib/gen/languageParser.js +1523 -1518
  40. package/lib/json/from-csn.js +13 -4
  41. package/lib/json/to-csn.js +12 -12
  42. package/lib/language/genericAntlrParser.js +14 -6
  43. package/lib/main.d.ts +67 -14
  44. package/lib/main.js +1 -0
  45. package/lib/model/cloneCsn.js +6 -3
  46. package/lib/model/csnRefs.js +23 -11
  47. package/lib/model/csnUtils.js +13 -7
  48. package/lib/model/enrichCsn.js +3 -1
  49. package/lib/model/revealInternalProperties.js +2 -1
  50. package/lib/model/sortViews.js +14 -6
  51. package/lib/modelCompare/compare.js +33 -34
  52. package/lib/optionProcessor.js +27 -2
  53. package/lib/render/DuplicateChecker.js +6 -6
  54. package/lib/render/manageConstraints.js +1 -0
  55. package/lib/render/toCdl.js +3 -1
  56. package/lib/transform/db/applyTransformations.js +33 -0
  57. package/lib/transform/db/constraints.js +75 -28
  58. package/lib/transform/db/expansion.js +8 -3
  59. package/lib/transform/db/flattening.js +2 -2
  60. package/lib/transform/db/groupByOrderBy.js +2 -2
  61. package/lib/transform/db/temporal.js +6 -3
  62. package/lib/transform/db/transformExists.js +2 -2
  63. package/lib/transform/effective/annotations.js +194 -0
  64. package/lib/transform/effective/main.js +6 -8
  65. package/lib/transform/effective/misc.js +31 -10
  66. package/lib/transform/forOdata.js +23 -7
  67. package/lib/transform/forRelationalDB.js +3 -3
  68. package/lib/transform/localized.js +7 -6
  69. package/lib/transform/odata/flattening.js +221 -124
  70. package/lib/transform/odata/toFinalBaseType.js +1 -1
  71. package/lib/transform/odata/typesExposure.js +15 -12
  72. package/lib/transform/parseExpr.js +4 -4
  73. package/lib/transform/transformUtils.js +47 -42
  74. package/lib/transform/translateAssocsToJoins.js +47 -47
  75. package/lib/transform/universalCsn/universalCsnEnricher.js +16 -19
  76. package/package.json +1 -1
  77. package/share/messages/anno-missing-rewrite.md +45 -0
  78. package/share/messages/message-explanations.json +1 -0
  79. package/bin/.eslintrc.json +0 -17
  80. package/lib/api/.eslintrc.json +0 -37
  81. package/lib/checks/.eslintrc.json +0 -31
  82. package/lib/compiler/.eslintrc.json +0 -8
  83. package/lib/edm/.eslintrc.json +0 -46
  84. package/lib/inspect/.eslintrc.json +0 -4
  85. package/lib/json/.eslintrc.json +0 -4
  86. package/lib/language/.eslintrc.json +0 -4
  87. package/lib/model/.eslintrc.json +0 -13
  88. package/lib/modelCompare/utils/.eslintrc.json +0 -22
  89. package/lib/render/.eslintrc.json +0 -22
  90. package/lib/transform/.eslintrc.json +0 -13
  91. package/lib/transform/db/.eslintrc.json +0 -41
  92. package/lib/transform/draft/.eslintrc.json +0 -4
  93. package/lib/transform/effective/.eslintrc.json +0 -4
  94. package/lib/transform/universalCsn/.eslintrc.json +0 -37
  95. package/lib/utils/.eslintrc.json +0 -7
@@ -9,7 +9,7 @@ const {
9
9
  applyTransformations,
10
10
  implicitAs,
11
11
  } = require('../../model/csnUtils');
12
- const { isBuiltinType } = require('../../base/builtins');
12
+ const { isBuiltinType, propagationRules } = require('../../base/builtins');
13
13
  const {
14
14
  forEachValue, forEach,
15
15
  } = require('../../utils/objectUtils');
@@ -29,24 +29,10 @@ module.exports = (csn, options) => {
29
29
  } = csnUtils;
30
30
  // Properties on definition level that we treat specially.
31
31
  const definitionPropagationRules = {
32
- '@cds.autoexpose': onlyViaArtifact,
33
- '@cds.external': skip,
34
- '@fiori.draft.enabled': onlyViaArtifact,
32
+ __proto__: null,
35
33
  '@': nullStopsPropagation,
36
34
  // Example: `type E : F;` does not have `elements`, but they are required for e.g. OData.
37
35
  elements: onlyTypeDef,
38
- '@cds.persistence.exists': skip,
39
- '@cds.persistence.table': skip,
40
- '@cds.persistence.calcview': skip,
41
- '@cds.persistence.udf': skip,
42
- '@cds.persistence.skip': notWithPersistenceTable,
43
- '@sql.append': skip,
44
- '@sql.prepend': skip,
45
- '@sql.replace': skip,
46
- '@Analytics.hidden': skip,
47
- '@Analytics.visible': skip,
48
- '@cds.autoexposed': skip,
49
- '@cds.redirection.target': skip,
50
36
  type: always,
51
37
  doc: nullStopsPropagation,
52
38
  length: always,
@@ -65,6 +51,16 @@ module.exports = (csn, options) => {
65
51
  keys: always,
66
52
  };
67
53
 
54
+ const ruleToFunction = {
55
+ __proto__: null,
56
+ never: skip,
57
+ onlyViaArtifact,
58
+ notWithPersistenceTable,
59
+ };
60
+
61
+ for (const rule in propagationRules)
62
+ definitionPropagationRules[rule] = ruleToFunction[propagationRules[rule]];
63
+
68
64
  // Properties on member level that we treat specially
69
65
  const memberPropagationRules = {
70
66
  key: skip,
@@ -284,7 +280,8 @@ module.exports = (csn, options) => {
284
280
  },
285
281
  params: (parent, prop, params) => {
286
282
  forEachValue(params, (param) => {
287
- const propagateToParams = typeof param.type === 'string' ? csn.definitions[param.type]?.kind !== 'entity' : true;
283
+ const propagateToParams = (param.type !== '$self' || csn.definitions.$self) &&
284
+ (typeof param.type !== 'string' || csn.definitions[param.type]?.kind !== 'entity');
288
285
  propagateMemberPropsFromOrigin(param, {
289
286
  '@': !propagateToParams, items: true, elements: true, enum: true, virtual: true,
290
287
  });
@@ -343,8 +340,8 @@ module.exports = (csn, options) => {
343
340
  copyProperties(origin, target, getMemberPropagationRuleFor, except, force);
344
341
 
345
342
  // For a `type of` with .items, we want to take stuff from types (which we skip for "normal" propagation, see specialItemsRules).
346
- // So for a type of we also propagate stuff from the virtual origin (which we don't give a "kind", therefore skipping that part of the check)
347
- if (target.type && target.type.ref)
343
+ // So for a `type of` we also propagate stuff from the virtual origin (which we don't give a "kind", therefore skipping that part of the check)
344
+ if (target.type?.ref)
348
345
  copyProperties(virtualOrigin, target, getMemberPropagationRuleFor, except);
349
346
 
350
347
  if (!target.kind)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "4.8.0",
3
+ "version": "4.9.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)",
@@ -0,0 +1,45 @@
1
+ # anno-missing-rewrite
2
+
3
+ A propagated annotation containing expressions can't be rewritten and would
4
+ end up with invalid paths.
5
+
6
+ While propagating annotations containing expressions such as `@anno: (path)`,
7
+ the compiler ensures that the path remains valid. If necessary, the paths
8
+ have to be rewritten, e.g. when being propagated to projections that rename
9
+ their source's elements. If rewriting is not possible, this error is emitted.
10
+
11
+ ## Example
12
+
13
+ Erroneous code example:
14
+
15
+ ```cds
16
+ type T : {
17
+ @anno: (sibling)
18
+ elem: String;
19
+ sibling: String;
20
+ };
21
+ type TString : T:elem; // ❌ there is no `sibling`
22
+ ```
23
+
24
+ The annotating `@anno` would be propagated to `TString`. However, because its
25
+ path refers to an element that is not reachable at `TString`, the path can't
26
+ be rewritten and compilation fails.
27
+
28
+ ## How to Fix
29
+
30
+ Explicitly override the annotation. Either remove it by setting its value to
31
+ `null` or by using another value.
32
+
33
+ ```cds
34
+ // (1) direct annotation
35
+ @anno: null
36
+ type TString : T:elem;
37
+
38
+ // (2) annotate statement
39
+ type TString : T:elem;
40
+ annotate TString with @(anno: null);
41
+ ```
42
+
43
+ Variant (1) may not always be applicable, e.g. if annotations in a structured
44
+ type would need to be overridden. In those cases, use variant (2) and assign
45
+ annotations via the `annotate` statement.
@@ -2,6 +2,7 @@
2
2
  "$comment": "This is an auto-generated file! Do not edit this file directly!",
3
3
  "messages": [
4
4
  "anno-duplicate-unrelated-layer",
5
+ "anno-missing-rewrite",
5
6
  "check-proper-type-of",
6
7
  "def-duplicate-autoexposed",
7
8
  "def-missing-type",
@@ -1,17 +0,0 @@
1
- {
2
- "extends": ["../.eslintrc-ydkjsi.json"],
3
- "rules": {
4
- "prefer-const": "error",
5
- "quotes": ["error", "single", "avoid-escape"],
6
- "prefer-template": "error",
7
- "no-trailing-spaces": "error",
8
- "template-curly-spacing": ["error", "never"],
9
- "max-len": "off",
10
- "no-console": "off",
11
- "no-process-exit": "off",
12
- "camelcase": "off",
13
- "radix": "off",
14
- "no-shadow": "warn",
15
- "global-require": "off"
16
- }
17
- }
@@ -1,37 +0,0 @@
1
- {
2
- "root": true,
3
- "env": {
4
- "es2022": true,
5
- "node": true
6
- },
7
- // we actually do not extend airbnb-base, as it weakens some eslint:recommended rules
8
- "extends": ["plugin:jsdoc/recommended", "../../.eslintrc-ydkjsi.json"],
9
- "parserOptions": {
10
- "ecmaVersion": 2022,
11
- "sourceType": "script"
12
- },
13
- "plugins": [
14
- "jsdoc"
15
- ],
16
- "rules": {
17
- // Does not recognize TS types
18
- "jsdoc/no-undefined-types": "off",
19
- // eslint-plugin-jsdoc warning
20
- "jsdoc/require-property": 0,
21
- "jsdoc/tag-lines": "off",
22
- // =airbnb, >eslint:
23
- "max-len": [ "error", {
24
- "code": 100,
25
- "tabWidth": 2,
26
- "ignoreComments": true,
27
- "ignoreRegExpLiterals": true,
28
- "ignoreStrings": true,
29
- "ignoreTemplateLiterals": true
30
- }]
31
- },
32
- "settings": {
33
- "jsdoc": {
34
- "mode": "typescript"
35
- }
36
- }
37
- }
@@ -1,31 +0,0 @@
1
- {
2
- // we actually do not extend airbnb-base, as it weakens some eslint:recommended rules
3
- "extends": ["plugin:jsdoc/recommended", "../../.eslintrc-ydkjsi.json"],
4
- "plugins": [
5
- "jsdoc"
6
- ],
7
- "rules": {
8
- "cds-compiler/message-no-quotes": "off",
9
- "quotes": ["error", "single", {
10
- "avoidEscape": true,
11
- "allowTemplateLiterals": true
12
- }],
13
- "jsdoc/no-undefined-types": 0,
14
- // eslint-plugin-jsdoc warning
15
- "jsdoc/require-property": 0,
16
- // most of the main functions have the normal forEachArtifact/Member signature anyway
17
- "jsdoc/require-param-description": 0,
18
- // there seem to be false positives
19
- "jsdoc/require-returns-check": 0,
20
- "jsdoc/tag-lines": 0,
21
- // =airbnb, >eslint:
22
- "max-len": [ "error", {
23
- "code": 110,
24
- "tabWidth": 2,
25
- "ignoreComments": true,
26
- "ignoreRegExpLiterals": true,
27
- "ignoreStrings": true,
28
- "ignoreTemplateLiterals": true
29
- }]
30
- }
31
- }
@@ -1,8 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json",
4
- "rules": {
5
- "cds-compiler/message-no-quotes": "warn",
6
- "cds-compiler/space-in-func-call": "warn"
7
- }
8
- }
@@ -1,46 +0,0 @@
1
- {
2
- "root": true,
3
- //"plugins": ["sonarjs", "jsdoc"],
4
- //"extends": ["plugin:jsdoc/recommended", "../../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
5
- "plugins": ["sonarjs"],
6
- "extends": ["../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
7
- "rules": {
8
- "cds-compiler/message-no-quotes": "off",
9
- "cds-compiler/message-template-string": "off",
10
- "prefer-const": "error",
11
- "quotes": ["error", "single", "avoid-escape"],
12
- "prefer-template": "error",
13
- "no-trailing-spaces": "error",
14
- "template-curly-spacing":["error", "never"],
15
- "complexity": ["warn", 50],
16
- "max-len": "off",
17
- // there seem to be false positives
18
- "jsdoc/require-returns-check": "off",
19
- // Don't enforce stupid descriptions
20
- "jsdoc/require-param-description": "off",
21
- "jsdoc/require-returns-description": "off",
22
- // Sometimes if-else's are more specific
23
- "sonarjs/prefer-single-boolean-return": "off",
24
- // Very whiny and nitpicky
25
- "sonarjs/cognitive-complexity": "off",
26
- "sonarjs/no-duplicate-string": "off",
27
- // Does not recognize TS types
28
- "jsdoc/no-undefined-types": "off",
29
- "jsdoc/tag-lines": "off",
30
- "no-nested-ternary": "off",
31
- "sonarjs/no-nested-template-literals": "off"
32
- },
33
- "parserOptions": {
34
- "ecmaVersion": 2022,
35
- "sourceType": "script"
36
- },
37
- "env": {
38
- "es2022": true,
39
- "node": true
40
- },
41
- "settings": {
42
- "jsdoc": {
43
- "mode": "typescript"
44
- }
45
- }
46
- }
@@ -1,4 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json"
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json"
4
- }
@@ -1,13 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json",
4
- "rules": {
5
- "max-len": [ "error", {
6
- "code": 180, // TODO: Remove
7
- "tabWidth": 2,
8
- "ignoreRegExpLiterals": false,
9
- "ignoreStrings": false,
10
- "ignoreTemplateLiterals": true
11
- }]
12
- }
13
- }
@@ -1,22 +0,0 @@
1
- {
2
- "plugins": ["sonarjs"],
3
- "extends": ["../../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
4
- "rules": {
5
- "prefer-const": "error",
6
- "quotes": ["error", "single", "avoid-escape"],
7
- "prefer-template": "error",
8
- "no-trailing-spaces": "error",
9
- "sonarjs/cognitive-complexity": "off",
10
- "sonarjs/no-duplicate-string": ["off"],
11
- "sonarjs/no-nested-template-literals": "off",
12
- "template-curly-spacing":["error", "never"],
13
- "class-methods-use-this": "off",
14
- // Who cares - just very whiny and in the way
15
- "complexity": "off",
16
- "max-len": "off",
17
- "no-shadow": "warn"
18
- },
19
- "env": {
20
- "es2022": true
21
- }
22
- }
@@ -1,22 +0,0 @@
1
- {
2
- "plugins": ["sonarjs"],
3
- "extends": ["../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
4
- "rules": {
5
- "cds-compiler/message-no-quotes": "off",
6
- "prefer-const": "error",
7
- "quotes": ["error", "single", "avoid-escape"],
8
- "prefer-template": "error",
9
- "no-trailing-spaces": "error",
10
- "sonarjs/cognitive-complexity": "off",
11
- "sonarjs/no-duplicate-string": ["off"],
12
- "sonarjs/no-nested-template-literals": "off",
13
- "template-curly-spacing":["error", "never"],
14
- "class-methods-use-this": "off",
15
- "complexity": "off",
16
- "max-len": "off",
17
- "no-shadow": "warn"
18
- },
19
- "env": {
20
- "es2022": true
21
- }
22
- }
@@ -1,13 +0,0 @@
1
- {
2
- "rules": {
3
- "no-shadow": "off"
4
- },
5
- "overrides": [
6
- {
7
- "files": [
8
- "addTenantFields.js"
9
- ],
10
- "extends": "../../.eslintrc-ydkjsi.json"
11
- }
12
- ]
13
- }
@@ -1,41 +0,0 @@
1
- {
2
- "root": true,
3
- "plugins": ["sonarjs", "jsdoc"],
4
- "extends": ["plugin:jsdoc/recommended", "../../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
5
- "rules": {
6
- "cds-compiler/message-no-quotes": "off",
7
- "prefer-const": "error",
8
- "quotes": ["error", "single", "avoid-escape"],
9
- "prefer-template": "error",
10
- "no-trailing-spaces": "error",
11
- "template-curly-spacing":["error", "never"],
12
- "complexity": ["warn", 40],
13
- "max-len": "off",
14
- // there seem to be false positives
15
- "jsdoc/require-returns-check": "off",
16
- // Don't enforce stupid descriptions
17
- "jsdoc/require-param-description": "off",
18
- "jsdoc/require-returns-description": "off",
19
- // Sometimes if-else's are more specific
20
- "sonarjs/prefer-single-boolean-return": "off",
21
- // Very whiny and nitpicky
22
- "sonarjs/cognitive-complexity": "off",
23
- "sonarjs/no-duplicate-string": "off",
24
- // Does not recognize TS types
25
- "jsdoc/no-undefined-types": "off",
26
- "jsdoc/tag-lines": "off"
27
- },
28
- "parserOptions": {
29
- "ecmaVersion": 2022,
30
- "sourceType": "script"
31
- },
32
- "env": {
33
- "es2022": true,
34
- "node": true
35
- },
36
- "settings": {
37
- "jsdoc": {
38
- "mode": "typescript"
39
- }
40
- }
41
- }
@@ -1,4 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": ["../db/.eslintrc.json"]
4
- }
@@ -1,4 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": ["../db/.eslintrc.json"]
4
- }
@@ -1,37 +0,0 @@
1
- {
2
- "root": true,
3
- "plugins": ["sonarjs", "jsdoc"],
4
- "extends": ["plugin:jsdoc/recommended", "../../../.eslintrc-ydkjsi.json", "plugin:sonarjs/recommended"],
5
- "rules": {
6
- "prefer-const": "error",
7
- "quotes": ["error", "single", "avoid-escape"],
8
- "prefer-template": "error",
9
- "no-trailing-spaces": "error",
10
- "template-curly-spacing":["error", "never"],
11
- "complexity": ["warn", 30],
12
- "max-len": "off",
13
- // Don't enforce stupid descriptions
14
- "jsdoc/require-param-description": "off",
15
- "jsdoc/require-returns-description": "off",
16
- // Very whiny and nitpicky
17
- "sonarjs/cognitive-complexity": "off",
18
- // Does not recognize TS types
19
- "jsdoc/no-undefined-types": "off",
20
- "jsdoc/tag-lines": "off",
21
- // Just annoying as hell
22
- "sonarjs/no-duplicate-string": "off"
23
- },
24
- "parserOptions": {
25
- "ecmaVersion": 2022,
26
- "sourceType": "script"
27
- },
28
- "env": {
29
- "es2022": true,
30
- "node": true
31
- },
32
- "settings": {
33
- "jsdoc": {
34
- "mode": "typescript"
35
- }
36
- }
37
- }
@@ -1,7 +0,0 @@
1
- {
2
- "root": true,
3
- "extends": "../../.eslintrc-ydkjsi.json",
4
- "rules": {
5
- "prefer-const": "warn"
6
- }
7
- }