All files / src/rules fully_type_constants.ts

96.15% Statements 25/26
81.82% Branches 18/22
100% Functions 8/8
96.15% Lines 25/26

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   14531x     1x 7265x     21669x                     10x       7008x       130x       144x   144x 758x     10x   10x 10x 10x   10x       10x                 144x       91x    
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],
    };
  }
 
  public 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();
        Eif (token === undefined) {
          token = stat.findFirstExpression(DefinitionName)?.getFirstToken();
        }
        Iif (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));
  }
}