@sap/cds-compiler 2.10.2 → 2.11.4

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 (82) hide show
  1. package/CHANGELOG.md +90 -5
  2. package/bin/.eslintrc.json +1 -2
  3. package/bin/cds_update_identifiers.js +3 -1
  4. package/bin/cdsc.js +49 -25
  5. package/bin/cdsse.js +1 -0
  6. package/bin/cdsv2m.js +3 -2
  7. package/doc/CHANGELOG_BETA.md +10 -0
  8. package/lib/api/.eslintrc.json +2 -0
  9. package/lib/api/main.js +8 -36
  10. package/lib/api/options.js +15 -6
  11. package/lib/api/validate.js +30 -3
  12. package/lib/backends.js +12 -13
  13. package/lib/base/dictionaries.js +2 -1
  14. package/lib/base/keywords.js +3 -2
  15. package/lib/base/message-registry.js +34 -10
  16. package/lib/base/messages.js +38 -18
  17. package/lib/base/model.js +5 -4
  18. package/lib/base/optionProcessorHelper.js +57 -23
  19. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  20. package/lib/checks/selectItems.js +4 -0
  21. package/lib/checks/unknownMagic.js +6 -3
  22. package/lib/compiler/assert-consistency.js +9 -2
  23. package/lib/compiler/base.js +65 -0
  24. package/lib/compiler/builtins.js +62 -16
  25. package/lib/compiler/checks.js +2 -1
  26. package/lib/compiler/definer.js +66 -108
  27. package/lib/compiler/index.js +29 -29
  28. package/lib/compiler/propagator.js +5 -2
  29. package/lib/compiler/resolver.js +225 -58
  30. package/lib/compiler/shared.js +53 -229
  31. package/lib/compiler/utils.js +184 -0
  32. package/lib/edm/annotations/genericTranslation.js +1 -1
  33. package/lib/edm/csn2edm.js +3 -2
  34. package/lib/edm/edmPreprocessor.js +34 -38
  35. package/lib/edm/edmUtils.js +3 -3
  36. package/lib/gen/language.checksum +1 -1
  37. package/lib/gen/language.interp +17 -1
  38. package/lib/gen/language.tokens +79 -73
  39. package/lib/gen/languageLexer.interp +19 -1
  40. package/lib/gen/languageLexer.js +779 -731
  41. package/lib/gen/languageLexer.tokens +71 -65
  42. package/lib/gen/languageParser.js +4668 -4072
  43. package/lib/json/from-csn.js +10 -10
  44. package/lib/json/to-csn.js +228 -47
  45. package/lib/language/antlrParser.js +11 -0
  46. package/lib/language/errorStrategy.js +26 -8
  47. package/lib/language/genericAntlrParser.js +73 -14
  48. package/lib/language/language.g4 +79 -3
  49. package/lib/main.d.ts +215 -18
  50. package/lib/main.js +3 -1
  51. package/lib/model/api.js +2 -2
  52. package/lib/model/csnRefs.js +117 -33
  53. package/lib/model/csnUtils.js +65 -133
  54. package/lib/model/enrichCsn.js +62 -37
  55. package/lib/model/revealInternalProperties.js +25 -8
  56. package/lib/model/sortViews.js +8 -1
  57. package/lib/modelCompare/compare.js +2 -1
  58. package/lib/optionProcessor.js +33 -18
  59. package/lib/render/.eslintrc.json +1 -2
  60. package/lib/render/DuplicateChecker.js +1 -1
  61. package/lib/render/toCdl.js +15 -8
  62. package/lib/render/toHdbcds.js +26 -49
  63. package/lib/render/toSql.js +61 -39
  64. package/lib/render/utils/common.js +1 -1
  65. package/lib/transform/db/applyTransformations.js +189 -0
  66. package/lib/transform/db/constraints.js +273 -119
  67. package/lib/transform/db/draft.js +3 -2
  68. package/lib/transform/db/expansion.js +6 -4
  69. package/lib/transform/db/flattening.js +19 -3
  70. package/lib/transform/db/transformExists.js +102 -9
  71. package/lib/transform/db/views.js +485 -0
  72. package/lib/transform/forHanaNew.js +93 -448
  73. package/lib/transform/forOdataNew.js +9 -2
  74. package/lib/transform/localized.js +2 -0
  75. package/lib/transform/odata/structuralPath.js +1 -5
  76. package/lib/transform/transformUtilsNew.js +22 -8
  77. package/lib/transform/translateAssocsToJoins.js +7 -15
  78. package/lib/utils/file.js +11 -5
  79. package/lib/utils/term.js +65 -42
  80. package/lib/utils/timetrace.js +48 -26
  81. package/package.json +1 -1
  82. package/lib/transform/db/helpers.js +0 -58
