@sap/cds-compiler 4.1.2 → 4.2.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 (74) hide show
  1. package/CHANGELOG.md +101 -1
  2. package/bin/cdsc.js +6 -3
  3. package/doc/CHANGELOG_BETA.md +5 -0
  4. package/doc/CHANGELOG_DEPRECATED.md +15 -0
  5. package/lib/api/main.js +2 -2
  6. package/lib/api/options.js +2 -2
  7. package/lib/api/validate.js +24 -24
  8. package/lib/base/message-registry.js +41 -6
  9. package/lib/base/messages.js +7 -0
  10. package/lib/base/model.js +37 -8
  11. package/lib/checks/elements.js +11 -10
  12. package/lib/checks/manyNavigations.js +33 -0
  13. package/lib/checks/onConditions.js +5 -2
  14. package/lib/checks/queryNoDbArtifacts.js +2 -3
  15. package/lib/checks/selectItems.js +4 -55
  16. package/lib/checks/utils.js +3 -2
  17. package/lib/checks/validator.js +3 -1
  18. package/lib/compiler/.eslintrc.json +2 -1
  19. package/lib/compiler/assert-consistency.js +27 -24
  20. package/lib/compiler/base.js +6 -2
  21. package/lib/compiler/builtins.js +34 -34
  22. package/lib/compiler/checks.js +179 -208
  23. package/lib/compiler/classes.js +2 -2
  24. package/lib/compiler/cycle-detector.js +6 -6
  25. package/lib/compiler/define.js +66 -45
  26. package/lib/compiler/extend.js +81 -72
  27. package/lib/compiler/finalize-parse-cdl.js +26 -26
  28. package/lib/compiler/generate.js +61 -45
  29. package/lib/compiler/index.js +47 -49
  30. package/lib/compiler/kick-start.js +8 -7
  31. package/lib/compiler/moduleLayers.js +1 -1
  32. package/lib/compiler/populate.js +42 -35
  33. package/lib/compiler/propagator.js +6 -6
  34. package/lib/compiler/resolve.js +170 -126
  35. package/lib/compiler/shared.js +122 -45
  36. package/lib/compiler/tweak-assocs.js +93 -40
  37. package/lib/compiler/utils.js +15 -12
  38. package/lib/edm/.eslintrc.json +40 -1
  39. package/lib/edm/annotations/genericTranslation.js +721 -707
  40. package/lib/edm/annotations/preprocessAnnotations.js +88 -77
  41. package/lib/edm/csn2edm.js +389 -378
  42. package/lib/edm/edm.js +678 -772
  43. package/lib/edm/edmAnnoPreprocessor.js +132 -146
  44. package/lib/edm/edmInboundChecks.js +29 -27
  45. package/lib/edm/edmPreprocessor.js +686 -646
  46. package/lib/edm/edmUtils.js +277 -296
  47. package/lib/gen/language.checksum +1 -1
  48. package/lib/gen/language.interp +1 -1
  49. package/lib/gen/languageParser.js +1253 -1276
  50. package/lib/json/from-csn.js +34 -4
  51. package/lib/json/to-csn.js +4 -4
  52. package/lib/language/language.g4 +2 -5
  53. package/lib/main.d.ts +61 -1
  54. package/lib/model/csnUtils.js +31 -2
  55. package/lib/model/revealInternalProperties.js +1 -1
  56. package/lib/modelCompare/compare.js +37 -2
  57. package/lib/modelCompare/utils/filter.js +1 -1
  58. package/lib/optionProcessor.js +15 -3
  59. package/lib/render/toCdl.js +30 -4
  60. package/lib/render/toSql.js +5 -9
  61. package/lib/render/utils/common.js +8 -6
  62. package/lib/transform/db/applyTransformations.js +1 -1
  63. package/lib/transform/db/cdsPersistence.js +1 -1
  64. package/lib/transform/db/constraints.js +47 -17
  65. package/lib/transform/db/expansion.js +121 -47
  66. package/lib/transform/db/flattening.js +75 -7
  67. package/lib/transform/forOdata.js +4 -1
  68. package/lib/transform/forRelationalDB.js +80 -62
  69. package/lib/transform/localized.js +91 -54
  70. package/lib/transform/transformUtils.js +9 -10
  71. package/lib/utils/file.js +7 -7
  72. package/lib/utils/moduleResolve.js +210 -121
  73. package/lib/utils/objectUtils.js +1 -1
  74. package/package.json +5 -5
