@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.
- package/CHANGELOG.md +58 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +58 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +124 -28
- package/lib/base/messages.js +247 -179
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +1 -1
- package/lib/compiler/assert-consistency.js +0 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +73 -15
- package/lib/compiler/define.js +3 -7
- package/lib/compiler/extend.js +212 -32
- package/lib/compiler/finalize-parse-cdl.js +7 -2
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +2 -5
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/shared.js +23 -12
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +6 -0
- package/lib/edm/annotations/genericTranslation.js +553 -319
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +88 -75
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +5 -5
- package/lib/edm/edmPreprocessor.js +106 -76
- package/lib/edm/edmUtils.js +41 -2
- package/lib/gen/Dictionary.json +34 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +66 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14360 -14146
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +82 -40
- package/lib/json/to-csn.js +82 -157
- package/lib/language/.eslintrc.json +1 -4
- package/lib/language/genericAntlrParser.js +59 -38
- package/lib/language/language.g4 +1508 -1490
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/utils/filter.js +4 -3
- package/lib/optionProcessor.js +5 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +225 -159
- package/lib/render/toHdbcds.js +63 -63
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +55 -65
- package/lib/render/utils/common.js +20 -37
- package/lib/render/utils/delta.js +3 -3
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +12 -40
- package/lib/transform/forRelationalDB.js +17 -7
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +106 -62
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -7
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Create a command line option processor and define valid commands, options and parameters.
|
|
@@ -46,7 +46,7 @@ function createOptionProcessor() {
|
|
|
46
46
|
// TODO: Why exported?
|
|
47
47
|
_parseCommandString,
|
|
48
48
|
_parseOptionString,
|
|
49
|
-
}
|
|
49
|
+
};
|
|
50
50
|
return optionProcessor;
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -55,7 +55,7 @@ function createOptionProcessor() {
|
|
|
55
55
|
* @param {string[]} [validValues] Array of valid values for the options.
|
|
56
56
|
* @param {object} [options] Further options such as `ignoreCase: true`
|
|
57
57
|
*/
|
|
58
|
-
function option(optString, validValues, options) {
|
|
58
|
+
function option( optString, validValues, options ) {
|
|
59
59
|
return _addOption(optionProcessor, optString, validValues, options);
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -63,7 +63,7 @@ function createOptionProcessor() {
|
|
|
63
63
|
* API: Define the main help text (header and general options)
|
|
64
64
|
* @param {string} text Help text describing all options, etc.
|
|
65
65
|
*/
|
|
66
|
-
function help(text) {
|
|
66
|
+
function help( text ) {
|
|
67
67
|
optionProcessor.helpText = text;
|
|
68
68
|
return optionProcessor;
|
|
69
69
|
}
|
|
@@ -72,7 +72,7 @@ function createOptionProcessor() {
|
|
|
72
72
|
* API: Define a command
|
|
73
73
|
* @param {string} cmdString Command name, short and long form, e.g. 'S, toSql'
|
|
74
74
|
*/
|
|
75
|
-
function command(cmdString) {
|
|
75
|
+
function command( cmdString ) {
|
|
76
76
|
/** @type {object} */
|
|
77
77
|
const cmd = {
|
|
78
78
|
options: {},
|
|
@@ -83,28 +83,28 @@ function createOptionProcessor() {
|
|
|
83
83
|
return cmd;
|
|
84
84
|
},
|
|
85
85
|
help: commandHelp,
|
|
86
|
-
..._parseCommandString(cmdString)
|
|
86
|
+
..._parseCommandString(cmdString),
|
|
87
87
|
};
|
|
88
|
-
if (optionProcessor.commands[cmd.longName])
|
|
89
|
-
throw new Error(`Duplicate assignment for long command ${cmd.longName}`);
|
|
90
|
-
|
|
88
|
+
if (optionProcessor.commands[cmd.longName])
|
|
89
|
+
throw new Error(`Duplicate assignment for long command ${ cmd.longName }`);
|
|
90
|
+
|
|
91
91
|
optionProcessor.commands[cmd.longName] = cmd;
|
|
92
92
|
|
|
93
93
|
if (cmd.shortName) {
|
|
94
|
-
if (optionProcessor.commands[cmd.shortName])
|
|
95
|
-
throw new Error(`Duplicate assignment for short command ${cmd.shortName}`);
|
|
96
|
-
|
|
94
|
+
if (optionProcessor.commands[cmd.shortName])
|
|
95
|
+
throw new Error(`Duplicate assignment for short command ${ cmd.shortName }`);
|
|
96
|
+
|
|
97
97
|
optionProcessor.commands[cmd.shortName] = cmd;
|
|
98
98
|
}
|
|
99
99
|
return cmd;
|
|
100
100
|
|
|
101
101
|
// Command API: Define a command option
|
|
102
|
-
function commandOption(optString, validValues, options) {
|
|
102
|
+
function commandOption( optString, validValues, options ) {
|
|
103
103
|
return _addOption(cmd, optString, validValues, options);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
// Command API: Define the command help text
|
|
107
|
-
function commandHelp(text) {
|
|
107
|
+
function commandHelp( text ) {
|
|
108
108
|
cmd.helpText = text;
|
|
109
109
|
return cmd;
|
|
110
110
|
}
|
|
@@ -120,29 +120,29 @@ function createOptionProcessor() {
|
|
|
120
120
|
* @param {object[]} argList Array, to which the parsed arguments will be added. Default is global scope.
|
|
121
121
|
* @private
|
|
122
122
|
*/
|
|
123
|
-
function _setPositionalArguments(argumentDefinition, argList = optionProcessor.positionalArguments) {
|
|
124
|
-
if (argList.find(
|
|
125
|
-
throw new Error(
|
|
126
|
-
|
|
123
|
+
function _setPositionalArguments( argumentDefinition, argList = optionProcessor.positionalArguments ) {
|
|
124
|
+
if (argList.find(arg => arg.isDynamic))
|
|
125
|
+
throw new Error('Can\'t add positional arguments after a dynamic one');
|
|
126
|
+
|
|
127
127
|
|
|
128
|
-
const registeredNames = argList.map(
|
|
128
|
+
const registeredNames = argList.map(arg => arg.name);
|
|
129
129
|
const args = argumentDefinition.split(' ');
|
|
130
130
|
|
|
131
131
|
for (const arg of args) {
|
|
132
132
|
// Remove braces, dots and camelify.
|
|
133
133
|
const argName = arg.replace('<', '').replace('>', '').replace('...', '').replace(/[ -]./g, s => s.substring(1).toUpperCase());
|
|
134
134
|
|
|
135
|
-
if (registeredNames.includes(argName))
|
|
136
|
-
throw new Error(`Duplicate positional argument: ${arg}`);
|
|
137
|
-
|
|
138
|
-
if (!isParam(arg) && !isDynamicPositionalArgument(arg))
|
|
139
|
-
throw new Error(`Unknown positional argument syntax: ${arg}`)
|
|
140
|
-
|
|
135
|
+
if (registeredNames.includes(argName))
|
|
136
|
+
throw new Error(`Duplicate positional argument: ${ arg }`);
|
|
137
|
+
|
|
138
|
+
if (!isParam(arg) && !isDynamicPositionalArgument(arg))
|
|
139
|
+
throw new Error(`Unknown positional argument syntax: ${ arg }`);
|
|
140
|
+
|
|
141
141
|
|
|
142
142
|
argList.push({
|
|
143
143
|
name: argName,
|
|
144
144
|
isDynamic: isDynamicPositionalArgument(arg),
|
|
145
|
-
required: true
|
|
145
|
+
required: true,
|
|
146
146
|
});
|
|
147
147
|
|
|
148
148
|
registeredNames.push(argName);
|
|
@@ -157,7 +157,7 @@ function createOptionProcessor() {
|
|
|
157
157
|
* @private
|
|
158
158
|
* @see option()
|
|
159
159
|
*/
|
|
160
|
-
function _addOption(cmd, optString, validValues, options) {
|
|
160
|
+
function _addOption( cmd, optString, validValues, options ) {
|
|
161
161
|
const cliOpt = _parseOptionString(optString, validValues);
|
|
162
162
|
Object.assign(cliOpt, options);
|
|
163
163
|
_addLongOption(cmd, cliOpt.longName, cliOpt);
|
|
@@ -180,14 +180,15 @@ function createOptionProcessor() {
|
|
|
180
180
|
* @private
|
|
181
181
|
* @see _addOption()
|
|
182
182
|
*/
|
|
183
|
-
function _addLongOption(cmd, longName, opt) {
|
|
183
|
+
function _addLongOption( cmd, longName, opt ) {
|
|
184
184
|
if (cmd.options[longName]) {
|
|
185
|
-
throw new Error(`Duplicate assignment for long option ${longName}`);
|
|
186
|
-
}
|
|
185
|
+
throw new Error(`Duplicate assignment for long option ${ longName }`);
|
|
186
|
+
}
|
|
187
|
+
else if (optionProcessor.options[longName]) {
|
|
187
188
|
// This path is only taken if optString is for commands
|
|
188
189
|
optionProcessor.optionClashes.push({
|
|
189
190
|
option: longName,
|
|
190
|
-
description: `Command '${cmd.longName}' has option clash with general options for: ${longName}
|
|
191
|
+
description: `Command '${ cmd.longName }' has option clash with general options for: ${ longName }`,
|
|
191
192
|
});
|
|
192
193
|
}
|
|
193
194
|
cmd.options[longName] = opt;
|
|
@@ -201,16 +202,17 @@ function createOptionProcessor() {
|
|
|
201
202
|
* @private
|
|
202
203
|
* @see _addOption()
|
|
203
204
|
*/
|
|
204
|
-
function _addShortOption(cmd, shortName, opt) {
|
|
205
|
+
function _addShortOption( cmd, shortName, opt ) {
|
|
205
206
|
if (!shortName)
|
|
206
207
|
return;
|
|
207
208
|
if (cmd.options[shortName]) {
|
|
208
|
-
throw new Error(`Duplicate assignment for short option ${shortName}`);
|
|
209
|
-
}
|
|
209
|
+
throw new Error(`Duplicate assignment for short option ${ shortName }`);
|
|
210
|
+
}
|
|
211
|
+
else if (optionProcessor.options[shortName]) {
|
|
210
212
|
// This path is only taken if optString is for commands
|
|
211
213
|
optionProcessor.optionClashes.push({
|
|
212
214
|
option: shortName,
|
|
213
|
-
description: `Command '${cmd.longName}' has option clash with general options for: ${shortName}
|
|
215
|
+
description: `Command '${ cmd.longName }' has option clash with general options for: ${ shortName }`,
|
|
214
216
|
});
|
|
215
217
|
}
|
|
216
218
|
cmd.options[shortName] = opt;
|
|
@@ -221,7 +223,7 @@ function createOptionProcessor() {
|
|
|
221
223
|
// longName: 'toFoo',
|
|
222
224
|
// shortName: 'F',
|
|
223
225
|
// }
|
|
224
|
-
function _parseCommandString(cmdString) {
|
|
226
|
+
function _parseCommandString( cmdString ) {
|
|
225
227
|
let longName;
|
|
226
228
|
let shortName;
|
|
227
229
|
|
|
@@ -237,12 +239,12 @@ function createOptionProcessor() {
|
|
|
237
239
|
longName = tokens[1];
|
|
238
240
|
break;
|
|
239
241
|
default:
|
|
240
|
-
throw new Error(`Invalid command description: ${cmdString}`);
|
|
242
|
+
throw new Error(`Invalid command description: ${ cmdString }`);
|
|
241
243
|
}
|
|
242
244
|
return {
|
|
243
245
|
longName,
|
|
244
246
|
shortName,
|
|
245
|
-
}
|
|
247
|
+
};
|
|
246
248
|
}
|
|
247
249
|
|
|
248
250
|
// Internal: Parse one option string like "-f, --foo-bar <p>". Returns an object like this
|
|
@@ -253,7 +255,7 @@ function createOptionProcessor() {
|
|
|
253
255
|
// param: '<p>'
|
|
254
256
|
// validValues
|
|
255
257
|
// }
|
|
256
|
-
function _parseOptionString(optString, validValues) {
|
|
258
|
+
function _parseOptionString( optString, validValues ) {
|
|
257
259
|
let longName;
|
|
258
260
|
let shortName;
|
|
259
261
|
let param;
|
|
@@ -263,16 +265,17 @@ function createOptionProcessor() {
|
|
|
263
265
|
switch (tokens.length) {
|
|
264
266
|
case 1:
|
|
265
267
|
// Must be "--foo"
|
|
266
|
-
if (isLongOption(tokens[0]))
|
|
268
|
+
if (isLongOption(tokens[0]))
|
|
267
269
|
longName = tokens[0];
|
|
268
|
-
|
|
270
|
+
|
|
269
271
|
break;
|
|
270
272
|
case 2:
|
|
271
273
|
// Could be "--foo <bar>", or "-f --foo"
|
|
272
274
|
if (isLongOption(tokens[0]) && isParam(tokens[1])) {
|
|
273
275
|
longName = tokens[0];
|
|
274
276
|
param = tokens[1];
|
|
275
|
-
}
|
|
277
|
+
}
|
|
278
|
+
else if (isShortOption(tokens[0]) && isLongOption(tokens[1])) {
|
|
276
279
|
shortName = tokens[0];
|
|
277
280
|
longName = tokens[1];
|
|
278
281
|
}
|
|
@@ -286,18 +289,18 @@ function createOptionProcessor() {
|
|
|
286
289
|
}
|
|
287
290
|
break;
|
|
288
291
|
default:
|
|
289
|
-
throw new Error(`Invalid option description, too many tokens: ${optString}`);
|
|
290
|
-
}
|
|
291
|
-
if (!longName) {
|
|
292
|
-
throw new Error(`Invalid option description, missing long name: ${optString}`);
|
|
293
|
-
}
|
|
294
|
-
if (!param && validValues) {
|
|
295
|
-
throw new Error(`Option description has valid values but no param: ${optString}`);
|
|
292
|
+
throw new Error(`Invalid option description, too many tokens: ${ optString }`);
|
|
296
293
|
}
|
|
294
|
+
if (!longName)
|
|
295
|
+
throw new Error(`Invalid option description, missing long name: ${ optString }`);
|
|
296
|
+
|
|
297
|
+
if (!param && validValues)
|
|
298
|
+
throw new Error(`Option description has valid values but no param: ${ optString }`);
|
|
299
|
+
|
|
297
300
|
if (validValues) {
|
|
298
301
|
validValues.forEach((value) => {
|
|
299
302
|
if (typeof value !== 'string')
|
|
300
|
-
throw new Error(`Valid values must be of type string: ${optString}`);
|
|
303
|
+
throw new Error(`Valid values must be of type string: ${ optString }`);
|
|
301
304
|
});
|
|
302
305
|
}
|
|
303
306
|
|
|
@@ -308,7 +311,7 @@ function createOptionProcessor() {
|
|
|
308
311
|
param,
|
|
309
312
|
validValues,
|
|
310
313
|
isAlias: false, // default
|
|
311
|
-
}
|
|
314
|
+
};
|
|
312
315
|
}
|
|
313
316
|
|
|
314
317
|
// API: Let the option processor digest a command line 'argv'
|
|
@@ -344,17 +347,17 @@ function createOptionProcessor() {
|
|
|
344
347
|
// cmdErrors: [],
|
|
345
348
|
// errors: [],
|
|
346
349
|
// }
|
|
347
|
-
function processCmdLine(argv) {
|
|
350
|
+
function processCmdLine( argv ) {
|
|
348
351
|
const result = {
|
|
349
352
|
command: undefined,
|
|
350
353
|
options: { },
|
|
351
354
|
unknownOptions: [],
|
|
352
355
|
args: {
|
|
353
|
-
length: 0
|
|
356
|
+
length: 0,
|
|
354
357
|
},
|
|
355
358
|
cmdErrors: [],
|
|
356
359
|
errors: [],
|
|
357
|
-
}
|
|
360
|
+
};
|
|
358
361
|
|
|
359
362
|
// Iterate command line
|
|
360
363
|
let seenDashDash = false;
|
|
@@ -363,7 +366,7 @@ function createOptionProcessor() {
|
|
|
363
366
|
let arg = argv[i];
|
|
364
367
|
// To be compatible with NPM arguments, we need to support `--arg=val` as well.
|
|
365
368
|
if (arg.includes('=')) {
|
|
366
|
-
argv = [ ...argv.slice(0, i), ...arg.split('='), ...argv.slice(i + 1)];
|
|
369
|
+
argv = [ ...argv.slice(0, i), ...arg.split('='), ...argv.slice(i + 1) ];
|
|
367
370
|
arg = argv[i];
|
|
368
371
|
}
|
|
369
372
|
|
|
@@ -385,30 +388,32 @@ function createOptionProcessor() {
|
|
|
385
388
|
// Found as command
|
|
386
389
|
result.command = optionProcessor.commands[arg].longName;
|
|
387
390
|
result.options[result.command] = {};
|
|
388
|
-
}
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
389
393
|
// Not found as command, take as arg and stop looking for commands
|
|
390
394
|
processPositionalArgument(arg);
|
|
391
395
|
result.command = null;
|
|
392
396
|
}
|
|
393
|
-
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
394
399
|
processPositionalArgument(arg);
|
|
395
400
|
}
|
|
396
401
|
}
|
|
397
402
|
}
|
|
398
403
|
// Avoid 'toXyz: {}' for command without options
|
|
399
|
-
if (result.command && Object.keys(result.options[result.command]).length === 0)
|
|
404
|
+
if (result.command && Object.keys(result.options[result.command]).length === 0)
|
|
400
405
|
delete result.options[result.command];
|
|
401
|
-
|
|
406
|
+
|
|
402
407
|
|
|
403
408
|
// Complain about first missing positional arguments
|
|
404
|
-
const missingArg = getCurrentPositionArguments().find(
|
|
409
|
+
const missingArg = getCurrentPositionArguments().find(arg => arg.required && !result.args[arg.name]);
|
|
405
410
|
if (missingArg) {
|
|
406
411
|
const forCommand = result.command ? ` for '${ result.command }'` : '';
|
|
407
|
-
const errorMsg = `Missing positional argument${forCommand}: <${missingArg.name}${missingArg.isDynamic ? '...' : ''}>`;
|
|
412
|
+
const errorMsg = `Missing positional argument${ forCommand }: <${ missingArg.name }${ missingArg.isDynamic ? '...' : '' }>`;
|
|
408
413
|
if (forCommand)
|
|
409
|
-
result.cmdErrors.push(errorMsg)
|
|
414
|
+
result.cmdErrors.push(errorMsg);
|
|
410
415
|
else
|
|
411
|
-
result.errors.push(errorMsg)
|
|
416
|
+
result.errors.push(errorMsg);
|
|
412
417
|
}
|
|
413
418
|
|
|
414
419
|
return result;
|
|
@@ -424,7 +429,7 @@ function createOptionProcessor() {
|
|
|
424
429
|
return ( cmd && cmd.positionalArguments && cmd.positionalArguments.length ) ? cmd.positionalArguments : optionProcessor.positionalArguments;
|
|
425
430
|
}
|
|
426
431
|
|
|
427
|
-
function processPositionalArgument(argumentValue) {
|
|
432
|
+
function processPositionalArgument( argumentValue ) {
|
|
428
433
|
const argList = getCurrentPositionArguments();
|
|
429
434
|
if ( result.args.length === 0 && argList.length === 0 )
|
|
430
435
|
return;
|
|
@@ -433,16 +438,17 @@ function createOptionProcessor() {
|
|
|
433
438
|
const nextUnsetArgument = argList[lastIndex];
|
|
434
439
|
if (!inBounds && !nextUnsetArgument.isDynamic) {
|
|
435
440
|
if (result.command)
|
|
436
|
-
result.errors.push(`Too many arguments. '${result.command}' expects ${argList.length}`);
|
|
441
|
+
result.errors.push(`Too many arguments. '${ result.command }' expects ${ argList.length }`);
|
|
437
442
|
else
|
|
438
|
-
result.errors.push(`Too many arguments. Expected ${argList.length}`);
|
|
443
|
+
result.errors.push(`Too many arguments. Expected ${ argList.length }`);
|
|
439
444
|
return;
|
|
440
445
|
}
|
|
441
446
|
result.args.length += 1;
|
|
442
447
|
if (nextUnsetArgument.isDynamic) {
|
|
443
448
|
result.args[nextUnsetArgument.name] = result.args[nextUnsetArgument.name] || [];
|
|
444
449
|
result.args[nextUnsetArgument.name].push(argumentValue);
|
|
445
|
-
}
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
446
452
|
result.args[nextUnsetArgument.name] = argumentValue;
|
|
447
453
|
}
|
|
448
454
|
}
|
|
@@ -452,7 +458,7 @@ function createOptionProcessor() {
|
|
|
452
458
|
// Check the option definition to see if a parameter is expected.
|
|
453
459
|
// If so, take it (complain if one is found in 'argv').
|
|
454
460
|
// Populate 'result.options' with the result. Return the number params found (0 or 1).
|
|
455
|
-
function processOption(i) {
|
|
461
|
+
function processOption( i ) {
|
|
456
462
|
const arg = argv[i];
|
|
457
463
|
let currentCommand = result.command;
|
|
458
464
|
|
|
@@ -491,18 +497,17 @@ function createOptionProcessor() {
|
|
|
491
497
|
*/
|
|
492
498
|
function reportUnknown() {
|
|
493
499
|
if (currentCommand)
|
|
494
|
-
result.unknownOptions.push(`Unknown option "${arg}" for the command "${currentCommand}"`);
|
|
500
|
+
result.unknownOptions.push(`Unknown option "${ arg }" for the command "${ currentCommand }"`);
|
|
495
501
|
else
|
|
496
|
-
result.unknownOptions.push(`Unknown option "${arg}"`);
|
|
502
|
+
result.unknownOptions.push(`Unknown option "${ arg }"`);
|
|
497
503
|
|
|
498
504
|
if (currentCommand) {
|
|
499
505
|
// Not found at all. We dig into the other cdsc commands in order to check if
|
|
500
506
|
// the option expects a parameter and if so to take the next argument as a value
|
|
501
507
|
const otherCmd = Object.keys(optionProcessor.commands).find(cmd => optionProcessor.commands[cmd].options[arg]);
|
|
502
508
|
const otherCmdOpt = otherCmd && optionProcessor.commands[otherCmd].options[arg];
|
|
503
|
-
if (otherCmdOpt && hasParamForUnknown(otherCmdOpt))
|
|
504
|
-
return 1
|
|
505
|
-
}
|
|
509
|
+
if (otherCmdOpt && hasParamForUnknown(otherCmdOpt))
|
|
510
|
+
return 1;
|
|
506
511
|
}
|
|
507
512
|
|
|
508
513
|
if (hasParamForUnknown(null))
|
|
@@ -511,7 +516,7 @@ function createOptionProcessor() {
|
|
|
511
516
|
return 0;
|
|
512
517
|
}
|
|
513
518
|
|
|
514
|
-
function setCurrentOption(val) {
|
|
519
|
+
function setCurrentOption( val ) {
|
|
515
520
|
if (currentCommand) {
|
|
516
521
|
if (!result.options[currentCommand])
|
|
517
522
|
result.options[currentCommand] = {};
|
|
@@ -522,20 +527,22 @@ function createOptionProcessor() {
|
|
|
522
527
|
}
|
|
523
528
|
}
|
|
524
529
|
|
|
525
|
-
function reportMissingParam(opt) {
|
|
526
|
-
|
|
530
|
+
function reportMissingParam( opt ) {
|
|
531
|
+
const short = opt.shortName ? `${ opt.shortName }, ` : '';
|
|
532
|
+
let error = `Missing param "${ opt.param }" for option "${ short }${ opt.longName }"`;
|
|
527
533
|
if (currentCommand) {
|
|
528
|
-
error = `${error} of command "${currentCommand}"`;
|
|
534
|
+
error = `${ error } of command "${ currentCommand }"`;
|
|
529
535
|
result.cmdErrors.push(error);
|
|
530
|
-
}
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
531
538
|
result.errors.push(error);
|
|
532
539
|
}
|
|
533
540
|
}
|
|
534
541
|
|
|
535
|
-
function reportInvalidValue(opt, value) {
|
|
536
|
-
const shortOption = opt.shortName ? `${opt.shortName}, ` : ''
|
|
542
|
+
function reportInvalidValue( opt, value ) {
|
|
543
|
+
const shortOption = opt.shortName ? `${ opt.shortName }, ` : '';
|
|
537
544
|
const errors = currentCommand ? result.cmdErrors : result.errors;
|
|
538
|
-
errors.push(`Invalid value "${value}" for option "${shortOption}${opt.longName}" - use one of [${opt.validValues}]`);
|
|
545
|
+
errors.push(`Invalid value "${ value }" for option "${ shortOption }${ opt.longName }" - use one of [${ opt.validValues }]`);
|
|
539
546
|
}
|
|
540
547
|
|
|
541
548
|
/**
|
|
@@ -544,17 +551,17 @@ function createOptionProcessor() {
|
|
|
544
551
|
*
|
|
545
552
|
* @returns {null|*}
|
|
546
553
|
*/
|
|
547
|
-
function paramForOption(opt, reportMissing = true) {
|
|
554
|
+
function paramForOption( opt, reportMissing = true ) {
|
|
548
555
|
if (i + 1 >= argv.length || argv[i + 1].startsWith('-')) {
|
|
549
556
|
if (reportMissing)
|
|
550
|
-
reportMissingParam(opt)
|
|
557
|
+
reportMissingParam(opt);
|
|
551
558
|
return null;
|
|
552
559
|
}
|
|
553
560
|
|
|
554
561
|
const value = argv[i + 1];
|
|
555
|
-
if (!isValidOptionValue(opt, value) && reportMissing)
|
|
562
|
+
if (!isValidOptionValue(opt, value) && reportMissing)
|
|
556
563
|
reportInvalidValue(opt, value);
|
|
557
|
-
|
|
564
|
+
|
|
558
565
|
return value;
|
|
559
566
|
}
|
|
560
567
|
|
|
@@ -567,7 +574,7 @@ function createOptionProcessor() {
|
|
|
567
574
|
* @param {object|null} opt
|
|
568
575
|
* @returns {boolean}
|
|
569
576
|
*/
|
|
570
|
-
function hasParamForUnknown(opt) {
|
|
577
|
+
function hasParamForUnknown( opt ) {
|
|
571
578
|
return ((!opt || opt.param) && (i + 1) < argv.length && !argv[i + 1].match('(^[.-])|[.](csn|cdl|cds|json)$'));
|
|
572
579
|
}
|
|
573
580
|
}
|
|
@@ -577,40 +584,40 @@ function createOptionProcessor() {
|
|
|
577
584
|
// If 'command' is supplied, check only 'options.command', otherwise check
|
|
578
585
|
// only top-level options
|
|
579
586
|
// Return an array of complaints (possibly empty)
|
|
580
|
-
function verifyOptions(options, commandName = undefined, silent = false) {
|
|
587
|
+
function verifyOptions( options, commandName = undefined, silent = false ) {
|
|
581
588
|
const result = [];
|
|
582
589
|
let opts;
|
|
583
590
|
|
|
584
591
|
if ((options.betaMode || options.beta) && !options.testMode && !silent) {
|
|
585
592
|
const mode = options.beta ? 'beta' : 'beta-mode';
|
|
586
|
-
result.push(`Option --${mode} was used. This option should not be used in productive scenarios!`)
|
|
593
|
+
result.push(`Option --${ mode } was used. This option should not be used in productive scenarios!`);
|
|
587
594
|
}
|
|
588
595
|
|
|
589
596
|
if (options) {
|
|
590
597
|
[
|
|
591
598
|
'defaultBinaryLength', 'defaultStringLength',
|
|
592
|
-
/*'length', 'precision', 'scale'*/
|
|
593
|
-
].forEach(facet => {
|
|
594
|
-
if(options[facet] && isNaN(options[facet]))
|
|
595
|
-
result.push(`Invalid value "${options[facet]}" for option "--${facet}" - not an Integer`);
|
|
596
|
-
|
|
599
|
+
/* 'length', 'precision', 'scale' */
|
|
600
|
+
].forEach((facet) => {
|
|
601
|
+
if (options[facet] && isNaN(options[facet]))
|
|
602
|
+
result.push(`Invalid value "${ options[facet] }" for option "--${ facet }" - not an Integer`);
|
|
603
|
+
else
|
|
597
604
|
options[facet] = parseInt(options[facet]);
|
|
598
|
-
}
|
|
599
605
|
});
|
|
600
606
|
}
|
|
601
607
|
|
|
602
608
|
if (commandName) {
|
|
603
609
|
const cmd = optionProcessor.commands[commandName];
|
|
604
|
-
if (!cmd)
|
|
605
|
-
throw new Error(`Expected existing command: "${cmd}"`);
|
|
606
|
-
|
|
610
|
+
if (!cmd)
|
|
611
|
+
throw new Error(`Expected existing command: "${ cmd }"`);
|
|
612
|
+
|
|
607
613
|
opts = cmd.options;
|
|
608
614
|
options = options[cmd] || {};
|
|
609
615
|
if (typeof options === 'boolean') {
|
|
610
616
|
// Special case: command without options
|
|
611
617
|
options = {};
|
|
612
618
|
}
|
|
613
|
-
}
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
614
621
|
opts = optionProcessor.options;
|
|
615
622
|
}
|
|
616
623
|
// Look at each supplied option
|
|
@@ -620,42 +627,43 @@ function createOptionProcessor() {
|
|
|
620
627
|
if (!opt) {
|
|
621
628
|
// Don't report commands in top-level options
|
|
622
629
|
if ((commandName || !optionProcessor.commands[camelName]) && !silent) {
|
|
623
|
-
|
|
630
|
+
const prefix = commandName ? `${commandName}.` : '';
|
|
631
|
+
error = `Unknown option "${prefix}${camelName}"`;
|
|
624
632
|
}
|
|
625
|
-
}
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
626
635
|
const param = options[camelName];
|
|
627
|
-
error = verifyOptionParam(param, opt, commandName ? commandName
|
|
636
|
+
error = verifyOptionParam(param, opt, commandName ? `${ commandName }.` : '');
|
|
628
637
|
}
|
|
629
|
-
if (error)
|
|
638
|
+
if (error)
|
|
630
639
|
result.push(error);
|
|
631
|
-
}
|
|
632
640
|
}
|
|
633
641
|
// hard-coded option dependencies (they disappear with command)
|
|
634
642
|
return result;
|
|
635
643
|
|
|
636
644
|
// Verify parameter value 'param' against option definition 'opt'. Return an error
|
|
637
645
|
// string or false for an accepted param. Use 'prefix' when mentioning the option name.
|
|
638
|
-
function verifyOptionParam(param, opt, prefix) {
|
|
646
|
+
function verifyOptionParam( param, opt, prefix ) {
|
|
639
647
|
if (opt.param) {
|
|
640
648
|
// Parameter is required for this option
|
|
641
|
-
if (typeof param === 'boolean')
|
|
642
|
-
return `Missing value for option "${prefix}${opt.camelName}"`;
|
|
643
|
-
|
|
644
|
-
return `Invalid value "${param}" for option "${prefix}${opt.camelName}" - use one of [${opt.validValues}]`;
|
|
645
|
-
|
|
649
|
+
if (typeof param === 'boolean')
|
|
650
|
+
return `Missing value for option "${ prefix }${ opt.camelName }"`;
|
|
651
|
+
else if (!isValidOptionValue(opt, param))
|
|
652
|
+
return `Invalid value "${ param }" for option "${ prefix }${ opt.camelName }" - use one of [${ opt.validValues }]`;
|
|
653
|
+
|
|
646
654
|
return false;
|
|
647
|
-
} else {
|
|
648
|
-
// Option does not expect a parameter
|
|
649
|
-
if (typeof param !== 'boolean') {
|
|
650
|
-
// FIXME: Might be a bit too strict in case of internal sub-options like 'forHana' etc...
|
|
651
|
-
return `Expecting boolean value for option "${prefix}${opt.camelName}"`;
|
|
652
|
-
}
|
|
653
655
|
}
|
|
656
|
+
// Option does not expect a parameter
|
|
657
|
+
if (typeof param !== 'boolean') {
|
|
658
|
+
// FIXME: Might be a bit too strict in case of internal sub-options like 'forHana' etc...
|
|
659
|
+
return `Expecting boolean value for option "${ prefix }${ opt.camelName }"`;
|
|
660
|
+
}
|
|
661
|
+
|
|
654
662
|
return false;
|
|
655
663
|
}
|
|
656
664
|
}
|
|
657
665
|
|
|
658
|
-
function isValidOptionValue(opt, value) {
|
|
666
|
+
function isValidOptionValue( opt, value ) {
|
|
659
667
|
// Explicitly convert to string, input 'value' may be boolean
|
|
660
668
|
value = String(value);
|
|
661
669
|
if (!opt.validValues || !opt.validValues.length)
|
|
@@ -667,12 +675,12 @@ function createOptionProcessor() {
|
|
|
667
675
|
|
|
668
676
|
// Return an array of unique camelNames of the options for the specified command
|
|
669
677
|
// If invalid command -> an empty array
|
|
670
|
-
function camelOptionsForCommand(cmd) {
|
|
678
|
+
function camelOptionsForCommand( cmd ) {
|
|
671
679
|
if (!cmd || !optionProcessor.commands[cmd])
|
|
672
|
-
return []
|
|
680
|
+
return [];
|
|
673
681
|
cmd = optionProcessor.commands[cmd];
|
|
674
682
|
const names = Object.keys(cmd.options).map(name => cmd.options[name].camelName);
|
|
675
|
-
return [...new Set(names)];
|
|
683
|
+
return [ ...new Set(names) ];
|
|
676
684
|
}
|
|
677
685
|
}
|
|
678
686
|
|
|
@@ -682,54 +690,55 @@ function createOptionProcessor() {
|
|
|
682
690
|
* @param {string[]} argv Argument array
|
|
683
691
|
* @param {number} i Current option index.
|
|
684
692
|
*/
|
|
685
|
-
function splitSingleLetterOption(argv, i) {
|
|
693
|
+
function splitSingleLetterOption( argv, i ) {
|
|
686
694
|
const arg = argv[i];
|
|
687
695
|
if (arg.length > 2) { // must be at least `-ab`.
|
|
688
696
|
const rest = argv.slice(i + 1);
|
|
689
697
|
argv.length = i; // trim array
|
|
690
|
-
argv.push(...arg.split('').slice(1).map(a => `-${a}`), ...rest);
|
|
698
|
+
argv.push(...arg.split('').slice(1).map(a => `-${ a }`), ...rest);
|
|
691
699
|
}
|
|
692
700
|
}
|
|
693
701
|
|
|
694
702
|
/**
|
|
695
703
|
* Return a camelCase name "fooBar" for a long option "--foo-bar"
|
|
696
704
|
*/
|
|
697
|
-
function camelifyLongOption(opt) {
|
|
705
|
+
function camelifyLongOption( opt ) {
|
|
698
706
|
return opt.substring(2).replace(/-./g, s => s.substring(1).toUpperCase());
|
|
699
707
|
}
|
|
700
708
|
|
|
701
709
|
/**
|
|
702
710
|
* Return a long option name like "--foo-bar" for a camel-case name "fooBar"
|
|
703
711
|
*/
|
|
704
|
-
function uncamelifyLongOption(opt) {
|
|
705
|
-
|
|
712
|
+
function uncamelifyLongOption( opt ) {
|
|
713
|
+
const longForm = opt.replace(/[A-Z]/g, s => `-${ s.toLowerCase() }`);
|
|
714
|
+
return `--${ longForm }`;
|
|
706
715
|
}
|
|
707
716
|
|
|
708
717
|
/**
|
|
709
718
|
* Check if 'opt' looks like a "-f" short option
|
|
710
719
|
*/
|
|
711
|
-
function isShortOption(opt) {
|
|
720
|
+
function isShortOption( opt ) {
|
|
712
721
|
return /^-[a-zA-Z?]$/.test(opt);
|
|
713
722
|
}
|
|
714
723
|
|
|
715
724
|
/**
|
|
716
725
|
* Check if 'opt' looks like a "--foo-bar" long option
|
|
717
726
|
*/
|
|
718
|
-
function isLongOption(opt) {
|
|
727
|
+
function isLongOption( opt ) {
|
|
719
728
|
return /^--[a-zA-Z0-9-]+$/.test(opt);
|
|
720
729
|
}
|
|
721
730
|
|
|
722
731
|
/**
|
|
723
732
|
* Check if 'opt' looks like a "<foobar>" parameter
|
|
724
733
|
*/
|
|
725
|
-
function isParam(opt) {
|
|
734
|
+
function isParam( opt ) {
|
|
726
735
|
return /^<[a-zA-Z-]+>$/.test(opt);
|
|
727
736
|
}
|
|
728
737
|
|
|
729
738
|
/**
|
|
730
739
|
* Check if 'arg' looks like "<foobar...>"
|
|
731
740
|
*/
|
|
732
|
-
function isDynamicPositionalArgument(arg) {
|
|
741
|
+
function isDynamicPositionalArgument( arg ) {
|
|
733
742
|
return /^<[a-zA-Z-]+[.]{3}>$/.test(arg);
|
|
734
743
|
}
|
|
735
744
|
|
|
@@ -738,5 +747,5 @@ module.exports = {
|
|
|
738
747
|
isShortOption,
|
|
739
748
|
isLongOption,
|
|
740
749
|
isParam,
|
|
741
|
-
isDynamicPositionalArgument
|
|
750
|
+
isDynamicPositionalArgument,
|
|
742
751
|
};
|