All files / src/rules method_length.ts

98.02% Statements 99/101
95.45% Branches 21/22
100% Functions 9/9
98.02% Lines 99/101

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 98 99 100 1011x 1x 1x 1x 1x 1x 1x 1x 15321x 15321x 15321x 15321x 15321x 15321x 15321x 15321x 15321x 15321x 1x 1x 1x 1x 1x 1x 7665x 7665x 7665x 7665x 7665x 22835x 22835x 22835x 22835x 22835x 22835x 22835x 22835x 7665x 7665x 20x 20x 15x 15x 20x 5x 5x 20x     20x 20x 7665x 7665x 7346x 7346x 7665x 7665x 151x 151x 7665x 7665x 156x 156x 7665x 7665x 182x 182x 182x 182x 182x 180x 180x 180x 182x 182x 182x 7665x 7665x 362x 362x 362x 56x 56x 2x 2x 56x 15x 15x 15x 15x 56x 5x 5x 5x 5x 56x 362x 362x 362x 7665x 7665x
import {Issue} from "../issue";
import {IObject} from "../objects/_iobject";
import {IRegistry} from "../_iregistry";
import {IMethodLengthResult, MethodLengthStats} from "../utils/method_length_stats";
import {IRule, IRuleMetadata, RuleTag} from "./_irule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {FormLengthStats} from "../utils/form_length_stats";
 
export class MethodLengthConf extends BasicRuleConfig {
  /** Maximum method/form length in statements. */
  public statements: number = 100;
  /** Checks for empty methods/forms. */
  public errorWhenEmpty: boolean = true;
  /** Option to ignore test classes for this check. */
  public ignoreTestClasses: boolean = false;
  /** Option to check forms. */
  public checkForms: boolean = true;
}
 
enum IssueType {
  EmptyMethod,
  MaxStatements,
}
 
export class MethodLength implements IRule {
 
  private conf = new MethodLengthConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "method_length",
      title: "Method/Form Length",
      shortDescription: `Checks relating to method/form length.`,
      extendedInformation: `https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#keep-methods-small`,
      tags: [RuleTag.Styleguide, RuleTag.SingleFile],
    };
  }
 
  private getDescription(issueType: IssueType, actual: string): string {
    switch (issueType) {
      case IssueType.EmptyMethod: {
        return "Empty method/form";
      }
      case IssueType.MaxStatements: {
        return "Reduce method/form length to max " + this.conf.statements + " statements, currently " + actual;
      }
      default: {
        return "";
      }
    }
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: MethodLengthConf) {
    this.conf = conf;
  }
 
  public initialize(_reg: IRegistry) {
    return this;
  }
 
  public run(obj: IObject): Issue[] {
    const methodStats = MethodLengthStats.run(obj);
    const methodIssues = this.check(methodStats);
 
    let formIssues: Issue[] = [];
    if (this.conf.checkForms) {
      const formStats = FormLengthStats.run(obj);
      formIssues = this.check(formStats);
    }
 
    return methodIssues.concat(formIssues);
  }
 
  private check(stats: IMethodLengthResult[]) {
    const issues: Issue[] = [];
 
    for (const s of stats) {
      if ((this.conf.ignoreTestClasses === true)
        && s.file.getFilename().includes(".testclasses.")) {
        continue;
      }
      if (s.count === 0 && this.conf.errorWhenEmpty === true) {
        const issue = Issue.atPosition(s.file, s.pos, this.getDescription(IssueType.EmptyMethod, "0"), this.getMetadata().key, this.conf.severity);
        issues.push(issue);
        continue;
      }
      if (s.count > this.conf.statements) {
        const message = this.getDescription(IssueType.MaxStatements, s.count.toString());
        const issue = Issue.atPosition(s.file, s.pos, message, this.getMetadata().key, this.conf.severity);
        issues.push(issue);
      }
    }
 
    return issues;
  }
 
}