@sap/cds-compiler 5.9.4 → 6.0.12

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 (114) hide show
  1. package/CHANGELOG.md +117 -319
  2. package/README.md +1 -1
  3. package/bin/cds_update_identifiers.js +3 -5
  4. package/bin/cdsc.js +24 -9
  5. package/bin/cdshi.js +1 -1
  6. package/bin/cdsse.js +4 -4
  7. package/doc/CHANGELOG_BETA.md +11 -0
  8. package/doc/CHANGELOG_DEPRECATED.md +29 -0
  9. package/lib/api/main.js +8 -5
  10. package/lib/api/options.js +12 -10
  11. package/lib/base/builtins.js +1 -0
  12. package/lib/base/message-registry.js +191 -99
  13. package/lib/base/messages.js +35 -21
  14. package/lib/base/model.js +14 -24
  15. package/lib/checks/actionsFunctions.js +10 -20
  16. package/lib/checks/annotationsOData.js +1 -1
  17. package/lib/checks/elements.js +35 -10
  18. package/lib/checks/enums.js +31 -0
  19. package/lib/checks/foreignKeys.js +2 -2
  20. package/lib/checks/hasPersistedElements.js +5 -0
  21. package/lib/checks/invalidTarget.js +1 -1
  22. package/lib/checks/managedWithoutKeys.js +5 -4
  23. package/lib/checks/queryNoDbArtifacts.js +10 -8
  24. package/lib/checks/types.js +5 -5
  25. package/lib/checks/validator.js +6 -4
  26. package/lib/compiler/assert-consistency.js +13 -9
  27. package/lib/compiler/checks.js +20 -52
  28. package/lib/compiler/define.js +31 -6
  29. package/lib/compiler/extend.js +5 -1
  30. package/lib/compiler/generate.js +14 -17
  31. package/lib/compiler/populate.js +8 -31
  32. package/lib/compiler/propagator.js +21 -35
  33. package/lib/compiler/resolve.js +64 -29
  34. package/lib/compiler/shared.js +16 -4
  35. package/lib/compiler/tweak-assocs.js +1 -1
  36. package/lib/compiler/utils.js +1 -1
  37. package/lib/edm/annotations/edmJson.js +23 -20
  38. package/lib/edm/annotations/genericTranslation.js +12 -10
  39. package/lib/edm/csn2edm.js +50 -56
  40. package/lib/edm/edm.js +33 -28
  41. package/lib/edm/edmInboundChecks.js +2 -2
  42. package/lib/edm/edmPreprocessor.js +54 -88
  43. package/lib/edm/edmUtils.js +9 -12
  44. package/lib/gen/BaseParser.js +63 -52
  45. package/lib/gen/CdlGrammar.checksum +1 -1
  46. package/lib/gen/CdlParser.js +1153 -1165
  47. package/lib/gen/Dictionary.json +21 -1
  48. package/lib/json/from-csn.js +70 -43
  49. package/lib/json/to-csn.js +6 -8
  50. package/lib/language/multiLineStringParser.js +3 -2
  51. package/lib/main.d.ts +58 -24
  52. package/lib/model/cloneCsn.js +3 -0
  53. package/lib/model/csnUtils.js +28 -39
  54. package/lib/model/xprAsTree.js +23 -9
  55. package/lib/modelCompare/compare.js +5 -4
  56. package/lib/optionProcessor.js +24 -17
  57. package/lib/parsers/AstBuildingParser.js +81 -25
  58. package/lib/parsers/XprTree.js +57 -3
  59. package/lib/parsers/identifiers.js +1 -1
  60. package/lib/parsers/index.js +0 -3
  61. package/lib/render/manageConstraints.js +25 -25
  62. package/lib/render/toCdl.js +173 -170
  63. package/lib/render/toHdbcds.js +126 -128
  64. package/lib/render/toRename.js +7 -7
  65. package/lib/render/toSql.js +128 -125
  66. package/lib/render/utils/common.js +47 -22
  67. package/lib/render/utils/delta.js +25 -25
  68. package/lib/render/utils/operators.js +2 -2
  69. package/lib/render/utils/pretty.js +5 -5
  70. package/lib/render/utils/sql.js +13 -13
  71. package/lib/render/utils/standardDatabaseFunctions.js +115 -103
  72. package/lib/render/utils/unique.js +4 -4
  73. package/lib/transform/db/applyTransformations.js +1 -1
  74. package/lib/transform/db/assertUnique.js +2 -2
  75. package/lib/transform/db/associations.js +6 -7
  76. package/lib/transform/db/assocsToQueries/utils.js +4 -5
  77. package/lib/transform/db/backlinks.js +12 -9
  78. package/lib/transform/db/cdsPersistence.js +8 -7
  79. package/lib/transform/db/constraints.js +13 -10
  80. package/lib/transform/db/expansion.js +7 -3
  81. package/lib/transform/db/flattening.js +4 -14
  82. package/lib/transform/db/processSqlServices.js +2 -1
  83. package/lib/transform/db/temporal.js +5 -7
  84. package/lib/transform/db/views.js +2 -4
  85. package/lib/transform/draft/db.js +8 -8
  86. package/lib/transform/draft/odata.js +10 -7
  87. package/lib/transform/forOdata.js +10 -5
  88. package/lib/transform/forRelationalDB.js +5 -75
  89. package/lib/transform/localized.js +1 -1
  90. package/lib/transform/odata/createForeignKeys.js +11 -10
  91. package/lib/transform/odata/flattening.js +8 -4
  92. package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +96 -0
  93. package/lib/transform/odata/typesExposure.js +3 -3
  94. package/lib/transform/transformUtils.js +4 -8
  95. package/lib/transform/translateAssocsToJoins.js +14 -7
  96. package/lib/transform/universalCsn/universalCsnEnricher.js +10 -4
  97. package/lib/utils/objectUtils.js +0 -17
  98. package/package.json +10 -13
  99. package/share/messages/def-upcoming-virtual-change.md +1 -1
  100. package/LICENSE +0 -37
  101. package/bin/cds_remove_invalid_whitespace.js +0 -138
  102. package/doc/CHANGELOG_ARCHIVE.md +0 -3604
  103. package/lib/gen/genericAntlrParser.js +0 -3
  104. package/lib/gen/language.checksum +0 -1
  105. package/lib/gen/language.interp +0 -456
  106. package/lib/gen/language.tokens +0 -180
  107. package/lib/gen/languageLexer.interp +0 -439
  108. package/lib/gen/languageLexer.js +0 -1483
  109. package/lib/gen/languageLexer.tokens +0 -167
  110. package/lib/gen/languageParser.js +0 -24941
  111. package/lib/language/antlrParser.js +0 -205
  112. package/lib/language/errorStrategy.js +0 -646
  113. package/lib/language/genericAntlrParser.js +0 -1572
  114. package/lib/parsers/CdlGrammar.g4 +0 -2070
