@abaplint/core 2.79.18 → 2.79.22

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 (77) hide show
  1. package/README.md +6 -6
  2. package/build/abaplint.d.ts +1 -0
  3. package/build/src/abap/5_syntax/_builtin.js +50 -50
  4. package/build/src/abap/5_syntax/basic_types.js +7 -1
  5. package/build/src/abap/5_syntax/expressions/method_source.js +8 -2
  6. package/build/src/abap/5_syntax/statements/tables.js +1 -1
  7. package/build/src/ddic.js +6 -6
  8. package/build/src/ddic_references.js +44 -16
  9. package/build/src/lsp/_lookup.js +14 -5
  10. package/build/src/lsp/help.js +7 -7
  11. package/build/src/objects/assignment_service_to_authorization_group.js +1 -1
  12. package/build/src/registry.js +1 -1
  13. package/build/src/rules/abapdoc.js +1 -1
  14. package/build/src/rules/ambiguous_statement.js +5 -5
  15. package/build/src/rules/avoid_use.js +6 -6
  16. package/build/src/rules/begin_end_names.js +4 -4
  17. package/build/src/rules/begin_single_include.js +12 -12
  18. package/build/src/rules/chain_mainly_declarations.js +4 -4
  19. package/build/src/rules/check_abstract.js +2 -2
  20. package/build/src/rules/check_comments.js +3 -3
  21. package/build/src/rules/check_include.js +3 -3
  22. package/build/src/rules/check_no_handler_pragma.js +8 -8
  23. package/build/src/rules/check_subrc.js +8 -8
  24. package/build/src/rules/commented_code.js +1 -1
  25. package/build/src/rules/constructor_visibility_public.js +4 -4
  26. package/build/src/rules/contains_tab.js +2 -2
  27. package/build/src/rules/downport.js +103 -43
  28. package/build/src/rules/exit_or_check.js +3 -3
  29. package/build/src/rules/exporting.js +1 -1
  30. package/build/src/rules/forbidden_identifier.js +1 -1
  31. package/build/src/rules/forbidden_void_type.js +2 -2
  32. package/build/src/rules/functional_writing.js +17 -17
  33. package/build/src/rules/global_class.js +4 -4
  34. package/build/src/rules/identical_conditions.js +2 -2
  35. package/build/src/rules/identical_contents.js +15 -15
  36. package/build/src/rules/identical_descriptions.js +4 -4
  37. package/build/src/rules/if_in_if.js +7 -7
  38. package/build/src/rules/implement_methods.js +3 -3
  39. package/build/src/rules/in_statement_indentation.js +11 -11
  40. package/build/src/rules/intf_referencing_clas.js +3 -3
  41. package/build/src/rules/line_break_style.js +2 -2
  42. package/build/src/rules/line_length.js +1 -1
  43. package/build/src/rules/line_only_punc.js +1 -1
  44. package/build/src/rules/local_variable_names.js +2 -2
  45. package/build/src/rules/many_parentheses.js +10 -10
  46. package/build/src/rules/max_one_method_parameter_per_line.js +7 -7
  47. package/build/src/rules/max_one_statement.js +3 -3
  48. package/build/src/rules/nesting.js +1 -1
  49. package/build/src/rules/no_public_attributes.js +1 -1
  50. package/build/src/rules/no_yoda_conditions.js +4 -4
  51. package/build/src/rules/obsolete_statement.js +36 -36
  52. package/build/src/rules/omit_parameter_name.js +3 -3
  53. package/build/src/rules/omit_receiving.js +13 -13
  54. package/build/src/rules/parser_702_chaining.js +2 -2
  55. package/build/src/rules/parser_error.js +2 -2
  56. package/build/src/rules/parser_missing_space.js +1 -1
  57. package/build/src/rules/prefer_inline.js +16 -16
  58. package/build/src/rules/prefer_is_not.js +7 -7
  59. package/build/src/rules/prefer_raise_exception_new.js +3 -3
  60. package/build/src/rules/prefer_returning_to_exporting.js +1 -1
  61. package/build/src/rules/prefer_xsdbool.js +2 -2
  62. package/build/src/rules/remove_descriptions.js +4 -4
  63. package/build/src/rules/rfc_error_handling.js +9 -9
  64. package/build/src/rules/select_add_order_by.js +5 -5
  65. package/build/src/rules/select_performance.js +2 -2
  66. package/build/src/rules/sicf_consistency.js +4 -4
  67. package/build/src/rules/space_before_dot.js +2 -2
  68. package/build/src/rules/start_at_tab.js +1 -1
  69. package/build/src/rules/sy_modification.js +2 -2
  70. package/build/src/rules/tabl_enhancement_category.js +2 -2
  71. package/build/src/rules/unused_methods.js +9 -9
  72. package/build/src/rules/unused_variables.js +6 -6
  73. package/build/src/rules/use_bool_expression.js +8 -8
  74. package/build/src/rules/use_line_exists.js +6 -6
  75. package/build/src/rules/use_new.js +2 -2
  76. package/build/src/rules/when_others_last.js +6 -6
  77. package/package.json +76 -76
