All files / src/rules fully_type_constants.ts

97.26% Statements 71/73
84.21% Branches 16/19
100% Functions 8/8
97.26% Lines 71/73

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 731x 1x 1x 1x 1x 1x 1x 1x 1x 29365x 29365x 29365x 29365x 1x 14682x 14682x 14682x 14682x 142759x 142759x 142759x 142759x 142759x 142759x 142759x 142759x 142759x 14682x 14682x 11x 11x 14682x 14682x 14120x 14120x 14682x 14682x 280x 280x 14682x 14682x 307x 307x 307x 1679x 1679x 1679x 11x 11x 11x 11x 11x 11x 11x     11x 11x 11x 11x 11x 11x 11x 11x 11x 1679x 307x 307x 14682x 14682x 184x 184x 14682x
import {BasicRuleConfig} from "./_basic_rule_config";
import {ABAPRule} from "./_abap_rule";
import {Issue} from "../issue";
import * as Statements from "../abap/2_statements/statements";
import {StatementNode} from "../abap/nodes/statement_node";
import {Type, TypeTable, NamespaceSimpleName, DefinitionName} from "../abap/2_statements/expressions";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
 
export class FullyTypeConsantsConf extends BasicRuleConfig {
  /** Add check for implicit data definition, require full typing. */
  public checkData: boolean = true;
}
 
export class FullyTypeConstants extends ABAPRule {
  private conf = new FullyTypeConsantsConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "fully_type_constants",
      title: "Fully type constants",
      shortDescription: `Checks constants for full typing - no implicit typing allowed.`,
      badExample: "CONSTANTS foo VALUE 'a'.",
      goodExample: "CONSTANTS foo TYPE c LENGTH 1 VALUE 'a'.",
      tags: [RuleTag.SingleFile],
    };
  }
 
  private getDescription(type: string): string {
    return `Fully type ${type}, no implicit typing`;
  }
 
  public getConfig(): FullyTypeConsantsConf {
    return this.conf;
  }
 
  public setConfig(conf: FullyTypeConsantsConf): void {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile): Issue[] {
    const issues: Issue[] = [];
 
    for (const stat of file.getStatements()) {
      if ((stat.get() instanceof Statements.Constant
          || (this.conf.checkData === true && stat.get() instanceof Statements.Data))
          && !this.isTyped(stat)) {
        const type = stat.get() instanceof Statements.Constant ? "constant definition" : "data definition";
 
        let token = stat.findFirstExpression(NamespaceSimpleName)?.getFirstToken();
        if (token === undefined) {
          token = stat.findFirstExpression(DefinitionName)?.getFirstToken();
        }
        if (token === undefined) {
          throw new Error("fully type constants, unexpected node");
        }
 
        issues.push(
          Issue.atToken(
            file,
            token,
            this.getDescription(type),
            this.getMetadata().key,
            this.conf.severity));
      }
    }
    return issues;
  }
 
  private isTyped(stat: StatementNode) {
    return stat.findFirstExpression(Type) || stat.findFirstExpression(TypeTable);
  }
}