@@ -79,7 +79,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
79
79
 
80
80
  const mergedVocabularies = translate.mergeOdataVocabularies(options, message);
81
81
 
82
- const Edm = getEdm(options, messageFunctions);
82
+ const Edm = getEdm(options);
83
83
 
84
84
  const { v } = options;
85
85
  if (Object.keys(allServices).length === 0) {
@@ -304,14 +304,13 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
304
304
 
305
305
  const usages = UsedTypes[typeName].filter(u => !u.$NameClashReported);
306
306
  if (usages.length > 0 && def && !def.$isRendered && def['@cds.external']) {
307
- message('odata-spec-violation-type', usages[0].$location,
307
+ message('odata-invalid-external-type', usages[0].$location,
308
308
  {
309
309
  type: typeName,
310
310
  anno: '@cds.external',
311
311
  name: serviceCsn.name,
312
312
  code: def.elements ? 'Edm.ComplexType' : 'Edm.TypeDefinition',
313
313
  version: options.isV4() ? '4.0' : '2.0',
314
- '#': 'external',
315
314
  });
316
315
  }
317
316
  }
@@ -407,14 +406,14 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
407
406
  const reservedNames = [ 'Edm', 'odata', 'System', 'Transient' ];
408
407
  const loc = [ 'definitions', schema.name ];
409
408
  if (reservedNames.includes(schema.name))
410
- message('odata-spec-violation-namespace', loc, { names: reservedNames });
409
+ message('odata-invalid-service-name', loc, { names: reservedNames });
411
410
  if (schema.name.length > 511) {
412
- message('odata-spec-violation-namespace', loc, { '#': 'length' });
411
+ message('odata-invalid-service-name', loc, { '#': 'length' });
413
412
  }
414
413
  else {
415
414
  schema.name.split('.').forEach((id) => {
416
415
  if (!edmUtils.isODataSimpleIdentifier(id))
417
- message('odata-spec-violation-id', loc, { id });
416
+ message('odata-invalid-name', loc, { id });
418
417
  });
419
418
  }
420
419
 
@@ -523,29 +522,31 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
523
522
  // this especially covers: 'items: composition of one { data : String; }'
524
523
  // "keyless" composition targets in structured containment mode
525
524
  else if (entityCsn.$hasEntitySet && entityCsn.$edmKeyPaths.length === 0 && !isSingleton)
526
- message('odata-spec-violation-no-key', location);
525
+ message('odata-missing-key', location);
527
526
 
528
527
  if (!edmUtils.isODataSimpleIdentifier(EntityTypeName))
529
- message('odata-spec-violation-id', location, { id: EntityTypeName });
528
+ message('odata-invalid-name', location, { id: EntityTypeName });
530
529
 
531
530
  properties.forEach((p) => {
532
531
  const pLoc = [ ...location, 'elements', p._edmAttributes.Name ];
533
532
  edmTypeCompatibilityCheck(p, pLoc);
534
533
  if (p._edmAttributes.Name === EntityTypeName)
535
- message('odata-spec-violation-property-name', pLoc, { meta: entityCsn.kind });
534
+ message('odata-invalid-property-name', pLoc, { meta: entityCsn.kind });
536
535
 
537
536
  if (options.isV2() && p.$isCollection && !p._csn.target)
538
- message('odata-spec-violation-array', pLoc, { version: '2.0' });
537
+ message('odata-unexpected-array', pLoc, { version: '2.0' });
539
538
 
540
539
  if (!edmUtils.isODataSimpleIdentifier(p._edmAttributes.Name)) {
541
- message('odata-spec-violation-id', pLoc, { id: p._edmAttributes.Name });
540
+ message('odata-invalid-name', pLoc, { id: p._edmAttributes.Name });
542
541
  }
543
542
  else if (options.isV2() && /^(_|\d)/.test(p._edmAttributes.Name)) {
544
543
  // FIXME: Rewrite signalIllegalIdentifier function to be more flexible
545
- message('odata-spec-violation-id', pLoc,
546
- {
547
- prop: p._edmAttributes.Name[0], id: p._edmAttributes.Name, version: '2.0', '#': 'v2firstChar',
548
- });
544
+ message('odata-invalid-name', pLoc, {
545
+ '#': 'v2firstChar',
546
+ prop: p._edmAttributes.Name[0],
547
+ id: p._edmAttributes.Name,
548
+ version: '2.0',
549
+ });
549
550
  }
550
551
  });
551
552
 
@@ -603,23 +604,23 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
603
604
  const location = [ 'definitions', structuredTypeCsn.name ];
604
605
 
605
606
  if (!edmUtils.isODataSimpleIdentifier(attributes.Name))
606
- message('odata-spec-violation-id', location, { id: attributes.Name });
607
+ message('odata-invalid-name', location, { id: attributes.Name });
607
608
 
608
609
  properties.forEach((p) => {
609
610
  const pLoc = [ ...location, ...(structuredTypeCsn.items ? [ 'items', 'elements' ] : [ 'elements' ]), p._edmAttributes.Name ];
610
611
  edmTypeCompatibilityCheck(p, pLoc);
611
612
  if (p._edmAttributes.Name === complexType._edmAttributes.Name)
612
- message('odata-spec-violation-property-name', pLoc, { meta: structuredTypeCsn.kind });
613
+ message('odata-invalid-property-name', pLoc, { meta: structuredTypeCsn.kind });
613
614
 
614
615
  if (!edmUtils.isODataSimpleIdentifier(p._edmAttributes.Name))
615
- message('odata-spec-violation-id', pLoc, { id: p._edmAttributes.Name });
616
+ message('odata-invalid-name', pLoc, { id: p._edmAttributes.Name });
616
617
 
617
618
  if (options.isV2()) {
618
619
  if (p.$isCollection && !p._csn.target)
619
- message('odata-spec-violation-array', pLoc, { version: '2.0' });
620
+ message('odata-unexpected-array', pLoc, { version: '2.0' });
620
621
 
621
622
  if (p._csn.target)
622
- message('odata-spec-violation-assoc', pLoc, { version: '2.0' });
623
+ message('odata-unexpected-assoc', pLoc, { version: '2.0' });
623
624
  }
624
625
  });
625
626
 
@@ -713,7 +714,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
713
714
  // derived types are already resolved to base types
714
715
  const attributes = { Name: typeCsn.name.replace(schemaNamePrefix, '') };
715
716
  if (!edmUtils.isODataSimpleIdentifier(attributes.Name))
716
- message('odata-spec-violation-id', typeCsn.$path, { id: attributes.Name });
717
+ message('odata-invalid-name', typeCsn.$path, { id: attributes.Name });
717
718
 
718
719
  const typeDef = new Edm.TypeDefinition(v, attributes, typeCsn );
719
720
  edmTypeCompatibilityCheck(typeDef, typeCsn.$path);
@@ -732,7 +733,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
732
733
 
733
734
 
734
735
  if (!edmUtils.isODataSimpleIdentifier(attributes.Name))
735
- message('odata-spec-violation-id', location, { id: attributes.Name });
736
+ message('odata-invalid-name', location, { id: attributes.Name });
736
737
 
737
738
  if (!iAmAnAction)
738
739
  attributes.IsComposable = false;
@@ -766,7 +767,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
766
767
  setProp(firstParam, '_edmType', bpType);
767
768
  }