@@ -34,14 +34,14 @@ class CheckSubrc extends _abap_rule_1.ABAPRule {
34
34
  key: "check_subrc",
35
35
  title: "Check sy-subrc",
36
36
  shortDescription: `Check sy-subrc`,
37
- extendedInformation: `Pseudo comment "#EC CI_SUBRC can be added to suppress findings
38
-
39
- If sy-dbcnt is checked after database statements, it is considered okay.
40
-
41
- "SELECT SINGLE @abap_true FROM " is considered as an existence check
42
-
43
- If IS ASSIGNED is checked after assigning, it is considered okay.
44
-
37
+ extendedInformation: `Pseudo comment "#EC CI_SUBRC can be added to suppress findings
38
+
39
+ If sy-dbcnt is checked after database statements, it is considered okay.
40
+
41
+ "SELECT SINGLE @abap_true FROM " is considered as an existence check
42
+
43
+ If IS ASSIGNED is checked after assigning, it is considered okay.
44
+
45
45
  FIND statement with MATCH COUNT is considered okay if subrc is not checked`,
46
46
  tags: [_irule_1.RuleTag.SingleFile],
47
47
  pseudoComment: "EC CI_SUBRC",
@@ -30,7 +30,7 @@ class CommentedCode extends _abap_rule_1.ABAPRule {
30
30
  key: "commented_code",
31
31
  title: "Find commented code",
32
32
  shortDescription: `Detects usage of commented out code.`,
33
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#delete-code-instead-of-commenting-it
33
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#delete-code-instead-of-commenting-it
34
34
  https://docs.abapopenchecks.org/checks/14/`,
35
35
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
36
36
  };
@@ -18,10 +18,10 @@ class ConstructorVisibilityPublic {
18
18
  key: "constructor_visibility_public",
19
19
  title: "Check constructor visibility is public",
20
20
  shortDescription: `Constructor must be placed in the public section, even if the class is not CREATE PUBLIC.`,
21
- extendedInformation: `
22
- This only applies to global classes.
23
-
24
- https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#if-your-global-class-is-create-private-leave-the-constructor-public
21
+ extendedInformation: `
22
+ This only applies to global classes.
23
+
24
+ https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#if-your-global-class-is-create-private-leave-the-constructor-public
25
25
  https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abeninstance_constructor_guidl.htm`,
26
26
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
27
27
  };
@@ -25,8 +25,8 @@ class ContainsTab extends _abap_rule_1.ABAPRule {
25
25
  key: "contains_tab",
26
26
  title: "Code contains tab",
27
27
  shortDescription: `Checks for usage of tabs (enable to enforce spaces)`,
28
- extendedInformation: `
29
- https://docs.abapopenchecks.org/checks/09/
28
+ extendedInformation: `
29
+ https://docs.abapopenchecks.org/checks/09/
30
30
  https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#indent-and-snap-to-tab`,
31
31
  tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
32
32
  };
@@ -5,6 +5,7 @@ const _basic_rule_config_1 = require("./_basic_rule_config");
5
5
  const issue_1 = require("../issue");
6
6
  const _irule_1 = require("./_irule");
7
7
  const _statement_1 = require("../abap/2_statements/statements/_statement");
8
+ const nodes_1 = require("../abap/nodes");
8
9
  const Statements = require("../abap/2_statements/statements");
9
10
  const Expressions = require("../abap/2_statements/expressions");
10
11
  const edit_helper_1 = require("../edit_helper");
