@sap/cds-compiler 4.8.0 → 4.9.0
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 +29 -4
- package/bin/cds_remove_invalid_whitespace.js +135 -0
- package/bin/cds_update_annotations.js +180 -0
- package/bin/cds_update_identifiers.js +3 -4
- package/bin/cdsc.js +14 -1
- package/doc/CHANGELOG_BETA.md +19 -0
- package/lib/api/main.js +59 -24
- package/lib/api/options.js +12 -1
- package/lib/api/validate.js +1 -5
- package/lib/base/builtins.js +27 -0
- package/lib/base/message-registry.js +32 -19
- package/lib/base/messages.js +50 -19
- package/lib/base/model.js +4 -5
- package/lib/checks/actionsFunctions.js +2 -2
- package/lib/checks/annotationsOData.js +3 -0
- package/lib/checks/defaultValues.js +5 -2
- package/lib/checks/queryNoDbArtifacts.js +3 -2
- package/lib/checks/validator.js +2 -34
- package/lib/compiler/assert-consistency.js +8 -2
- package/lib/compiler/checks.js +44 -18
- package/lib/compiler/define.js +34 -22
- package/lib/compiler/extend.js +33 -10
- package/lib/compiler/index.js +0 -1
- package/lib/compiler/lsp-api.js +5 -0
- package/lib/compiler/propagator.js +21 -18
- package/lib/compiler/resolve.js +44 -28
- package/lib/compiler/shared.js +60 -20
- package/lib/compiler/tweak-assocs.js +13 -88
- package/lib/compiler/xpr-rewrite.js +689 -0
- package/lib/edm/annotations/genericTranslation.js +80 -60
- package/lib/edm/edm.js +4 -4
- package/lib/edm/edmInboundChecks.js +33 -0
- package/lib/edm/edmPreprocessor.js +9 -6
- package/lib/gen/Dictionary.json +129 -14
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1523 -1518
- package/lib/json/from-csn.js +13 -4
- package/lib/json/to-csn.js +10 -11
- package/lib/language/genericAntlrParser.js +14 -6
- package/lib/main.d.ts +67 -14
- package/lib/main.js +1 -0
- package/lib/model/cloneCsn.js +6 -3
- package/lib/model/csnRefs.js +12 -7
- package/lib/model/csnUtils.js +13 -7
- package/lib/model/enrichCsn.js +3 -1
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/model/sortViews.js +14 -6
- package/lib/modelCompare/compare.js +33 -34
- package/lib/optionProcessor.js +27 -2
- package/lib/render/DuplicateChecker.js +6 -6
- package/lib/render/manageConstraints.js +1 -0
- package/lib/render/toCdl.js +3 -1
- package/lib/transform/db/applyTransformations.js +33 -0
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +8 -3
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/temporal.js +6 -3
- package/lib/transform/db/transformExists.js +2 -2
- package/lib/transform/effective/annotations.js +194 -0
- package/lib/transform/effective/main.js +6 -8
- package/lib/transform/effective/misc.js +31 -10
- package/lib/transform/forOdata.js +23 -7
- package/lib/transform/forRelationalDB.js +1 -1
- package/lib/transform/localized.js +7 -6
- package/lib/transform/odata/flattening.js +189 -106
- package/lib/transform/odata/toFinalBaseType.js +1 -1
- package/lib/transform/odata/typesExposure.js +15 -12
- package/lib/transform/parseExpr.js +4 -4
- package/lib/transform/transformUtils.js +40 -37
- package/lib/transform/translateAssocsToJoins.js +47 -47
- package/lib/transform/universalCsn/universalCsnEnricher.js +12 -16
- package/package.json +1 -1
- package/share/messages/anno-missing-rewrite.md +45 -0
- package/share/messages/message-explanations.json +1 -0
- package/bin/.eslintrc.json +0 -17
- package/lib/api/.eslintrc.json +0 -37
- package/lib/checks/.eslintrc.json +0 -31
- package/lib/compiler/.eslintrc.json +0 -8
- package/lib/edm/.eslintrc.json +0 -46
- package/lib/inspect/.eslintrc.json +0 -4
- package/lib/json/.eslintrc.json +0 -4
- package/lib/language/.eslintrc.json +0 -4
- package/lib/model/.eslintrc.json +0 -13
- package/lib/modelCompare/utils/.eslintrc.json +0 -22
- package/lib/render/.eslintrc.json +0 -22
- package/lib/transform/.eslintrc.json +0 -13
- package/lib/transform/db/.eslintrc.json +0 -41
- package/lib/transform/draft/.eslintrc.json +0 -4
- package/lib/transform/effective/.eslintrc.json +0 -4
- package/lib/transform/universalCsn/.eslintrc.json +0 -37
- package/lib/utils/.eslintrc.json +0 -7
package/lib/compiler/shared.js
CHANGED
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
isAssocToPrimaryKeys,
|
|
20
20
|
artifactRefLocation,
|
|
21
21
|
} = require('./utils');
|
|
22
|
+
const { isBetaEnabled } = require('../base/model');
|
|
22
23
|
|
|
23
24
|
const $inferred = Symbol.for( 'cds.$inferred' );
|
|
24
25
|
const $location = Symbol.for( 'cds.$location' );
|
|
@@ -133,14 +134,14 @@ function fns( model ) {
|
|
|
133
134
|
param: paramSemantics,
|
|
134
135
|
},
|
|
135
136
|
filter: {
|
|
136
|
-
lexical:
|
|
137
|
+
lexical: justDollarAliases,
|
|
137
138
|
dollar: true,
|
|
138
139
|
dynamic: targetElements,
|
|
139
140
|
notFound: undefinedTargetElement,
|
|
140
141
|
param: paramSemantics,
|
|
141
142
|
},
|
|
142
143
|
'calc-filter': {
|
|
143
|
-
lexical:
|
|
144
|
+
lexical: justDollarAliases,
|
|
144
145
|
dollar: true,
|
|
145
146
|
dynamic: targetElements,
|
|
146
147
|
navigation: calcElemNavigation,
|
|
@@ -181,7 +182,7 @@ function fns( model ) {
|
|
|
181
182
|
check: checkColumnRef,
|
|
182
183
|
param: paramSemantics,
|
|
183
184
|
nestedColumn: () => ({ // in expand and inline
|
|
184
|
-
lexical:
|
|
185
|
+
lexical: justDollarAliases,
|
|
185
186
|
dollar: true,
|
|
186
187
|
dynamic: nestedElements,
|
|
187
188
|
notFound: undefinedNestedElement,
|
|
@@ -197,7 +198,7 @@ function fns( model ) {
|
|
|
197
198
|
param: paramSemantics,
|
|
198
199
|
},
|
|
199
200
|
calc: {
|
|
200
|
-
lexical:
|
|
201
|
+
lexical: justDollarAliases,
|
|
201
202
|
dollar: true,
|
|
202
203
|
dynamic: parentElements,
|
|
203
204
|
navigation: calcElemNavigation,
|
|
@@ -213,7 +214,7 @@ function fns( model ) {
|
|
|
213
214
|
param: paramSemantics,
|
|
214
215
|
},
|
|
215
216
|
on: { // unmanaged assoc: outside query, redirected or new assoc in column
|
|
216
|
-
lexical:
|
|
217
|
+
lexical: justDollarAliases,
|
|
217
218
|
dollar: true,
|
|
218
219
|
dynamic: parentElements,
|
|
219
220
|
navigation: assocOnNavigation,
|
|
@@ -222,7 +223,7 @@ function fns( model ) {
|
|
|
222
223
|
check: checkAssocOn,
|
|
223
224
|
param: paramUnsupported,
|
|
224
225
|
nestedColumn: () => ({ // in expand and inline
|
|
225
|
-
lexical:
|
|
226
|
+
lexical: justDollarAliases,
|
|
226
227
|
dollar: true,
|
|
227
228
|
dynamic: parentElements,
|
|
228
229
|
navigation: assocOnNavigation,
|
|
@@ -276,7 +277,7 @@ function fns( model ) {
|
|
|
276
277
|
param: paramSemantics,
|
|
277
278
|
},
|
|
278
279
|
annotation: { // annotation assignments
|
|
279
|
-
lexical:
|
|
280
|
+
lexical: justDollarAliases,
|
|
280
281
|
dollar: true,
|
|
281
282
|
dynamic: parentElements,
|
|
282
283
|
navigation: assocOnNavigation,
|
|
@@ -287,8 +288,8 @@ function fns( model ) {
|
|
|
287
288
|
'ref-undefined-param': 'anno-undefined-param',
|
|
288
289
|
},
|
|
289
290
|
param: paramSemantics,
|
|
290
|
-
nestedColumn: () => ({
|
|
291
|
-
lexical:
|
|
291
|
+
nestedColumn: () => ({
|
|
292
|
+
lexical: justDollarAliases,
|
|
292
293
|
dollar: true,
|
|
293
294
|
dynamic: parentElements,
|
|
294
295
|
navigation: assocOnNavigation,
|
|
@@ -298,14 +299,21 @@ function fns( model ) {
|
|
|
298
299
|
},
|
|
299
300
|
// TODO: introduce some kind of inheritance
|
|
300
301
|
annoRewrite: { // annotation assignments
|
|
301
|
-
lexical:
|
|
302
|
+
lexical: justDollarAliases,
|
|
302
303
|
dollar: true,
|
|
303
304
|
dynamic: parentElements,
|
|
304
305
|
navigation: assocOnNavigation,
|
|
305
306
|
noDep: true,
|
|
306
307
|
notFound: null, // no error, just falsy links
|
|
307
308
|
param: paramSemantics,
|
|
308
|
-
|
|
309
|
+
nestedColumn: () => ({
|
|
310
|
+
lexical: justDollarAliases,
|
|
311
|
+
dollar: true,
|
|
312
|
+
dynamic: parentElements,
|
|
313
|
+
navigation: assocOnNavigation,
|
|
314
|
+
notFound: undefinedParentElement,
|
|
315
|
+
rewriteProjectionToSelf: true,
|
|
316
|
+
}),
|
|
309
317
|
},
|
|
310
318
|
};
|
|
311
319
|
|
|
@@ -313,9 +321,11 @@ function fns( model ) {
|
|
|
313
321
|
traverseExpr,
|
|
314
322
|
resolveUncheckedPath,
|
|
315
323
|
resolveTypeArgumentsUnchecked, // TODO: move to some other file
|
|
324
|
+
resolvePathRoot,
|
|
316
325
|
resolvePath,
|
|
317
326
|
checkExpr,
|
|
318
327
|
checkOnCondition,
|
|
328
|
+
navigationEnv,
|
|
319
329
|
nestedElements,
|
|
320
330
|
attachAndEmitValidNames,
|
|
321
331
|
} );
|
|
@@ -354,7 +364,6 @@ function fns( model ) {
|
|
|
354
364
|
const { path } = ref;
|
|
355
365
|
if (!path || path.broken) // incomplete type AST
|
|
356
366
|
return undefined;
|
|
357
|
-
|
|
358
367
|
const semantics = referenceSemantics[refCtx];
|
|
359
368
|
if (!semantics.isMainRef)
|
|
360
369
|
throw new CompilerAssertion( `resolveUncheckedPath() called for reference ctx '${ refCtx }'` );
|
|
@@ -628,6 +637,22 @@ function fns( model ) {
|
|
|
628
637
|
return art;
|
|
629
638
|
}
|
|
630
639
|
|
|
640
|
+
/**
|
|
641
|
+
* Resolve the _path-root_ only. Used for rewriting annotation paths.
|
|
642
|
+
*
|
|
643
|
+
* @param ref
|
|
644
|
+
* @param {string} expected
|
|
645
|
+
* @param user
|
|
646
|
+
*/
|
|
647
|
+
function resolvePathRoot( ref, expected, user ) {
|
|
648
|
+
if (ref == null || !ref.path) // no references -> nothing to do
|
|
649
|
+
return undefined;
|
|
650
|
+
const s = referenceSemantics[expected];
|
|
651
|
+
const semantics = (typeof s === 'string') ? referenceSemantics[s] : s;
|
|
652
|
+
const r = getPathRoot( ref, semantics, user );
|
|
653
|
+
return r && acceptPathRoot( r, ref, semantics, user );
|
|
654
|
+
}
|
|
655
|
+
|
|
631
656
|
// Helper functions for resolve[Unchecked]Path, getPath{Root,Item}: -----------
|
|
632
657
|
|
|
633
658
|
function acceptLexical( art, path, semantics, user ) {
|
|
@@ -687,9 +712,14 @@ function fns( model ) {
|
|
|
687
712
|
// TODO: remove again, should be easy enough in to-csn without.
|
|
688
713
|
if (path.length === 1 && art.kind === '$tableAlias')
|
|
689
714
|
(user._user || user).$noOrigin = true;
|
|
715
|
+
if (head.id === '$projection' && user.kind === '$annotation') {
|
|
716
|
+
error( 'ref-unsupported-projection', [ head.location, user ],
|
|
717
|
+
{ code: '$projection', newcode: '$self' },
|
|
718
|
+
'$(CODE) is not supported in annotations; replace by $(NEWCODE)' );
|
|
719
|
+
}
|
|
690
720
|
return art;
|
|
691
721
|
}
|
|
692
|
-
case '$parameters': {
|
|
722
|
+
case '$parameters': {
|
|
693
723
|
// TODO: if ref.scope='param' is handled, test that here, too ?
|
|
694
724
|
const { id } = path[1];
|
|
695
725
|
message( 'ref-obsolete-parameters', [ head.location, user ],
|
|
@@ -756,10 +786,10 @@ function fns( model ) {
|
|
|
756
786
|
function userBlock( user ) {
|
|
757
787
|
return definedViaCdl( user ) && user._block;
|
|
758
788
|
}
|
|
759
|
-
function
|
|
789
|
+
function justDollarAliases( user ) {
|
|
760
790
|
const query = userQuery( user );
|
|
761
791
|
if (!query)
|
|
762
|
-
return user._main || user;
|
|
792
|
+
return user._main || user; // TODO: also contains `up_` for aspects; remove
|
|
763
793
|
// query.$tableAliases contains both aliases and $self/$projection
|
|
764
794
|
const aliases = query.$tableAliases;
|
|
765
795
|
const r = Object.create( null );
|
|
@@ -783,7 +813,7 @@ function fns( model ) {
|
|
|
783
813
|
const aliases = userQuery( user ).$tableAliases;
|
|
784
814
|
user.$extended = Object.keys( aliases )[0];
|
|
785
815
|
}
|
|
786
|
-
return
|
|
816
|
+
return justDollarAliases( user );
|
|
787
817
|
}
|
|
788
818
|
|
|
789
819
|
// Functions called via semantics.dynamic: ------------------------------------
|
|
@@ -829,7 +859,13 @@ function fns( model ) {
|
|
|
829
859
|
return query._combined; // TODO: do we need query._parent._combined ?
|
|
830
860
|
}
|
|
831
861
|
function parentElements( user ) {
|
|
832
|
-
|
|
862
|
+
// Note: We could have `$self` in bound actions refer to its entity, but reject it now.
|
|
863
|
+
// If users request it, we can either allow it later or point them to binding parameters.
|
|
864
|
+
const useParent = user._main &&
|
|
865
|
+
user.kind !== 'select' &&
|
|
866
|
+
user.kind !== 'action' &&
|
|
867
|
+
user.kind !== 'function';
|
|
868
|
+
return environment( useParent ? user._parent : user );
|
|
833
869
|
}
|
|
834
870
|
|
|
835
871
|
function queryElements( user ) {
|
|
@@ -1144,7 +1180,7 @@ function fns( model ) {
|
|
|
1144
1180
|
// corresponding column expression; this might have references to elements
|
|
1145
1181
|
// of invisible table aliases; at least one stakeholder uses this,
|
|
1146
1182
|
// so it can't be an error (yet).
|
|
1147
|
-
|
|
1183
|
+
message( 'ref-deprecated-self-element', [ ref.path[0].location, user._user ], {},
|
|
1148
1184
|
// eslint-disable-next-line max-len
|
|
1149
1185
|
'Referring to the query\'s own elements here might lead to invalid SQL references; use source elements only' );
|
|
1150
1186
|
return false;
|
|
@@ -1199,8 +1235,12 @@ function fns( model ) {
|
|
|
1199
1235
|
}
|
|
1200
1236
|
|
|
1201
1237
|
function acceptRealArtifact( art, user, ref ) {
|
|
1202
|
-
|
|
1203
|
-
|
|
1238
|
+
if (art.kind !== 'namespace')
|
|
1239
|
+
return art;
|
|
1240
|
+
// For compatibility (≤v4), we accept `extend Unknown` without elements/actions/includes
|
|
1241
|
+
// In v5, only allow `extend with definitions`.
|
|
1242
|
+
if (!isBetaEnabled( model.options, 'v5preview' ) &&
|
|
1243
|
+
!(user.elements || user.actions || user.includes))
|
|
1204
1244
|
return art;
|
|
1205
1245
|
const { location } = ref.path[ref.path.length - 1];
|
|
1206
1246
|
signalNotFound( 'ref-undefined-def', [ location, user ], null, { art } );
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
6
|
forEachGeneric,
|
|
7
|
-
forEachMember,
|
|
8
7
|
forEachInOrder,
|
|
9
8
|
} = require('../base/model');
|
|
10
9
|
const { dictLocation, weakLocation, weakRefLocation } = require('../base/location');
|
|
@@ -33,7 +32,6 @@ function tweakAssocs( model ) {
|
|
|
33
32
|
info, warning, error,
|
|
34
33
|
} = model.$messageFunctions;
|
|
35
34
|
const {
|
|
36
|
-
resolvePath,
|
|
37
35
|
traverseExpr,
|
|
38
36
|
checkExpr,
|
|
39
37
|
checkOnCondition,
|
|
@@ -78,8 +76,6 @@ function tweakAssocs( model ) {
|
|
|
78
76
|
traverseQueryPost( art.query, false, ( query ) => {
|
|
79
77
|
forEachGeneric( query, 'elements', rewriteAssociationCheck );
|
|
80
78
|
} );
|
|
81
|
-
|
|
82
|
-
checkForAnnotationRefs( art );
|
|
83
79
|
}
|
|
84
80
|
|
|
85
81
|
// function rewriteView( view ) {
|
|
@@ -124,90 +120,6 @@ function tweakAssocs( model ) {
|
|
|
124
120
|
}
|
|
125
121
|
}
|
|
126
122
|
|
|
127
|
-
function checkForAnnotationRefs( art ) {
|
|
128
|
-
// TODO: no check for type inheritance yet
|
|
129
|
-
const origin = art._origin ||
|
|
130
|
-
art.includes && art.includes[art.includes.length - 1]._artifact;
|
|
131
|
-
// Make sure not to waste time if no inherited annotation has checked refs:
|
|
132
|
-
if (!origin?.$contains?.$annotation)
|
|
133
|
-
return;
|
|
134
|
-
for (const prop in origin) {
|
|
135
|
-
const anno = prop.charAt(0) === '@' && !art[prop] && origin[prop];
|
|
136
|
-
// Remark: to be on the academic safe side, we should consider the
|
|
137
|
-
// annotations which are not propagated, but they never have references as
|
|
138
|
-
// value. So “no” for the moment. We also do not perform these checks in
|
|
139
|
-
// propagator.js, as it should go away in compiler v6.
|
|
140
|
-
if (anno.kind) { // i.e. with values refs
|
|
141
|
-
art[prop] = { ...anno, $inferred: 'prop' };
|
|
142
|
-
setLink( art[prop], '_outer', art );
|
|
143
|
-
const errorRef = checkAnnotationForRefs( art[prop], art );
|
|
144
|
-
if (errorRef) {
|
|
145
|
-
const valid = errorRef.path[errorRef.path.length - 1]._artifact;
|
|
146
|
-
error( 'anno-missing-rewrite', [ weakLocation( art.location ), art ], {
|
|
147
|
-
'#': (valid ? 'unrelated' : 'std'),
|
|
148
|
-
anno: prop,
|
|
149
|
-
art: origin,
|
|
150
|
-
elemref: errorRef,
|
|
151
|
-
} );
|
|
152
|
-
}
|
|
153
|
-
art.$contains ??= {};
|
|
154
|
-
art.$contains.$annotation = true;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
forEachMember( art, checkForAnnotationRefs );
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function checkAnnotationForRefs( expr, user ) {
|
|
161
|
-
if (expr.$tokenTexts)
|
|
162
|
-
return traverseExpr( expr, 'annoRewrite', user, checkAnnotationRef );
|
|
163
|
-
if (expr.literal === 'array') {
|
|
164
|
-
for (const val of expr.val) {
|
|
165
|
-
const found = checkAnnotationForRefs( val, user );
|
|
166
|
-
if (found)
|
|
167
|
-
return found;
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
if (expr.literal !== 'struct')
|
|
172
|
-
return null;
|
|
173
|
-
const struct = Object.values( expr.struct );
|
|
174
|
-
for (const val of struct) {
|
|
175
|
-
const found = checkAnnotationForRefs( val, user );
|
|
176
|
-
if (found)
|
|
177
|
-
return found;
|
|
178
|
-
}
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function checkAnnotationRef( ref, refCtx, user ) {
|
|
183
|
-
const origPath = ref.path;
|
|
184
|
-
if (!origPath[origPath.length - 1]._artifact) // already wrong in original
|
|
185
|
-
return null;
|
|
186
|
-
ref = { ...ref, path: [ ...origPath.map( item => ({ ...item }) ) ] };
|
|
187
|
-
if (!resolvePath( ref, refCtx, user ))
|
|
188
|
-
return ref;
|
|
189
|
-
return ref.path.some( isUnrelated ) && ref;
|
|
190
|
-
|
|
191
|
-
function isUnrelated( item, idx ) {
|
|
192
|
-
let elem = item._artifact;
|
|
193
|
-
const orig = origPath[idx]._artifact;
|
|
194
|
-
// With includes, we allow shadowing: an included element might seem to be
|
|
195
|
-
// unrelated.
|
|
196
|
-
if (elem._main?.includes && elem._main === (user._main || user))
|
|
197
|
-
return false;
|
|
198
|
-
if (!elem._effectiveType) // safety
|
|
199
|
-
return false;
|
|
200
|
-
// With redirections, the originally referred object might not be the same
|
|
201
|
-
// or even the direct _origin
|
|
202
|
-
do {
|
|
203
|
-
if (elem === orig)
|
|
204
|
-
return false;
|
|
205
|
-
elem = elem._origin;
|
|
206
|
-
} while (elem);
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
123
|
function rewriteAssociationCheck( element ) {
|
|
212
124
|
const elem = element.items || element; // TODO v5: nested items
|
|
213
125
|
if (elem.elements)
|
|
@@ -524,6 +436,18 @@ function tweakAssocs( model ) {
|
|
|
524
436
|
$inferred: 'copy',
|
|
525
437
|
};
|
|
526
438
|
|
|
439
|
+
// Published paths with filters are always associations, never
|
|
440
|
+
// compositions, hence we need to change the type to avoid type propagation.
|
|
441
|
+
const assocType = { id: 'cds.Association', location };
|
|
442
|
+
setArtifactLink( assocType, model.definitions['cds.Association'] );
|
|
443
|
+
elem.type = {
|
|
444
|
+
path: [ assocType ],
|
|
445
|
+
scope: 'global',
|
|
446
|
+
location,
|
|
447
|
+
$inferred: '$generated',
|
|
448
|
+
};
|
|
449
|
+
setArtifactLink( elem.type, assocType._artifact );
|
|
450
|
+
|
|
527
451
|
elem.$filtered = {
|
|
528
452
|
val: true,
|
|
529
453
|
literal: 'boolean',
|
|
@@ -820,6 +744,7 @@ function tweakAssocs( model ) {
|
|
|
820
744
|
return null;
|
|
821
745
|
}
|
|
822
746
|
item.id = name;
|
|
747
|
+
// TODO: Why not break here? Test test3/scenarios/AFC/db/view/consumption/C_ScopedRole.cds
|
|
823
748
|
}
|
|
824
749
|
}
|
|
825
750
|
let env = name && elem._effectiveType; // should have been computed
|