768
769
  if (!edmUtils.isODataSimpleIdentifier(bpName))
769
- message('odata-spec-violation-id', [ ...location, 'params', bpName ], { id: bpName });
770
+ message('odata-invalid-name', [ ...location, 'params', bpName ], { id: bpName });
770
771
  }
771
772
  }
772
773
 
@@ -795,7 +796,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
795
796
  }
796
797
 
797
798
  if (!edmUtils.isODataSimpleIdentifier(bpName))
798
- message('odata-spec-violation-id', bpnAnnoLoc, { id: bpName });
799
+ message('odata-invalid-name', bpnAnnoLoc, { id: bpName });
799
800
  if (actionCsn.params && actionCsn.params[bpName])
800
801
  error('duplicate-definition', bpnAnnoLoc, { '#': 'param', name: bpName });
801
802
  }
@@ -839,7 +840,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
839
840
  const p = new Edm.Parameter(v, { Name: parameterName }, parameterCsn );
840
841
  const pLoc = [ ...location, 'params', p._edmAttributes.Name ];
841
842
  if (!edmUtils.isODataSimpleIdentifier(parameterName))
842
- message('odata-spec-violation-id', pLoc, { id: parameterName });
843
+ message('odata-invalid-name', pLoc, { id: parameterName });
843
844
  collectUsedType(parameterCsn);
