@sap/cds-compiler 3.4.4 → 3.5.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 (129) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
@@ -10,9 +10,9 @@ const { setProp } = require('../base/model');
10
10
  const { copyAnnotations, applyTransformations } = require('../model/csnUtils');
11
11
  const { cloneCsnNonDict, cloneCsnDictionary, getUtils } = require('../model/csnUtils');
12
12
  const { typeParameters, isBuiltinType } = require('../compiler/builtins');
13
- const { ModelError } = require("../base/error");
13
+ const { ModelError } = require('../base/error');
14
14
  const { forEach } = require('../utils/objectUtils');
15
- const { pathName } = require("../compiler/utils");
15
+ const { pathName } = require('../compiler/utils');
16
16
 
17
17
  const RestrictedOperators = ['<', '>', '>=', '<='];
18
18
  const RelationalOperators = ['=', '!=', '<>', 'is' /*, 'like'*/,...RestrictedOperators];
@@ -12,16 +12,16 @@ const { timetrace } = require('../utils/timetrace');
12
12
  const internalArtifactKinds = ['builtin', '$parameters', 'param'];
13
13
 
14
14
  function translateAssocsToJoinsCSN(csn, options){
15
- timetrace.start('Recompiling model');
15
+ timetrace.start('A2J: Recompiling model');
16
16
  // Do not re-complain about localized
17
17
  const compileOptions = { ...options, $skipNameCheck: true };
18
18
  delete compileOptions.csnFlavor;
19
19
  const model = recompileX(csn, compileOptions);
20
- timetrace.stop();
21
- timetrace.start('Translating associations to joins');
20
+ timetrace.stop('A2J: Recompiling model');
21
+ timetrace.start('A2J: Translating associations to joins');
22
22
  translateAssocsToJoins(model, options);
23
- timetrace.stop();
24
- timetrace.start('Post-processing columns');
23
+ timetrace.stop('A2J: Translating associations to joins');
24
+ timetrace.start('A2J: Post-processing columns');
25
25
  // Use the effective elements list as columns
26
26
  forEachDefinition(model, art => {
27
27
  if (art.$queries) {
@@ -36,7 +36,7 @@ function translateAssocsToJoinsCSN(csn, options){
36
36
  }
37
37
  }
38
38
  });
39
- timetrace.stop();
39
+ timetrace.stop('A2J: Post-processing columns');
40
40
 
41
41
  if (options.messages) {
42
42
  // Make sure that we don't complain twice about the same things
@@ -46,8 +46,7 @@ function translateAssocsToJoinsCSN(csn, options){
46
46
  // If A2J reports error - end! Continuing with a broken CSN makes no sense
47
47
  makeMessageFunction(model, options).throwWithAnyError();
48
48
  // FIXME: Move this somewhere more appropriate
49
- const compact = compactModel(model, compileOptions);
50
- return compact;
49
+ return compactModel(model, compileOptions);
51
50
  }
52
51
 
53
52
  function translateAssocsToJoins(model, inputOptions = {})
@@ -329,9 +328,10 @@ function translateAssocsToJoins(model, inputOptions = {})
329
328
 
330
329
  for(let i = 0; i < tail.length-1; i++) {
331
330
  if(tail[i]._navigation && tail[i]._navigation.$njr) {
332
- // the correct flattened foreign key must match the leaf artifact of this path
331
+ // the correct flattened foreign key must match the leaf artifact and access path prefix of this path
333
332
  const leafArt = tail[tail.length-1]._artifact;
334
- const fk = tail[i]._artifact.$flatSrcFKs.find(f => f._artifact === leafArt);
333
+ const tailPath = tail.map(p=>p.id).join(pathDelimiter);
334
+ const fk = tail[i]._artifact.$flatSrcFKs.find(f => f._artifact === leafArt && f.acc.startsWith(tailPath));
335
335
  if(!fk) {
336
336
  // const revealInternalProperties = require('../model/revealInternalProperties.js');
337
337
  // console.log('++++++++ Path tail: ', revealInternalProperties(tail[tail.length-1]._artifact));
@@ -565,7 +565,7 @@ function translateAssocsToJoins(model, inputOptions = {})
565
565
  QATs until a QA has been found).
566
566
  */
567
567
  if(!assoc.$flatSrcFKs)
568
- setProp(assoc, '$flatSrcFKs', flattenElement(assoc, true, assoc.name.id));
568
+ setProp(assoc, '$flatSrcFKs', flattenElement(assoc, true, assoc.name.id, assoc.name.id));
569
569
  if(!assoc.$flatTgtFKs)
570
570
  setProp(assoc, '$flatTgtFKs', flattenElement(assoc, false));
571
571
 
@@ -664,7 +664,8 @@ function translateAssocsToJoins(model, inputOptions = {})
664
664
  }
665
665
  // If this is a backlink condition, produce the
666
666
  // ON cond of the forward assoc with swapped src/tgt aliases
667
- else if(i < args.length-2 && args[i].path && args[i+1] === '=' && args[i+2].path)
667
+ else if(i < args.length-2 && args[i].path &&
668
+ args[i+1]?.literal === 'token' && args[i+1]?.val === '=' && args[i+2].path)
668
669
  {
669
670
  let fwdAssoc = getForwardAssociation(args[i].path, args[i+2].path);
670
671
  if(fwdAssoc)
@@ -1088,11 +1089,11 @@ function translateAssocsToJoins(model, inputOptions = {})
1088
1089
  respecting the src or the target side of the ON condition.
1089
1090
  Return an array of column names and it's leaf element.
1090
1091
  */
1091
- function flattenElement(element, srcSide, prefix)
1092
+ function flattenElement(element, srcSide, prefix, acc)
1092
1093
  {
1093
1094
  // terminate if element is unstructured
1094
1095
  if(!element.foreignKeys && !element.elements)
1095
- return [ { id: prefix, _artifact: element } ];
1096
+ return [ { id: prefix, _artifact: element, acc } ];
1096
1097
 
1097
1098
  let paths = [];
1098
1099
  // get paths of managed assocs (unmanaged assocs are not allowed in FK paths)
@@ -1103,7 +1104,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1103
1104
  let fk = element.foreignKeys[fkn];
1104
1105
  // once a fk is to be followed, treat all sub patsh as srcSide, this will add fk.name.id only
1105
1106
  if(srcSide)
1106
- paths = paths.concat(flattenElement(fk.targetElement._artifact, true, fk.name.id));
1107
+ paths = paths.concat(flattenElement(fk.targetElement._artifact, true, fk.name.id, fk.targetElement.path.map(ps => ps.id).join(pathDelimiter)));
1107
1108
  else
1108
1109
  {
1109
1110
  // consume path segments until the next assoc and substitute against fk alias until path is eaten up
@@ -1113,7 +1114,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1113
1114
  [tail, fkPrefix] = substituteFKAliasForPath(assocStep, tail, fkPrefix);
1114
1115
  [assocStep, tail, fkPrefix] = pathAsStringUpToAssoc(tail, fkPrefix);
1115
1116
  }
1116
- paths = paths.concat(flattenElement(fk.targetElement._artifact, true, fkPrefix));
1117
+ paths = paths.concat(flattenElement(fk.targetElement._artifact, true, fkPrefix, fk.targetElement.path.map(ps => ps.id).join(pathDelimiter)));
1117
1118
  }
1118
1119
  }
1119
1120
  }
@@ -1123,11 +1124,15 @@ function translateAssocsToJoins(model, inputOptions = {})
1123
1124
  for(let n in element.elements)
1124
1125
  {
1125
1126
  let elt = element.elements[n];
1126
- paths = paths.concat(flattenElement(elt, true, elt.name.id));
1127
+ paths = paths.concat(flattenElement(elt, true, elt.name.id, elt.name.id));
1127
1128
  }
1128
1129
  }
1129
1130
  return paths.map(p => {
1130
- return { id: (prefix ? prefix + pathDelimiter : '' ) + p.id, _artifact: p._artifact }
1131
+ return {
1132
+ id: (prefix ? prefix + pathDelimiter : '' ) + p.id,
1133
+ acc: (acc ? acc + pathDelimiter : '') + p.acc,
1134
+ _artifact: p._artifact
1135
+ }
1131
1136
  } );
1132
1137
  }
