@sap/cds-compiler 2.13.8 → 3.0.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +155 -1594
  2. package/bin/cdsc.js +144 -66
  3. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  4. package/doc/CHANGELOG_BETA.md +3 -4
  5. package/doc/CHANGELOG_DEPRECATED.md +35 -1
  6. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  7. package/doc/Versioning.md +20 -1
  8. package/lib/api/.eslintrc.json +2 -2
  9. package/lib/api/main.js +237 -122
  10. package/lib/api/options.js +17 -88
  11. package/lib/api/validate.js +12 -16
  12. package/lib/base/keywords.js +216 -109
  13. package/lib/base/message-registry.js +152 -37
  14. package/lib/base/messages.js +145 -83
  15. package/lib/base/model.js +44 -2
  16. package/lib/base/optionProcessorHelper.js +19 -0
  17. package/lib/checks/actionsFunctions.js +7 -5
  18. package/lib/checks/annotationsOData.js +11 -32
  19. package/lib/checks/arrayOfs.js +1 -34
  20. package/lib/checks/cdsPersistence.js +1 -0
  21. package/lib/checks/elements.js +6 -6
  22. package/lib/checks/invalidTarget.js +1 -1
  23. package/lib/checks/nonexpandableStructured.js +1 -1
  24. package/lib/checks/queryNoDbArtifacts.js +2 -1
  25. package/lib/checks/selectItems.js +5 -1
  26. package/lib/checks/types.js +4 -2
  27. package/lib/checks/utils.js +2 -2
  28. package/lib/checks/validator.js +4 -5
  29. package/lib/compiler/assert-consistency.js +16 -10
  30. package/lib/compiler/base.js +1 -0
  31. package/lib/compiler/builtins.js +98 -9
  32. package/lib/compiler/checks.js +22 -70
  33. package/lib/compiler/define.js +61 -13
  34. package/lib/compiler/extend.js +79 -14
  35. package/lib/compiler/finalize-parse-cdl.js +46 -29
  36. package/lib/compiler/index.js +100 -37
  37. package/lib/compiler/moduleLayers.js +7 -0
  38. package/lib/compiler/populate.js +19 -18
  39. package/lib/compiler/propagator.js +7 -4
  40. package/lib/compiler/resolve.js +297 -234
  41. package/lib/compiler/shared.js +107 -102
  42. package/lib/compiler/tweak-assocs.js +16 -11
  43. package/lib/compiler/utils.js +5 -0
  44. package/lib/edm/annotations/genericTranslation.js +93 -21
  45. package/lib/edm/csn2edm.js +230 -115
  46. package/lib/edm/edm.js +305 -226
  47. package/lib/edm/edmPreprocessor.js +509 -438
  48. package/lib/edm/edmUtils.js +31 -45
  49. package/lib/gen/Dictionary.json +98 -22
  50. package/lib/gen/language.checksum +1 -1
  51. package/lib/gen/language.interp +10 -30
  52. package/lib/gen/language.tokens +105 -114
  53. package/lib/gen/languageLexer.interp +1 -34
  54. package/lib/gen/languageLexer.js +889 -1007
  55. package/lib/gen/languageLexer.tokens +95 -106
  56. package/lib/gen/languageParser.js +20786 -22199
  57. package/lib/json/csnVersion.js +10 -11
  58. package/lib/json/from-csn.js +59 -51
  59. package/lib/json/to-csn.js +10 -10
  60. package/lib/language/antlrParser.js +2 -2
  61. package/lib/language/docCommentParser.js +62 -39
  62. package/lib/language/errorStrategy.js +52 -40
  63. package/lib/language/genericAntlrParser.js +348 -229
  64. package/lib/language/language.g4 +629 -653
  65. package/lib/language/multiLineStringParser.js +14 -42
  66. package/lib/language/textUtils.js +44 -0
  67. package/lib/main.d.ts +46 -43
  68. package/lib/main.js +108 -79
  69. package/lib/model/csnRefs.js +34 -7
  70. package/lib/model/csnUtils.js +337 -332
  71. package/lib/model/enrichCsn.js +1 -0
  72. package/lib/model/revealInternalProperties.js +30 -10
  73. package/lib/model/sortViews.js +32 -31
  74. package/lib/modelCompare/compare.js +6 -6
  75. package/lib/optionProcessor.js +73 -46
  76. package/lib/render/.eslintrc.json +1 -1
  77. package/lib/render/DuplicateChecker.js +4 -7
  78. package/lib/render/manageConstraints.js +70 -2
  79. package/lib/render/toCdl.js +1042 -882
  80. package/lib/render/toHdbcds.js +195 -245
  81. package/lib/render/toRename.js +44 -22
  82. package/lib/render/toSql.js +225 -241
  83. package/lib/render/utils/common.js +145 -15
  84. package/lib/render/utils/sql.js +20 -19
  85. package/lib/sql-identifier.js +6 -0
  86. package/lib/transform/db/.eslintrc.json +4 -3
  87. package/lib/transform/db/associations.js +2 -2
  88. package/lib/transform/db/cdsPersistence.js +5 -15
  89. package/lib/transform/db/constraints.js +4 -2
  90. package/lib/transform/db/expansion.js +22 -16
  91. package/lib/transform/db/flattening.js +109 -80
  92. package/lib/transform/db/transformExists.js +7 -7
  93. package/lib/transform/db/views.js +9 -6
  94. package/lib/transform/draft/.eslintrc.json +2 -2
  95. package/lib/transform/draft/db.js +6 -6
  96. package/lib/transform/draft/odata.js +6 -7
  97. package/lib/transform/forHanaNew.js +62 -48
  98. package/lib/transform/forOdataNew.js +49 -50
  99. package/lib/transform/localized.js +31 -20
  100. package/lib/transform/odata/toFinalBaseType.js +16 -14
  101. package/lib/transform/odata/typesExposure.js +146 -198
  102. package/lib/transform/odata/utils.js +1 -38
  103. package/lib/transform/transformUtilsNew.js +67 -84
  104. package/lib/transform/translateAssocsToJoins.js +7 -3
  105. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  106. package/lib/transform/universalCsn/coreComputed.js +16 -9
  107. package/lib/transform/universalCsn/universalCsnEnricher.js +60 -10
  108. package/lib/utils/file.js +3 -3
  109. package/lib/utils/moduleResolve.js +13 -6
  110. package/lib/utils/timetrace.js +20 -21
  111. package/package.json +35 -4
  112. package/share/messages/message-explanations.json +2 -1
  113. package/share/messages/syntax-expected-integer.md +37 -0
  114. package/doc/ApiMigration.md +0 -237
  115. package/doc/CommandLineMigration.md +0 -58
  116. package/doc/ErrorMessages.md +0 -175
  117. package/doc/FioriAnnotations.md +0 -94
  118. package/doc/ODataTransformation.md +0 -273
  119. package/lib/backends.js +0 -529
  120. package/lib/fix_antlr4-8_warning.js +0 -56
  121. package/lib/transform/odata/attachPath.js +0 -96
  122. package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
  123. package/lib/transform/odata/generateForeignKeyElements.js +0 -261
  124. package/lib/transform/odata/referenceFlattener.js +0 -296
  125. package/lib/transform/odata/sortByAssociationDependency.js +0 -105
  126. package/lib/transform/odata/structuralPath.js +0 -72
  127. package/lib/transform/odata/structureFlattener.js +0 -171