844
845
  edmTypeCompatibilityCheck(p, pLoc);
845
846
  actionNode.append(p);
@@ -880,7 +881,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
880
881
  : [ 'definitions', actionCsn.name ];
881
882
 
882
883
  if (!edmUtils.isODataSimpleIdentifier(attributes.Name))
883
- message('odata-spec-violation-id', location, { id: attributes.Name });
884
+ message('odata-invalid-name', location, { id: attributes.Name });
884
885
 
885
886
  const rt = actionCsn.returns && ((actionCsn.returns.items && actionCsn.returns.items.type) || actionCsn.returns.type);
886
887
  if (rt) { // add EntitySet attribute only if return type is an entity
@@ -936,17 +937,17 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
936
937
  collectUsedType(parameterCsn);
937
938
  edmTypeCompatibilityCheck(param, pLoc);
938
939
  if (!edmUtils.isODataSimpleIdentifier(parameterName))
939
- message('odata-spec-violation-id', pLoc, { id: parameterName });
940
+ message('odata-invalid-name', pLoc, { id: parameterName });
940
941
 
941
942
  // only scalar or structured type in V2 (not entity)
942
943
  if (param._type &&
943
- !param._type.startsWith('Edm.') &&
944
- csn.definitions[param._type] &&
945
- !edmUtils.isStructuredType(csn.definitions[param._type]))
946
- message('odata-spec-violation-param', pLoc, { version: '2.0' });
944
+ !param._type.startsWith('Edm.') &&
945
+ csn.definitions[param._type] &&
946
+ !edmUtils.isStructuredType(csn.definitions[param._type]))
947
+ message('odata-invalid-param-type', pLoc, { version: '2.0' });
947
948
 
