@sap/cds-compiler 2.4.4 → 2.10.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.
- package/CHANGELOG.md +241 -1
- package/bin/.eslintrc.json +17 -0
- package/bin/cds_update_identifiers.js +8 -7
- package/bin/cdsc.js +180 -132
- package/bin/cdshi.js +18 -11
- package/bin/cdsse.js +38 -32
- package/bin/cdsv2m.js +8 -7
- package/doc/CHANGELOG_BETA.md +36 -1
- package/lib/api/main.js +81 -100
- package/lib/api/options.js +17 -11
- package/lib/api/validate.js +12 -8
- package/lib/backends.js +0 -81
- package/lib/base/keywords.js +32 -2
- package/lib/base/location.js +2 -2
- package/lib/base/message-registry.js +66 -4
- package/lib/base/messages.js +84 -27
- package/lib/base/model.js +2 -61
- package/lib/checks/arrayOfs.js +0 -1
- package/lib/checks/defaultValues.js +27 -2
- package/lib/checks/elements.js +1 -6
- package/lib/checks/enricher.js +8 -2
- package/lib/checks/foreignKeys.js +0 -6
- package/lib/checks/managedWithoutKeys.js +17 -0
- package/lib/checks/nonexpandableStructured.js +38 -0
- package/lib/checks/onConditions.js +9 -45
- package/lib/checks/queryNoDbArtifacts.js +27 -9
- package/lib/checks/selectItems.js +25 -2
- package/lib/checks/types.js +26 -2
- package/lib/checks/unknownMagic.js +38 -0
- package/lib/checks/utils.js +61 -0
- package/lib/checks/validator.js +66 -13
- package/lib/compiler/assert-consistency.js +24 -12
- package/lib/compiler/builtins.js +2 -0
- package/lib/compiler/checks.js +6 -4
- package/lib/compiler/definer.js +101 -39
- package/lib/compiler/index.js +88 -59
- package/lib/compiler/resolver.js +455 -209
- package/lib/compiler/shared.js +57 -33
- package/lib/edm/annotations/genericTranslation.js +183 -187
- package/lib/edm/csn2edm.js +128 -99
- package/lib/edm/edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +361 -127
- package/lib/edm/edmUtils.js +103 -33
- package/lib/gen/Dictionary.json +74 -28
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +18 -4
- package/lib/gen/language.tokens +124 -118
- package/lib/gen/languageLexer.interp +13 -1
- package/lib/gen/languageLexer.js +870 -839
- package/lib/gen/languageLexer.tokens +116 -111
- package/lib/gen/languageParser.js +5894 -5614
- package/lib/json/from-csn.js +152 -67
- package/lib/json/to-csn.js +334 -135
- package/lib/language/antlrParser.js +4 -3
- package/lib/language/errorStrategy.js +1 -0
- package/lib/language/genericAntlrParser.js +24 -14
- package/lib/language/language.g4 +188 -128
- package/lib/main.d.ts +435 -0
- package/lib/main.js +31 -7
- package/lib/model/api.js +78 -0
- package/lib/model/csnRefs.js +463 -187
- package/lib/model/csnUtils.js +280 -136
- package/lib/model/enrichCsn.js +75 -4
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/modelCompare/compare.js +70 -25
- package/lib/optionProcessor.js +13 -10
- package/lib/render/.eslintrc.json +4 -1
- package/lib/render/DuplicateChecker.js +8 -5
- package/lib/render/toCdl.js +123 -40
- package/lib/render/toHdbcds.js +156 -65
- package/lib/render/toSql.js +87 -11
- package/lib/render/utils/common.js +55 -9
- package/lib/render/utils/sql.js +3 -3
- package/lib/sql-identifier.js +6 -1
- package/lib/transform/{sql → db}/.eslintrc.json +0 -0
- package/lib/transform/{sql → db}/assertUnique.js +7 -8
- package/lib/transform/{sql → db}/constraints.js +35 -20
- package/lib/transform/db/draft.js +353 -0
- package/lib/transform/db/expansion.js +582 -0
- package/lib/transform/db/flattening.js +325 -0
- package/lib/transform/{sql → db}/groupByOrderBy.js +8 -16
- package/lib/transform/{sql → db}/helpers.js +0 -0
- package/lib/transform/{sql → db}/transformExists.js +256 -60
- package/lib/transform/forHanaNew.js +216 -765
- package/lib/transform/forOdataNew.js +60 -56
- package/lib/transform/localized.js +48 -26
- package/lib/transform/odata/attachPath.js +19 -4
- package/lib/transform/odata/expandStructKeysInAssociations.js +2 -2
- package/lib/transform/odata/generateForeignKeyElements.js +13 -12
- package/lib/transform/odata/referenceFlattener.js +60 -36
- package/lib/transform/odata/sortByAssociationDependency.js +4 -4
- package/lib/transform/odata/structuralPath.js +76 -0
- package/lib/transform/odata/structureFlattener.js +21 -22
- package/lib/transform/odata/toFinalBaseType.js +5 -5
- package/lib/transform/odata/typesExposure.js +27 -17
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +141 -77
- package/lib/transform/translateAssocsToJoins.js +17 -14
- package/lib/transform/universalCsnEnricher.js +67 -0
- package/lib/utils/file.js +0 -11
- package/lib/utils/moduleResolve.js +6 -8
- package/lib/utils/timetrace.js +6 -1
- package/package.json +2 -1
- package/lib/base/deepCopy.js +0 -66
- package/lib/json/walker.js +0 -26
- package/lib/utils/string.js +0 -17
package/lib/render/toCdl.js
CHANGED
|
@@ -8,11 +8,13 @@ const {
|
|
|
8
8
|
isBuiltinType, generatedByCompilerVersion, getNormalizedQuery,
|
|
9
9
|
} = require('../model/csnUtils');
|
|
10
10
|
const keywords = require('../base/keywords');
|
|
11
|
-
const { renderFunc,
|
|
11
|
+
const { renderFunc, beautifyExprArray, findElement } = require('./utils/common');
|
|
12
12
|
const { checkCSNVersion } = require('../json/csnVersion');
|
|
13
13
|
const timetrace = require('../utils/timetrace');
|
|
14
14
|
const { csnRefs } = require('../model/csnRefs');
|
|
15
15
|
const { forEachDefinition } = require('../model/csnUtils');
|
|
16
|
+
const enrichUniversalCsn = require('../transform/universalCsnEnricher');
|
|
17
|
+
const { isBetaEnabled } = require('../base/model');
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Render the CSN model 'model' to CDS source text. One source is created per
|
|
@@ -33,6 +35,9 @@ function toCdsSourceCsn(csn, options) {
|
|
|
33
35
|
// Skip compactModel if already using CSN
|
|
34
36
|
// const csn = cloneCsn(model, options);
|
|
35
37
|
|
|
38
|
+
if (options.csnFlavor === 'universal' && isBetaEnabled(options, 'enableUniversalCsn'))
|
|
39
|
+
enrichUniversalCsn(csn, options);
|
|
40
|
+
|
|
36
41
|
checkCSNVersion(csn, options);
|
|
37
42
|
|
|
38
43
|
const result = Object.create(null);
|
|
@@ -50,16 +55,20 @@ function toCdsSourceCsn(csn, options) {
|
|
|
50
55
|
result[main] += `${sourceStr}\n`;
|
|
51
56
|
});
|
|
52
57
|
|
|
53
|
-
// Apply possible subelement annotations with an "annotate X with"
|
|
58
|
+
// Apply possible subelement/action return annotations with an "annotate X with"
|
|
59
|
+
// Some of them appear in csn.extensions, some not...
|
|
54
60
|
if (subelementAnnotates.length > 0) {
|
|
55
|
-
for (const [ artName, element, elementName ] of subelementAnnotates) {
|
|
56
|
-
|
|
57
|
-
sourceStr
|
|
61
|
+
for (const [ artName, element, elementName, suffix ] of subelementAnnotates) {
|
|
62
|
+
// Suffix is used with action return annotations
|
|
63
|
+
let sourceStr = `annotate ${artName} with ${suffix ? `${suffix} ` : ''}{\n`;
|
|
64
|
+
if (elementName) // action returns do not have element name - we need less {} there
|
|
65
|
+
sourceStr += ` ${elementName} {\n`;
|
|
58
66
|
const env = increaseIndent(increaseIndent(createEnv()));
|
|
59
67
|
const subelements = renderSubelementAnnotates(element, env);
|
|
60
68
|
if (subelements !== '') {
|
|
61
69
|
sourceStr += `${subelements}\n`;
|
|
62
|
-
|
|
70
|
+
if (elementName) // action returns do not have element name - we need less {} there
|
|
71
|
+
sourceStr += ' }\n';
|
|
63
72
|
sourceStr += '}\n';
|
|
64
73
|
result[main] += `${sourceStr}\n`;
|
|
65
74
|
}
|
|
@@ -145,6 +154,12 @@ function toCdsSourceCsn(csn, options) {
|
|
|
145
154
|
if (ext.elements)
|
|
146
155
|
result += renderElementExtensions(ext.elements, env);
|
|
147
156
|
|
|
157
|
+
// Returns annotations
|
|
158
|
+
if (ext.returns) {
|
|
159
|
+
const childEnv = increaseIndent(env);
|
|
160
|
+
result += ` with returns${renderElementExtensions(ext.returns.elements, childEnv)}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
148
163
|
// Action annotations
|
|
149
164
|
if (ext.actions) {
|
|
150
165
|
result += ' actions {\n';
|
|
@@ -162,10 +177,19 @@ function toCdsSourceCsn(csn, options) {
|
|
|
162
177
|
|
|
163
178
|
result += `${paramAnnotations.join(',\n')}\n${childEnv.indent})`;
|
|
164
179
|
}
|
|
180
|
+
// Annotations on action returns
|
|
181
|
+
if (action.returns && action.returns.elements) {
|
|
182
|
+
const grandChildEnv = increaseIndent(childEnv);
|
|
183
|
+
result += ` returns${renderElementExtensions(action.returns.elements, grandChildEnv)}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
165
187
|
result += ';\n';
|
|
166
188
|
}
|
|
167
189
|
result += `${env.indent}}`;
|
|
168
190
|
}
|
|
191
|
+
|
|
192
|
+
|
|
169
193
|
result += ';';
|
|
170
194
|
return result;
|
|
171
195
|
}).join('\n');
|
|
@@ -205,6 +229,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
205
229
|
function renderArtifact(artifactName, art, env) {
|
|
206
230
|
// FIXME: Correctly build the paths during runtime to give better locations
|
|
207
231
|
env.path = [ 'definitions', artifactName ];
|
|
232
|
+
env.artifactName = artifactName;
|
|
208
233
|
|
|
209
234
|
switch (art.kind) {
|
|
210
235
|
case 'entity':
|
|
@@ -509,6 +534,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
509
534
|
* @param {Boolean} [isSubElement]
|
|
510
535
|
*/
|
|
511
536
|
function renderElement(elementName, elm, env, isSubElement) {
|
|
537
|
+
env.elementName = elementName;
|
|
512
538
|
let result = renderDocComment(elm, env) + renderAnnotationAssignments(elm, env);
|
|
513
539
|
const quotedElementName = quoteOrUppercaseId(elementName);
|
|
514
540
|
result += `${env.indent + (elm.virtual ? 'virtual ' : '') +
|
|
@@ -516,10 +542,11 @@ function toCdsSourceCsn(csn, options) {
|
|
|
516
542
|
((elm.masked && !elm._ignoreMasked) ? 'masked ' : '') +
|
|
517
543
|
quotedElementName} : ${
|
|
518
544
|
renderTypeReference(elm, env, undefined)
|
|
519
|
-
}${renderNullability(elm)}`;
|
|
545
|
+
}${elm.on ? '' : renderNullability(elm)}`;
|
|
520
546
|
if (elm.default)
|
|
521
547
|
result += ` default ${renderExpr(elm.default, env)}`;
|
|
522
548
|
|
|
549
|
+
delete env.elementName;
|
|
523
550
|
return `${result};\n`;
|
|
524
551
|
}
|
|
525
552
|
|
|
@@ -727,27 +754,25 @@ function toCdsSourceCsn(csn, options) {
|
|
|
727
754
|
*
|
|
728
755
|
* @param {object} col
|
|
729
756
|
* @param {CdlRenderEnvironment} env
|
|
757
|
+
* @param {CSN.Element} element Element corresponding to the column. Generated by the compiler.
|
|
730
758
|
*/
|
|
731
|
-
function renderViewColumn(col, env) {
|
|
759
|
+
function renderViewColumn(col, env, element) {
|
|
732
760
|
// Annotations and column
|
|
733
|
-
let result = renderDocComment(col, env) + renderAnnotationAssignments(col, env);
|
|
761
|
+
let result = renderDocComment(col.doc ? col : element, env) + renderAnnotationAssignments(col, env);
|
|
734
762
|
result += env.indent;
|
|
763
|
+
|
|
735
764
|
// only if column is virtual, keyword virtual was present in the source text
|
|
736
765
|
if (col.virtual)
|
|
737
766
|
result += 'virtual ';
|
|
738
767
|
|
|
739
|
-
const key =
|
|
740
|
-
|
|
768
|
+
const key = col.key ? 'key ' : '';
|
|
769
|
+
// Use special rendering for .expand/.inline - renderExpr cannot easily handle some cases
|
|
770
|
+
result += key + ((col.expand || col.inline) ? renderInlineExpand(col, env) : renderExpr(col, env, true));
|
|
741
771
|
|
|
742
|
-
|
|
772
|
+
// Alias is already handled by renderInlineExpand
|
|
773
|
+
if (!col.inline && !col.expand && col.as)
|
|
743
774
|
result += ` as ${quoteOrUppercaseId(col.as)}`;
|
|
744
775
|
|
|
745
|
-
if (col.inline)
|
|
746
|
-
renderInlineExpand('inline');
|
|
747
|
-
|
|
748
|
-
if (col.expand)
|
|
749
|
-
renderInlineExpand('expand');
|
|
750
|
-
|
|
751
776
|
// Explicit type provided for the view element?
|
|
752
777
|
if (col.cast) {
|
|
753
778
|
// Special case: Explicit association type is actually a redirect
|
|
@@ -762,24 +787,69 @@ function toCdsSourceCsn(csn, options) {
|
|
|
762
787
|
}
|
|
763
788
|
}
|
|
764
789
|
return result;
|
|
790
|
+
}
|
|
765
791
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
792
|
+
/**
|
|
793
|
+
* For the current column, render a (nested) inline/expand. If the current column
|
|
794
|
+
* does not have an .expand/.inline, '' is returned
|
|
795
|
+
*
|
|
796
|
+
* @param {object} col Thing with .expand or .inline
|
|
797
|
+
* @param {CdlRenderEnvironment} parentEnv
|
|
798
|
+
* @returns {string}
|
|
799
|
+
*/
|
|
800
|
+
function renderInlineExpand(col, parentEnv) {
|
|
801
|
+
if (!col.inline && !col.expand)
|
|
802
|
+
return '';
|
|
803
|
+
|
|
804
|
+
return renderIX(col, parentEnv);
|
|
805
|
+
|
|
806
|
+
function renderIX(obj, env) {
|
|
807
|
+
// No expression to render for { * } as alias
|
|
808
|
+
let result = (obj.as && obj.expand && !obj.ref) ? '' : renderExpr(obj, env);
|
|
809
|
+
|
|
810
|
+
// s as alias { * }
|
|
811
|
+
if (obj.as && (obj.ref || obj.xpr || obj.val !== undefined || obj.func !== undefined))
|
|
812
|
+
result += ` as ${obj.as}`;
|
|
813
|
+
|
|
814
|
+
// We found a leaf - no further drilling
|
|
815
|
+
if (!obj.inline && !obj.expand) {
|
|
816
|
+
if (obj.cast && obj.cast.type) {
|
|
817
|
+
result += ` : ${renderTypeReference(obj.cast, createEnv())}`;
|
|
818
|
+
}
|
|
819
|
+
else if (obj.cast && obj.cast.target) { // test tbd
|
|
820
|
+
result += ` : redirected to ${renderAbsoluteNameWithQuotes(obj.cast.target)}`;
|
|
821
|
+
if (obj.cast.on)
|
|
822
|
+
result += ` on ${renderExpr(obj.cast.on, env, true, true)}`;
|
|
823
|
+
else if (obj.cast.keys)
|
|
824
|
+
result += ` { ${Object.keys(obj.cast.keys).map(name => renderForeignKey(obj.cast.keys[name], env)).join(', ')} }`;
|
|
825
|
+
}
|
|
826
|
+
return result;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (obj.inline)
|
|
773
830
|
result += '.{\n';
|
|
774
831
|
else
|
|
775
|
-
result += ' {\n';
|
|
832
|
+
result += result !== '' ? ' {\n' : '{\n';
|
|
776
833
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
834
|
+
// Drill down and render children of the expand/inline
|
|
835
|
+
const childEnv = increaseIndent(env);
|
|
836
|
+
const expandInline = obj.expand || obj.inline;
|
|
837
|
+
expandInline.forEach((elm, i) => {
|
|
838
|
+
result += `${childEnv.indent}${renderIX(elm, childEnv)}`;
|
|
839
|
+
if (i < expandInline.length - 1)
|
|
780
840
|
result += ',\n';
|
|
781
841
|
});
|
|
782
842
|
result += `\n${env.indent}}`;
|
|
843
|
+
|
|
844
|
+
// Don't forget about the .excluding
|
|
845
|
+
if (obj.excluding)
|
|
846
|
+
result += ` excluding { ${obj.excluding.join(',')} }`;
|
|
847
|
+
|
|
848
|
+
// { * } as expand
|
|
849
|
+
if (!obj.ref && obj.as)
|
|
850
|
+
result += ` as ${obj.as}`;
|
|
851
|
+
|
|
852
|
+
return result;
|
|
783
853
|
}
|
|
784
854
|
}
|
|
785
855
|
|
|
@@ -791,8 +861,11 @@ function toCdsSourceCsn(csn, options) {
|
|
|
791
861
|
* @returns {String}
|
|
792
862
|
*/
|
|
793
863
|
function renderDocComment(obj, env) {
|
|
794
|
-
if (!
|
|
864
|
+
if (!obj || obj && obj.doc === undefined)
|
|
795
865
|
return '';
|
|
866
|
+
else if (obj && obj.doc === null) // empty doc comment needs to be rendered
|
|
867
|
+
return `\n${env.indent}/** */\n`;
|
|
868
|
+
|
|
796
869
|
return `\n${env.indent}/**\n${obj.doc.split('\n').map(line => `${env.indent} * ${line}`).join('\n')}\n${env.indent} */\n`;
|
|
797
870
|
}
|
|
798
871
|
|
|
@@ -818,7 +891,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
818
891
|
result += ' as ';
|
|
819
892
|
}
|
|
820
893
|
env._artifact = art;
|
|
821
|
-
result += renderQuery(getNormalizedQuery(art).query, true, syntax, env, [ 'definitions', artifactName, 'query' ]);
|
|
894
|
+
result += renderQuery(getNormalizedQuery(art).query, true, syntax, env, [ 'definitions', artifactName, 'query' ], art.elements);
|
|
822
895
|
result += ';\n';
|
|
823
896
|
result += renderQueryElementAnnotations(artifactName, art, env);
|
|
824
897
|
result += renderQueryActionsAndFunctions(artifactName, art, env);
|
|
@@ -837,18 +910,17 @@ function toCdsSourceCsn(csn, options) {
|
|
|
837
910
|
* @param {CdlRenderEnvironment} env
|
|
838
911
|
* @param {CSN.Path} [path=[]]
|
|
839
912
|
*/
|
|
840
|
-
function renderQuery(query, isLeadingQuery, syntax, env, path = []) {
|
|
913
|
+
function renderQuery(query, isLeadingQuery, syntax, env, path = [], elements = query.elements || Object.create(null)) {
|
|
841
914
|
let result = renderDocComment(query, env);
|
|
842
|
-
env.skipKeys = !isLeadingQuery;
|
|
843
915
|
// Set operator, like UNION, INTERSECT, ...
|
|
844
916
|
if (query.SET) {
|
|
845
917
|
// First arg may be leading query
|
|
846
|
-
result += `(${renderQuery(query.SET.args[0], isLeadingQuery, 'view', env, path.concat([ 'SET', 'args', 0 ]))}`;
|
|
918
|
+
result += `(${renderQuery(query.SET.args[0], isLeadingQuery, 'view', env, path.concat([ 'SET', 'args', 0 ]), elements)}`;
|
|
847
919
|
// FIXME: Clarify if set operators can be n-ary (assuming binary here)
|
|
848
920
|
if (query.SET.op) {
|
|
849
921
|
// Loop over all other arguments, i.e. for A UNION B UNION C UNION D ...
|
|
850
922
|
for (let i = 1; i < query.SET.args.length; i++)
|
|
851
|
-
result += `\n${env.indent}${query.SET.op}${query.SET.all ? ' all' : ''} ${renderQuery(query.SET.args[i], false, 'view', env, path.concat([ 'SET', 'args', i ]))}`;
|
|
923
|
+
result += `\n${env.indent}${query.SET.op}${query.SET.all ? ' all' : ''} ${renderQuery(query.SET.args[i], false, 'view', env, path.concat([ 'SET', 'args', i ]), elements)}`;
|
|
852
924
|
}
|
|
853
925
|
result += ')';
|
|
854
926
|
// Set operation may also have an ORDER BY and LIMIT/OFFSET (in contrast to the ones belonging to
|
|
@@ -890,7 +962,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
890
962
|
result += select.distinct ? ' distinct' : '';
|
|
891
963
|
if (select.columns) {
|
|
892
964
|
result += ' {\n';
|
|
893
|
-
result += `${select.columns.map(col => renderViewColumn(col, childEnv))
|
|
965
|
+
result += `${select.columns.map(col => renderViewColumn(col, childEnv, findElement(elements, col)))
|
|
894
966
|
.filter(s => s !== '')
|
|
895
967
|
.join(',\n')}\n`;
|
|
896
968
|
result += `${env.indent}}`;
|
|
@@ -1011,8 +1083,11 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1011
1083
|
const childEnv = increaseIndent(env);
|
|
1012
1084
|
const parameters = Object.keys(act.params || []).map(name => renderParameter(name, act.params[name], childEnv)).join(',\n');
|
|
1013
1085
|
result += (parameters === '') ? '()' : `(\n${parameters}\n${env.indent})`;
|
|
1014
|
-
if (act.returns)
|
|
1086
|
+
if (act.returns) {
|
|
1087
|
+
if (act.returns.type && act.returns.elements) // action returns annotations
|
|
1088
|
+
subelementAnnotates.push([ actionName, act.returns, '', 'returns' ]);
|
|
1015
1089
|
result += ` returns ${renderTypeReference(act.returns, env)}${renderNullability(act.returns)}`;
|
|
1090
|
+
}
|
|
1016
1091
|
|
|
1017
1092
|
result += ';\n';
|
|
1018
1093
|
return result;
|
|
@@ -1080,7 +1155,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1080
1155
|
* @return {string}
|
|
1081
1156
|
*/
|
|
1082
1157
|
function renderTypeReference(elm, env, noEnum = false) {
|
|
1083
|
-
let result =
|
|
1158
|
+
let result = '';
|
|
1084
1159
|
|
|
1085
1160
|
// Array type: Render items instead
|
|
1086
1161
|
if (elm.items && !elm.type) {
|
|
@@ -1088,6 +1163,10 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1088
1163
|
let rc = `many ${renderTypeReference(elm.items, env)}`;
|
|
1089
1164
|
if (elm.items.notNull != null)
|
|
1090
1165
|
rc += elm.items.notNull ? ' not null' : ' null';
|
|
1166
|
+
// many sub element annotates
|
|
1167
|
+
if (elm.items.type && elm.items.elements && env.artifactName)
|
|
1168
|
+
subelementAnnotates.push([ env.artifactName, elm.items, env.elementName ]);
|
|
1169
|
+
|
|
1091
1170
|
return rc;
|
|
1092
1171
|
}
|
|
1093
1172
|
|
|
@@ -1205,10 +1284,11 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1205
1284
|
* @return {string}
|
|
1206
1285
|
*/
|
|
1207
1286
|
function renderEnum(enumPart, env) {
|
|
1208
|
-
let result =
|
|
1287
|
+
let result = ' enum {\n';
|
|
1209
1288
|
const childEnv = increaseIndent(env);
|
|
1210
1289
|
for (const name in enumPart) {
|
|
1211
1290
|
const enumConst = enumPart[name];
|
|
1291
|
+
result += renderDocComment(enumConst, childEnv);
|
|
1212
1292
|
result += renderAnnotationAssignments(enumConst, childEnv);
|
|
1213
1293
|
result += childEnv.indent + quoteIdIfRequired(name);
|
|
1214
1294
|
if (enumConst.val !== undefined)
|
|
@@ -1270,7 +1350,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1270
1350
|
function renderExpr(x, env, inline = true, inExpr = false) {
|
|
1271
1351
|
// Compound expression
|
|
1272
1352
|
if (Array.isArray(x))
|
|
1273
|
-
return
|
|
1353
|
+
return beautifyExprArray(x.map(item => renderExpr(item, env, inline, inExpr)));
|
|
1274
1354
|
|
|
1275
1355
|
if (typeof x === 'object' && x !== null) {
|
|
1276
1356
|
if (inExpr && x.cast && x.cast.type)
|
|
@@ -1406,6 +1486,7 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1406
1486
|
// Filter, possibly with cardinality
|
|
1407
1487
|
result += `[${s.cardinality ? (`${s.cardinality.max}: `) : ''}${renderExpr(s.where, env, inline, true)}]`;
|
|
1408
1488
|
}
|
|
1489
|
+
|
|
1409
1490
|
return result;
|
|
1410
1491
|
}
|
|
1411
1492
|
|
|
@@ -1814,6 +1895,8 @@ function toCdsSourceCsn(csn, options) {
|
|
|
1814
1895
|
*
|
|
1815
1896
|
* @property {string} indent Current indentation as a string, e.g. ' ' for two spaces.
|
|
1816
1897
|
* @property {CSN.Path} [path] CSN path to the current artifact
|
|
1898
|
+
* @property {string} artifactName Name of the artifact - set in renderArtifact
|
|
1899
|
+
* @property {string} elementName Name of the element being rendered - set in renderElement
|
|
1817
1900
|
* @property {{[name: string]: {
|
|
1818
1901
|
quotedName: string,
|
|
1819
1902
|
quotedAlias: string
|