@@ -24,7 +24,7 @@ const publicOptionsNewAPI = [
24
24
  'sqlChangeMode',
25
25
  'allowCsnDowngrade',
26
26
  'joinfk',
27
- 'magicVars', // deprecated
27
+ 'magicVars', // deprecated, not removed in v3 as we have specific error messages for it
28
28
  'variableReplacements',
29
29
  // ODATA
30
30
  'odataVersion',
@@ -80,13 +80,12 @@ const overallOptions = publicOptionsNewAPI.concat(privateOptions);
80
80
  function translateOptions(input = {}, defaults = {}, hardRequire = {},
81
81
  customValidators = {}, combinationValidators = [], moduleName = '') {
82
82
  const options = Object.assign({}, defaults);
83
- const inputOptionNames = Object.keys(input);
84
83
  for (const name of overallOptions) {
85
84
  // Ensure that arrays are not passed as a reference!
86
85
  // This caused issues with the way messages are handled in processMessages
87
- if (Array.isArray(input[name]) && inputOptionNames.includes(name))
86
+ if (Array.isArray(input[name]))
88
87
  options[name] = [ ...input[name] ];
89
- else if (inputOptionNames.includes(name))
88
+ else if (Object.hasOwnProperty.call(input, name))
90
89
  options[name] = input[name];
91
90
  }
92
91
 
@@ -108,47 +107,10 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
108
107
  // Overwrite with the hardRequire options - like src: sql in to.sql()
109
108
  Object.assign(options, hardRequire);
110
109
 
111
- for (const optionName in options) {
112
- const optionValue = options[optionName];
113
- mapToOldNames(optionName, optionValue);
114
- }
115
-
116
110
  // Convenience for $user -> $user.id replacement
117
111
  if (options.variableReplacements && options.variableReplacements.$user && typeof options.variableReplacements.$user === 'string')
118
112
  options.variableReplacements.$user = { id: options.variableReplacements.$user };
119
113
 
120
- /**
121
- * Map a new-style option to it's old format
122
- *
123
- * @param {string} optionName Name of the option to map
124
- * @param {any} optionValue Value of the option to map
125
- */
126
- function mapToOldNames(optionName, optionValue) {
127
- // Keep all input options and add the "compatibility" options
128
- switch (optionName) {
129
- case 'beta':
130
- options.betaMode = optionValue;
131
- break;
132
- case 'odataVersion':
133
- options.version = optionValue;
134
- break;
135
- case 'sqlDialect':
136
- options.dialect = optionValue;
137
- break;
138
- case 'sqlMapping':
139
- options.names = optionValue;
140
- break;
141
- // No need to remap variableReplacements here - we use the new mechanism with that directly
142
- case 'magicVars':
143
- if (optionValue.user)
144
- options.user = optionValue.user;
145
- if (optionValue.locale)
146
- options.locale = optionValue.locale;
147
- break;
148
- default: break;
149
- }
150
- }
151
-
152
114
  return options;
153
115
  }
154
116
 
@@ -156,78 +118,45 @@ module.exports = {
156
118
  to: {
157
119
  cdl: options => translateOptions(options, undefined, undefined, undefined, undefined, 'to.cdl'),
158
120
  sql: (options) => {
159
- const hardOptions = { src: 'sql' };
121
+ const hardOptions = { src: 'sql', toSql: true, forHana: true };
160
122
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'plain' };
161
123
  const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ], 'to.sql');
162
124
 
163
- const result = Object.assign({}, processed);
164
- result.toSql = Object.assign({}, processed);
165
-
166
- return result;
125
+ return Object.assign({}, processed);
167
126
  },