@@ -25,7 +25,7 @@ const layers = require('./moduleLayers');
25
25
  const { CompilerAssertion } = require('../base/error');
26
26
  const { CsnLocation } = require('./classes');
27
27
 
28
- const $location = Symbol.for('cds.$location');
28
+ const $location = Symbol.for( 'cds.$location' );
29
29
 
30
30
  // attach stupid location - TODO: remove in v5
31
31
  const genLocation = new CsnLocation( '' );
@@ -53,10 +53,10 @@ function extend( model ) {
53
53
  applyIncludes, // TODO: re-check
54
54
  } );
55
55
 
56
- const includesNonShadowedFirst = isDeprecatedEnabled(model.options, 'includesNonShadowedFirst');
56
+ const includesNonShadowedFirst = isDeprecatedEnabled( model.options, 'includesNonShadowedFirst' );
57
57
 
58
58
  sortModelSources();
59
- const extensionsDict = Object.create(null); // TODO TMP
59
+ const extensionsDict = Object.create( null ); // TODO TMP
60
60
  forEachDefinition( model, tagIncludes ); // TODO TMP
61
61
 
62
62
  forEachDefinition( model, extendArtifactBefore );
@@ -134,46 +134,32 @@ function extend( model ) {
134
134
  delete art.$typeExts;
135
135
  }
136
136
 
137
- if (art.kind === 'annotate' && !art.returns && extensionsMap.returns)
137
+ if (art.kind === 'annotate' && !art.returns && extensionsMap.returns && !art._parent?.returns)
138
138
  annotateCreate( art, '', art, 'returns' );
139
139
 
140
+ moveDictExtensions( art, extensionsMap, 'actions' );
140
141
  moveDictExtensions( art, extensionsMap, 'params' );
141
142
  moveReturnsExtensions( art, extensionsMap );
