All files / src/rules nesting.ts

100% Statements 27/27
100% Branches 20/20
100% Functions 7/7
100% Lines 27/27

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 821x 1x 1x 1x 1x     1x   14543x     1x   7272x     21681x                     1x       7015x       114x       130x   130x   130x 733x   733x             19x 714x             8x     733x 1x 1x           1x 1x       130x      
import {Issue} from "../issue";
import * as Statements from "../abap/2_statements/statements";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
 
export class NestingConf extends BasicRuleConfig {
  /** Maximum allowed nesting depth */
  public depth: number = 5;
}
 
export class Nesting extends ABAPRule {
 
  private conf = new NestingConf();
 
  public getMetadata() {
    return {
      key: "nesting",
      title: "Check nesting depth",
      shortDescription: `Checks for methods exceeding a maximum nesting depth`,
      extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-the-nesting-depth-low
https://docs.abapopenchecks.org/checks/74/`,
      tags: [RuleTag.Styleguide, RuleTag.SingleFile],
    };
  }
 
  private getDescription(max: string): string {
    return "Reduce nesting depth to max " + max;
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: NestingConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile) {
    const issues: Issue[] = [];
 
    let depth: number = 0;
 
    for (const statement of file.getStatements()) {
      const type = statement.get();
 
      if (type instanceof Statements.If
        || type instanceof Statements.Case
        || type instanceof Statements.While
        || type instanceof Statements.Loop
        || type instanceof Statements.SelectLoop
        || type instanceof Statements.Do
        || type instanceof Statements.Try) {
        depth = depth + 1;
      } else if (type instanceof Statements.EndIf
        || type instanceof Statements.EndCase
        || type instanceof Statements.EndWhile
        || type instanceof Statements.EndLoop
        || type instanceof Statements.EndSelect
        || type instanceof Statements.EndDo
        || type instanceof Statements.EndTry) {
        depth = depth - 1;
      }
 
      if (depth > this.conf.depth) {
        const pos = statement.getFirstToken().getStart();
        const issue = Issue.atPosition(
          file,
          pos,
          this.getDescription(this.conf.depth.toString()),
          this.getMetadata().key,
          this.conf.severity);
        issues.push(issue);
        break; // only one finding per file
      }
    }
 
    return issues;
  }
 
}