948
949
  if (param.$isCollection)
949
- message('odata-spec-violation-array', pLoc, { version: '2.0' });
950
+ message('odata-unexpected-array', pLoc, { version: '2.0' });
950
951
 
951
952
  functionImport.append(param);
952
953
  }
@@ -966,27 +967,26 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
966
967
  if (type) {
967
968
  collectUsedType(action.returns);
968
969
  if (!isBuiltinType(type) && csn.definitions[type].kind !== 'entity' && csn.definitions[type].kind !== 'type') {
969
- message('odata-spec-violation-returns', returnsLoc, { kind: action.kind, version: '2.0' });
970
+ message('odata-invalid-return-type', returnsLoc, { kind: action.kind, version: '2.0' });
970
971
  }
971
972
  else if (isBuiltinType(type)) {
972
973
  type = edmUtils.mapCdsToEdmType(returns, messageFunctions, _options);
973
974
  if (type) {
974
975
  const td = EdmPrimitiveTypeMap[type];
975
976
  if (td && !td.v2) {
976
- message('odata-spec-violation-type', returnsLoc,
977
- { type, version: '2.0', '#': 'incompatible' });
977
+ message('odata-unexpected-edm-type', returnsLoc,
978
+ { type, version: '2.0' });
978
979
  }
979
980
  }
980
981
  else {
981
- message('odata-spec-violation-type-unknown', returnsLoc, { type });
982
+ message('odata-unknown-edm-type', returnsLoc, { type });
982
983
  }
983
984
  }
984
985
  if (action.returns.$isCollection)
985
986
  type = `Collection(${ type })`;
986
987
  }
987
988
  else {
988
- // type is missing
989
- message('odata-spec-violation-type', returnsLoc);
989
+ message('odata-missing-type', returnsLoc);
990
990
  }
991
991
  }
992
992
  return type;