142
- const sub = art.returns || art.items || art.targetAspect?.elements && art.targetAspect;
143
- if (sub) {
144
- if (art.returns) { // after having applied params!
143
+
144
+ if (art.returns) {
145
+ pushToDict( art.returns, '_extensions', ...extensionsMap.elements || [] );
146
+ pushToDict( art.returns, '_extensions', ...extensionsMap.enum || [] );
147
+ if (art.kind !== 'annotate') {
145
148
  extendHandleReturns( extensionsMap.elements, art );
146
149
  extendHandleReturns( extensionsMap.enum, art );
150
+ return;
147
151
  }
148
- // care about 'ext-unexpected-returns' in a later change if we have XSN returns
149
- pushToDict( sub, '_extensions', ...avoidRecursiveReturns(extensionsMap, 'elements'));
150
- pushToDict( sub, '_extensions', ...avoidRecursiveReturns(extensionsMap, 'enum') );
152
+ }
153
+ const sub = art.items || art.targetAspect?.elements && art.targetAspect;
154
+ if (sub) {
155
+ pushToDict( sub, '_extensions', ...extensionsMap.elements || [] );
156
+ pushToDict( sub, '_extensions', ...extensionsMap.enum || [] );
151
157
  }
152
158
  else {
153
159
  moveDictExtensions( art, extensionsMap,
154
160
  (art.enum && art.kind !== 'annotate' ? 'enum' : 'elements'), 'elements' );
155
161
  moveDictExtensions( art, extensionsMap, 'enum' );
156
162
  }
157
- moveDictExtensions( art, extensionsMap, 'actions' );
158
- }
159
-
160
- /**
161
- * FIXME: Remove this workaround. This workaround avoids endless recursion for annotate statements
162
- * that have both "returns" and "elements". The endless recursion happens due to the
163
- * pushDict on `sub`. The `elements` extensions will point to the same extension on which
164
- * `returns` exist.
165
- *
166
- * @param extensionsMap
167
- * @param {string} prop
168
- * @return {XSN.Extension[]}
169
- */
170
- function avoidRecursiveReturns( extensionsMap, prop ) {
171
- if (!extensionsMap[prop])
172
- return [];
173
- const exts = [];
174
- for (const ext of extensionsMap[prop])
175
- exts.push({ ...ext, returns: undefined });
176
- return exts;
177
163
  }
178
164
 
179
165
  /**
@@ -224,7 +210,7 @@ function extend( model ) {
224
210
  annotate: 'There is no artifact $(ART), use $(CODE) instead',
225
211
  // do not mention 'extend context', that is not in CAPire
226
212
  service: 'Artifact $(ART) is not of kind $(KIND), use $(CODE) or $(KEYWORD) instead',
227
- });
213
+ } );
228
214
  }
229
215
  // TODO: Use similar checks for EXTEND ENTITY etc - 'ext-ignoring-kind'
230
216
  }
@@ -234,7 +220,7 @@ function extend( model ) {
234
220
  // TODO: if extensions has more than one of returns,items,elements,enum, delete all those props
235
221
  function transformArtifactExtensions( art ) {
236
222
  const hasOnlySubExtensions = art._outer; // items, anonymous aspects
237
- const dict = Object.create(null);
223
+ const dict = Object.create( null );
238
224
  for (const ext of art._extensions) {
239
225
  for (const prop in ext) {
240
226
  if (ext[prop] === undefined) // deleted property
@@ -435,7 +421,7 @@ function extend( model ) {
435
421
  while (prevPos < previousValue.length) {
436
422
  const prevItem = previousValue[prevPos++];
437
423
  result.push( prevItem );
438
- if (upToSpec && prevItem && equalUpTo( prevItem, item.upTo)) {
424
+ if (upToSpec && prevItem && equalUpTo( prevItem, item.upTo )) {
439
425
  upToSpec = false;
440
426
  break;
441
427
  }
@@ -606,32 +592,41 @@ function extend( model ) {
606
592
  continue; // definitions inside extend, already handled
607
593
  dictCheck = dictCheck && checkRemainingMemberExtensions( art, elemExt, artProp, name );
608
594
  const elem = artDict[name] || annotateFor( art, extProp, name );
609
- setLink( elemExt.name, '_artifact', (elem.kind !== 'annotate' ? elem : null) );
595
+ setLink( elemExt.name, '_artifact', (elem.kind !== 'annotate' ? elem : null ) );
610
596
  pushToDict( elem, '_extensions', elemExt );
611
597
  }
612
598
  }
613
599
  }
614
600
 
615
601
  function moveReturnsExtensions( art, extensionsMap ) {
616
- if (!extensionsMap.returns)
602
+ const extensions = extensionsMap.returns;
603
+ if (!extensions)
617
604
  return;
605
+ const artReturns = art.returns;
606
+ let extReturns = artReturns;
607
+ const isAction = art.kind === 'action' || art.kind === 'function';
618
608
 
619
- for (const ext of extensionsMap.returns) {
620
- if (!art.returns && art.kind !== 'annotate') { // no check in super annotate statement
621
- const variant = art.kind === 'action' || art.kind === 'function' ? art.kind : 'std';
609
+ for (const ext of extensions) {
610
+ if (!artReturns && art.kind !== 'annotate') {
622
611
  warning( 'ext-unexpected-returns', [ ext.returns.location, ext ], {
623
- '#': variant, keyword: 'returns',
612
+ '#': (isAction ? art.kind : 'std'), keyword: 'returns',
624
613
  }, {
625
614
  std: 'Unexpected $(KEYWORD); only actions and functions have return parameters',
626
615
  action: 'Unexpected $(KEYWORD) for action without return parameter',
627
616
  // function without `returns` can happen via CSN input!
628
617
  function: 'Unexpected $(KEYWORD) for function without return parameter',
629
- });
618
+ } );
619
+ // Do not put completely wrong returns into a “super annotate” statement;
620
+ // this could induce consequential errors with [..., …]:
621
+ if (!isAction)
622
+ continue; // do not put into 'extensions'
623
+ // add to 'extensions' for action/function without returns:
624
+ extReturns ??= annotateFor( art, 'params', '' );
625
+ }
626
+ if (extReturns) {
627
+ setLink( ext.name, '_artifact', (isAction ? artReturns : null ) );
628
+ pushToDict( extReturns, '_extensions', ext.returns );
630
629
  }
631
- // If `!art.returns`, then it could be CSN from SQL, where actions are replaced by dummies.
632
- const elem = art.returns || annotateFor( art, 'params', '' );
633
- setLink( ext.name, '_artifact', (elem.kind !== 'annotate' ? elem : null) );
634
- pushToDict(elem, '_extensions', ext.returns);
635
630
  }
636
631
  }
637
632
 
@@ -720,7 +715,7 @@ function extend( model ) {
720
715
  { '#': (parent._effectiveType?.kind === 'entity') ? 'entity' : 'std' }, {
721
716
  std: 'Elements only exist in entities, types or typed constructs',
722
717
  entity: 'Elements of entity types can\'t be annotated',
723
- });
718
+ } );
724
719
  break;
725
720
  case 'params':
726
721
  warning( 'anno-unexpected-params', [ location, ext._parent ], {},
@@ -808,8 +803,6 @@ function extend( model ) {
808
803
  return;
809
804
  if (!resolvePath( ext.name, ext.kind, ext )) // error for extend, info for annotate
810
805
  return;
811
- // else if (ext.kind === 'extend') { // TODO v4 - add error
812
- // }
813
806
  if (art?.kind === 'namespace') {
814
807
  // TODO: not at all different to having no definition
815
808
  info( 'anno-namespace', [ ext.name.location, ext ], {}, // TODO: better location?
@@ -834,13 +827,13 @@ function extend( model ) {
834
827
  }
835
828
  else if (!construct.returns &&
836
829
  (art.kind === 'action' || art.kind === 'function') && construct.elements) {
837
- warning('ext-expecting-returns', [ construct.name.location, construct ], {
830
+ warning( 'ext-expecting-returns', [ construct.name.location, construct ], {
838
831
  '#': art.kind, keyword: 'returns', code: 'annotate ‹name› with returns { … }',
839
832
  }, {
840
833
  std: 'Expected $(CODE)', // unused variant
841
834
  action: 'Expected $(KEYWORD) when annotating action return structure, i.e. $(CODE)',
842
835
  function: 'Expected $(KEYWORD) when annotating function return structure, i.e. $(CODE)',
843
- });
836
+ } );
844
837
  }
845
838
  }
846
839
  }
@@ -883,7 +876,7 @@ function extend( model ) {
883
876
  */
884
877
  function extendArtifact( extensions, art, noIncludes = false ) {
885
878
  if (!noIncludes && !(canApplyIncludes( art, art ) &&
886
- extensions.every( ext => canApplyIncludes(ext, art) )))
879
+ extensions.every( ext => canApplyIncludes( ext, art ) )))
887
880
  return false;
