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 11303x 11303x 11303x 11303x 11303x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 33761x 11303x 11303x 10829x 10829x 11303x 11303x 232x 232x 11303x 11303x 249x 249x 249x 80x 80x 169x 169x 249x 10x 10x 159x 159x 159x 249x 357x 7x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 357x 146x 146x 146x 107x 107x 39x 350x 204x     204x 204x 357x 159x 249x 26x 26x 26x 26x 26x 26x 26x 159x 159x 159x 11303x 11303x  
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;
  }
 
}