@@ -1159,7 +1159,7 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
1159
1159
  function edmTypeCompatibilityCheck( p, pLoc ) {
1160
1160
  const edmType = p._type;
1161
1161
  if (!edmType) {
1162
- message('odata-spec-violation-type', pLoc);
1162
+ message('odata-missing-type', pLoc);
1163
1163
  }
1164
1164
  else if (p._scalarType) {
1165
1165
  const td = EdmPrimitiveTypeMap[edmType];
@@ -1167,41 +1167,35 @@ function csn2edmAll( _csn, _options, serviceNames, messageFunctions ) {
1167
1167
  // The renderer/type mapper doesn't/shouldn't produce incompatible types and facets.
1168
1168
  // Only the unknown type warning may be triggered by an unknown @odata.Type override.
1169
1169
  if (td.v2 !== p.v2 && td.v4 !== p.v4) {
1170
- message('odata-spec-violation-type', pLoc,
1171
- { type: edmType, version: (p.v4 ? '4.0' : '2.0'), '#': 'incompatible' });
1170
+ message('odata-unexpected-edm-type', pLoc,
1171
+ { type: edmType, version: (p.v4 ? '4.0' : '2.0') });
1172
1172
  }
1173
1173
  EdmTypeFacetNames.forEach((name) => {
1174
1174
  const facet = EdmTypeFacetMap[name];
1175
- const optional
1176
- = (facet.optional !== undefined)
1177
- ? (Array.isArray(facet.optional)
1178
- ? facet.optional.includes(edmType)
1179
- : facet.optional)
1180
- : false;
1175
+ const optional = (facet.optional !== undefined) &&
1176
+ (Array.isArray(facet.optional)
1177
+ ? facet.optional.includes(edmType)
1178
+ : facet.optional);
1181
1179
 
1182
1180
  // facet is not in attributes
1183
1181
  // facet is member of type definition and mandatory
1184
1182
  // node and facet version match
1185
1183
  if (!p._edmAttributes[name] && td[name] && !optional && (p.v2 === facet.v2 || p.v4 === facet.v4)) {
1186
- message('odata-spec-violation-type', pLoc,
1187
- {
1188
- type: edmType, name, version: (p.v4 ? '4.0' : '2.0'), '#': 'facet',
1189
- });
1184
+ message('odata-unexpected-edm-facet', pLoc,
1185
+ { type: edmType, name, version: (p.v4 ? '4.0' : '2.0') });
1190
1186
  }
1191
1187
  });
1192
1188
  if (edmType === 'Edm.Decimal') {
1193
1189
  const precision = Number.parseInt(p._edmAttributes.Precision, 10);
1194
1190
  const scale = Number.parseInt(p._edmAttributes.Scale, 10);
1195
1191
  if (!Number.isNaN(precision) && !Number.isNaN(scale) && scale > precision) {
1196
- message('odata-spec-violation-type', pLoc,
1197
- {
1198
- type: edmType, number: scale, rawvalue: precision, '#': 'scale',
1199
- });
1192
+ message('odata-invalid-scale', pLoc,
1193
+ { number: scale, rawvalue: precision });
1200
1194
  }
1201
1195
  }
1202
1196
  }
1203
1197
  else {
1204
- message('odata-spec-violation-type-unknown', pLoc, { type: edmType });
1198
+ message('odata-unknown-edm-type', pLoc, { type: edmType });
1205
1199
  }
1206
1200
  }
1207
1201
  }
package/lib/edm/edm.js CHANGED
@@ -8,9 +8,9 @@ const {
8
8
  EdmTypeFacetNames,
9
9
  EdmPrimitiveTypeMap,
10
10
  } = require('./EdmPrimitiveTypeDefinitions.js');
11
+ const { CompilerAssertion } = require('../base/error');
11
12
 
