@abaplint/cli 2.108.1 → 2.108.3

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 (2) hide show
  1. package/build/cli.js +104 -44
  2. package/package.json +2 -2
package/build/cli.js CHANGED
@@ -41422,8 +41422,8 @@ class Issue {
41422
41422
  severity,
41423
41423
  });
41424
41424
  }
41425
- static atStatement(file, statement, message, key, severity, fix) {
41426
- return this.atRange(file, statement.getStart(), statement.getEnd(), message, key, severity, fix);
41425
+ static atStatement(file, statement, message, key, severity, fix, alternativeFixes) {
41426
+ return this.atRange(file, statement.getStart(), statement.getEnd(), message, key, severity, fix, alternativeFixes);
41427
41427
  }
41428
41428
  static atPosition(file, start, message, key, severity, fix) {
41429
41429
  const row = start.getRow();
@@ -41453,7 +41453,7 @@ class Issue {
41453
41453
  severity,
41454
41454
  });
41455
41455
  }
41456
- static atRange(file, start, end, message, key, severity, fix) {
41456
+ static atRange(file, start, end, message, key, severity, fix, alternativeFixes) {
41457
41457
  severity = severity !== null && severity !== void 0 ? severity : severity_1.Severity.Error;
41458
41458
  return new Issue({
41459
41459
  filename: file.getFilename(),
@@ -41463,6 +41463,7 @@ class Issue {
41463
41463
  end,
41464
41464
  defaultFix: fix,
41465
41465
  severity,
41466
+ alternativeFixes,
41466
41467
  });
41467
41468
  }
41468
41469
  static atToken(file, token, message, key, severity, fix) {
@@ -42062,26 +42063,36 @@ class CodeActions {
42062
42063
  const ret = [];
42063
42064
  for (const i of issues) {
42064
42065
  const fix = i.getDefaultFix();
42065
- if (fix === undefined) {
42066
- continue;
42067
- }
42068
- if (totals[i.getKey()] === undefined) {
42069
- totals[i.getKey()] = 1;
42070
- }
42071
- else {
42072
- totals[i.getKey()]++;
42066
+ if (fix !== undefined) {
42067
+ if (totals[i.getKey()] === undefined) {
42068
+ totals[i.getKey()] = 1;
42069
+ }
42070
+ else {
42071
+ totals[i.getKey()]++;
42072
+ }
42073
+ if (this.inRange(i, params.range) === true) {
42074
+ ret.push({
42075
+ title: "Apply fix, " + i.getKey(),
42076
+ kind: LServer.CodeActionKind.QuickFix,
42077
+ diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
42078
+ isPreferred: true,
42079
+ edit: _edit_1.LSPEdit.mapEdit(fix),
42080
+ });
42081
+ shown.add(i.getKey());
42082
+ }
42073
42083
  }
42074
- if (this.inRange(i, params.range) === false) {
42075
- continue;
42084
+ for (const alternative of i.getAlternativeFixes() || []) {
42085
+ if (this.inRange(i, params.range) === true) {
42086
+ ret.push({
42087
+ title: alternative.description,
42088
+ kind: LServer.CodeActionKind.QuickFix,
42089
+ diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
42090
+ isPreferred: true,
42091
+ edit: _edit_1.LSPEdit.mapEdit(alternative.edit),
42092
+ });
42093
+ shown.add(i.getKey());
42094
+ }
42076
42095
  }
42077
- ret.push({
42078
- title: "Apply fix, " + i.getKey(),
42079
- kind: LServer.CodeActionKind.QuickFix,
42080
- diagnostics: [diagnostics_1.Diagnostics.mapDiagnostic(i)],
42081
- isPreferred: true,
42082
- edit: _edit_1.LSPEdit.mapEdit(fix),
42083
- });
42084
- shown.add(i.getKey());
42085
42096
  }
42086
42097
  for (const s of shown) {
42087
42098
  if (totals[s] > 1) {
@@ -51483,7 +51494,7 @@ class Registry {
51483
51494
  }
51484
51495
  static abaplintVersion() {
51485
51496
  // magic, see build script "version.sh"
51486
- return "2.108.1";
51497
+ return "2.108.3";
51487
51498
  }
51488
51499
  getDDICReferences() {
51489
51500
  return this.ddicReferences;
@@ -52518,6 +52529,8 @@ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./
52518
52529
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
52519
52530
  const issue_1 = __webpack_require__(/*! ../issue */ "./node_modules/@abaplint/core/build/src/issue.js");
52520
52531
  const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
52532
+ const position_1 = __webpack_require__(/*! ../position */ "./node_modules/@abaplint/core/build/src/position.js");
52533
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
52521
52534
  class AlignPseudoCommentsConf extends _basic_rule_config_1.BasicRuleConfig {
52522
52535
  }
52523
52536
  exports.AlignPseudoCommentsConf = AlignPseudoCommentsConf;
@@ -52531,7 +52544,7 @@ class AlignPseudoComments extends _abap_rule_1.ABAPRule {
52531
52544
  key: "align_pseudo_comments",
52532
52545
  title: "Align pseudo comments",
52533
52546
  shortDescription: `Align code inspector pseudo comments in statements`,
52534
- tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Whitespace],
52547
+ tags: [_irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix],
52535
52548
  badExample: `WRITE 'sdf'. "#EC sdf`,
52536
52549
  goodExample: `WRITE 'sdf'. "#EC sdf`,
52537
52550
  };
@@ -52558,16 +52571,22 @@ class AlignPseudoComments extends _abap_rule_1.ABAPRule {
52558
52571
  else if (previousEnd === undefined) {
52559
52572
  continue;
52560
52573
  }
52561
- else if (commentLength > 10) {
52562
- const expectedColumn = 72 - commentLength;
52563
- if (previousEnd.getCol() < expectedColumn && firstCommentToken.getStart().getCol() !== expectedColumn) {
52564
- const message = "Align pseudo comment to column " + expectedColumn;
52565
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
52566
- }
52574
+ let expectedColumn = 61;
52575
+ if (commentLength > 10) {
52576
+ expectedColumn = 72 - commentLength;
52567
52577
  }
52568
- else if (previousEnd.getCol() < 61 && firstCommentToken.getStart().getCol() !== 61) {
52569
- const message = "Align pseudo comment to column 61";
52570
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
52578
+ const col = firstCommentToken.getStart().getCol();
52579
+ if (previousEnd.getCol() < expectedColumn && col !== expectedColumn) {
52580
+ let fix = undefined;
52581
+ if (col < expectedColumn) {
52582
+ fix = edit_helper_1.EditHelper.insertAt(file, firstCommentToken.getStart(), " ".repeat(expectedColumn - col));
52583
+ }
52584
+ else {
52585
+ const from = new position_1.Position(firstCommentToken.getStart().getRow(), expectedColumn);
52586
+ fix = edit_helper_1.EditHelper.deleteRange(file, from, firstCommentToken.getStart());
52587
+ }
52588
+ const message = "Align pseudo comment to column " + expectedColumn;
52589
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, fix));
52571
52590
  }
52572
52591
  }
52573
52592
  return issues;
@@ -54304,6 +54323,7 @@ const _basic_rule_config_1 = __webpack_require__(/*! ./_basic_rule_config */ "./
54304
54323
  const _abap_rule_1 = __webpack_require__(/*! ./_abap_rule */ "./node_modules/@abaplint/core/build/src/rules/_abap_rule.js");
54305
54324
  const _irule_1 = __webpack_require__(/*! ./_irule */ "./node_modules/@abaplint/core/build/src/rules/_irule.js");
54306
54325
  const _statement_1 = __webpack_require__(/*! ../abap/2_statements/statements/_statement */ "./node_modules/@abaplint/core/build/src/abap/2_statements/statements/_statement.js");
54326
+ const edit_helper_1 = __webpack_require__(/*! ../edit_helper */ "./node_modules/@abaplint/core/build/src/edit_helper.js");
54307
54327
  class CheckSubrcConf extends _basic_rule_config_1.BasicRuleConfig {
54308
54328
  constructor() {
54309
54329
  super(...arguments);
@@ -54350,6 +54370,12 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
54350
54370
  setConfig(conf) {
54351
54371
  this.conf = conf;
54352
54372
  }
54373
+ buildFix(file, statement) {
54374
+ return {
54375
+ description: "Add ##SUBRC_OK",
54376
+ edit: edit_helper_1.EditHelper.insertAt(file, statement.getLastToken().getEnd(), " ##SUBRC_OK"),
54377
+ };
54378
+ }
54353
54379
  runParsed(file) {
54354
54380
  const issues = [];
54355
54381
  const statements = file.getStatements();
@@ -54364,11 +54390,13 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
54364
54390
  if (config.openDataset === true
54365
54391
  && statement.get() instanceof Statements.OpenDataset
54366
54392
  && this.isChecked(i, statements) === false) {
54393
+ // it doesnt make sense to ignore the subrc for open dataset, so no quick fix
54367
54394
  issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54368
54395
  }
54369
54396
  else if (config.authorityCheck === true
54370
54397
  && statement.get() instanceof Statements.AuthorityCheck
54371
54398
  && this.isChecked(i, statements) === false) {
54399
+ // it doesnt make sense to ignore the subrc for authority checks, so no quick fix
54372
54400
  issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54373
54401
  }
54374
54402
  else if (config.selectSingle === true
@@ -54380,7 +54408,8 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
54380
54408
  if (concat.startsWith("SELECT SINGLE @ABAP_TRUE FROM ")) {
54381
54409
  continue;
54382
54410
  }
54383
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54411
+ const fix = this.buildFix(file, statement);
54412
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54384
54413
  }
54385
54414
  else if (config.selectTable === true
54386
54415
  && statement.get() instanceof Statements.Select
@@ -54389,42 +54418,49 @@ FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
54389
54418
  && statement.concatTokens().toUpperCase().startsWith("SELECT COUNT(*) ") === false
54390
54419
  && this.isChecked(i, statements) === false
54391
54420
  && this.checksDbcnt(i, statements) === false) {
54392
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54421
+ const fix = this.buildFix(file, statement);
54422
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54393
54423
  }
54394
54424
  else if (config.updateDatabase === true
54395
54425
  && statement.get() instanceof Statements.UpdateDatabase
54396
54426
  && this.isChecked(i, statements) === false
54397
54427
  && this.checksDbcnt(i, statements) === false) {
54398
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54428
+ const fix = this.buildFix(file, statement);
54429
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54399
54430
  }
54400
54431
  else if (config.insertDatabase === true
54401
54432
  && statement.get() instanceof Statements.InsertDatabase
54402
54433
  && this.isChecked(i, statements) === false
54403
54434
  && this.checksDbcnt(i, statements) === false) {
54404
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54435
+ const fix = this.buildFix(file, statement);
54436
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54405
54437
  }
54406
54438
  else if (config.modifyDatabase === true
54407
54439
  && statement.get() instanceof Statements.ModifyDatabase
54408
54440
  && this.isChecked(i, statements) === false
54409
54441
  && this.checksDbcnt(i, statements) === false) {
54410
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54442
+ const fix = this.buildFix(file, statement);
54443
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54411
54444
  }
54412
54445
  else if (config.readTable === true
54413
54446
  && statement.get() instanceof Statements.ReadTable
54414
54447
  && this.isChecked(i, statements) === false) {
54415
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54448
+ const fix = this.buildFix(file, statement);
54449
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54416
54450
  }
54417
54451
  else if (config.assign === true
54418
54452
  && statement.get() instanceof Statements.Assign
54419
54453
  && this.isSimpleAssign(statement) === false
54420
54454
  && this.isChecked(i, statements) === false) {
54421
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54455
+ const fix = this.buildFix(file, statement);
54456
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54422
54457
  }
54423
54458
  else if (config.find === true
54424
54459
  && statement.get() instanceof Statements.Find
54425
54460
  && this.isExemptedFind(statement) === false
54426
54461
  && this.isChecked(i, statements) === false) {
54427
- issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity));
54462
+ const fix = this.buildFix(file, statement);
54463
+ issues.push(issue_1.Issue.atStatement(file, statement, message, this.getMetadata().key, this.conf.severity, undefined, [fix]));
54428
54464
  }
54429
54465
  }
54430
54466
  return issues;
@@ -59672,6 +59708,8 @@ class EmptyStructureConf extends _basic_rule_config_1.BasicRuleConfig {
59672
59708
  super(...arguments);
59673
59709
  /** Checks for empty LOOP blocks */
59674
59710
  this.loop = true;
59711
+ /** Allow empty LOOP if subrc is checked after the loop */
59712
+ this.loopAllowIfSubrc = true;
59675
59713
  /** Checks for empty IF blocks */
59676
59714
  this.if = true;
59677
59715
  /** Checks for empty WHILE blocks */
@@ -59704,6 +59742,14 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
59704
59742
  shortDescription: `Checks that the code does not contain empty blocks.`,
59705
59743
  extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#no-empty-if-branches`,
59706
59744
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
59745
+ badExample: `IF foo = bar.
59746
+ ENDIF.
59747
+
59748
+ DO 2 TIMES.
59749
+ ENDDO.`,
59750
+ goodExample: `LOOP AT itab WHERE qty = 0 OR date > sy-datum.
59751
+ ENDLOOP.
59752
+ result = xsdbool( sy-subrc = 0 ).`,
59707
59753
  };
59708
59754
  }
59709
59755
  getDescription(name) {
@@ -59721,15 +59767,13 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
59721
59767
  if (stru === undefined) {
59722
59768
  return [];
59723
59769
  }
59724
- for (const statement of file.getStatements()) {
59770
+ const statements = file.getStatements();
59771
+ for (const statement of statements) {
59725
59772
  if (statement.get() instanceof _statement_1.Unknown) {
59726
59773
  return []; // contains parser errors
59727
59774
  }
59728
59775
  }
59729
59776
  const candidates = [];
59730
- if (this.getConfig().loop === true) {
59731
- candidates.push(...stru.findAllStructuresRecursive(Structures.Loop));
59732
- }
59733
59777
  if (this.getConfig().while === true) {
59734
59778
  candidates.push(...stru.findAllStructuresRecursive(Structures.While));
59735
59779
  }
@@ -59765,6 +59809,22 @@ class EmptyStructure extends _abap_rule_1.ABAPRule {
59765
59809
  }
59766
59810
  }
59767
59811
  }
59812
+ if (this.getConfig().loop === true) {
59813
+ const loops = stru.findAllStructuresRecursive(Structures.Loop);
59814
+ for (const loop of loops) {
59815
+ if (loop.getChildren().length === 2) {
59816
+ const endloopStatement = loop.getLastChild();
59817
+ const endloopIndex = statements.findIndex((s) => s === endloopStatement);
59818
+ const afterEndloop = statements[endloopIndex + 1];
59819
+ if (afterEndloop !== undefined && afterEndloop.concatTokens().toUpperCase().includes("SY-SUBRC")) {
59820
+ continue;
59821
+ }
59822
+ const token = loop.getFirstToken();
59823
+ const issue = issue_1.Issue.atToken(file, token, this.getDescription(loop.get().constructor.name), this.getMetadata().key, this.conf.severity);
59824
+ issues.push(issue);
59825
+ }
59826
+ }
59827
+ }
59768
59828
  if (this.getConfig().if === true) {
59769
59829
  const tries = stru.findAllStructuresRecursive(Structures.If)
59770
59830
  .concat(stru.findAllStructuresRecursive(Structures.Else))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abaplint/cli",
3
- "version": "2.108.1",
3
+ "version": "2.108.3",
4
4
  "description": "abaplint - Command Line Interface",
5
5
  "funding": "https://github.com/sponsors/larshp",
6
6
  "bin": {
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "homepage": "https://abaplint.org",
40
40
  "devDependencies": {
41
- "@abaplint/core": "^2.108.1",
41
+ "@abaplint/core": "^2.108.3",
42
42
  "@types/chai": "^4.3.16",
43
43
  "@types/glob": "^8.1.0",
44
44
  "@types/minimist": "^1.2.5",