All files / src/rules db_operation_in_loop.ts

100% Statements 87/87
100% Branches 15/15
100% Functions 5/5
100% Lines 87/87

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 881x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 11087x 11087x 11087x 11087x 11087x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 96531x 11087x 11087x 10568x 10568x 11087x 11087x 244x 244x 11087x 11087x 267x 267x 267x 267x 12x 12x 255x 255x 255x 255x 255x 267x 4x 4x 4x 4x 4x 3x 3x 4x 3x 3x 4x 2x 2x 4x 2x 2x 4x 2x 2x 4x 4x 2x 2x 2x 4x 255x 255x 255x 11087x 11087x  
import * as Statements from "../abap/2_statements/statements";
import * as Structures from "../abap/3_structures/structures";
import {ABAPRule} from "./_abap_rule";
import {BasicRuleConfig} from "./_basic_rule_config";
import {Issue} from "../issue";
import {IRuleMetadata, RuleTag} from "./_irule";
import {ABAPFile} from "../abap/abap_file";
import {StatementNode} from "../abap/nodes/statement_node";
 
export class DbOperationInLoopConf extends BasicRuleConfig {
}
 
export class DbOperationInLoop extends ABAPRule {
 
  private conf = new DbOperationInLoopConf();
 
  public getMetadata(): IRuleMetadata {
    return {
      key: "db_operation_in_loop",
      title: "Database operation in loop",
      shortDescription: `Database operation in LOOP/DO/WHILE`,
      tags: [RuleTag.SingleFile, RuleTag.Performance],
      badExample: `LOOP AT lt_items INTO DATA(ls_item).
  SELECT SINGLE name FROM zcustomer INTO @DATA(lv_name) WHERE id = @ls_item-customer_id.
ENDLOOP.`,
      goodExample: `ASSERT lines( lt_items ) > 0.
SELECT id, name FROM zcustomer INTO TABLE @DATA(lt_customers)
  FOR ALL ENTRIES IN @lt_items
  WHERE id = @lt_items-customer_id.
 
LOOP AT lt_items INTO DATA(ls_item).
  READ TABLE lt_customers INTO DATA(ls_customer) WITH KEY id = ls_item-customer_id.
ENDLOOP.`,
    };
  }
 
  public getConfig() {
    return this.conf;
  }
 
  public setConfig(conf: DbOperationInLoopConf): void {
    this.conf = conf;
  }
 
  public runParsed(file: ABAPFile) {
    const issues: Issue[] = [];
 
    const stru = file.getStructure();
    if (stru === undefined) {
      return issues;
    }
 
    const loops = stru.findAllStructures(Structures.Loop);
    loops.push(...stru.findAllStructures(Structures.Do));
    loops.push(...stru.findAllStructures(Structures.While));
 
    for (const l of loops) {
      let found: StatementNode | undefined = undefined;
      if (found === undefined) {
        found = l.findFirstStatement(Statements.Select);
      }
      if (found === undefined) {
        found = l.findFirstStatement(Statements.SelectLoop);
      }
      if (found === undefined) {
        found = l.findFirstStatement(Statements.InsertDatabase);
      }
      if (found === undefined) {
        found = l.findFirstStatement(Statements.DeleteDatabase);
      }
      if (found === undefined) {
        found = l.findFirstStatement(Statements.UpdateDatabase);
      }
      if (found === undefined) {
        found = l.findFirstStatement(Statements.ModifyDatabase);
      }
 
      if (found) {
        const message = "Database operation in loop";
        issues.push(Issue.atStatement(file, found, message, this.getMetadata().key, this.conf.severity));
      }
    }
 
    return issues;
  }
 
}