168
127
  hdi: (options) => {
169
- const hardOptions = { src: 'hdi' };
128
+ const hardOptions = { src: 'hdi', toSql: true, forHana: true };
170
129
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
171
- const processed = translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
172
-
173
- const result = Object.assign({}, processed);
174
- result.toSql = Object.assign({}, processed);
175
-
176
- return result;
130
+ return translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
177
131
  },
178
132
  hdbcds: (options) => {
133
+ const hardOptions = { forHana: true };
179
134
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
180
- const processed = translateOptions(options, defaultOptions, {}, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdbcds');
181
-
182
- const result = Object.assign({}, processed);
183
- result.forHana = Object.assign({}, processed);
184
-
185
- return result;
135
+ return translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdbcds');
186
136
  },
187
137
  edm: (options) => {
188
- const hardOptions = { json: true, combined: true };
138
+ const hardOptions = { json: true, combined: true, toOdata: true };
189
139
  const defaultOptions = { odataVersion: 'v4', odataFormat: 'flat' };
190
- const processed = translateOptions(options, defaultOptions, hardOptions, { odataVersion: generateStringValidator([ 'v4' ]) }, [ 'valid-structured' ], 'to.edm');
191
-
192
- const result = Object.assign({}, processed);
193
- result.toOdata = Object.assign({}, processed);
194
-
195
- return result;
140
+ return translateOptions(options, defaultOptions, hardOptions, { odataVersion: generateStringValidator([ 'v4' ]) }, [ 'valid-structured' ], 'to.edm');
196
141
  },
197
142
  edmx: (options) => {
198
- const hardOptions = { xml: true, combined: true };
143
+ const hardOptions = { xml: true, combined: true, toOdata: true };
199
144
  const defaultOptions = {
200
145
  odataVersion: 'v4', odataFormat: 'flat',
201
146
  };
202
- const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'to.edmx');
203
-
204
- const result = Object.assign({}, processed);
205
- result.toOdata = Object.assign({}, processed);
206
-
207
- return result;
147
+ return translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'to.edmx');
208
148
  },
209
149
  },
210
150
  for: { // TODO: Rename version to oDataVersion
211
-
212
151
  odata: (options) => {
152
+ const hardOptions = { toOdata: true };
213
153
  const defaultOptions = { odataVersion: 'v4', odataFormat: 'flat' };
214
- const processed = translateOptions(options, defaultOptions, undefined, undefined, [ 'valid-structured' ], 'for.odata');
215
-
216
- const result = Object.assign({}, processed);
217
- result.toOdata = Object.assign({}, processed);
218
-
219
-
220
- return result;
154
+ return translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'for.odata');
221
155
  },
222
156
  hana: (options) => {
157
+ const hardOptions = { forHana: true };
223
158
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
224
- const processed = translateOptions(options, defaultOptions, undefined, undefined, undefined, 'for.hana');
225
-
226
- const result = Object.assign({}, processed);
227
- result.forHana = Object.assign({}, processed);
228
-
229
-
230
- return result;
159
+ return translateOptions(options, defaultOptions, hardOptions, undefined, undefined, 'for.hana');
231
160
  },
232
161
  },