@@ -30,25 +31,26 @@ class Downport {
30
31
  key: "downport",
31
32
  title: "Downport statement",
32
33
  shortDescription: `Experimental downport functionality`,
33
- extendedInformation: `Much like the 'commented_code' rule this rule loops through unknown statements and tries parsing with
34
- a higher level language version. If successful, various rules are applied to downport the statement.
35
- Target downport version is always v702, thus rule is only enabled if target version is v702.
36
-
37
- Current rules:
38
- * NEW transformed to CREATE OBJECT, opposite of https://rules.abaplint.org/use_new/
39
- * DATA() definitions are outlined, opposite of https://rules.abaplint.org/prefer_inline/
40
- * FIELD-SYMBOL() definitions are outlined
41
- * CONV is outlined
42
- * EMPTY KEY is changed to DEFAULT KEY, opposite of DEFAULT KEY in https://rules.abaplint.org/avoid_use/
43
- * CAST changed to ?=
44
- * LOOP AT method_call( ) is outlined
45
- * VALUE # with structure fields
46
- * VALUE # with internal table lines
47
- * Table Expressions[ index ] are outlined
48
- * SELECT INTO @DATA definitions are outlined
49
- * Some occurrences of string template formatting option ALPHA changed to function module call
50
- * SELECT/INSERT/MODIFY/DELETE/UPDATE "," in field list removed, "@" in source/targets removed
51
-
34
+ extendedInformation: `Much like the 'commented_code' rule this rule loops through unknown statements and tries parsing with
35
+ a higher level language version. If successful, various rules are applied to downport the statement.
36
+ Target downport version is always v702, thus rule is only enabled if target version is v702.
37
+
38
+ Current rules:
39
+ * NEW transformed to CREATE OBJECT, opposite of https://rules.abaplint.org/use_new/
40
+ * DATA() definitions are outlined, opposite of https://rules.abaplint.org/prefer_inline/
41
+ * FIELD-SYMBOL() definitions are outlined
42
+ * CONV is outlined
43
+ * COND is outlined
44
+ * EMPTY KEY is changed to DEFAULT KEY, opposite of DEFAULT KEY in https://rules.abaplint.org/avoid_use/
45
+ * CAST changed to ?=
46
+ * LOOP AT method_call( ) is outlined
47
+ * VALUE # with structure fields
48
+ * VALUE # with internal table lines
49
+ * Table Expressions[ index ] are outlined
50
+ * SELECT INTO @DATA definitions are outlined
51
+ * Some occurrences of string template formatting option ALPHA changed to function module call
52
+ * SELECT/INSERT/MODIFY/DELETE/UPDATE "," in field list removed, "@" in source/targets removed
53
+
52
54
  Only one transformation is applied to a statement at a time, so multiple steps might be required to do the full downport.`,
53
55
  tags: [_irule_1.RuleTag.Experimental, _irule_1.RuleTag.Downport, _irule_1.RuleTag.Quickfix],
54
56
  };
@@ -175,6 +177,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
175
177
  if (found) {
176
178
  return found;
177
179
  }
180
+ found = this.outlineCond(high, lowFile, highSyntax);
181
+ if (found) {
182
+ return found;
183
+ }
178
184
  found = this.outlineDataSimple(high, lowFile);
179
185
  if (found) {
180
186
  return found;
@@ -294,10 +300,10 @@ Only one transformation is applied to a statement at a time, so multiple steps m
294
300
  const fieldName = f.concatTokens();
295
301
  fieldDefinition += indentation + " " + fieldName + " TYPE " + tableName + "-" + fieldName + ",\n";
296
302
  }
297
- fieldDefinition = `DATA: BEGIN OF ${name},
303
+ fieldDefinition = `DATA: BEGIN OF ${name},
298
304
  ${fieldDefinition}${indentation} END OF ${name}.`;
299
305
  }
300
- const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
306
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `${fieldDefinition}
301
307
  ${indentation}`);
302
308
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
303
309
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
@@ -333,9 +339,9 @@ ${indentation}`);
333
339
  }
334
340
  const uniqueName = this.uniqueName(high.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
335
341
  const name = ((_c = inlineData.findFirstExpression(Expressions.TargetField)) === null || _c === void 0 ? void 0 : _c.concatTokens()) || "error";
336
- const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `TYPES: BEGIN OF ${uniqueName},
337
- ${fieldDefinitions}${indentation} END OF ${uniqueName}.
338
- ${indentation}DATA ${name} TYPE STANDARD TABLE OF ${uniqueName} WITH DEFAULT KEY.
342
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, high.getStart(), `TYPES: BEGIN OF ${uniqueName},
343
+ ${fieldDefinitions}${indentation} END OF ${uniqueName}.
344
+ ${indentation}DATA ${name} TYPE STANDARD TABLE OF ${uniqueName} WITH DEFAULT KEY.
339
345
  ${indentation}`);
340
346
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, inlineData.getFirstToken().getStart(), inlineData.getLastToken().getEnd(), name);
341
347
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
@@ -369,11 +375,11 @@ ${indentation}`);
369
375
  const uniqueName = this.uniqueName(node.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
370
376
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
371
377
  const firstToken = node.getFirstToken();
372
- const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
373
- ${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
374
- ${indentation}IF sy-subrc <> 0.
375
- ${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
376
- ${indentation}ENDIF.
378
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, firstToken.getStart(), `DATA ${uniqueName} LIKE LINE OF ${pre}.
379
+ ${indentation}READ TABLE ${pre} INDEX ${(_a = tableExpression.findFirstExpression(Expressions.Source)) === null || _a === void 0 ? void 0 : _a.concatTokens()} INTO ${uniqueName}.
380
+ ${indentation}IF sy-subrc <> 0.
381
+ ${indentation} RAISE EXCEPTION TYPE cx_sy_itab_line_not_found.
382
+ ${indentation}ENDIF.
377
383
  ${indentation}`);
378
384
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, startToken.getStart(), tableExpression.getLastToken().getEnd(), uniqueName);
379
385
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
@@ -424,7 +430,7 @@ ${indentation}`);
424
430
  }
