@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
package/bin/cdsc.js CHANGED
@@ -19,7 +19,7 @@ const compiler = require('../lib/compiler');
19
19
  const main = require('../lib/main');
20
20
  const { for_sql, for_hdi, for_hdbcds } = require('../lib/api/main');
21
21
  const { compactModel } = require('../lib/json/to-csn');
22
- const { toRenameWithCsn, alterConstraintsWithCsn } = require('../lib/backends');
22
+ const { toRename: _toRename } = require('../lib/render/toRename');
23
23
  const util = require('util');
24
24
  const fs = require('fs');
25
25
  const path = require('path');
@@ -33,6 +33,7 @@ const { term } = require('../lib/utils/term');
33
33
  const { splitLines } = require('../lib/utils/file');
34
34
  const { addLocalizationViews } = require('../lib/transform/localized');
35
35
  const { availableBetaFlags } = require('../lib/base/model');
36
+ const { alterConstraintsWithCsn } = require('../lib/render/manageConstraints');
36
37
 
37
38
  // Note: Instead of throwing ProcessExitError, we would rather just call process.exit(exitCode),
38
39
  // but that might truncate the output of stdout and stderr, both of which are async (or rather,
@@ -44,11 +45,23 @@ class ProcessExitError extends Error {
44
45
  }
45
46
  }
46
47
 
