All files / src/rules newline_between_methods.ts

100% Statements 90/90
96.87% Branches 31/32
100% Functions 8/8
100% Lines 90/90

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 1x 1x 1x 18724x 18724x 18724x 18724x 18724x 18724x 18724x 18724x 18724x 18724x 1x 9361x 9361x 9361x 9361x 27934x 27934x 27934x 27934x 27934x 27934x 27934x 9361x 9361x 11x 11x 11x 11x 11x 11x 9361x 9361x 8898x 8898x 9361x 9361x 231x 231x 9361x 9361x 246x 246x 246x 5x 5x 246x 1483x 1483x 1466x 1466x 17x 1483x 26x 26x 26x 1483x 1483x 1483x 11x 11x 11x 11x 11x 11x 11x 1483x 241x 241x 9361x 9361x 246x 5x 246x 241x 241x 246x 9361x
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;
    }
  }
}