233
162
  };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { makeMessageFunction } = require('../base/messages');
4
+ const { forEach } = require('../utils/objectUtils');
4
5
 
5
6
  /* eslint-disable arrow-body-style */
6
7
  const booleanValidator = {
@@ -64,13 +65,6 @@ const validators = {
64
65
  return val === null ? val : `type ${ typeof val }`;
65
66
  },
66
67
  },
67
- magicVars: {
68
- validate: val => val !== null && typeof val === 'object' && !Array.isArray(val),
69
- expected: () => 'type object',
70
- found: (val) => {
71
- return val === null ? val : `type ${ typeof val }`;
72
- },
73
- },
74
68
  // TODO: Maybe do a deep validation of the whole object with leafs?
75
69
  variableReplacements: {
76
70
  validate: val => val !== null && typeof val === 'object' && !Array.isArray(val),
@@ -84,7 +78,7 @@ const validators = {
84
78
  expected: () => 'type array',
85
79
  found: val => `type ${ typeof val }`,
86
80
  },
87
- sqlDialect: generateStringValidator([ 'sqlite', 'hana', 'plain' ]),
81
+ sqlDialect: generateStringValidator([ 'sqlite', 'hana', 'plain', 'postgres' ]),
88
82
  sqlMapping: generateStringValidator([ 'plain', 'quoted', 'hdbcds' ]),
89
83
  odataVersion: generateStringValidator([ 'v2', 'v4' ]),
90
84
  odataFormat: generateStringValidator([ 'flat', 'structured' ]),
@@ -130,16 +124,19 @@ const allCombinationValidators = {
130
124
  'valid-structured': {
131
125
  validate: options => options.odataVersion === 'v2' && options.odataFormat === 'structured',
132
126
  severity: 'error',
127
+ getParameters: () => {},
133
128
  getMessage: () => 'Structured OData is only supported with OData version v4',
134
129
  },
135
130
  'sql-dialect-and-naming': {
136
131
  validate: options => options.sqlDialect && options.sqlMapping && ![ 'hana' ].includes(options.sqlDialect) && [ 'quoted', 'hdbcds' ].includes(options.sqlMapping),
137
132
  severity: 'error',
138
- getMessage: options => `sqlDialect '${ options.sqlDialect }' can't be combined with sqlMapping '${ options.sqlMapping }'`,
133
+ getParameters: options => ({ name: options.sqlDialect, prop: options.sqlMapping }),
134
+ getMessage: () => 'sqlDialect $(NAME) can\'t be combined with sqlMapping $(PROP)',
139
135
  },
140
136
  'beta-no-test': {
141
137
  validate: options => options.beta && !options.testMode,
142
138
  severity: 'warning',
139
+ getParameters: () => {},
143
140
  getMessage: () => 'Option "beta" was used. This option should not be used in productive scenarios!',
144
141
  },
145
142
  };
@@ -159,16 +156,15 @@ function validate(options, moduleName, customValidators = {}, combinationValidat
159
156
  // TODO: issuing messages in this function looks very strange...
160
157
  {
161
158
  const messageCollector = { messages: [] };
162
- const { error, throwWithError } = makeMessageFunction(null, messageCollector, moduleName);
159
+ const { error, throwWithAnyError } = makeMessageFunction(null, messageCollector, moduleName);
163
160
 
164
- for (const optionName of Object.keys(options)) {
165
- const optionValue = options[optionName];
161
+ forEach(options, (optionName, optionValue) => {
166
162
  const validator = customValidators[optionName] || validators[optionName] || booleanValidator;
167
163
 
168
164
  if (!validator.validate(optionValue))
169
165
  error('invalid-option', null, {}, `Expected option "${ optionName }" to have "${ validator.expected(optionValue) }". Found: "${ validator.found(optionValue) }"`);
170
- }
171
- throwWithError();
166
+ });
167
+ throwWithAnyError();
172
168
  }
173
169
 
174
170
  const message = makeMessageFunction(null, options, moduleName);
@@ -176,10 +172,10 @@ function validate(options, moduleName, customValidators = {}, combinationValidat
176
172
  for (const combinationValidatorName of combinationValidators.concat([ 'beta-no-test' ])) {
177
173
  const combinationValidator = allCombinationValidators[combinationValidatorName];
178
174
  if (combinationValidator.validate(options))
179
- message[combinationValidator.severity]('invalid-option-combination', null, {}, combinationValidator.getMessage(options));
175
+ message[combinationValidator.severity]('invalid-option-combination', null, combinationValidator.getParameters(options), combinationValidator.getMessage(options));
180
176
  }
181
177
 
182
- message.throwWithError();
178
+ message.throwWithAnyError();
183
179
  }
184
180
  /* eslint-enable jsdoc/no-undefined-types */
185
181