@@ -0,0 +1,189 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Module for general (partial) CSN looper functions, respecting dictionaries and allowing
5
+ * to pass custom callbacks for certain properties like "ref".
6
+ *
7
+ * Functions are also published in csnUtils.js for convenience.
8
+ *
9
+ * They should stay here due to the stricter linter rules for the time being.
10
+ *
11
+ * @module lib/transform/db/applyTransformations
12
+ */
13
+ const { setProp } = require('../../base/model');
14
+
15
+
16
+ /**
17
+ * @param {object} parent The "parent" of which we transform a property of
18
+ * @param {string} prop The property of parent to start at
19
+ * @param {object} customTransformers Map of prop to transform and function to apply
20
+ * @param {Function[]} [artifactTransformers=[]] Transformations to run on the artifacts, like forEachDefinition
21
+ * @param {boolean} [skipIgnore=true] Wether to skip _ignore elements or not
22
+ * @param {object} [options={}] "skipArtifact": (artifact, name) => Boolean to skip certain artifacts, drillRef: boolean - whether to drill into infix/args
23
+ * @param {CSN.Path} path Path to parent
24
+ * @returns {object} parent with transformations applied
25
+ */
26
+ function applyTransformationsInternal(parent, prop, customTransformers, artifactTransformers, skipIgnore, options, path = []) {
27
+ const transformers = {
28
+ elements: dictionary,
29
+ definitions: dictionary,
30
+ actions: dictionary,
31
+ params: dictionary,
32
+ enum: dictionary,
33
+ mixin: dictionary,
34
+ ref: pathRef,
35
+ };
36
+
37
+ const csnPath = [ ...path ];
38
+ if (prop === 'definitions')
39
+ definitions( parent, 'definitions', parent.definitions );
40
+ else
41
+ standard(parent, prop, parent[prop]);
42
+ return parent;
43
+
44
+ /**
45
+ * Default transformer for things that are not dictionaries, like "type" or "keys".
46
+ * The customTransformers are applied here (and only here).
47
+ *
48
+ * @param {object | Array} _parent the thing that has _prop
49
+ * @param {string|number} _prop the name of the current property
50
+ * @param {object} node The value of node[_prop]
51
+ */
52
+ function standard( _parent, _prop, node ) {
53
+ if (!node || typeof node !== 'object' || !{}.propertyIsEnumerable.call( _parent, _prop ) || (typeof _prop === 'string' && _prop.startsWith('@')) || (skipIgnore && node._ignore))
54
+ return;
55
+
56
+ csnPath.push( _prop );
57
+
58
+ if (Array.isArray(node)) {
59
+ node.forEach( (n, i) => standard( node, i, n ) );
60
+ }
61
+
62
+ else {
63
+ for (const name of Object.getOwnPropertyNames( node )) {
64
+ const trans = transformers[name] || standard;
65
+ if (customTransformers[name])
66
+ customTransformers[name](node, name, node[name], csnPath, _parent, _prop);
67
+
68
+ trans( node, name, node[name], csnPath );
69
+ }
70
+ }
71
+ csnPath.pop();
72
+ }
73
+
74
+ /**
75
+ * Transformer for things that are dictionaries - like "elements".
76
+ *
77
+ * @param {object | Array} node the thing that has _prop
78
+ * @param {string|number} _prop the name of the current property
79
+ * @param {object} dict The value of node[_prop]
80
+ */
81
+ function dictionary( node, _prop, dict ) {
82
+ // Allow skipping dicts like actions in forHanaNew
83
+ if (options.skipDict && options.skipDict[_prop])
84
+ return;
85
+ csnPath.push( _prop );
86
+ for (const name of Object.getOwnPropertyNames( dict ))
87
+ standard( dict, name, dict[name] );
88
+
89
+ if (!Object.prototype.propertyIsEnumerable.call( node, _prop ))
90
+ setProp(node, `$${_prop}`, dict);
91
+ csnPath.pop();
92
+ }
93
+
94
+ /**
95
+ * Special version of "dictionary" to apply artifactTransformers.
96
+ *
97
+ * @param {object | Array} node the thing that has _prop
98
+ * @param {string|number} _prop the name of the current property
99
+ * @param {object} dict The value of node[_prop]
100
+ */
101
+ function definitions( node, _prop, dict ) {
102
+ csnPath.push( _prop );
103
+ for (const name of Object.getOwnPropertyNames( dict )) {
104
+ const skip = options && options.skipArtifact && options.skipArtifact(dict[name], name) || false;
105
+ if (!skip) {
106
+ artifactTransformers.forEach(fn => fn(dict, name, dict[name]));
107
+ standard( dict, name, dict[name] );
108
+ }
109
+ }
110
+ if (!Object.prototype.propertyIsEnumerable.call( node, _prop ))
111
+ setProp(node, `$${_prop}`, dict);
112
+ csnPath.pop();
113
+ }
114
+
115
+ /**
116
+ * Keep looping through the pathRef - because in a .ref we can have .args and .where
117
+ *
118
+ * @param {object | Array} node the thing that has _prop
119
+ * @param {string|number} _prop the name of the current property
120
+ * @param {any} _path The value of node[_prop]
121
+ */
122
+ function pathRef( node, _prop, _path ) {
123
+ csnPath.push( _prop );
124
+ _path.forEach( ( s, i ) => {
125
+ if (s && typeof s === 'object') {
126
+ csnPath.push( i );
127
+ if (options.drillRef) {
128
+ standard(_path, i, s);
129
+ }
130
+ else {
131
+ if (s.args)
132
+ standard( s, 'args', s.args );
133
+ if (s.where)
134
+ standard( s, 'where', s.where );
135
+ }
136
+ csnPath.pop();
137
+ }
138
+ } );
139
+ csnPath.pop();
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Loop through the model, applying the custom transformations on the node's matching.
145
+ *
146
+ * Each transformer gets:
147
+ * - the parent having the property
148
+ * - the name of the property
149
+ * - the value of the property
150
+ * - the path to the property
151
+ *
152
+ * @param {object} csn CSN to enrich in-place
153
+ * @param {object} customTransformers Map of _prop to transform and function to apply
154
+ * @param {Function[]} [artifactTransformers=[]] Transformations to run on the artifacts, like forEachDefinition
155
+ * @param {boolean} [skipIgnore=true] Wether to skip _ignore elements or not
156
+ * @param {object} [options={}] "skipArtifact": (artifact, name) => Boolean to skip certain artifacts, drillRef: boolean - whether to drill into infix/args
157
+ * @returns {object} CSN with transformations applied
158
+ */
159
+ function applyTransformations( csn, customTransformers = {}, artifactTransformers = [], skipIgnore = true, options = {} ) {
160
+ if (csn && csn.definitions)
161
+ return applyTransformationsInternal(csn, 'definitions', customTransformers, artifactTransformers, skipIgnore, options);
162
+ return csn;
163
+ }
164
+
165
+
166
+ /**
167
+ * Instead of looping through the whole model, start at a given thing (like an on-condition),
168
+ * as long as it is not a dictionary.
169
+ *
170
+ * Each transformer gets:
171
+ * - the parent having the property
172
+ * - the name of the property
173
+ * - the value of the property
174
+ * - the path to the property
175
+ *
176
+ * @param {object} parent The "parent" of which we transform a property of
177
+ * @param {string} prop The property of parent to start at
178
+ * @param {object} customTransformers Map of prop to transform and function to apply
179
+ * @param {CSN.Path} path Path pointing to parent
180
+ * @returns {object} parent[prop] with transformations applied
181
+ */
182
+ function applyTransformationsOnNonDictionary(parent, prop, customTransformers = {}, path = []) {
183
+ return applyTransformationsInternal(parent, prop, customTransformers, [], true, {}, path)[prop];
184
+ }
185
+
186
+ module.exports = {
187
+ applyTransformations,
188
+ applyTransformationsOnNonDictionary,
189
+ };