All files / src/rules space_before_colon.ts

97.56% Statements 80/82
95.23% Branches 20/21
100% Functions 6/6
97.56% Lines 80/82

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 1x 1x 1x 1x 1x 1x 1x 11652x 11652x 11652x 11652x 11652x 34802x 34802x 34802x 34802x 34802x 34802x 34802x 34802x 34802x 34802x 11652x 11652x 2x 2x 11652x 11652x 11142x 11142x 11652x 11652x 239x 239x 11652x 11652x 255x 255x 255x 1446x 1446x 1446x 1446x 1275x 1275x 171x 171x 171x 171x 171x 171x 171x 171x 1446x 1137x     1137x 1137x 1137x 2x 2x 2x 2x 2x 2x 2x 2x 1137x 1137x 171x 255x 255x 255x 11652x 11652x
import {Position} from "../position";
import {ABAPFile} from "../abap/abap_file";
import {EditHelper} from "../edit_helper";
import {Issue} from "../issue";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {IRuleMetadata, RuleTag} from "./_irule";
import {NativeSQL} from "../abap/2_statements/statements/_statement";
import {Comment} from "../abap/1_lexer/tokens";
 
export class SpaceBeforeColonConf extends BasicRuleConfig {
}
 
export class SpaceBeforeColon extends ABAPRule {
 
  private conf = new SpaceBeforeColonConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "space_before_colon",
      title: "Space before colon",
      shortDescription: `Checks that there are no spaces in front of colons in chained statements.`,
      extendedInformation: `https://docs.abapopenchecks.org/checks/80/`,
      tags: [RuleTag.Whitespace, RuleTag.SingleFile, RuleTag.Quickfix],
      badExample: `DATA : foo TYPE string.`,
      goodExample: `DATA: foo TYPE string.`,
    };
  }
 
  private getMessage(): string {
    return "Remove space before colon";
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: SpaceBeforeColonConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile) {
    const issues: Issue[] = [];
 
    for (const statement of file.getStatements()) {
      const colon = statement.getColon();
      if (colon === undefined
          || statement.get() instanceof NativeSQL
          || statement.get() instanceof Comment) {
        continue;
      }
 
      // todo: this can be more smart, performance wise
      const tokens = [...statement.getTokens()];
      tokens.push(colon);
      tokens.sort((a, b) => a.getStart().isAfter(b.getStart()) ? 1 : -1);
 
      let prev = tokens[0];
 
      for (const token of tokens) {
        if (token.getStr() === ":" && !prev) {
          const issue = Issue.atToken(file, token, this.getMessage(), this.getMetadata().key, this.conf.severity);
          issues.push(issue);
        } else if (token.getStr() === ":"
            && prev.getRow() === token.getRow()
            && prev.getCol() + prev.getStr().length < token.getCol()) {
          const start = new Position(token.getRow(), prev.getEnd().getCol());
          const end = new Position(token.getRow(), token.getStart().getCol());
          const fix = EditHelper.deleteRange(file, start, end);
          const issue = Issue.atRowRange(file, start.getRow(),
                                         start.getCol(), end.getCol(),
                                         this.getMessage(), this.getMetadata().key, this.conf.severity, fix);
          issues.push(issue);
        }
        prev = token;
      }
    }
 
    return issues;
  }
 
}