@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/model/enrichCsn.js
CHANGED
|
@@ -32,7 +32,7 @@ const { locationString } = require('../base/location');
|
|
|
32
32
|
|
|
33
33
|
function enrichCsn( csn, options = {} ) {
|
|
34
34
|
const transformers = {
|
|
35
|
-
$env: reveal,
|
|
35
|
+
// $env: reveal,
|
|
36
36
|
elements: dictionary,
|
|
37
37
|
definitions: dictionary,
|
|
38
38
|
actions: dictionary,
|
|
@@ -44,15 +44,21 @@ function enrichCsn( csn, options = {} ) {
|
|
|
44
44
|
targetAspect: simpleRef,
|
|
45
45
|
target: simpleRef,
|
|
46
46
|
includes: simpleRef,
|
|
47
|
-
|
|
47
|
+
$origin,
|
|
48
|
+
// TODO: excluding
|
|
49
|
+
'@': () => { /* ignore annotations */ },
|
|
48
50
|
}
|
|
49
51
|
setLocations( csn, false, null );
|
|
50
|
-
const { inspectRef, artifactRef } =
|
|
52
|
+
const { inspectRef, artifactRef, getOrigin, __getCache_forEnrichCsnDebugging } =
|
|
53
|
+
csnRefs( csn );
|
|
54
|
+
let $$cacheObjectNumber = 0; // for debugging
|
|
51
55
|
const csnPath = [];
|
|
52
56
|
if (csn.definitions)
|
|
53
57
|
dictionary( csn, 'definitions', csn.definitions );
|
|
54
58
|
if (csn.$location)
|
|
55
59
|
reveal( csn, '$location', locationString( csn.$location ) );
|
|
60
|
+
if (csn.$sources)
|
|
61
|
+
reveal( csn, '$sources', csn.$sources );
|
|
56
62
|
return csn;
|
|
57
63
|
|
|
58
64
|
function standard( parent, prop, obj ) {
|
|
@@ -68,6 +74,9 @@ function enrichCsn( csn, options = {} ) {
|
|
|
68
74
|
const trans = transformers[name] || transformers[name.charAt(0)] || standard;
|
|
69
75
|
trans( obj, name, obj[name] );
|
|
70
76
|
}
|
|
77
|
+
if (obj.$parens)
|
|
78
|
+
reveal( obj, '$parens', obj.$parens );
|
|
79
|
+
_cache_debug( obj );
|
|
71
80
|
}
|
|
72
81
|
csnPath.pop();
|
|
73
82
|
}
|
|
@@ -112,8 +121,23 @@ function enrichCsn( csn, options = {} ) {
|
|
|
112
121
|
// parent['_' + prop] = e.toString(); }
|
|
113
122
|
}
|
|
114
123
|
|
|
124
|
+
function $origin( parent, prop, ref ) {
|
|
125
|
+
if (options.testMode) {
|
|
126
|
+
if (Array.isArray( ref )) // $origin: […], not $origin: {…}
|
|
127
|
+
parent._origin = refLocation( getOrigin( parent ) );
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
try {
|
|
131
|
+
if (Array.isArray( ref )) // $origin: […], not $origin: {…}
|
|
132
|
+
parent._origin = refLocation( getOrigin( parent ) );
|
|
133
|
+
} catch (e) {
|
|
134
|
+
parent._origin = e.toString();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
115
139
|
function pathRef( parent, prop, path ) {
|
|
116
|
-
const { links, art, scope } = (() => {
|
|
140
|
+
const { links, art, scope, $env } = (() => {
|
|
117
141
|
if (options.testMode)
|
|
118
142
|
return inspectRef( csnPath );
|
|
119
143
|
else {
|
|
@@ -130,6 +154,8 @@ function enrichCsn( csn, options = {} ) {
|
|
|
130
154
|
if (links && links[links.length-1].art !== art)
|
|
131
155
|
parent._art = refLocation( art );
|
|
132
156
|
parent._scope = scope;
|
|
157
|
+
if ($env)
|
|
158
|
+
parent._env = $env;
|
|
133
159
|
|
|
134
160
|
csnPath.push( prop );
|
|
135
161
|
path.forEach( function step( s, i ) {
|
|
@@ -144,6 +170,51 @@ function enrichCsn( csn, options = {} ) {
|
|
|
144
170
|
} );
|
|
145
171
|
csnPath.pop();
|
|
146
172
|
}
|
|
173
|
+
|
|
174
|
+
function _cache_debug( obj ) {
|
|
175
|
+
if (options.enrichCsn !== 'DEBUG')
|
|
176
|
+
return;
|
|
177
|
+
const cache = __getCache_forEnrichCsnDebugging( obj );
|
|
178
|
+
if (!cache)
|
|
179
|
+
return;
|
|
180
|
+
if (cache.$$objectNumber > 0) {
|
|
181
|
+
obj.$$cacheObjectNumber = cache.$$objectNumber;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
cache.$$objectNumber = (cache.$$objectNumber)
|
|
185
|
+
? -cache.$$objectNumber
|
|
186
|
+
: ++$$cacheObjectNumber;
|
|
187
|
+
obj.$$cacheObject = {};
|
|
188
|
+
for (const name of Object.keys( cache )) {
|
|
189
|
+
const val = cache[name];
|
|
190
|
+
if (val === null || typeof val !== 'object') {
|
|
191
|
+
obj.$$cacheObject[name] = val;
|
|
192
|
+
}
|
|
193
|
+
else if (name[0] === '_') {
|
|
194
|
+
// _‹name›: link to CSN node, usually with kind & location
|
|
195
|
+
obj.$$cacheObject[name]
|
|
196
|
+
= (val.$location) ? locationString( val.$location ) : 'CSN node';
|
|
197
|
+
}
|
|
198
|
+
else if (name[0] !== '$' || !Object.getPrototypeOf( val )) {
|
|
199
|
+
// ‹name›: dictionary of CSN nodes,
|
|
200
|
+
// ‹$name›: dictionary of cache values if no prototype,
|
|
201
|
+
obj.$$cacheObject[name] = Object.keys( val ); // TODO: or dict?
|
|
202
|
+
}
|
|
203
|
+
else if (Array.isArray( val )) {
|
|
204
|
+
obj.$$cacheObject[name] = val.map( item => {
|
|
205
|
+
if (!item.$$objectNumber)
|
|
206
|
+
item.$$objectNumber = -(++$$cacheObjectNumber);
|
|
207
|
+
return item.$$objectNumber;
|
|
208
|
+
} );
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
if (!val.$$objectNumber)
|
|
212
|
+
val.$$objectNumber = -(++$$cacheObjectNumber);
|
|
213
|
+
obj.$$cacheObject[name] = val.$$objectNumber || -(++$$cacheObjectNumber);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
147
218
|
}
|
|
148
219
|
|
|
149
220
|
function reveal( node, prop, value ) {
|
|
@@ -76,6 +76,7 @@ function revealInternalProperties( model, name ) {
|
|
|
76
76
|
_annotate: reveal,
|
|
77
77
|
_deps: dependencyInfo,
|
|
78
78
|
_status: primOrString, // is a string anyway
|
|
79
|
+
$messageFunctions: () => '‹some functions›',
|
|
79
80
|
}
|
|
80
81
|
unique_id = 1;
|
|
81
82
|
return revealXsnPath(name, model);
|
|
@@ -159,7 +160,7 @@ function revealInternalProperties( model, name ) {
|
|
|
159
160
|
|
|
160
161
|
function columns( nodes, query ) {
|
|
161
162
|
// If we will have specified elements, we need another test to see columns in --parse-cdl
|
|
162
|
-
return nodes && nodes.map( c => (c._parent && c._parent.elements
|
|
163
|
+
return nodes && nodes.map( c => (c._parent && c._parent.elements)
|
|
163
164
|
? artifactIdentifier( c, query )
|
|
164
165
|
: reveal( c, nodes ) );
|
|
165
166
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { makeMessageFunction } = require('../base/messages');
|
|
3
4
|
const {
|
|
4
5
|
forEachDefinition,
|
|
5
6
|
forEachMember,
|
|
6
|
-
|
|
7
|
+
hasAnnotationValue
|
|
7
8
|
} = require('../model/csnUtils');
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -11,55 +12,92 @@ const {
|
|
|
11
12
|
*
|
|
12
13
|
* @param beforeModel the before-model
|
|
13
14
|
* @param afterModel the after-model
|
|
15
|
+
* @param {hdiOptions|false} options
|
|
14
16
|
* @returns {object} the sets of deletions, extensions, and migrations of entities necessary to transform the before-model
|
|
15
17
|
* to the after-model, together with all the definitions of the after-model
|
|
16
18
|
*/
|
|
17
|
-
function compareModels(beforeModel, afterModel) {
|
|
19
|
+
function compareModels(beforeModel, afterModel, options) {
|
|
20
|
+
if(!(options && options.testMode)) // no $version with testMode
|
|
21
|
+
validateCsnVersions(beforeModel, afterModel, options);
|
|
22
|
+
|
|
18
23
|
const deletedEntities = Object.create(null);
|
|
19
24
|
const elementAdditions = [];
|
|
20
|
-
const
|
|
25
|
+
const migrations = []; // element changes/removals or changes of entity properties
|
|
21
26
|
|
|
22
27
|
// There is currently no use in knowing the added entities only. If this changes, hand in `addedEntities` to `getArtifactComparator` below.
|
|
23
|
-
forEachDefinition(afterModel, getArtifactComparator(beforeModel, null, null, elementAdditions,
|
|
24
|
-
forEachDefinition(beforeModel, getArtifactComparator(afterModel, null, deletedEntities, null, null));
|
|
28
|
+
forEachDefinition(afterModel, getArtifactComparator(beforeModel, null, null, elementAdditions, migrations));
|
|
29
|
+
forEachDefinition(beforeModel, getArtifactComparator(afterModel, null, deletedEntities, null, null));
|
|
25
30
|
|
|
26
31
|
const returnObj = Object.create(null);
|
|
27
32
|
returnObj.definitions = afterModel.definitions;
|
|
28
33
|
returnObj.deletions = deletedEntities;
|
|
29
34
|
returnObj.extensions = elementAdditions;
|
|
30
|
-
returnObj.migrations =
|
|
35
|
+
returnObj.migrations = migrations;
|
|
31
36
|
return returnObj;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
function
|
|
35
|
-
|
|
39
|
+
function validateCsnVersions(beforeModel, afterModel, options) {
|
|
40
|
+
const beforeVersion = beforeModel.$version;
|
|
41
|
+
const afterVersion = afterModel.$version;
|
|
42
|
+
let beforeVersionParts = beforeVersion && beforeVersion.split('.');
|
|
43
|
+
let afterVersionParts = afterVersion && afterVersion.split('.');
|
|
44
|
+
|
|
45
|
+
if (!beforeVersionParts || beforeVersionParts.length < 2) {
|
|
46
|
+
const { error, throwWithError } = makeMessageFunction(beforeModel, options, 'modelCompare');
|
|
47
|
+
error(null, null, `Invalid CSN version: ${beforeVersion}`);
|
|
48
|
+
throwWithError();
|
|
49
|
+
}
|
|
50
|
+
if (!afterVersionParts || afterVersionParts.length < 2) {
|
|
51
|
+
const { error, throwWithError } = makeMessageFunction(afterModel, options, 'modelCompare');
|
|
52
|
+
error(null, null, `Invalid CSN version: ${afterVersion}`);
|
|
53
|
+
throwWithError();
|
|
54
|
+
}
|
|
55
|
+
if (beforeVersionParts[0] > afterVersionParts[0] && !(options && options.allowCsnDowngrade)) {
|
|
56
|
+
const { error, throwWithError } = makeMessageFunction(afterModel, options, 'modelCompare');
|
|
57
|
+
error(null, null, `Incompatible CSN versions: ${afterVersion} is a major downgrade from ${beforeVersion}. Is @sap/cds-compiler version ${require('../../package.json').version} outdated?`);
|
|
58
|
+
throwWithError();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getArtifactComparator(otherModel, addedEntities, deletedEntities, elementAdditions, migrations) {
|
|
63
|
+
return function compareArtifacts(artifact, name) {
|
|
36
64
|
function addElements() {
|
|
37
65
|
const elements = {};
|
|
38
66
|
forEachMember(artifact, getElementComparator(otherArtifact, elements));
|
|
39
67
|
if (Object.keys(elements).length > 0) {
|
|
40
|
-
elementAdditions.push(
|
|
41
|
-
extend: name,
|
|
42
|
-
elements: elements
|
|
43
|
-
});
|
|
68
|
+
elementAdditions.push(addedElements(name, elements));
|
|
44
69
|
}
|
|
45
70
|
}
|
|
46
|
-
function
|
|
71
|
+
function changePropsOrRemoveOrChangeElements() {
|
|
72
|
+
const relevantProperties = ['doc'];
|
|
73
|
+
const changedProperties = {};
|
|
74
|
+
|
|
47
75
|
const removedElements = {};
|
|
48
76
|
const changedElements = {};
|
|
49
|
-
|
|
77
|
+
|
|
78
|
+
const migration = { migrate: name };
|
|
79
|
+
|
|
80
|
+
relevantProperties.forEach(prop => {
|
|
81
|
+
if (artifact[prop] !== otherArtifact[prop]) {
|
|
82
|
+
changedProperties[prop] = changedElement(artifact[prop], otherArtifact[prop] || null);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
if (Object.keys(changedProperties).length > 0) {
|
|
86
|
+
migration.properties = changedProperties;
|
|
87
|
+
}
|
|
50
88
|
|
|
51
89
|
forEachMember(otherArtifact, getElementComparator(artifact, removedElements));
|
|
52
90
|
if (Object.keys(removedElements).length > 0) {
|
|
53
|
-
|
|
91
|
+
migration.remove = removedElements;
|
|
54
92
|
}
|
|
55
93
|
|
|
56
94
|
forEachMember(artifact, getElementComparator(otherArtifact, null, changedElements));
|
|
57
95
|
if (Object.keys(changedElements).length > 0) {
|
|
58
|
-
|
|
96
|
+
migration.change = changedElements;
|
|
59
97
|
}
|
|
60
98
|
|
|
61
|
-
if (
|
|
62
|
-
|
|
99
|
+
if (migration.properties || migration.remove || migration.change) {
|
|
100
|
+
migrations.push(migration);
|
|
63
101
|
}
|
|
64
102
|
}
|
|
65
103
|
|
|
@@ -96,8 +134,8 @@ function getArtifactComparator(otherModel, addedEntities, deletedEntities, eleme
|
|
|
96
134
|
if (elementAdditions) {
|
|
97
135
|
addElements();
|
|
98
136
|
}
|
|
99
|
-
if (
|
|
100
|
-
|
|
137
|
+
if (migrations) {
|
|
138
|
+
changePropsOrRemoveOrChangeElements();
|
|
101
139
|
}
|
|
102
140
|
};
|
|
103
141
|
}
|
|
@@ -106,13 +144,13 @@ function isPersistedAsTable(artifact) {
|
|
|
106
144
|
return artifact.kind === 'entity'
|
|
107
145
|
&& !artifact._ignore
|
|
108
146
|
&& !artifact.abstract
|
|
109
|
-
&& (!artifact.query && !artifact.projection ||
|
|
110
|
-
&& !
|
|
111
|
-
&& !
|
|
147
|
+
&& (!artifact.query && !artifact.projection || hasAnnotationValue(artifact, '@cds.persistence.table'))
|
|
148
|
+
&& !hasAnnotationValue(artifact, '@cds.persistence.skip')
|
|
149
|
+
&& !hasAnnotationValue(artifact, '@cds.persistence.exists');
|
|
112
150
|
}
|
|
113
151
|
|
|
114
|
-
function getElementComparator(otherArtifact, addedElements = null, changedElements = null) {
|
|
115
|
-
return function compareElements(element, name) {
|
|
152
|
+
function getElementComparator(otherArtifact, addedElements = null, changedElements = null) {
|
|
153
|
+
return function compareElements(element, name) {
|
|
116
154
|
if (element._ignore) {
|
|
117
155
|
return;
|
|
118
156
|
}
|
|
@@ -181,6 +219,13 @@ function typeParametersChanged(element, otherElement) {
|
|
|
181
219
|
return !deepEqual(element, otherElement, (key, depth) => !(depth === 0 && key === 'type'));
|
|
182
220
|
}
|
|
183
221
|
|
|
222
|
+
function addedElements(entity, elements) {
|
|
223
|
+
return {
|
|
224
|
+
extend: entity,
|
|
225
|
+
elements
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
184
229
|
function changedElement(element, otherElement) {
|
|
185
230
|
return {
|
|
186
231
|
old: otherElement,
|
package/lib/optionProcessor.js
CHANGED
|
@@ -33,12 +33,14 @@ optionProcessor
|
|
|
33
33
|
.option(' --hana-flavor')
|
|
34
34
|
.option(' --direct-backend')
|
|
35
35
|
.option(' --parse-only')
|
|
36
|
-
.option(' --fallback-parser <type>', ['cdl', 'csn'])
|
|
36
|
+
.option(' --fallback-parser <type>', ['cdl', 'csn', 'csn!'])
|
|
37
37
|
.option(' --test-mode')
|
|
38
38
|
.option(' --test-sort-csn')
|
|
39
39
|
.option(' --doc-comment')
|
|
40
|
+
.option(' --add-texts-language-assoc')
|
|
40
41
|
.option(' --localized-without-coalesce')
|
|
41
42
|
.option(' --defaultStringLength <length>')
|
|
43
|
+
.option(' --no-recompile')
|
|
42
44
|
.positionalArgument('<files...>')
|
|
43
45
|
.help(`
|
|
44
46
|
Usage: cdsc <command> [options] <files...>
|
|
@@ -88,12 +90,12 @@ optionProcessor
|
|
|
88
90
|
--beta-mode Enable all unsupported, incomplete (beta) features
|
|
89
91
|
--beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
|
|
90
92
|
Valid values are:
|
|
91
|
-
keylessManagedAssoc
|
|
92
93
|
foreignKeyConstraints
|
|
93
94
|
addTextsLanguageAssoc
|
|
94
95
|
hanaAssocRealCardinality
|
|
95
96
|
mapAssocToJoinCardinality
|
|
96
97
|
ignoreAssocPublishingInUnion
|
|
98
|
+
windowFunctions
|
|
97
99
|
--constraints-not-enforced If this option is supplied, referential constraints are NOT ENFORCED
|
|
98
100
|
This option is also applied to result of "cdsc manageConstraints"
|
|
99
101
|
--constraints-not-validated If this option is supplied, referential constraints are NOT VALIDATED
|
|
@@ -111,8 +113,9 @@ optionProcessor
|
|
|
111
113
|
--parse-only Stop compilation after parsing and write result to <stdout>
|
|
112
114
|
--fallback-parser <type> If the language cannot be deduced by the file's extensions, use this
|
|
113
115
|
parser as a fallback. Valid values are:
|
|
114
|
-
cdl
|
|
115
|
-
csn
|
|
116
|
+
cdl : Use CDL parser
|
|
117
|
+
csn : Use CSN parser
|
|
118
|
+
csn! : Use CSN parser even with extension cds, cdl, hdbcds and hdbdd
|
|
116
119
|
--direct-backend Do not compile the given CSN but directly pass it to the backend.
|
|
117
120
|
Can only be used with certain new CSN based backends. Combination with
|
|
118
121
|
other flags is limited, e.g. --test-mode will not run a consistency check.
|
|
@@ -123,8 +126,11 @@ optionProcessor
|
|
|
123
126
|
OData CSN, CDL order and more. When --test-mode is enabled, this
|
|
124
127
|
option is implicitly enabled as well.
|
|
125
128
|
--doc-comment Preserve /** */ comments at annotation positions as doc property in CSN
|
|
129
|
+
--add-texts-language-assoc In generated texts entities, add association "language"
|
|
130
|
+
to "sap.common.Languages" if it exists
|
|
126
131
|
--localized-without-coalesce Omit coalesce in localized convenience views
|
|
127
|
-
|
|
132
|
+
--no-recompile Don't recompile in case of internal errors
|
|
133
|
+
|
|
128
134
|
Commands
|
|
129
135
|
H, toHana [options] <files...> Generate HANA CDS source files
|
|
130
136
|
O, toOdata [options] <files...> Generate ODATA metadata and annotations
|
|
@@ -179,8 +185,6 @@ optionProcessor.command('O, toOdata')
|
|
|
179
185
|
.option('-v, --version <version>', ['v2', 'v4', 'v4x'])
|
|
180
186
|
.option('-x, --xml')
|
|
181
187
|
.option('-j, --json')
|
|
182
|
-
.option(' --separate')
|
|
183
|
-
.option(' --combined')
|
|
184
188
|
.option(' --odata-containment')
|
|
185
189
|
.option(' --odata-proxies')
|
|
186
190
|
.option(' --odata-x-service-refs')
|
|
@@ -202,8 +206,6 @@ optionProcessor.command('O, toOdata')
|
|
|
202
206
|
v4x: { version: 'v4', odataContainment:true, format:'structured' }
|
|
203
207
|
-x, --xml (default) Generate XML output (separate or combined)
|
|
204
208
|
-j, --json Generate JSON output as "<svc>.json" (not available for v2)
|
|
205
|
-
--separate Generate "<svc>_metadata.xml" and "<svc>_annotations.xml"
|
|
206
|
-
--combined (default) Generate "<svc>.xml"
|
|
207
209
|
-c, --csn Generate "odata_csn.json" with ODATA-preprocessed model
|
|
208
210
|
-f, --odata-format <format> Set the format of the identifier rendering
|
|
209
211
|
flat : (default) Flat type and property names
|
|
@@ -338,7 +340,7 @@ optionProcessor.command('manageConstraints')
|
|
|
338
340
|
|
|
339
341
|
optionProcessor.command('toCsn')
|
|
340
342
|
.option('-h, --help')
|
|
341
|
-
.option('-f, --flavor <flavor>', ['client', 'gensrc'])
|
|
343
|
+
.option('-f, --flavor <flavor>', ['client', 'gensrc', 'universal'])
|
|
342
344
|
.option(' --with-localized')
|
|
343
345
|
.help(`
|
|
344
346
|
Usage: cdsc toCsn [options] <files...>
|
|
@@ -353,6 +355,7 @@ optionProcessor.command('toCsn')
|
|
|
353
355
|
combination with additional "extend" or "annotate"
|
|
354
356
|
statements, but not suitable for consumption by clients or
|
|
355
357
|
backends
|
|
358
|
+
universal: in development (BETA)
|
|
356
359
|
|
|
357
360
|
Internal options (for testing only, may be changed/removed at any time)
|
|
358
361
|
--with-localized Add localized convenience views to the CSN output.
|
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
"prefer-template": "error",
|
|
8
8
|
"no-trailing-spaces": "error",
|
|
9
9
|
"sonarjs/cognitive-complexity": "off",
|
|
10
|
+
"sonarjs/no-duplicate-string": ["off"],
|
|
11
|
+
"sonarjs/no-nested-template-literals": "off",
|
|
10
12
|
"template-curly-spacing":["error", "never"],
|
|
11
|
-
|
|
13
|
+
// Who cares - just very whiny and in the way
|
|
14
|
+
"complexity": "off",
|
|
12
15
|
"max-len": "off",
|
|
13
16
|
// We should enable this
|
|
14
17
|
"no-shadow": "off"
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
const walker = require('../json/walker');
|
|
12
|
-
|
|
13
11
|
/**
|
|
14
12
|
* database name - uppercase if not quoted
|
|
15
13
|
*
|
|
@@ -87,13 +85,13 @@ class DuplicateChecker {
|
|
|
87
85
|
* @param {CSN.Options} options Options used for the compilation
|
|
88
86
|
*/
|
|
89
87
|
check(error, options = null) {
|
|
90
|
-
|
|
88
|
+
forEach(this.seenArtifacts, (artifactName, artifacts) => {
|
|
91
89
|
if (artifacts.length > 1) {
|
|
92
90
|
artifacts.slice(1).forEach((artifact) => { // report all colliding artifacts, except the first one
|
|
93
91
|
const collidesWith = this.seenArtifacts[artifactName].find( art => art !== artifact );
|
|
94
92
|
let namingMode;
|
|
95
93
|
if (options)
|
|
96
|
-
namingMode = options.
|
|
94
|
+
namingMode = options.sqlMapping;
|
|
97
95
|
else
|
|
98
96
|
namingMode = 'plain';
|
|
99
97
|
|
|
@@ -106,7 +104,7 @@ class DuplicateChecker {
|
|
|
106
104
|
});
|
|
107
105
|
}
|
|
108
106
|
artifacts.forEach((artifact) => {
|
|
109
|
-
|
|
107
|
+
forEach(artifact.elements, (elementName, elements) => {
|
|
110
108
|
if (elements.length > 1) {
|
|
111
109
|
elements.forEach((element) => { // report all colliding elements
|
|
112
110
|
error(null,
|
|
@@ -123,4 +121,9 @@ class DuplicateChecker {
|
|
|
123
121
|
}
|
|
124
122
|
}
|
|
125
123
|
|
|
124
|
+
function forEach(obj, callback) {
|
|
125
|
+
for (const key in obj)
|
|
126
|
+
callback(key, obj[key]);
|
|
127
|
+
}
|
|
128
|
+
|
|
126
129
|
module.exports = DuplicateChecker;
|