888
881
  if (Array.isArray( noIncludes )) {
889
882
  canApplyIncludes( art, art, noIncludes );
@@ -891,7 +884,7 @@ function extend( model ) {
891
884
  }
892
885
  else if (!noIncludes &&
893
886
  !(canApplyIncludes( art, art ) &&
894
- extensions.every( ext => canApplyIncludes( ext, art) ))) {
887
+ extensions.every( ext => canApplyIncludes( ext, art ) ))) {
895
888
  // console.log( 'FALSE:',art.name, extensions.map( e => e.name ) )
896
889
  return false;
897
890
  }
@@ -942,7 +935,7 @@ function extend( model ) {
942
935
  // includes = ['Base1',3,'Base2']
943
936
  // where 3 means adding the next 3 elements before applying include 'Base2'
944
937
  if (art.includes)
945
- art.includes.push(...ext.includes);
938
+ art.includes.push( ...ext.includes );
946
939
  else
947
940
  art.includes = [ ...ext.includes ];
948
941
  applyIncludes( ext, art );
@@ -951,7 +944,7 @@ function extend( model ) {
951
944
  checkAnnotate( ext, art );
952
945
  // TODO: do we allow to add elements with array of {...}? If yes, adapt
953
946
  initMembers( ext, art, ext._block ); // might set _extend, _annotate
954
- dependsOnSilent(art, ext); // art depends silently on ext (inverse to normal dep!)
947
+ dependsOnSilent( art, ext ); // art depends silently on ext (inverse to normal dep!)
955
948
  }
956
949
  for (const name in ext.elements) {
957
950
  const elem = ext.elements[name];
@@ -965,7 +958,7 @@ function extend( model ) {
965
958
  reportUnstableExtensions( elemExtensions );
966
959
 
967
960
  // This whole function will be removed with a next change - no need to have nice code here:
968
- const dict = Object.create(null);
961
+ const dict = Object.create( null );
969
962
  // actions cannot be extended anyway. TODO: there should be a message
970
963
  // (possible with CSN input), but that was missing before this change, too.
971
964
  for (const e of extensions) {
@@ -1007,7 +1000,8 @@ function extend( model ) {
1007
1000
  let lastExt = null;
1008
1001
  let open = []; // the "highest" layers
1009
1002
  for (const ext of extensions) {
1010
- const extLayer = layers.layer( ext ) || { realname: '', _layerExtends: Object.create(null) };
1003
+ const extLayer = layers.layer( ext ) ||
1004
+ { realname: '', _layerExtends: Object.create( null ) };
1011
1005
  if (!open.length) {
1012
1006
  lastExt = ext;
1013
1007
  open = [ extLayer.realname ];
@@ -1055,7 +1049,7 @@ function extend( model ) {
1055
1049
  element: 'Artifact $(ART) has no element or enum $(MEMBER) - nothing to extend',
1056
1050
  action: 'Artifact $(ART) has no action $(MEMBER) - nothing to extend',
1057
1051
  } );
1058
- attachAndEmitValidNames(msg, validDict);
1052
+ attachAndEmitValidNames( msg, validDict );
1059
1053
  }
1060
1054
  }
1061
1055
 
@@ -1097,7 +1091,10 @@ function extend( model ) {
1097
1091
  * Apply all includes of `ext` on `ext`. Checks that `art` allows includes.
1098
1092
  * If `ext === art`, then includes of the artifact itself are applied.
1099
1093
  * If `ext !== art`, applies includes on the extensions, not artifact.
1100
- * Sets `_ancestor` links on `art`.
1094
+ * Sets `_ancestors` links on `art`.
1095
+ *
1096
+ * TODO: try to set `_ancestors` only to entities (but beware “intermediate”
1097
+ * non-entities).
1101
1098
  *
1102
1099
  * Examples:
1103
1100
  * ext === art: `entity E : F {}` => add elements of F to E
@@ -1126,7 +1123,18 @@ function extend( model ) {
1126
1123
  }
1127
1124
  if (!art.query && art.elements) // do not set art.elements and art.enums with query entity!
1128
1125
  includeMembers( ext, art, 'elements' );
1129
- includeMembers( ext, art, 'actions' );
1126
+ if (art.kind !== 'type') {
1127
+ includeMembers( ext, art, 'actions' );
1128
+ }
1129
+ else {
1130
+ for (const ref of ext.includes) {
1131
+ const template = ref._artifact; // already resolved
1132
+ if (template?.actions && Object.keys( template.actions ).length) {
1133
+ warning( 'ref-ignoring-actions', [ ref.location, ext ], { art: template },
1134
+ 'The actions of $(ART) are not added to the type' );
1135
+ }
1136
+ }
1137
+ }
1130
1138
  }
1131
1139
 
1132
1140
  /**
@@ -1143,15 +1151,15 @@ function extend( model ) {
1143
1151
  // Warning 'Overwrites definition from include "I" (at elem def)
1144
1152
  const parent = ext === art && art;
1145
1153
  const members = ext[prop];
1146
- if (members || art[prop])
1147
- ext[prop] = Object.create(null);
1154
+ if (members)
1155
+ ext[prop] = Object.create( null );
1148
1156
  let hasNewElement = false;
1149
1157
 
1150
1158
  for (const ref of ext.includes) {
1151
1159
  const template = ref._artifact; // already resolved
1152
1160
  if (template) { // be robust
1153
1161
  if (template[prop] && !ext[prop])
1154
- ext[prop] = Object.create(null);
1162
+ ext[prop] = Object.create( null );
1155
1163
  // eslint-disable-next-line no-loop-func
1156
1164
  forEachInOrder( template, prop, ( origin, name ) => {
1157
1165
  if (members && members[name]) {
@@ -1165,7 +1173,7 @@ function extend( model ) {
1165
1173
  if (!parent) // not yet set for EXTEND foo WITH bar => linkToOrigin() did not add it
1166
1174
  dictAdd( ext[prop], name, elem );
1167
1175
  elem.$inferred = 'include';
1168
- if (origin.masked)
1176
+ if (origin.masked) // TODO(v5): remove 'masked'
1169
1177
  elem.masked = Object.assign( { $inferred: 'include' }, origin.masked );
1170
1178
  if (origin.key)
1171
1179
  elem.key = Object.assign( { $inferred: 'include' }, origin.key );
@@ -1178,7 +1186,7 @@ function extend( model ) {
1178
1186
  setLink( elem, '_calcOrigin', origin._calcOrigin || origin );
1179
1187
  }
1180
1188
  // TODO: also complain if elem is just defined in art
1181
- });
1189
+ } );
1182
1190
  }
1183
1191
  }
1184
1192
 
@@ -1194,7 +1202,7 @@ function extend( model ) {
1194
1202
  // the element order.
1195
1203
  if (ext[prop][name] !== elem )
1196
1204
  dictAdd( ext[prop], name, elem );
1197
- });
1205
+ } );
1198
1206
  }
1199
1207
  }
1200
1208
 
@@ -1207,13 +1215,13 @@ function extend( model ) {
1207
1215
  function checkRedefinitionThroughIncludes( parent, prop ) {
1208
1216
  if (!parent[prop])
1209
1217
  return;
1210
- forEachInOrder(parent, prop, ( member, name ) => {
1211
- if (member.$inferred === 'include' && Array.isArray(member.$duplicates)) {
1212
- const includes = [ member, ...member.$duplicates ].map(dup => dup._origin._main);
1218
+ forEachInOrder( parent, prop, ( member, name ) => {
1219
+ if (member.$inferred === 'include' && Array.isArray( member.$duplicates )) {
1220
+ const includes = [ member, ...member.$duplicates ].map( dup => dup._origin._main );
1213
1221
  error( 'duplicate-definition', [ parent.name.location, member ],
1214
1222
  { '#': `include-${ prop }`, name, sorted_arts: includes } );
1215
1223
  }
1216
- });
1224
+ } );
1217
1225
  }
1218
1226
  }
1219
1227
 
@@ -1225,7 +1233,7 @@ function extend( model ) {
1225
1233
  * @returns {Record<string, object>} key: layer name, value: {name, layer, extensions[]}`
1226
1234
  */
1227
1235
  function layeredExtensions( extensions ) {
1228
- const layered = Object.create(null);
1236
+ const layered = Object.create( null );
1229
1237
  for (const ext of extensions) {
1230
1238
  const layer = (ext.kind === 'annotate' || ext.kind === 'extend' || ext.kind === 'source') &&
1231
1239
  layers.layer( ext );
@@ -1257,12 +1265,13 @@ function extensionsOfHighestLayers( layered ) {
1257
1265
  if (layerNames.length <= 1) {
1258
1266
  const name = layerNames[0];
1259
1267
  const highest = layered[name]?.extensions || [];
1268
+ highest.sort( compareExtensions );
1260
1269
  delete layered[name];
1261
1270
  return { highest, issue: inMoreThanOneFile( highest ) };
1262
1271
  }
1263
1272
 
1264
1273
  // collect all layers which are lower than another layer
1265
- const allExtends = Object.create(null);
1274
+ const allExtends = Object.create( null );
1266
1275
  allExtends[''] = {}; // the "Define" layer
1267
1276
  for (const name of layerNames) {
1268
1277
  if (name) // not the "Define" layer
@@ -1280,7 +1289,7 @@ function extensionsOfHighestLayers( layered ) {
1280
1289
  }
1281
1290
  }
1282
1291
  highest.sort( compareExtensions );
1283
- const good = highestLayers.every( layer => !inMoreThanOneFile( layer.extensions ));
1292
+ const good = highestLayers.every( layer => !inMoreThanOneFile( layer.extensions ) );
1284
1293
  // TODO: use layer.file instead
1285
1294
  const issue = !good || highestLayers.length > 1 && 'unrelated';
1286
1295
  // console.log('HI:',highest.map(l=>l.name),issue,issue&&extensions)
@@ -1291,7 +1300,7 @@ function inMoreThanOneFile( extensions ) {
1291
1300
  if (extensions.length <= 1)
1292
1301
  return false;
1293
1302
  const file = extensions[0].location?.file;
1294
- return !file || extensions.slice(1).some( e => e.location?.file !== file );
1303
+ return !file || extensions.some( e => e.location?.file !== file );
1295
1304
  }
1296
1305
 
1297
1306
  /**
@@ -47,14 +47,14 @@ function finalizeParseCdl( model ) {
47
47
  }
48
48
  }
49
49
 
50
- forEachGeneric(model, 'definitions', art => resolveTypesForParseCdl(art, art));
51
- forEachGeneric(model, 'vocabularies', art => resolveTypesForParseCdl(art, art));
50
+ forEachGeneric( model, 'definitions', art => resolveTypesForParseCdl( art, art ) );
51
+ forEachGeneric( model, 'vocabularies', art => resolveTypesForParseCdl( art, art ) );
52
52
 
53
53
  if (extensions.length > 0) {
54
54
  // TODO: do a sort based on the location in case there were two extensions
55
55
  // on the same definition? Yes: anno first outside, then inside service def
56
56
  model.extensions = extensions;
57
- model.extensions.forEach(ext => resolveTypesForParseCdl(ext, ext));
57
+ model.extensions.forEach( ext => resolveTypesForParseCdl( ext, ext ) );
58
58
  }
59
59
  }
60
60
 
@@ -69,9 +69,9 @@ function finalizeParseCdl( model ) {
69
69
  if (!artifact || typeof artifact !== 'object')
70
70
  return;
71
71
 
72
- if (Array.isArray(artifact)) {
72
+ if (Array.isArray( artifact )) {
73
73
  // e.g. `args` array
74
- artifact.forEach(art => resolveTypesForParseCdl(art, main));
74
+ artifact.forEach( art => resolveTypesForParseCdl( art, main ) );
75
75
  return;
76
76
  }
77
77
 
@@ -80,66 +80,66 @@ function finalizeParseCdl( model ) {
80
80
  return;
81
81
 
82
82
  if (artifact.type)
83
- resolveTypeUnchecked(artifact, main);
83
+ resolveTypeUnchecked( artifact, main );
84
84
 
85
85
  for (const include of artifact.includes || [])
86
- resolveUncheckedPath(include, 'include', main);
86
+ resolveUncheckedPath( include, 'include', main );
87
87
 
88
88
  // define.js takes care that `target` is a ref and
89
89
  // `targetAspect` is a structure.
90
90
  if (artifact.target)
91
- resolveUncheckedPath(artifact.target, 'target', main);
91
+ resolveUncheckedPath( artifact.target, 'target', main );
92
92
  if (artifact.targetAspect)
93
- resolveTypesForParseCdl(artifact.targetAspect, main);
93
+ resolveTypesForParseCdl( artifact.targetAspect, main );
94
94
 
95
95
  if (artifact.from) {
96
96
  const { from } = artifact;
97
- resolveUncheckedPath(from, 'from', main);
98
- resolveTypesForParseCdl(from, main);
97
+ resolveUncheckedPath( from, 'from', main );
98
+ resolveTypesForParseCdl( from, main );
99
99
  }
100
100
 
101
101
  // Recursively go through all XSN properties. There are a few that need to be
102
102
  // handled specifically. Refer to the code below this loop for details.
103
103
  for (const prop in artifact) {
104
- if (artifact[prop] === undefined || parseCdlSpeciallyHandledXsnProps.includes(prop) ||
105
- parseCdlIgnoredXsnProps.includes(prop))
104
+ if (artifact[prop] === undefined || parseCdlSpeciallyHandledXsnProps.includes( prop ) ||
105
+ parseCdlIgnoredXsnProps.includes( prop ))
106
106
  continue;
107
107
 
108
- if (artifact[prop] && Object.getPrototypeOf(artifact[prop]) === null)
108
+ if (artifact[prop] && Object.getPrototypeOf( artifact[prop] ) === null)
109
109
  // Dictionary in XSN
110
- forEachGeneric(artifact, prop, art => resolveTypesForParseCdl(art, art));
110
+ forEachGeneric( artifact, prop, art => resolveTypesForParseCdl( art, art ) );
111
111
  else
112
- resolveTypesForParseCdl(artifact[prop], main);
112
+ resolveTypesForParseCdl( artifact[prop], main );
113
113
  }
114
114
 
115
115
  // `$queries` has a flat structure that we can use instead of going through all `query`.
116
116
  // For these query-related properties, we need to keep the reference to the artifact
117
117
  // containing it. Otherwise some type's aren't properly resolved.
118
118
  // TODO: If resolveTypeUnchecked is reworked, we may be able to simplify this coding.
119
- (artifact.$queries || []).forEach( art => resolveTypesForParseCdl(art, artifact) );
120
- (artifact.columns || []).forEach( art => resolveTypesForParseCdl(art, artifact) );
121
- forEachGeneric( artifact, 'mixin', art => resolveTypesForParseCdl(art, artifact) );
119
+ (artifact.$queries || []).forEach( art => resolveTypesForParseCdl( art, artifact ) );
120
+ (artifact.columns || []).forEach( art => resolveTypesForParseCdl( art, artifact ) );
121
+ forEachGeneric( artifact, 'mixin', art => resolveTypesForParseCdl( art, artifact ) );
122
122
 
123
123
  // For better error messages for `type of`s in `returns`, we pass the object as the new main.
124
- resolveTypesForParseCdl(artifact.returns, artifact.returns);
124
+ resolveTypesForParseCdl( artifact.returns, artifact.returns );
125
125
 
126
126
  // Because `args` can be used in different contexts with different semantics,
127
127
  // it needs to be handled specifically.
128
128
  if (artifact.args && typeof artifact.args === 'object') {
129
- if (Array.isArray(artifact.args)) {
129
+ if (Array.isArray( artifact.args )) {
130
130
  // `args` may either be an array (e.g. query 'from' args) ...
131
- artifact.args.forEach((from) => {
131
+ artifact.args.forEach( (from) => {
132
132
  // ... and could be either inside a `from` ...
133
133
  if (from && from.kind === '$tableAlias')
134
- resolveUncheckedPath(from, 'from', from._main);
134
+ resolveUncheckedPath( from, 'from', from._main );
135
135
 
136
136
  // ... or only params ...
137
- resolveTypesForParseCdl(from, main);
138
- });
137
+ resolveTypesForParseCdl( from, main );
138
+ } );
139
139
  }
140
140
  else {
141
141
  // ... or dictionary (e.g. params)
142
- forEachGeneric(artifact, 'args', obj => resolveTypesForParseCdl(obj, obj));
142
+ forEachGeneric( artifact, 'args', obj => resolveTypesForParseCdl( obj, obj ) );
143
143
  }
144
144
  }
145
145
  }