All files / src/rules check_comments.ts

97.82% Statements 90/92
92% Branches 23/25
100% Functions 7/7
97.82% Lines 90/92

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 921x 1x 1x 1x 1x 1x 1x 24157x 24157x 24157x 24157x 24157x 1x 1x 1x 1x 12078x 12078x 12078x 12078x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 47645x 12078x 12078x 15x 15x 15x 15x 15x 12078x 12078x 11819x 11819x 12078x 12078x 271x 271x 12078x 12078x 289x 289x 289x 7x 7x 282x 282x 289x     282x 282x 289x 1952x 1952x 17x 17x 1952x 282x 289x 1623x 1623x 25x 25x 10x 10x 15x 15x 15x 15x 15x 15x 15x 25x 1x 1x 25x 1623x 282x 282x 12078x
import {Issue} from "../issue";
import {Comment} from "../abap/2_statements/statements/_statement";
import {BasicRuleConfig} from "./_basic_rule_config";
import {ABAPRule} from "./_abap_rule";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
 
export class CheckCommentsConf extends BasicRuleConfig {
  /** Allows the use of end-of-line comments. */
  public allowEndOfLine: boolean = false;
  public maxIssuesPerFile: number | undefined = 10;
}
 
enum IssueType {
  EndOfLine,
}
export class CheckComments extends ABAPRule {
  private conf = new CheckCommentsConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "check_comments",
      title: "Check Comments",
      shortDescription: `
Various checks for comment usage.`,
      extendedInformation: `
Detects end of line comments. Comments starting with "#EC" or "##" are ignored
 
https://github.com/SAP/styleguides/blob/main/clean-abap/CleanABAP.md#put-comments-before-the-statement-they-relate-to`,
      tags: [RuleTag.Styleguide, RuleTag.SingleFile],
      badExample: `WRITE 2. " descriptive comment`,
      goodExample: `" descriptive comment\nWRITE 2.`,
    };
  }
 
  private getDescription(issueType: IssueType): string {
    switch (issueType) {
      case IssueType.EndOfLine: return `Do not use end of line comments - move comment to previous row instead`;
      default: return "";
    }
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: CheckCommentsConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile): Issue[] {
    const issues: Issue[] = [];
    const rows = file.getRawRows();
    if (this.conf.allowEndOfLine === true) {
      return [];
    }
 
    let max = this.getConfig().maxIssuesPerFile;
    if (max === undefined || max < 1) {
      max = 10;
    }
 
    const commentRows: number[] = [];
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      if (row.trim().startsWith("*") || row.trim().startsWith(`"`)) {
        commentRows.push(i);
      }
    }
    const statements = file.getStatements();
    for (let i = statements.length - 1; i >= 0; i--) {
      const statement = statements[i];
      if (statement.get() instanceof Comment && !commentRows.includes(statement.getStart().getRow() - 1)) {
        if (statement.getFirstToken().getStr().startsWith(`"#EC`)
            || statement.getFirstToken().getStr().startsWith(`"##`)) {
          continue;
        }
        issues.push(
          Issue.atStatement(
            file,
            statement,
            this.getDescription(IssueType.EndOfLine),
            this.getMetadata().key,
            this.conf.severity));
        if (issues.length >= max) {
          break;
        }
      }
    }
    return issues;
  }
}