47
- function remapCmdOptions(options, cmdOptions) {
48
- if (!cmdOptions)
49
- return options;
48
+ try {
49
+ cdsc_main();
50
+ }
51
+ catch (err) {
52
+ // This whole try/catch is only here because process.exit does not work in combination with
53
+ // stdout/err - see comment at ProcessExitError
54
+ if (err instanceof ProcessExitError)
55
+ process.exitCode = err.exitCode;
56
+ else
57
+ throw err;
58
+ }
50
59
 
51
- for (const [ key, value ] of Object.entries(cmdOptions)) {
60
+ function remapCmdOptions(options, command) {
61
+ if (!command || !options[command])
62
+ return;
63
+
64
+ for (const [ key, value ] of Object.entries(options[command])) {
52
65
  switch (key) {
53
66
  case 'names':
54
67
  options.sqlMapping = value;
@@ -73,15 +86,22 @@ function remapCmdOptions(options, cmdOptions) {
73
86
  options.variableReplacements.$user = {};
74
87
  options.variableReplacements.$user.locale = value;
75
88
  break;
89
+ case 'serviceNames':
90
+ options.serviceNames = value.split(',');
91
+ break;
92
+ case 'flavor':
93
+ options.csnFlavor = value;
94
+ break;
76
95
  default:
77
96
  options[key] = value;
78
97
  }
79
98
  }
80
- return options;
99
+ delete options[command];
81
100
  }
82
101
 
83
- // Parse the command line and translate it into options
84
- try {
102
+ function cdsc_main() {
103
+ // Parse the command line and translate it into options
104
+
85
105
  const cmdLine = optionProcessor.processCmdLine(process.argv);
86
106
  // Deal with '--version' explicitly
87
107
  if (cmdLine.options.version) {
@@ -115,6 +135,11 @@ try {
115
135
  displayUsage(cmdLine.errors, optionProcessor.helpText, 2);
116
136
  }
117
137
 
138
+ if (cmdLine.options.options) {
139
+ if (!loadOptionsFromJson(cmdLine))
140
+ return;
141
+ }
142
+
118
143
  // Default warning level is 2 (info)
119
144
  // FIXME: Is that not set anywhere in the API?
120
145
  if (!cmdLine.options.warning)
@@ -125,11 +150,7 @@ try {
125
150
  cmdLine.options.out = '-';
126
151
 
127
152
  // --cds-home <dir>: modules starting with '@sap/cds/' are searched in <dir>
128
- if (cmdLine.options.cdsHome) {
129
- if (!global.cds)
130
- global.cds = {};
131
- global.cds.home = cmdLine.options.cdsHome;
132
- }
153
+ // -> cmdLine.options.cdsHome is passed down to moduleResolve
133
154
 
134
155
  // Set default command if required
135
156
  cmdLine.command = cmdLine.command || 'toCsn';
@@ -147,8 +168,8 @@ try {
147
168
  if (cmdLine.options.directBackend)
148
169
  validateDirectBackendOption(cmdLine.command, cmdLine.options, cmdLine.args);
149
170
 
150
-
151
- if (cmdLine.options.beta) {
171
+ // If set through CLI (and not options file), `beta` is a string and needs processing.
172
+ if (cmdLine.options.beta && typeof cmdLine.options.beta === 'string') {
152
173
  const features = cmdLine.options.beta.split(',');
153
174
  cmdLine.options.beta = {};
154
175
  features.forEach((val) => {
@@ -156,35 +177,32 @@ try {
156
177
  });
157
178
  }
158
179
 
180
+ const to = cmdLine.options.toSql ? 'toSql' : 'toHana';
159
181
  // remap string values for `assertIntegrity` option to boolean
160
- if (cmdLine.options.assertIntegrity &&
161
- cmdLine.options.assertIntegrity === 'true' ||
162
- cmdLine.options.assertIntegrity === 'false'
182
+ if (cmdLine.options[to] && cmdLine.options[to].assertIntegrity &&
183
+ (cmdLine.options[to].assertIntegrity === 'true' ||
184
+ cmdLine.options[to].assertIntegrity === 'false')
163
185
  )
164
- cmdLine.options.assertIntegrity = cmdLine.options.assertIntegrity === 'true';
186
+ cmdLine.options[to].assertIntegrity = cmdLine.options[to].assertIntegrity === 'true';
165
187
 
166
188
  // Enable all beta-flags if betaMode is set to true
167
189
  if (cmdLine.options.betaMode)
168
190
  cmdLine.options.beta = availableBetaFlags;
169
191
 
170
- if (cmdLine.options.deprecated) {
192
+ // If set through CLI (and not options file), `deprecated` is a string and needs processing.
193
+ if (cmdLine.options.deprecated && typeof cmdLine.options.deprecated === 'string') {
171
194
  const features = cmdLine.options.deprecated.split(',');
172
195
  cmdLine.options.deprecated = {};
173
196
  features.forEach((val) => {
174
197
  cmdLine.options.deprecated[val] = true;
175
198
  });
176
199
  }
200
+
201
+ parseSeverityOptions(cmdLine);
202
+
177
203
  // Do the work for the selected command
178
204
  executeCommandLine(cmdLine.command, cmdLine.options, cmdLine.args);
179
205
  }
180
- catch (err) {
181
- // This whole try/catch is only here because process.exit does not work in combination with
182
- // stdout/err - see comment at ProcessExitError
183
- if (err instanceof ProcessExitError)
184
- process.exitCode = err.exitCode;
185
- else
186
- throw err;
187
- }
188
206
 
189
207
  /**
190
208
  * `--direct-backend` can only be used with certain backends and with certain files.
@@ -230,10 +248,10 @@ function displayUsage(error, helpText, code) {
230
248
  function executeCommandLine(command, options, args) {
231
249
  const normalizeFilename = options.testMode && process.platform === 'win32';
232
250
  const messageLevels = {
233
- Error: 0, Warning: 1, Info: 2, None: 3,
251
+ Error: 0, Warning: 1, Info: 2, Debug: 3,
234
252
  };
235
253
  // All messages are put into the message array, even those which should not
236
- // been displayed (severity 'None')
254
+ // been displayed (severity 'Debug')
237
255
 
238
256
  // Create output directory if necessary
239
257
  if (options.out && options.out !== '-' && !fs.existsSync(options.out))
@@ -259,6 +277,7 @@ function executeCommandLine(command, options, args) {
259
277
  if (!commands[command] && !commandsWithoutCompilation[command])
260
278
  throw new Error(`Missing implementation for command ${command}`);
261
279
 
280
+ remapCmdOptions( options, command );
262
281
 
263
282
  if (commandsWithoutCompilation[command]) {
264
283
  commandsWithoutCompilation[command]();
@@ -282,7 +301,7 @@ function executeCommandLine(command, options, args) {
282
301
  // Return the original model (for chaining)
283
302
  function toCdl( model ) {
284
303
  const csn = options.directBackend ? model : compactModel(model, options);
285
- const cdlResult = main.to.cdl(csn, remapCmdOptions(options));
304
+ const cdlResult = main.to.cdl(csn, options);
286
305
  for (const name in cdlResult)
287
306
  writeToFileOrDisplay(options.out, `${name}.cds`, cdlResult[name]);
288
307
 
@@ -307,11 +326,11 @@ function executeCommandLine(command, options, args) {
307
326
  function toHana( model ) {
308
327
  const csn = options.directBackend ? model : compactModel(model, options);
309
328
 
310
- if (options.toHana && options.toHana.csn) {
311
- displayNamedCsn(for_hdbcds(csn, remapCmdOptions(options, options.toHana)), 'hana_csn');
329
+ if (options.csn) {
330
+ displayNamedCsn(for_hdbcds(csn, options), 'hana_csn');
312
331
  }
313
332
  else {
314
- const hanaResult = main.to.hdbcds(csn, remapCmdOptions(options, options.toHana));
333
+ const hanaResult = main.to.hdbcds(csn, options);
315
334
  for (const name in hanaResult)
316
335
  writeToFileOrDisplay(options.out, name, hanaResult[name]);
317
336
  }
@@ -322,24 +341,23 @@ function executeCommandLine(command, options, args) {
322
341
  // Execute the command line option '--to-odata' and display the results.
323
342
  // Return the original model (for chaining)
324
343
  function toOdata( model ) {
325
- if (options.toOdata &&
326
- options.toOdata.version === 'v4x') {
327
- options.toOdata.version = 'v4';
328
- options.toOdata.odataFormat = 'structured';
329
- options.toOdata.odataContainment = true;
344
+ if (options.odataVersion === 'v4x') {
345
+ options.odataVersion = 'v4';
346
+ options.odataFormat = 'structured';
347
+ options.odataContainment = true;
330
348
  }
331
349
  const csn = options.directBackend ? model : compactModel(model, options);
332
- const odataCsn = main.for.odata(csn, remapCmdOptions(options, options.toOdata));
333
- if (options.toOdata && options.toOdata.csn) {
350
+ if (options.csn) {
351
+ const odataCsn = main.for.odata(csn, options);
334
352
  displayNamedCsn(odataCsn, 'odata_csn');
335
353
  }
336
- else if (options.toOdata && options.toOdata.json) {
337
- const result = main.to.edm.all(odataCsn, options);
354
+ else if (options.json) {
355
+ const result = main.to.edm.all(csn, options);
338
356
  for (const serviceName in result)
339
357
  writeToFileOrDisplay(options.out, `${serviceName}.json`, result[serviceName]);
340
358
  }
341
359
  else {
342
- const result = main.to.edmx.all(odataCsn, options);
360
+ const result = main.to.edmx.all(csn, options);
343
361
  for (const serviceName in result)
344
362
  writeToFileOrDisplay(options.out, `${serviceName}.xml`, result[serviceName]);
345
363
  }
@@ -353,14 +371,14 @@ function executeCommandLine(command, options, args) {
353
371
  // / DO NOT DELETE THIS TORENAME FUNCTIONALITY!!
354
372
  function toRename( model ) {
355
373
  const csn = options.directBackend ? model : compactModel(model, options);
356
- const renameResult = toRenameWithCsn(csn, options);
357
- let storedProcedure = `PROCEDURE RENAME_${renameResult.options.toRename.names.toUpperCase()}_TO_PLAIN LANGUAGE SQLSCRIPT AS BEGIN\n`;
374
+ const renameResult = _toRename(csn, options);
375
+ let storedProcedure = `PROCEDURE RENAME_${renameResult.options.sqlMapping.toUpperCase()}_TO_PLAIN LANGUAGE SQLSCRIPT AS BEGIN\n`;
358
376
  for (const name in renameResult.rename) {
359
377
  storedProcedure += ` --\n -- ${name}\n --\n`;
360
378
  storedProcedure += renameResult.rename[name];
361
379
  }
362
380
  storedProcedure += 'END;\n';
363
- writeToFileOrDisplay(options.out, `storedProcedure_${renameResult.options.toRename.names}_to_plain.sql`, storedProcedure, true);
381
+ writeToFileOrDisplay(options.out, `storedProcedure_${renameResult.options.sqlMapping}_to_plain.sql`, storedProcedure, true);
364
382
  return model;
365
383
  }
366
384
 
@@ -382,21 +400,21 @@ function executeCommandLine(command, options, args) {
382
400
  // Return the original model (for chaining)
383
401
  function toSql( model ) {
384
402
  const csn = options.directBackend ? model : compactModel(model, options);
385
- if (options.toSql && options.toSql.src === 'hdi') {
386
- if (options.toSql.csn) {
387
- displayNamedCsn(for_hdi(csn, remapCmdOptions(options, options.toSql)), 'hdi_csn');
403
+ if (options.src === 'hdi') {
404
+ if (options.csn) {
405
+ displayNamedCsn(for_hdi(csn, options), 'hdi_csn');
388
406
  }
389
407
  else {
390
- const hdiResult = main.to.hdi(csn, remapCmdOptions(options, options.toSql));
408
+ const hdiResult = main.to.hdi(csn, options);
391
409
  for (const name in hdiResult)
392
410
  writeToFileOrDisplay(options.out, name, hdiResult[name]);
393
411
  }
394
412
  }
395
- else if (options.toSql && options.toSql.csn) {
396
- displayNamedCsn(for_sql(csn, remapCmdOptions(options, options.toSql)), 'sql_csn');
413
+ else if (options.csn) {
414
+ displayNamedCsn(for_sql(csn, options), 'sql_csn');
397
415
  }
398
416
  else {
399
- const sqlResult = main.to.sql(csn, remapCmdOptions(options, options.toSql));
417
+ const sqlResult = main.to.sql(csn, options);
400
418
  writeToFileOrDisplay(options.out, 'model.sql', sqlResult.join('\n'), true);
401
419
  }
402
420
  return model;
@@ -447,7 +465,7 @@ function executeCommandLine(command, options, args) {
447
465
  * @param {CompileMessage[]} messages
448
466
  */
449
467
  function displayMessages( model, messages = options.messages ) {
450
- if (!Array.isArray(messages))
468
+ if (!Array.isArray(messages) || options.quiet)
451
469
  return model;
452
470
 
453
471
  const log = console.error;
@@ -509,7 +527,7 @@ function executeCommandLine(command, options, args) {
509
527
  }
510
528
  else if (!options.lintMode) {
511
529
  const csn = compactModel(xsn, options);
512
- if (command === 'toCsn' && options.toCsn && options.toCsn.withLocalized)
530
+ if (command === 'toCsn' && options.withLocalized)
513
531
  addLocalizationViews(csn, options);
514
532
  if (options.enrichCsn)
515
533
  enrichCsn( csn, options );
@@ -528,7 +546,7 @@ function executeCommandLine(command, options, args) {
528
546
  writeToFileOrDisplay(options.out, `${name}_raw.txt`, options.messages, true);
529
547
  }
530
548
  else if (!options.lintMode && !options.internalMsg) {
531
- if (command === 'toCsn' && options.toCsn && options.toCsn.withLocalized)
549
+ if (command === 'toCsn' && options.withLocalized)
532
550
  addLocalizationViews(csn, options);
533
551
  writeToFileOrDisplay(options.out, `${name}.json`, csn, true);
534
552
  }
@@ -552,6 +570,8 @@ function executeCommandLine(command, options, args) {
552
570
  content = JSON.stringify(content, null, 2);
553
571
 
554
572
  if (dir === '-') {
573
+ if (options.quiet)
574
+ return;
555
575
  if (!omitHeadline) {
556
576
  const sqlTypes = {
557
577
  sql: true, hdbconstraint: true, hdbtable: true, hdbview: true,
@@ -569,15 +589,73 @@ function executeCommandLine(command, options, args) {
569
589
  fs.writeFileSync(path.join(dir, fileName), content);
570
590
  }
571
591
  }
592
+ }
572
593
 
573
- function catchErrors(err) {
574
- // @ts-ignore
575
- if (err instanceof Error && err.hasBeenReported)
576
- return;
577
- console.error( '' );
578
- console.error( 'INTERNAL ERROR:' );
579
- console.error( util.inspect(err, false, null) );
580
- console.error( '' );
581
- process.exitCode = 70;
594
+ function loadOptionsFromJson(cmdLine) {
595
+ try {
596
+ let opt = JSON.parse(fs.readFileSync(cmdLine.options.options, 'utf-8'));
597
+ if (opt.cds)
598
+ opt = opt.cds;
599
+ if (opt.cdsc)
600
+ opt = opt.cdsc;
601
+ Object.assign(cmdLine.options, opt);
602
+ return true;
603
+ }
604
+ catch (e) {
605
+ catchErrors(e);
606
+ return false;
607
+ }
608
+ }
609
+
610
+ function catchErrors(err) {
611
+ // @ts-ignore
612
+ if (err instanceof Error && err.hasBeenReported)
613
+ return;
614
+ console.error( '' );
615
+ console.error( 'INTERNAL ERROR:' );
616
+ console.error( util.inspect(err, false, null) );
617
+ console.error( '' );
618
+ process.exitCode = 70;
619
+ }
620
+
621
+ /**
622
+ * Parses the options `--error` and similar.
623
+ * Sets the dictionary `severities` on the given options.
624
+ *
625
+ * @param {object} options
626
+ */
627
+ function parseSeverityOptions({ options }) {
628
+ if (!options.severities)
629
+ options.severities = Object.create(null);
630
+
631
+ const severityMap = {
632
+ error: 'Error',
633
+ warn: 'Warning',
634
+ info: 'Info',
635
+ debug: 'Debug',
636
+ };
637
+
638
+ // Note: We use a for loop to ensure that the order of the options on the command line is respected, i.e.
639
+ // `--warn id --error id` would lead to `id` being reclassified as an error and not a warning.
640
+ for (const key in options) {
641
+ switch (key) {
642
+ case 'error':
643
+ case 'warn':
644
+ case 'info':
645
+ case 'debug':
646
+ parseSeverityOption(options[key], severityMap[key]);
647
+ break;
648
+ default:
649
+ break;
650
+ }
651
+ }
652
+
653
+ function parseSeverityOption(list, severity) {
654
+ const ids = list.split(',');
655
+ for (let id of ids) {
656
+ id = id.trim();
657
+ if (id)
658
+ options.severities[id] = severity;
659
+ }
582
660
  }
583
661
  }