All files / src/rules if_in_if.ts

97.96% Statements 96/98
95.83% Branches 23/24
100% Functions 6/6
97.96% 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 7653x 7653x 7653x 7653x 7653x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 22817x 7653x 7653x 3x 3x 7653x 7653x 7346x 7346x 7653x 7653x 139x 139x 7653x 7653x 160x 160x 160x 10x 10x 150x 150x 160x 12x 12x 138x 138x 138x 138x 160x 22x 22x 7x 7x 15x 15x 22x 4x 4x 11x 11x 22x 3x 3x 8x 8x 22x 5x 5x 3x 3x 3x 22x 22x     3x 3x 3x 3x 3x 138x 138x 138x 7653x 7653x
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;
  }
 
}