All files / src/rules selection_screen_naming.ts

95.83% Statements 92/96
92% Branches 23/25
100% Functions 9/9
95.83% Lines 92/96

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 92 93 94 95 96 971x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15310x 15310x 15310x 15310x 15310x 15310x 7655x 7655x 7655x 7655x 7655x 22823x 22823x 22823x 22823x 22823x 22823x 22823x 7655x 7655x 7x 7x 7x 7x 7655x 7655x 7346x 7346x 7655x 7655x 142x 142x 7655x 7655x 167x 167x     167x 167x 167x 6x 6x 167x 6x 6x 167x 167x 857x 857x 13x 13x 13x 7x 7x 7x 7x 7x 7x 7x 13x 857x 167x 167x 7655x 7655x 20x 20x 9x 20x 11x 11x 20x 20x 7655x 7655x 13x 6x 13x 7x 7x     13x 7655x  
import {ABAPRule} from "./_abap_rule";
import {Issue} from "../issue";
import {NamingRuleConfig} from "./_naming_rule_config";
import {Parameter, SelectOption} from "../abap/2_statements/statements";
import {IStatement} from "../abap/2_statements/statements/_statement";
import {NameValidator} from "../utils/name_validator";
import {FieldSub} from "../abap/2_statements/expressions";
import {StatementNode, ExpressionNode} from "../abap/nodes";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
 
export class SelectionScreenNamingConf extends NamingRuleConfig {
  /** The pattern for selection-screen parameters */
  public parameter: string = "^P_.+$";
  /** The pattern for selection-screen select-options */
  public selectOption: string = "^S_.+$";
}
export class SelectionScreenNaming extends ABAPRule {
 
  private conf = new SelectionScreenNamingConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "selection_screen_naming",
      title: "Selection screen naming conventions",
      shortDescription: `Allows you to enforce a pattern, such as a prefix, for selection-screen variable names.`,
      tags: [RuleTag.Naming, RuleTag.SingleFile],
    };
  }
 
  private getDescription(expected: string, actual: string): string {
    return this.conf.patternKind === "required" ?
      `Selection-Screen variable name does not match pattern ${expected}: ${actual}` :
      `Selection-Screen variable name must not match pattern ${expected}: ${actual}`;
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: SelectionScreenNamingConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile) {
    const issues: Issue[] = [];
    if (this.conf.patternKind === undefined) {
      this.conf.patternKind = "required";
    }
    let parameterCheckDisabled: boolean = false;
    let selectOptionDisabled: boolean = false;
    if (this.conf.parameter === undefined || this.conf.parameter.length === 0) {
      parameterCheckDisabled = true;
    }
    if (this.conf.selectOption === undefined || this.conf.selectOption.length === 0) {
      selectOptionDisabled = true;
    }
 
    for (const stat of file.getStatements()) {
      if ((stat.get() instanceof Parameter && !parameterCheckDisabled)
          || (stat.get() instanceof SelectOption && !selectOptionDisabled)) {
        const fieldNode = this.getFieldForStatementNode(stat);
        const regex = new RegExp(this.getPatternForStatement(stat.get()), "i");
        if (fieldNode && NameValidator.violatesRule(fieldNode.getFirstToken().getStr(), regex, this.conf)) {
          issues.push(Issue.atToken(
            file,
            fieldNode.getFirstToken(),
            this.getDescription(this.getPatternForStatement(stat.get()), fieldNode.getFirstToken().getStr()),
            this.getMetadata().key,
            this.conf.severity));
        }
      }
    }
    return issues;
  }
 
  private getPatternForStatement(statement: IStatement): string {
    let pattern = "";
    if (statement instanceof Parameter) {
      pattern = this.conf.parameter;
    } else if (statement instanceof SelectOption) {
      pattern = this.conf.selectOption;
    }
    return pattern;
  }
 
  private getFieldForStatementNode(statNode: StatementNode): ExpressionNode | undefined {
    if (statNode.get() instanceof Parameter) {
      return statNode.findFirstExpression(FieldSub);
    } else if (statNode.get() instanceof SelectOption) {
      return statNode.findFirstExpression(FieldSub);
    } else {
      return undefined;
    }
  }
}