425
431
  i = key;
426
432
  const concat = i.concatTokens();
427
- if (concat.includes("WITH EMPTY KEY") === false) {
433
+ if (concat.toUpperCase().includes("WITH EMPTY KEY") === false) {
428
434
  continue;
429
435
  }
430
436
  const token = i.findDirectTokenByText("EMPTY");
@@ -472,10 +478,10 @@ ${indentation}`);
472
478
  const indentation = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
473
479
  const source = (_b = templateSource === null || templateSource === void 0 ? void 0 : templateSource.findDirectExpression(Expressions.Source)) === null || _b === void 0 ? void 0 : _b.concatTokens();
474
480
  const topTarget = (_c = node.findDirectExpression(Expressions.Target)) === null || _c === void 0 ? void 0 : _c.concatTokens();
475
- const code = `CALL FUNCTION '${functionName}'
476
- ${indentation} EXPORTING
477
- ${indentation} input = ${source}
478
- ${indentation} IMPORTING
481
+ const code = `CALL FUNCTION '${functionName}'
482
+ ${indentation} EXPORTING
483
+ ${indentation} input = ${source}
484
+ ${indentation} IMPORTING
479
485
  ${indentation} output = ${topTarget}.`;
480
486
  const fix = edit_helper_1.EditHelper.replaceRange(lowFile, node.getFirstToken().getStart(), node.getLastToken().getEnd(), code);
481
487
  return issue_1.Issue.atToken(lowFile, node.getFirstToken(), "Downport ALPHA", this.getMetadata().key, this.conf.severity, fix);
@@ -582,12 +588,13 @@ ${indentation} output = ${topTarget}.`;
582
588
  return undefined;
583
589
  }
584
590
  findType(i, lowFile, highSyntax) {
591
+ var _a;
585
592
  const expr = i.findDirectExpression(Expressions.TypeNameOrInfer);
586
593
  if (expr === undefined) {
587
594
  return undefined;
588
595
  }
589
596
  const firstToken = expr.getFirstToken();
590
- const concat = expr.concatTokens();
597
+ const concat = expr.concatTokens().toLowerCase();
591
598
  if (concat !== "#") {
592
599
  return concat;
593
600
  }
@@ -608,10 +615,10 @@ ${indentation} output = ${topTarget}.`;
608
615
  if (inferred === undefined) {
609
616
  return undefined;
610
617
  }
611
- return inferred.getType().getQualifiedName();
618
+ return (_a = inferred.getType().getQualifiedName()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
612
619
  }
613
620
  outlineFS(node, lowFile, highSyntax) {
614
- var _a;
621
+ var _a, _b;
615
622
  for (const i of node.findAllExpressionsRecursive(Expressions.InlineFS)) {
616
623
  const nameToken = (_a = i.findDirectExpression(Expressions.TargetFieldSymbol)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
617
624
  if (nameToken === undefined) {
@@ -629,7 +636,7 @@ ${indentation} output = ${topTarget}.`;
629
636
  else if (found.getType() instanceof basic_1.VoidType) {
630
637
  return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
631
638
  }
632
- const type = found.getType().getQualifiedName() ? found.getType().getQualifiedName() : found.getType().toABAP();
639
+ const type = found.getType().getQualifiedName() ? (_b = found.getType().getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toLowerCase() : found.getType().toABAP();
633
640
  const code = `FIELD-SYMBOLS ${name} TYPE ${type}.\n` +
634
641
  " ".repeat(node.getFirstToken().getStart().getCol() - 1);
635
642
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
@@ -640,7 +647,7 @@ ${indentation} output = ${topTarget}.`;
640
647
  return undefined;
641
648
  }
642
649
  outlineData(node, lowFile, highSyntax) {
643
- var _a;
650
+ var _a, _b;
644
651
  for (const i of node.findAllExpressionsRecursive(Expressions.InlineData)) {
645
652
  const nameToken = (_a = i.findDirectExpression(Expressions.TargetField)) === null || _a === void 0 ? void 0 : _a.getFirstToken();
646
653
  if (nameToken === undefined) {
@@ -658,7 +665,7 @@ ${indentation} output = ${topTarget}.`;
658
665
  else if (found.getType() instanceof basic_1.VoidType) {
659
666
  return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Error outlining voided type", this.getMetadata().key, this.conf.severity);
660
667
  }
661
- const type = found.getType().getQualifiedName() ? found.getType().getQualifiedName() : found.getType().toABAP();
668
+ const type = found.getType().getQualifiedName() ? (_b = found.getType().getQualifiedName()) === null || _b === void 0 ? void 0 : _b.toLowerCase() : found.getType().toABAP();
662
669
  const code = `DATA ${name} TYPE ${type}.\n` +
663
670
  " ".repeat(node.getFirstToken().getStart().getCol() - 1);
664
671
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), code);
@@ -668,6 +675,59 @@ ${indentation} output = ${topTarget}.`;
668
675
  }
669
676
  return undefined;
670
677
  }
678
+ outlineCond(node, lowFile, highSyntax) {
679
+ for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
680
+ if (i.getFirstToken().getStr().toUpperCase() !== "COND") {
681
+ continue;
682
+ }
683
+ const body = i.findDirectExpression(Expressions.CondBody);
684
+ if (body === undefined) {
685
+ continue;
686
+ }
687
+ const uniqueName = this.uniqueName(i.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
688
+ const type = this.findType(i, lowFile, highSyntax);
689
+ const indent = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
690
+ const bodyCode = this.buildCondBody(body, uniqueName, indent);
691
+ const abap = `DATA ${uniqueName} TYPE ${type}.\n` + bodyCode;
692
+ const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
693
+ const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, i.getFirstToken().getStart(), i.getLastToken().getEnd(), uniqueName);
694
+ const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
695
+ return issue_1.Issue.atToken(lowFile, i.getFirstToken(), "Downport COND", this.getMetadata().key, this.conf.severity, fix);
696
+ }
697
+ return undefined;
698
+ }
699
+ buildCondBody(body, uniqueName, indent) {
700
+ let code = indent;
701
+ for (const c of body.getChildren()) {
702
+ if (c instanceof nodes_1.TokenNode) {
703
+ switch (c.getFirstToken().getStr().toUpperCase()) {
704
+ case "WHEN":
705
+ code += "IF ";
706
+ break;
707
+ case "THEN":
708
+ code += ".\n";
709
+ break;
710
+ case "ELSE":
711
+ code += indent + "ELSE.\n";
712
+ break;
713
+ default:
714
+ throw "buildCondBody, unexpected token";
715
+ }
716
+ }
717
+ else if (c.get() instanceof Expressions.Cond) {
718
+ code += c.concatTokens();
719
+ }
720
+ else if (c.get() instanceof Expressions.Source) {
721
+ code += indent + " " + uniqueName + " = " + c.concatTokens() + ".\n";
722
+ }
723
+ else {
724
+ throw "buildCondBody, unexpected expression";
725
+ }
726
+ }
727
+ code += indent + "ENDIF.\n";
728
+ code += indent;
729
+ return code;
730
+ }
671
731
  outlineConv(node, lowFile, highSyntax) {
672
732
  var _a;
673
733
  for (const i of node.findAllExpressionsRecursive(Expressions.Source)) {
@@ -680,10 +740,10 @@ ${indentation} output = ${topTarget}.`;
680
740
  }
681
741
  const uniqueName = this.uniqueName(i.getFirstToken().getStart(), lowFile.getFilename(), highSyntax);
682
742
  const type = this.findType(i, lowFile, highSyntax);
743
+ const indent = " ".repeat(node.getFirstToken().getStart().getCol() - 1);
683
744
  const abap = `DATA ${uniqueName} TYPE ${type}.\n` +
684
- " ".repeat(node.getFirstToken().getStart().getCol() - 1) +
685
- `${uniqueName} = ${body}.\n` +
686
- " ".repeat(node.getFirstToken().getStart().getCol() - 1);
745
+ indent + `${uniqueName} = ${body}.\n` +
746
+ indent;
687
747
  const fix1 = edit_helper_1.EditHelper.insertAt(lowFile, node.getFirstToken().getStart(), abap);
688
748
  const fix2 = edit_helper_1.EditHelper.replaceRange(lowFile, i.getFirstToken().getStart(), i.getLastToken().getEnd(), uniqueName);
689
749
  const fix = edit_helper_1.EditHelper.merge(fix2, fix1);
@@ -24,10 +24,10 @@ class ExitOrCheck extends _abap_rule_1.ABAPRule {
24
24
  return {
25
25
  key: "exit_or_check",
26
26
  title: "Find EXIT or CHECK outside loops",
27
- shortDescription: `Detects usages of EXIT or CHECK statements outside of loops.
27
+ shortDescription: `Detects usages of EXIT or CHECK statements outside of loops.
28
28
  Use RETURN to leave procesing blocks instead.`,
29
- extendedInformation: `https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenleave_processing_blocks.htm
30
- https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapcheck_processing_blocks.htm
29
+ extendedInformation: `https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenleave_processing_blocks.htm
30
+ https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapcheck_processing_blocks.htm
31
31
  https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#check-vs-return`,
32
32
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile, _irule_1.RuleTag.Quickfix],
33
33
  };
@@ -22,7 +22,7 @@ class Exporting extends _abap_rule_1.ABAPRule {
22
22
  shortDescription: `Detects EXPORTING statements which can be omitted.`,
23
23
  badExample: `call_method( EXPORTING foo = bar ).`,
24
24
  goodExample: `call_method( foo = bar ).`,
25
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#omit-the-optional-keyword-exporting
25
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#omit-the-optional-keyword-exporting
26
26
  https://docs.abapopenchecks.org/checks/30/`,
27
27
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
28
28
  };
@@ -26,7 +26,7 @@ class ForbiddenIdentifier extends _abap_rule_1.ABAPRule {
26
26
  key: "forbidden_identifier",
27
27
  title: "Forbidden Identifier",
28
28
  shortDescription: `Forbid use of specified identifiers, list of regex.`,
29
- extendedInformation: `Used in the transpiler to find javascript keywords in ABAP identifiers,
29
+ extendedInformation: `Used in the transpiler to find javascript keywords in ABAP identifiers,
30
30
  https://github.com/abaplint/transpiler/blob/bda94b8b56e2b7f2f87be2168f12361aa530220e/packages/transpiler/src/validation.ts#L44`,
31
31
  tags: [_irule_1.RuleTag.SingleFile],
32
32
  };
@@ -28,8 +28,8 @@ class ForbiddenVoidType {
28
28
  key: "forbidden_void_type",
29
29
  title: "Forbidden Void Types",
30
30
  shortDescription: `Avoid usage of specified void types.`,
31
- extendedInformation: `Inspiration:
32
- BOOLEAN, BOOLE_D, CHAR01, CHAR1, CHAR10, CHAR12, CHAR128, CHAR2, CHAR20, CHAR4, CHAR70,
31
+ extendedInformation: `Inspiration:
32
+ BOOLEAN, BOOLE_D, CHAR01, CHAR1, CHAR10, CHAR12, CHAR128, CHAR2, CHAR20, CHAR4, CHAR70,
33
33
  DATS, TIMS, DATUM, FLAG, INT4, NUMC3, NUMC4, SAP_BOOL, TEXT25, TEXT80, X255, XFELD`,
34
34
  };
35
35
  }
@@ -28,26 +28,26 @@ class FunctionalWriting extends _abap_rule_1.ABAPRule {
28
28
  key: "functional_writing",
29
29
  title: "Use functional writing",
30
30
  shortDescription: `Detects usage of call method when functional style calls can be used.`,
31
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-functional-to-procedural-calls
31
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#prefer-functional-to-procedural-calls
32
32
  https://docs.abapopenchecks.org/checks/07/`,
33
33
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
34
- badExample: `CALL METHOD zcl_class=>method( ).
35
- CALL METHOD cl_abap_typedescr=>describe_by_name
36
- EXPORTING
37
- p_name = 'NAME'
38
- RECEIVING
39
- p_descr_ref = lr_typedescr
40
- EXCEPTIONS
41
- type_not_found = 1
34
+ badExample: `CALL METHOD zcl_class=>method( ).
35
+ CALL METHOD cl_abap_typedescr=>describe_by_name
36
+ EXPORTING
37
+ p_name = 'NAME'
38
+ RECEIVING
39
+ p_descr_ref = lr_typedescr
40
+ EXCEPTIONS
41
+ type_not_found = 1
42
42
  OTHERS = 2.`,
43
- goodExample: `zcl_class=>method( ).
44
- cl_abap_typedescr=>describe_by_name(
45
- EXPORTING
46
- p_name = 'NAME'
47
- RECEIVING
48
- p_descr_ref = lr_typedescr
49
- EXCEPTIONS
50
- type_not_found = 1
43
+ goodExample: `zcl_class=>method( ).
44
+ cl_abap_typedescr=>describe_by_name(
45
+ EXPORTING
46
+ p_name = 'NAME'
47
+ RECEIVING
48
+ p_descr_ref = lr_typedescr
49
+ EXCEPTIONS
50
+ type_not_found = 1
51
51
  OTHERS = 2 ).`,
52
52
  };
53
53
  }
@@ -18,10 +18,10 @@ class GlobalClass extends _abap_rule_1.ABAPRule {
18
18
  return {
19
19
  key: "global_class",
20
20
  title: "Global class checks",
21
- shortDescription: `Checks related to global classes.
22
- * global classes must be in own files
23
- * file names must match class name
24
- * global classes must be global definitions
21
+ shortDescription: `Checks related to global classes.
22
+ * global classes must be in own files
23
+ * file names must match class name
24
+ * global classes must be global definitions
25
25
  * global interfaces must be global definitions`,
26
26
  tags: [_irule_1.RuleTag.Syntax],
27
27
  };
@@ -33,8 +33,8 @@ class IdenticalConditions extends _abap_rule_1.ABAPRule {
33
33
  return {
34
34
  key: "identical_conditions",
35
35
  title: "Identical conditions",
36
- shortDescription: `Find identical conditions in IF + CASE + WHILE etc
37
-
36
+ shortDescription: `Find identical conditions in IF + CASE + WHILE etc
37
+
38
38
  Prerequsites: code is pretty printed with identical cAsE`,
39
39
  tags: [_irule_1.RuleTag.SingleFile],
40
40
  };
@@ -19,24 +19,24 @@ class IdenticalContents extends _abap_rule_1.ABAPRule {
19
19
  return {
20
20
  key: "identical_contents",
21
21
  title: "Identical contents",
22
- shortDescription: `Find identical contents in blocks inside IFs, both in the beginning and in the end.
23
-
24
- Prerequsites: code is pretty printed with identical cAsE
25
-
22
+ shortDescription: `Find identical contents in blocks inside IFs, both in the beginning and in the end.
23
+
24
+ Prerequsites: code is pretty printed with identical cAsE
25
+
26
26
  Chained statments are ignored`,
27
27
  tags: [_irule_1.RuleTag.SingleFile],
28
- badExample: `IF foo = bar.
29
- WRITE 'bar'.
30
- WRITE 'world'.
31
- ELSE.
32
- WRITE 'foo'.
33
- WRITE 'world'.
28
+ badExample: `IF foo = bar.
29
+ WRITE 'bar'.
30
+ WRITE 'world'.
31
+ ELSE.
32
+ WRITE 'foo'.
33
+ WRITE 'world'.
34
34
  ENDIF.`,
35
- goodExample: `IF foo = bar.
36
- WRITE 'bar'.
37
- ELSE.
38
- WRITE 'foo'.
39
- ENDIF.
35
+ goodExample: `IF foo = bar.
36
+ WRITE 'bar'.
37
+ ELSE.
38
+ WRITE 'foo'.
39
+ ENDIF.
40
40
  WRITE 'world'.`,
41
41
  };
42
42
  }
@@ -16,10 +16,10 @@ class IdenticalDescriptions {
16
16
  key: "identical_descriptions",
17
17
  title: "Identical descriptions",
18
18
  shortDescription: `Searches for objects with the same type and same description`,
19
- extendedInformation: `Case insensitive
20
-
21
- Only checks the master language descriptions
22
-
19
+ extendedInformation: `Case insensitive
20
+
21
+ Only checks the master language descriptions
22
+
23
23
  Works for: INTF, CLAS, DOMA, DTEL, FUNC in same FUGR`,
24
24
  tags: [],
25
25
  };
@@ -19,15 +19,15 @@ class IfInIf extends _abap_rule_1.ABAPRule {
19
19
  key: "if_in_if",
20
20
  title: "IF in IF",
21
21
  shortDescription: `Detects nested ifs which can be refactored to a single condition using AND.`,
22
- extendedInformation: `https://docs.abapopenchecks.org/checks/01/
22
+ extendedInformation: `https://docs.abapopenchecks.org/checks/01/
23
23
  https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low`,
24
- badExample: `IF condition1.
25
- IF condition2.
26
- ...
27
- ENDIF.
24
+ badExample: `IF condition1.
25
+ IF condition2.
26
+ ...
27
+ ENDIF.
28
28
  ENDIF.`,
29
- goodExample: `IF ( condition1 ) AND ( condition2 ).
30
- ...
29
+ goodExample: `IF ( condition1 ) AND ( condition2 ).
30
+ ...
31
31
  ENDIF.`,
32
32
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
33
33
  };
@@ -97,9 +97,9 @@ class ImplementMethods extends _abap_rule_1.ABAPRule {
97
97
  for (const i of ((_a = file.getStructure()) === null || _a === void 0 ? void 0 : _a.findAllStatements(Statements.ClassImplementation)) || []) {
98
98
  const name = (_b = i.findFirstExpression(Expressions.ClassName)) === null || _b === void 0 ? void 0 : _b.getFirstToken().getStr().toUpperCase();
99
99
  if (name === impl.identifier.getName().toUpperCase()) {
100
- return edit_helper_1.EditHelper.insertAt(file, i.getLastToken().getEnd(), `
101
- METHOD ${methodName.toLowerCase()}.
102
- RETURN. " todo, implement method
100
+ return edit_helper_1.EditHelper.insertAt(file, i.getLastToken().getEnd(), `
101
+ METHOD ${methodName.toLowerCase()}.
102
+ RETURN. " todo, implement method
103
103
  ENDMETHOD.`);
104
104
  }
105
105
  }
@@ -31,19 +31,19 @@ class InStatementIndentation extends _abap_rule_1.ABAPRule {
31
31
  key: "in_statement_indentation",
32
32
  title: "In-statement indentation",
33
33
  shortDescription: "Checks alignment within statements which span multiple lines.",
34
- extendedInformation: `Lines following the first line should be indented once (2 spaces).
35
-
36
- For block declaration statements, lines after the first should be indented an additional time (default: +2 spaces)
34
+ extendedInformation: `Lines following the first line should be indented once (2 spaces).
35
+
36
+ For block declaration statements, lines after the first should be indented an additional time (default: +2 spaces)
37
37
  to distinguish them better from code within the block.`,
38
- badExample: `IF 1 = 1
39
- AND 2 = 2.
40
- WRITE 'hello' &&
41
- 'world'.
38
+ badExample: `IF 1 = 1
39
+ AND 2 = 2.
40
+ WRITE 'hello' &&
41
+ 'world'.
42
42
  ENDIF.`,
43
- goodExample: `IF 1 = 1
44
- AND 2 = 2.
45
- WRITE 'hello' &&
46
- 'world'.
43
+ goodExample: `IF 1 = 1
44
+ AND 2 = 2.
45
+ WRITE 'hello' &&
46
+ 'world'.
47
47
  ENDIF.`,
48
48
  tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
49
49
  };
@@ -26,9 +26,9 @@ class IntfReferencingClas {
26
26
  key: "intf_referencing_clas",
27
27
  title: "INTF referencing CLAS",
28
28
  shortDescription: `Interface contains references to class`,
29
- extendedInformation: `Only global interfaces are checked.
30
- Only first level references are checked.
31
- Exception class references are ignored.
29
+ extendedInformation: `Only global interfaces are checked.
30
+ Only first level references are checked.
31
+ Exception class references are ignored.
32
32
  Void references are ignored.`,
33
33
  };
34
34
  }
@@ -15,8 +15,8 @@ class LineBreakStyle {
15
15
  return {
16
16
  key: "line_break_style",
17
17
  title: "Makes sure line breaks are consistent in the ABAP code",
18
- shortDescription: `Enforces LF as newlines in ABAP files
19
-
18
+ shortDescription: `Enforces LF as newlines in ABAP files
19
+
20
20
  abapGit does not work with CRLF`,
21
21
  tags: [_irule_1.RuleTag.Whitespace, _irule_1.RuleTag.SingleFile],
22
22
  };
@@ -23,7 +23,7 @@ class LineLength extends _abap_rule_1.ABAPRule {
23
23
  key: "line_length",
24
24
  title: "Line length",
25
25
  shortDescription: `Detects lines exceeding the provided maximum length.`,
26
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#stick-to-a-reasonable-line-length
26
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#stick-to-a-reasonable-line-length
27
27
  https://docs.abapopenchecks.org/checks/04/`,
28
28
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.SingleFile],
29
29
  };
@@ -27,7 +27,7 @@ class LineOnlyPunc extends _abap_rule_1.ABAPRule {
27
27
  key: "line_only_punc",
28
28
  title: "Line containing only punctuation",
29
29
  shortDescription: `Detects lines containing only punctuation.`,
30
- extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#close-brackets-at-line-end
30
+ extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#close-brackets-at-line-end
31
31
  https://docs.abapopenchecks.org/checks/16/`,
32
32
  tags: [_irule_1.RuleTag.Styleguide, _irule_1.RuleTag.Quickfix, _irule_1.RuleTag.SingleFile],
33
33
  badExample: "zcl_class=>method(\n).",
@@ -30,8 +30,8 @@ class LocalVariableNames extends _abap_rule_1.ABAPRule {
30
30
  return {
31
31
  key: "local_variable_names",
32
32
  title: "Local variable naming conventions",
33
- shortDescription: `
34
- Allows you to enforce a pattern, such as a prefix, for local variables, constants and field symbols.
33
+ shortDescription: `
34
+ Allows you to enforce a pattern, such as a prefix, for local variables, constants and field symbols.
35
35
  Regexes are case-insensitive.`,
36
36
  tags: [_irule_1.RuleTag.Naming, _irule_1.RuleTag.SingleFile],
37
37
  };