All files / src/rules if_in_if.ts

97.95% Statements 96/98
95.83% Branches 23/24
100% Functions 6/6
97.95% Lines 96/98

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 981x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8922x 8922x 8922x 8922x 8922x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 26611x 8922x 8922x 3x 3x 8922x 8922x 8485x 8485x 8922x 8922x 202x 202x 8922x 8922x 224x 224x 224x 18x 18x 206x 206x 224x 12x 12x 194x 194x 194x 194x 224x 27x 27x 7x 7x 20x 20x 27x 4x 4x 16x 16x 27x 5x 5x 11x 11x 27x 8x 8x 3x 3x 3x 27x 27x     3x 3x 3x 3x 3x 194x 194x 194x 8922x 8922x
import {Issue} from "../issue";
import * as Structures from "../abap/3_structures/structures";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {ABAPObject} from "../objects/_abap_object";
 
export class IfInIfConf extends BasicRuleConfig {
}
 
export class IfInIf extends ABAPRule {
 
  private conf = new IfInIfConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "if_in_if",
      title: "IF in IF",
      shortDescription: `Detects nested ifs which can be refactored to a single condition using AND.`,
      extendedInformation: `https://docs.abapopenchecks.org/checks/01/
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low`,
      badExample: `IF condition1.
  IF condition2.
    ...
  ENDIF.
ENDIF.`,
      goodExample: `IF ( condition1 ) AND ( condition2 ).
  ...
ENDIF.`,
      tags: [RuleTag.Styleguide, RuleTag.SingleFile],
    };
  }
 
  private getMessage(): string {
    return "IF in IF. Use IF cond1 AND cond2 instead";
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: IfInIfConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile, obj: ABAPObject) {
    const issues: Issue[] = [];
 
    if (obj.getType() === "INTF") {
      return [];
    }
 
    const stru = file.getStructure();
    if (stru === undefined) {
      return [];
    }
 
    let possible = stru.findAllStructures(Structures.If);
    possible = possible.concat(stru.findAllStructures(Structures.Else));
 
    for (const i of possible) {
      if (i.findDirectStructures(Structures.ElseIf).length > 0
          || i.findDirectStructures(Structures.Else).length > 0) {
        continue;
      }
 
      const blist = i.findDirectStructures(Structures.Body);
      if (blist.length === 0) {
        continue;
      }
 
      const nlist = blist[0].findDirectStructures(Structures.Normal);
      if (nlist.length !== 1) {
        continue;
      }
 
      const niflist = nlist[0].findDirectStructures(Structures.If);
      if (niflist.length !== 1) {
        continue;
      }
 
      const nestedIf = niflist[0];
      if (i.get() instanceof Structures.If
          && (nestedIf.findDirectStructures(Structures.ElseIf).length > 0
          || nestedIf.findDirectStructures(Structures.Else).length > 0)) {
        continue;
      }
 
      const token = i.getFirstToken();
      const issue = Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
      issues.push(issue);
    }
 
    return issues;
  }
 
}