All files / src/rules implicit_start_of_selection.ts

97.95% Statements 96/98
88.88% Branches 24/27
100% Functions 5/5
97.95% Lines 96/98

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 97 98 991x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11261x 11261x 11261x 11261x 11261x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 33633x 11261x 11261x 10795x 10795x 11261x 11261x 228x 228x 11261x 11261x 245x 245x 245x 80x 80x 165x 165x 245x 10x 10x 155x 155x 155x 245x 351x 7x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 351x 142x 142x 142x 103x 103x 39x 344x 202x     202x 202x 351x 155x 245x 26x 26x 26x 26x 26x 26x 26x 155x 155x 155x 11261x 11261x  
import {Issue} from "../issue";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import * as Structures from "../abap/3_structures/structures";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {ABAPObject} from "../objects/_abap_object";
import {Program} from "../objects";
import {StatementNode, StructureNode} from "../abap/nodes";
import {DECLARATION_STUFF, SELECTION_EVENTS} from "../stuff";
 
export class ImplicitStartOfSelectionConf extends BasicRuleConfig {
}
 
export class ImplicitStartOfSelection extends ABAPRule {
 
  private conf = new ImplicitStartOfSelectionConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "implicit_start_of_selection",
      title: "Implicit START-OF-SELECTION",
      shortDescription: `Add explicit selection screen event handling`,
      extendedInformation: `Only runs for executable programs
 
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-us/abapstart-of-selection.htm`,
      tags: [RuleTag.SingleFile],
      badExample: `REPORT zfoo.
WRITE 'hello'.`,
      goodExample: `
START-OF-SELECTION.
  WRITE 'hello'.`,
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: ImplicitStartOfSelectionConf) {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile, obj: ABAPObject) {
    const issues: Issue[] = [];
 
    if (!(obj instanceof Program) || obj.isInclude()) {
      return issues;
    }
 
    const stru = file.getStructure();
    if (stru === undefined) {
      return [];
    }
 
    let inEvent = false;
    let collected: (StatementNode | StructureNode)[] = [];
    for (const s of stru.getChildren() || []) {
      if (SELECTION_EVENTS.some(f => s.get() instanceof f)) {
        if (inEvent === false && collected.length > 0) {
          // implicit START-OF-SELECTION
          let first = collected[0];
          if (first instanceof StructureNode) {
            first = first.getFirstStatement()!;
          }
          issues.push(Issue.atStatement(file, first, "Implicit START-OF-SELECTION", this.getMetadata().key, this.getConfig().severity));
        }
 
        collected = [];
        inEvent = true;
      } else if (s.get() instanceof Structures.Normal) {
        const stru = s as StructureNode;
        // ignore declaration stuff
        if (DECLARATION_STUFF.some(d => stru.getFirstStatement()?.get() instanceof d)) {
          continue;
        }
        collected.push(s);
      } else {
        if (inEvent === true) {
          inEvent = false;
        }
        collected = [];
      }
    }
 
    if (inEvent === false && collected.length > 0) {
      // implicit START-OF-SELECTION
      let first = collected[0];
      if (first instanceof StructureNode) {
        first = first.getFirstStatement()!;
      }
      issues.push(Issue.atStatement(file, first, "Implicit START-OF-SELECTION", this.getMetadata().key, this.getConfig().severity));
    }
 
    return issues;
  }
 
}