12
- function getEdm( options, messageFunctions ) {
13
- const { error } = messageFunctions || { error: () => true, warning: () => true };
13
+ function getEdm( options ) {
14
14
  class Node {
15
15
  /**
16
16
  * @param {boolean[]} version Versions in the form of [<v2>, <v4>].
@@ -19,11 +19,11 @@ function getEdm( options, messageFunctions ) {
19
19
  */
20
20
  constructor(version, attributes = Object.create(null), csn = undefined) {
21
21
  if (!attributes || typeof attributes !== 'object')
22
- error(null, 'Debug me: attributes must be a dictionary');
22
+ throw new CompilerAssertion('Debug me: attributes must be a dictionary');
23
23
  if (!Array.isArray(version))
24
- error(null, `Debug me: v is either undefined or not an array: ${ version }`);
24
+ throw new CompilerAssertion(`Debug me: v is either undefined or not an array: ${ version }`);
25
25
  if (version.filter(v => v).length !== 1)
26
- error(null, 'Debug me: exactly one version must be set');
26
+ throw new CompilerAssertion('Debug me: exactly one version must be set');
27
27
 
28
28
  // Common attributes of JSON and XML.
29
29
  // Note: Can't assign attributes directly, due to the input object being modified.
@@ -633,17 +633,17 @@ function getEdm( options, messageFunctions ) {
633
633
  this._typeName = typeName;
634
634
  this._scalarType = undefined;
635
635
  if (this._edmAttributes[typeName] === undefined) {
636
- const typecsn = csn.type ? csn : (csn.items && csn.items.type ? csn.items : csn);
636
+ const typeCsn = csn.items?.type ? csn.items : csn;
637
637
  // Complex/EntityType are derived from TypeBase
638
638
  // but have no type attribute in their CSN
639
- if (typecsn.type) { // this thing has a type
639
+ if (typeCsn.type) { // this thing has a type
640
640
  // check whether this is a scalar type (or array of scalar type) or a named type
641
- if (typecsn.items && typecsn.items.type &&
642
- isBuiltinType(typecsn.items.type))
643
- this._scalarType = typecsn.items;
641
+ if (typeCsn.items?.type &&
642
+ isBuiltinType(typeCsn.items.type))
643
+ this._scalarType = typeCsn.items;
644
644
 
645
- else if (isBuiltinType(typecsn.type))
646
- this._scalarType = typecsn;
645
+ else if (isBuiltinType(typeCsn.type))
646
+ this._scalarType = typeCsn;
647
647
 
648
648
  if (this._scalarType) {
649
649
  this._edmAttributes[typeName] = csn._edmType;
@@ -658,7 +658,7 @@ function getEdm( options, messageFunctions ) {
658
658
  }
659
659
  else {
660
660
  // it's either _edmType or type (_edmType only used for explicit binding param)
661
- this._edmAttributes[typeName] = typecsn._edmType || typecsn.type;
661
+ this._edmAttributes[typeName] = typeCsn._edmType || typeCsn.type;
662
662
  }
663
663
  }
664
664
  // CDXCORE-245:
@@ -666,7 +666,7 @@ function getEdm( options, messageFunctions ) {
666
666
  // optionally add @odata { MaxLength, Precision, Scale, SRID }
667
667
  // but only in combination with @odata.Type
668
668
  // Allow to override type only on scalar and undefined types
669
- if ((this._scalarType || typecsn.type == null) && !csn.elements) {
669
+ if ((this._scalarType || typeCsn.type == null) && !csn.elements) {
670
670
  const odataType = csn['@odata.Type'];
671
671
  if (odataType) {
672
672
  const td = EdmPrimitiveTypeMap[odataType];
@@ -741,6 +741,7 @@ function getEdm( options, messageFunctions ) {
741
741
  this._edmAttributes.OpenType = true;
742
742
  }
743
743
  }
744
+
744
745
  class EntityType extends ComplexType {
745
746
  constructor(version, details, properties, csn) {
746
747
  super(version, details, csn);
@@ -1052,15 +1053,15 @@ function getEdm( options, messageFunctions ) {
1052
1053
  delete this._edmAttributes.Nullable;
1053
1054
  }
1054
1055
  // we have exactly one selfReference or the default partner
1055
- const partner
1056
- = !csn.$noPartner
1057
- ? csn._selfReferences.length === 1
1058
- ? csn._selfReferences[0]
1059
- : csn._constraints._partnerCsn
1060
- : undefined;
1061
- if (partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
1062
- // $abspath[0] is main entity
1063
- this._edmAttributes.Partner = partner.$abspath.slice(1).join('/');
1056
+
1057
+ if ( !csn.$noPartner) {
1058
+ const partner = csn._selfReferences.length === 1
1059
+ ? csn._selfReferences[0]
1060
+ : csn._constraints._partnerCsn;
1061
+ if (partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
1062
+ // $abspath[0] is main entity
1063
+ this._edmAttributes.Partner = partner.$abspath.slice(1).join('/');
1064
+ }
1064
1065
  }
1065
1066
 
1066
1067
  /*
@@ -1142,7 +1143,7 @@ function getEdm( options, messageFunctions ) {
1142
1143
  json.$OnDelete = c._edmAttributes.Action;
1143
1144
  break;
1144
1145
  default:
1145
- error(null, `Debug me: Unhandled NavProp child: ${ c.kind }`);
1146
+ throw new CompilerAssertion(`Debug me: Unhandled NavProp child: ${ c.kind }`);
1146
1147
  }
1147
1148
  });
1148
1149
  // TODO Annotations
@@ -1211,8 +1212,11 @@ function getEdm( options, messageFunctions ) {
1211
1212
  /* short notation for Edm.Boolean, Edm.String and Edm.Float, see internal project:
1212
1213
  edmx2csn-npm/edm-converters/blob/835d92a1aa6b0be25c56cef85e260c9188187429/lib/edmxV40ToJsonV40/README.md
1213
1214
  */
1214
- if (inline[0] === 'Edm.Boolean')
1215
- return (v === 'true' ? true : (v === 'false' ? false : v));
1215
+ if (inline[0] === 'Edm.Boolean') {
1216
+ if (v === 'true')
1217
+ return true;
1218
+ return (v === 'false') ? false : v;
1219
+ }
1216
1220
  return v;
1217
1221
  }
1218
1222
 
@@ -1291,7 +1295,8 @@ function getEdm( options, messageFunctions ) {
1291
1295
  }
1292
1296
 
1293
1297
  getJsonFQTermName() {
1294
- return `@${ this._edmAttributes.Term }${ this._edmAttributes.Qualifier ? `#${ this._edmAttributes.Qualifier }` : '' }`;
1298
+ const qualifier = this._edmAttributes.Qualifier ? `#${ this._edmAttributes.Qualifier }` : '';
1299
+ return `@${ this._edmAttributes.Term }${ qualifier }`;
1295
1300
  }
1296
1301
  }
1297
1302
 
@@ -1340,7 +1345,7 @@ function getEdm( options, messageFunctions ) {
1340
1345
  break;
1341
1346
  }
1342
1347
  default:
1343
- error(null, `Pease debug me: Unhandled Record child: ${ c.kind }`);
1348
+ throw new CompilerAssertion(`Debug me: Unhandled Record child: ${ c.kind }`);
1344
1349
  }
1345
1350
  });
1346
1351
  return json;
@@ -117,13 +117,13 @@ function inboundQualificationChecks( csn, options, messageFunctions,
117
117
  i++;
118
118
  }
119
119
  if (i > 1) {
120
- message('chained-array-of', path);
120
+ message('type-invalid-items', path, { '#': 'nested', prop: 'items' });
121
121
  return;
122
122
  }
123
123
 
124
124
  const itemsType = csnUtils.effectiveType(memberType.items);
125
125
  if (itemsType.items)
126
- message('chained-array-of', path);
126
+ message('type-invalid-items', path, { '#': 'chained-service', prop: 'items' });
127
127
  }
128
128
  }
129
129