All files / src/rules newline_between_methods.ts

97.44% Statements 38/39
96.55% Branches 28/29
100% Functions 9/9
97.44% Lines 38/39

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 901x 1x 1x 1x 1x 1x     1x 1x 1x     1x   14532x           14532x     1x 7265x     21670x                 11x 4x 7x           7008x       129x       143x 143x 143x 5x   138x 864x 864x 847x   17x 17x 26x 26x   17x     11x               138x       143x 5x   138x      
import {Issue} from "../issue";
import {BasicRuleConfig} from "./_basic_rule_config";
import {ABAPRule} from "./_abap_rule";
import {SequentialBlank} from "./sequential_blank";
import * as Statements from "../abap/2_statements/statements";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
 
export enum NewlineLogic {
  Exact = "exact",
  Less = "less",
}
 
export class NewlineBetweenMethodsConf extends BasicRuleConfig {
  /** Amount of newlines, works in conjunction with "newlineLogic" */
  public count: number = 3;
  /**
   *  Exact: the exact number of required newlines between methods is defined by "newlineAmount"
   *
   *  Less: the required number of newlines has to be less than "newlineAmount"
   */
  public logic: NewlineLogic = NewlineLogic.Less;
}
 
export class NewlineBetweenMethods extends ABAPRule {
  private conf = new NewlineBetweenMethodsConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "newline_between_methods",
      title: "New line between methods",
      shortDescription: `Checks for newlines between method implementations.`,
      tags: [RuleTag.Whitespace, RuleTag.SingleFile],
    };
  }
 
  private getMessage(): string {
    switch (this.conf.logic) {
      case NewlineLogic.Exact: return `Exactly ${this.conf.count} newlines are required in between methods`;
      case NewlineLogic.Less: return `Less than ${this.conf.count} newlines and at least a single newline are required in between methods`;
      default: return "";
    }
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: NewlineBetweenMethodsConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile): Issue[] {
    const issues: Issue[] = [];
    const rows = file.getRawRows();
    if (!this.isConfigurationValid()) {
      return [];
    }
    for (const statement of file.getStatements()) {
      let nextRow = statement.getStart().getRow();
      if (!(statement.get() instanceof Statements.EndMethod) || (rows[nextRow]?.toUpperCase().includes("ENDCLASS."))) {
        continue;
      }
      let counter = 0;
      while (SequentialBlank.isBlankOrWhitespace(rows[nextRow]) && (counter <= this.conf.count + 1)) {
        counter++;
        nextRow++;
      }
      if ((counter !== this.conf.count && this.conf.logic === NewlineLogic.Exact)
        || (counter >= this.conf.count && this.conf.logic === NewlineLogic.Less)
        || counter === 0) {
        issues.push(Issue.atStatement(
          file,
          statement,
          this.getMessage(),
          this.getMetadata().key,
          this.conf.severity));
      }
    }
    return issues;
  }
 
  private isConfigurationValid(): boolean {
    if (this.conf.count < 1 || (this.conf.count === 1 && this.conf.logic === NewlineLogic.Less)) {
      return false;
    } else {
      return true;
    }
  }
}