1133
1138
 
@@ -1556,7 +1561,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1556
1561
  if(!qat[qatChildrenName]) {
1557
1562
  setProp(qat, '$njr', true);
1558
1563
  // flatten left hand side ON condition paths ( => foreign keys to the source side)
1559
- setProp(art, '$flatSrcFKs', flattenElement(art, true, art.name.id));
1564
+ setProp(art, '$flatSrcFKs', flattenElement(art, true, art.name.id, art.name.id));
1560
1565
  }
1561
1566
  }
1562
1567
  else {
@@ -10,17 +10,17 @@ const { setAnnotationIfNotDefined } = require('./utils');
10
10
  *
11
11
  * @param {CSN.Model} csn
12
12
  */
13
- function setCoreComputedOnViews(csn) {
13
+ function setCoreComputedOnViews( csn ) {
14
14
  const {
15
15
  artifactRef, getColumn, getElement, getOrigin,
16
16
  } = getUtils(csn, 'init-all');
17
17
 
18
- forEachDefinition(csn, (artifact) => {
18
+ forEachDefinition(csn, (artifact, name, prop, path) => {
19
19
  if (artifact.query || artifact.projection) {
20
20
  forAllQueries(getNormalizedQuery(artifact).query, (query) => {
21
21
  if (query.SELECT)
22
22
  traverseQueryAndAttachCoreComputed(query, query.SELECT.elements || artifact.elements);
23
- });
23
+ }, path);
24
24
  }
25
25
  });
26
26
  /**
@@ -33,7 +33,7 @@ function setCoreComputedOnViews(csn) {
33
33
  * @param {CSN.Query} query
34
34
  * @param {CSN.Elements} elements
35
35
  */
36
- function traverseQueryAndAttachCoreComputed(query, elements) {
36
+ function traverseQueryAndAttachCoreComputed( query, elements ) {
37
37
  for (const [ name, element ] of Object.entries(elements)) {
38
38
  const ancestor = getAncestor(element, name, query.SELECT);
39
39
 
@@ -53,7 +53,7 @@ function setCoreComputedOnViews(csn) {
53
53
  * @param {CSN.QuerySelect} base
54
54
  * @returns {CSN.Column|CSN.Element}
55
55
  */
56
- function getAncestor(element, name, base) {
56
+ function getAncestor( element, name, base ) {
57
57
  const column = getColumn(element);
58
58
  if (column)
59
59
  return column;
@@ -81,7 +81,7 @@ function setCoreComputedOnViews(csn) {
81
81
  * @returns {CSN.Element}
82
82
  * @todo cleanup throw(s) - but leave in during dev
83
83
  */
84
- function getElementFromFrom(name, base) {
84
+ function getElementFromFrom( name, base ) {
85
85
  if (base.SELECT && base.SELECT.elements) {
86
86
  return getAncestor(base.SELECT.elements[name], name, base.SELECT);
87
87
  }
@@ -108,7 +108,7 @@ function setCoreComputedOnViews(csn) {
108
108
  * @param {string} name
109
109
  * @returns {CSN.Element|null} Null if no element was found
110
110
  */
111
- function checkJoinSources(args, name) {
111
+ function checkJoinSources( args, name ) {
112
112
  for (const arg of args) {
113
113
  if (arg.args) { // Join after join - A join B on <..> join C on <..>
114
114
  const result = checkJoinSources(arg.args, name);
@@ -130,7 +130,7 @@ function setCoreComputedOnViews(csn) {
130
130
  *
131
131
  * @param {CSN.Column} column
132
132
  */
133
- function attachCoreComputed(column) {
133
+ function attachCoreComputed( column ) {
134
134
  if (needsCoreComputed(column))
135
135
  setAnnotationIfNotDefined(getElement(column), '@Core.Computed', true);
136
136
  }
@@ -141,7 +141,7 @@ function setCoreComputedOnViews(csn) {
141
141
  * @param {CSN.Column} column
142
142
  * @returns {boolean}
143
143
  */
144
- function needsCoreComputed(column) {
144
+ function needsCoreComputed( column ) {
145
145
  return column &&
146
146
  (
147
147
  column.xpr || column.func || column.val !== undefined || column.param || column.SELECT || column.SET ||
@@ -155,7 +155,7 @@ function setCoreComputedOnViews(csn) {
155
155
  * @param {CSN.Column} column
156
156
  * @param {Function} callback
157
157
  */
158
- function traverseExpandInline(column, callback) {
158
+ function traverseExpandInline( column, callback ) {
159
159
  if (column.expand) {
160
160
  column.expand.forEach((col) => {
161
161
  callback(col);
@@ -206,7 +206,7 @@ module.exports = (csn, options) => {
206
206
  * @param {object} root
207
207
  * @returns {object|string|null}
208
208
  */
209
- function getTargetAspectBase(root) {
209
+ function getTargetAspectBase( root ) {
210
210
  if (root.target && root.target.elements) {
211
211
  return root.target;
212
212
  }
@@ -229,7 +229,7 @@ module.exports = (csn, options) => {
229
229
  * @see getTargetAspectBase for details on how we find our "start"
230
230
  * @param {object} root
231
231
  */
232
- function setTargetAspectIfRequired(root) {
232
+ function setTargetAspectIfRequired( root ) {
233
233
  if (root.$origin || root.target && root.target.elements) {
234
234
  const base = getTargetAspectBase(root);
235
235
  if (base && (base.elements || typeof base === 'string' && csn.definitions[base].kind === 'aspect')) {
@@ -324,7 +324,7 @@ module.exports = (csn, options) => {
324
324
  * of the `member`
325
325
  * @param {object} [force=null] Overwrite any member propagation rules or any except and always propagate the corresponding keys
326
326
  */
327
- function propagateMemberPropsFromOrigin(member, except = null, force = null) {
327
+ function propagateMemberPropsFromOrigin( member, except = null, force = null ) {
328
328
  const memberChain = getOriginChain(member);
329
329
  const virtualOrigin = Object.create(null); // To collect stuff across the origin chain - currently only for .items via type-of
330
330
 
@@ -359,7 +359,7 @@ module.exports = (csn, options) => {
359
359
  * @returns {boolean} whether props from the members origin should be propagated
360
360
  * @todo check if still necessary
361
361
  */
362
- function skipMemberPropagation(origin) {
362
+ function skipMemberPropagation( origin ) {
363
363
  // For empty members (`{}`), the origin was set in a previous call to `getOrigin(definition)`.
364
364
  return !origin;
365
365
  }
@@ -374,7 +374,7 @@ module.exports = (csn, options) => {
374
374
  * @param {CSN.Element} target
375
375
  * @param {CSN.Element} source
376
376
  */
377
- function onlyWithTypeRef(prop, target, source) {
377
+ function onlyWithTypeRef( prop, target, source ) {
378
378
  const typeIsTypeRef = Boolean(typeof target.type === 'object' && target.type.ref);
379
379
  if (typeIsTypeRef) {
380
380
  const referencedArtifact = csn.definitions[target.type.ref[0]];
@@ -390,7 +390,7 @@ module.exports = (csn, options) => {
390
390
  *
391
391
  * @param {object} art Target object for propagation
392
392
  */
393
- function propagateOnArtifactLevel(art) {
393
+ function propagateOnArtifactLevel( art ) {
394
394
  // check if art was already processed by the status flag
395
395
  // TODO: clean up later on, together with validator clean up probably or
396
396
  // when this module is meant to be used standalone -> use internal cache to store already processed definitions?
@@ -407,7 +407,7 @@ module.exports = (csn, options) => {
407
407
  * @param {CSN.Element} targetsOrigin
408
408
  * @param {CSN.Element} rootOrigin
409
409
  */
410
- function definitionPropagation(targetDefinition, targetsOrigin, rootOrigin) {
410
+ function definitionPropagation( targetDefinition, targetsOrigin, rootOrigin ) {
411
411
  // if target was already processed -> continue
412
412
  if (targetDefinition._status === 'propagated')
413
413
  return;
@@ -430,7 +430,7 @@ module.exports = (csn, options) => {
430
430
  * @param {CSN.Definition|CSN.Element} source
431
431
  * @param {CSN.Definition|CSN.Element} root
432
432
  */
433
- function propagateDefProps(definition, source, root) {
433
+ function propagateDefProps( definition, source, root ) {
434
434
  copyProperties(source, definition, getDefinitionPropagationRuleFor);
435
435
  // If $origin is an object, it is the anonymous prototype of `definition`
436
436
  // e.g. for structure includes annotations are part of the $origin object and must be copied over to the `definition`
@@ -454,7 +454,7 @@ module.exports = (csn, options) => {
454
454
  * @param {CSN.Artifact|CSN.Element} start
455
455
  * @returns {CSN.Artifact|CSN.Element|null} Null if no origin with .elements was found
456
456
  */
457
- function getFirstOriginWithElements(start) {
457
+ function getFirstOriginWithElements( start ) {
458
458
  let target = start;
459
459
  let firstOriginWithElements;
460
460
  do {
@@ -479,7 +479,7 @@ module.exports = (csn, options) => {
479
479
  * @returns {object[]} chain of origin - target
480
480
  * @todo Optimize: Only return the chain until the first propagated thing?
481
481
  */
482
- function getOriginChain(start) {
482
+ function getOriginChain( start ) {
483
483
  const chain = [];
484
484
  let target = start;
485
485
  let origin;
@@ -504,7 +504,7 @@ module.exports = (csn, options) => {
504
504
  * @param {CSN.Query} query
505
505
  * @param {CSN.Artifact} artifact
506
506
  */
507
- function propagateToPublishedMixin(query, artifact) {
507
+ function propagateToPublishedMixin( query, artifact ) {
508
508
  const elements = query.SELECT.elements || artifact.elements;
509
509
  forEachValue(elements, (element) => {
510
510
  if (element.target) {
@@ -520,7 +520,7 @@ module.exports = (csn, options) => {
520
520
  /**
521
521
  * @param {CSN.Element} member
522
522
  */
523
- function calculateForeignKeys(member) {
523
+ function calculateForeignKeys( member ) {
524
524
  // managed assocs in universal CSN have no longer keys
525
525
  // if they are not explicitly defined - PR#8064
526
526
  const target = artifactRef(member.target);
@@ -538,7 +538,7 @@ module.exports = (csn, options) => {
538
538
  * @param {CSN.Definition} target
539
539
  * @param {CSN.Definition} source
540
540
  */
541
- function onlyViaArtifact(prop, target, source) {
541
+ function onlyViaArtifact( prop, target, source ) {
542
542
  if (!target.kind)
543
543
  return;
544
544
  const primarySourceRef = getQueryPrimarySource(target.query || target.projection);
@@ -553,7 +553,7 @@ module.exports = (csn, options) => {
553
553
  * @param {string} key identifier of the csn prop we are looking for
554
554
  * @returns {Function} which can be used to apply custom propagation rules for certain props
555
555
  */
556
- function getMemberPropagationRuleFor(key) {
556
+ function getMemberPropagationRuleFor( key ) {
557
557
  return memberPropagationRules[key] || memberPropagationRules[key.charAt(0)] || getDefinitionPropagationRuleFor(key);
558
558
  }
559
559
 
@@ -563,7 +563,7 @@ module.exports = (csn, options) => {
563
563
  * @param {string} key identifier of the csn prop we are looking for
564
564
  * @returns {Function} which can be used to apply custom propagation rules for certain props
565
565
  */
566
- function getDefinitionPropagationRuleFor(key) {
566
+ function getDefinitionPropagationRuleFor( key ) {
567
567
  return definitionPropagationRules[key] || definitionPropagationRules[key.charAt(0)];
568
568
  }
569
569
 
@@ -573,7 +573,7 @@ module.exports = (csn, options) => {
573
573
  * @param {CSN.Artifact} parent
574
574
  * @param {CSN.Artifact} rootArtifact The artifact that had the localized
575
575
  */
576
- function attachAnnosForTextsTable(parent, rootArtifact) {
576
+ function attachAnnosForTextsTable( parent, rootArtifact ) {
577
577
  const isFioriDraftEnabled = rootArtifact && (rootArtifact['@fiori.draft.enabled'] === true || getOriginChain(rootArtifact).some(({ origin }) => origin['@fiori.draft.enabled'] === true));
578
578
  if (isFioriDraftEnabled) {
579
579
  setAnnotationIfNotDefined(parent, '@assert.unique.locale', [ { '=': 'locale' } ]);
@@ -606,7 +606,7 @@ module.exports = (csn, options) => {
606
606
  * @param {object} [except=null] array of properties which should not be propagated
607
607
  * @param {object} [force=null] Force propagation of the contained keys via a custom rule.
608
608
  */
609
- function copyProperties(from, to, getCustomRule, except = null, force = null) {
609
+ function copyProperties( from, to, getCustomRule, except = null, force = null ) {
610
610
  const keys = Object.keys(from);
611
611
  // Copy over properties from the origin element to the target.
612
612
  for (const key of keys) {
@@ -626,7 +626,7 @@ function copyProperties(from, to, getCustomRule, except = null, force = null) {
626
626
  * @param {object} elements
627
627
  * @returns {boolean} whether some element in the elements has an annotation
628
628
  */
629
- function hasAnnotationOnSubelement(elements) {
629
+ function hasAnnotationOnSubelement( elements ) {
630
630
  for (const element of Object.values(elements)) {
631
631
  if (Object.keys(element).some(key => key.startsWith('@')))
632
632
  return true;
@@ -654,7 +654,7 @@ function skip() {
654
654
  * @param {object} target
655
655
  * @param {object} source
656
656
  */
657
- function always(prop, target, source) {
657
+ function always( prop, target, source ) {
658
658
  const val = source[prop];
659
659
  if (Array.isArray(val))
660
660
  target[prop] = [ ...val ];
@@ -669,7 +669,7 @@ function always(prop, target, source) {
669
669
  * @param {CSN.Definition} target
670
670
  * @param {CSN.Definition} source
671
671
  */
672
- function onlyTypeDef(prop, target, source) {
672
+ function onlyTypeDef( prop, target, source ) {
673
673
  if (target.kind !== 'type')
674
674
  return;
675
675
  target[prop] = source[prop];
@@ -684,7 +684,7 @@ function onlyTypeDef(prop, target, source) {
684
684
  * @param {object} target
685
685
  * @param {object} source
686
686
  */
687
- function notWithPersistenceTable(prop, target, source) {
687
+ function notWithPersistenceTable( prop, target, source ) {
688
688
  const tableAnno = target['@cds.persistence.table'];
689
689
  if (tableAnno === undefined || tableAnno === null)
690
690
  target[prop] = source[prop];
@@ -699,7 +699,7 @@ function notWithPersistenceTable(prop, target, source) {
699
699
  * @param {CSN.Element} target
700
700
  * @param {CSN.Element} source
701
701
  */
702
- function notWithTypeOrigin(prop, target, source) {
702
+ function notWithTypeOrigin( prop, target, source ) {
703
703
  if (source.kind !== 'type')
704
704
  target[prop] = source[prop];
705
705
  }
@@ -712,7 +712,7 @@ function notWithTypeOrigin(prop, target, source) {
712
712
  * @param {CSN.Element} target
713
713
  * @param {CSN.Element} source
714
714
  */
715
- function nullStopsPropagation(prop, target, source) {
715
+ function nullStopsPropagation( prop, target, source ) {
716
716
  if (source[prop] !== null)
717
717
  target[prop] = source[prop];
718
718
  }
@@ -732,7 +732,7 @@ function nullStopsPropagation(prop, target, source) {
732
732
  * @param {CSN.Element} target
733
733
  * @param {CSN.Element} source
734
734
  */
735
- function specialItemsRules(prop, target, source) {
735
+ function specialItemsRules( prop, target, source ) {
736
736
  if (source.kind !== 'type' && ((!source.type && !target.type) || !(source[prop].type && source[prop].type.ref || !isBuiltinType(source[prop].type))))
737
737
  target[prop] = source[prop];
738
738
  }
@@ -746,7 +746,7 @@ function specialItemsRules(prop, target, source) {
746
746
  * @param {CSN.Element} target
747
747
  * @param {CSN.Element} source
748
748
  */
749
- function notWithItemsOrElements(prop, target, source) {
749
+ function notWithItemsOrElements( prop, target, source ) {
750
750
  if (!target.items && !target.elements || !source.target)
751
751
  target[prop] = source[prop];
752
752
  }
@@ -759,7 +759,7 @@ function notWithItemsOrElements(prop, target, source) {
759
759
  * @param {CSN.Element} target
760
760
  * @param {CSN.Element} source
761
761
  */
762
- function notWithTypeRef(prop, target, source) {
762
+ function notWithTypeRef( prop, target, source ) {
763
763
  const typeIsTypeRef = Boolean(typeof target.type === 'object' && target.type.ref);
764
764
  if (!typeIsTypeRef)
765
765
  target[prop] = source[prop];
@@ -12,7 +12,7 @@ const { setProp } = require('../../base/model');
12
12
  * @param {string} name Name of the annotations
13
13
  * @param {any} value Value of the annotation
14
14
  */
15
- function setAnnotationIfNotDefined(carrier, name, value) {
15
+ function setAnnotationIfNotDefined( carrier, name, value ) {
16
16
  if (carrier[name] === undefined)
17
17
  carrier[name] = value;
18
18
  }
@@ -26,7 +26,7 @@ function setAnnotationIfNotDefined(carrier, name, value) {
26
26
  *
27
27
  * @param {CSN.Model} csn
28
28
  */
29
- function makeClientCompatible(csn) {
29
+ function makeClientCompatible( csn ) {
30
30
  applyTransformations(csn, {
31
31
  actions: removeNullProperty,
32
32
  notNull: removeNullProperty,
@@ -52,7 +52,7 @@ function makeClientCompatible(csn) {
52
52
  * @param {object} node
53
53
  * @param {string} prop
54
54
  */
55
- function removeNullProperty(node, prop) {
55
+ function removeNullProperty( node, prop ) {
56
56
  if (node[prop] === null)
57
57
  delete node[prop];
58
58
  }
package/lib/utils/file.js CHANGED
@@ -12,7 +12,7 @@ const util = require('util');
12
12
  * @param {string} src
13
13
  * @returns {string[]}
14
14
  */
15
- function splitLines(src) {
15
+ function splitLines( src ) {
16
16
  return src.split(/\r\n?|\n/);
17
17
  }
18
18
 
@@ -27,7 +27,7 @@ function splitLines(src) {
27
27
  * @param {object} fileCache
28
28
  * @param {boolean} enableTrace
29
29
  */
30
- function cdsFs(fileCache, enableTrace) {
30
+ function cdsFs( fileCache, enableTrace ) {
31
31
  const readFile = _wrapReadFileCached(fs.readFile);
32
32
  const readFileSync = _wrapReadFileCached((filename, enc, cb) => {
33
33
  try {
@@ -60,11 +60,11 @@ function cdsFs(fileCache, enableTrace) {
60
60
  realpathSync,
61
61
  };
62
62
 
63
- function realpath(path, cb) {
63
+ function realpath( path, cb ) {
64
64
  return fs.realpath.native(path, cb);
65
65
  }
66
66
 
67
- function realpathSync(path, cb) {
67
+ function realpathSync( path, cb ) {
68
68
  try {
69
69
  cb(null, fs.realpathSync.native(path));
70
70
  }
@@ -133,7 +133,7 @@ function cdsFs(fileCache, enableTrace) {
133
133
  *
134
134
  * @param {(filename: string, cb: (err, data) => void) => void} fsStat
135
135
  */
136
- function _wrapIsFileCached(fsStat) {
136
+ function _wrapIsFileCached( fsStat ) {
137
137
  return ( filename, cb ) => {
138
138
  let body = fileCache[filename];
139
139
  if (body !== undefined) {
@@ -30,7 +30,7 @@ const extensions = [ '.cds', '.csn', '.json' ];
30
30
  * @param {CSN.Options} options
31
31
  * @returns {string}
32
32
  */
33
- function adaptCdsModule(modulePath, options = {}) {
33
+ function adaptCdsModule( modulePath, options = {} ) {
34
34
  if (modulePath.startsWith( '@sap/cds/' )) {
35
35
  if (options.cdsHome)
36
36
  return options.cdsHome + modulePath.slice(8);
@@ -166,7 +166,7 @@ function resolveModuleSync( dep, fileCache, options, messageFunctions ) {
166
166
  return result;
167
167
  }
168
168
 
169
- function _errorFileNotFound(dep, options, { error }) {
169
+ function _errorFileNotFound( dep, options, { error } ) {
170
170
  if (dep.resolved) {
171
171
  let resolved = path.relative( dep.basedir, dep.resolved );
172
172
  if (options.testMode)
@@ -204,7 +204,7 @@ function _errorFileNotFound(dep, options, { error }) {
204
204
  * @param {ResolveOptions} options
205
205
  * @param {(err, result) => void} callback
206
206
  */
207
- function resolveCDS(moduleName, options, callback) {
207
+ function resolveCDS( moduleName, options, callback ) {
208
208
  const isWindows = (process.platform === 'win32');
209
209
  let resolvedBaseDir = path.resolve(options.basedir);
210
210
 
@@ -252,7 +252,7 @@ function resolveCDS(moduleName, options, callback) {
252
252
  * @param {string} absoluteModulePath
253
253
  * @param {(err, filepath: string|null) => void} cb
254
254
  */
255
- function loadAsLocalFileOrDirectory(absoluteModulePath, cb) {
255
+ function loadAsLocalFileOrDirectory( absoluteModulePath, cb ) {
256
256
  loadAsFile(absoluteModulePath, (err, filepath) => {
257
257
  if (!err && filepath)
258
258
  cb(null, filepath);
@@ -268,7 +268,7 @@ function resolveCDS(moduleName, options, callback) {
268
268
  * @param {string} absoluteModulePath
269
269
  * @param {(err, filepath: string|null) => void} cb
270
270
  */
271
- function loadAsFile(absoluteModulePath, cb) {
271
+ function loadAsFile( absoluteModulePath, cb ) {
272
272
  const extensionsToTry = [ '' ].concat(options.extensions);
273
273
  loadFileWithExtensions(extensionsToTry);
274
274
 
@@ -277,7 +277,7 @@ function resolveCDS(moduleName, options, callback) {
277
277
  *
278
278
  * @param {string[]} exts The extensions to try. Loaded in the order of the array.
279
279
  */
280
- function loadFileWithExtensions(exts) {
280
+ function loadFileWithExtensions( exts ) {
281
281
  if (exts.length === 0) {
282
282
  // If we reach this point then no file with the given extensions could be found.
283
283
  cb(makeNotFoundError(), null);
@@ -300,7 +300,7 @@ function resolveCDS(moduleName, options, callback) {
300
300
  * @param {string} absoluteModulePath
301
301
  * @param {(err, filepath: string|null) => void} cb
302
302
  */
303
- function loadAsDirectory(absoluteModulePath, cb) {
303
+ function loadAsDirectory( absoluteModulePath, cb ) {
304
304
  loadAndParsePackageJsonInDirectory(absoluteModulePath, (packageErr, packageJson) => {
305
305
  const main = packageCdsMain(packageJson);
306
306
  if (!packageErr && main)
@@ -309,7 +309,7 @@ function resolveCDS(moduleName, options, callback) {
309
309
  loadIndex();
310
310
  });
311
311
 
312
- function loadMain(main) {
312
+ function loadMain( main ) {
313
313
  const file = path.join(absoluteModulePath, main);
314
314
  loadAsFile(file, (fileErr, filePath) => {
315
315
  if (!fileErr && filePath)
@@ -337,11 +337,11 @@ function resolveCDS(moduleName, options, callback) {
337
337
  *
338
338
  * @param {string} absoluteDir
339
339
  */
340
- function loadNodeModules(absoluteDir) {
340
+ function loadNodeModules( absoluteDir ) {
341
341
  const dirs = nodeModulesPaths(absoluteDir);
342
342
  loadFromNodeDirs(dirs);
343
343
 
344
- function loadFromNodeDirs(nodeDirs) {
344
+ function loadFromNodeDirs( nodeDirs ) {
345
345
  const dir = nodeDirs.shift();
346
346
  if (!dir) {
347
347
  // We're at root
@@ -365,7 +365,7 @@ function resolveCDS(moduleName, options, callback) {
365
365
  * @param {string} packageDir
366
366
  * @param {(err, json) => void} cb
367
367
  */
368
- function loadAndParsePackageJsonInDirectory(packageDir, cb) {
368
+ function loadAndParsePackageJsonInDirectory( packageDir, cb ) {
369
369
  const file = path.join(packageDir, 'package.json');
370
370
 
371
371
  options.readFile(file, DEFAULT_ENCODING, (err, content) => {
@@ -390,7 +390,7 @@ function resolveCDS(moduleName, options, callback) {
390
390
  * @param {string} absoluteStart
391
391
  * @returns {string[]} Array of possible "node_modules" folders for the given path.
392
392
  */
393
- function nodeModulesPaths(absoluteStart) {
393
+ function nodeModulesPaths( absoluteStart ) {
394
394
  // Use platform-dependent separator. All NodeJS `path` methods use the system's path separator.
395
395
  const parts = absoluteStart.split(path.sep);
396
396
  // Do NOT use global node_modules directories.
@@ -429,7 +429,7 @@ function resolveCDS(moduleName, options, callback) {
429
429
  *
430
430
  * @param {string} moduleName
431
431
  */
432
- function isLocalFile(moduleName) {
432
+ function isLocalFile( moduleName ) {
433
433
  // Starts with or is equal to '..'
434
434
  // Starts with '/'
435
435
  // Starts with 'C:/' or 'C:\'