All files / src/rules implicit_start_of_selection.ts

97.93% Statements 95/97
88.88% Branches 24/27
100% Functions 5/5
97.93% Lines 95/97

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 981x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11460x 11460x 11460x 11460x 11460x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 34236x 11460x 11460x 10955x 10955x 11460x 11460x 247x 247x 11460x 11460x 277x 277x 277x 89x 89x 188x 188x 277x 10x 10x 178x 178x 178x 277x 413x 11x 1x 1x 1x 1x 1x 1x 1x 11x 11x 11x 413x 170x 170x 170x 124x 124x 46x 402x 232x     232x 232x 413x 178x 277x 29x 29x 29x 29x 29x 29x 29x 178x 178x 178x 11460x 11460x  
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_latest_index_htm/latest/en-us/abapstart-of-selection.html`,
      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;
  }
 
}