All files / src/abap/5_syntax/statements loop.ts

95.41% Statements 104/109
90% Branches 54/60
100% Functions 1/1
95.41% Lines 104/109

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 99 100 101 102 103 104 105 106 107 108 1091x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 124x 124x 124x 124x 124x 46x 46x 117x 124x 124x 124x 124x 124x 2x 2x 124x 124x 124x 124x 124x   124x   112x 112x 112x 112x 1x 112x 111x 111x 111x 111x   111x 111x 111x 1x 1x 110x 124x 124x 100x 100x 100x 18x 18x 100x 110x 110x 124x 124x 1x 1x 109x 124x 124x 54x 54x 109x 124x 6x 2x 2x 4x 4x 108x 124x 124x 1x 124x 107x 107x 35x 35x 107x 107x 124x 10x 10x 105x 124x     105x 105x 124x 19x 19x 124x 124x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {CurrentScope} from "../_current_scope";
import {VoidType, TableType, UnknownType, DataReference, AnyType, DataType} from "../../types/basic";
import {Target} from "../expressions/target";
import {Source} from "../expressions/source";
import {InlineData} from "../expressions/inline_data";
import {InlineFS} from "../expressions/inline_fs";
import {FSTarget} from "../expressions/fstarget";
import {ComponentCond} from "../expressions/component_cond";
import {Dynamic} from "../expressions/dynamic";
import {StatementSyntax} from "../_statement_syntax";
import {LoopGroupBy} from "../expressions/loop_group_by";
import {AbstractType} from "../../types/basic/_abstract_type";
 
export class Loop implements StatementSyntax {
  public runSyntax(node: StatementNode, scope: CurrentScope, filename: string): void {
    const loopTarget = node.findDirectExpression(Expressions.LoopTarget);
 
    let target = loopTarget?.findDirectExpression(Expressions.Target);
    const targetType = target ? new Target().runSyntax(target, scope, filename) : undefined;
    if (target === undefined) {
      target = node.findDirectExpression(Expressions.FSTarget);
    }
 
    const write = loopTarget?.findDirectTokenByText("ASSIGNING") !== undefined;
 
    const sources = node.findDirectExpressions(Expressions.Source);
    let firstSource = node.findDirectExpression(Expressions.SimpleSource2);
    if (firstSource === undefined) {
      firstSource = sources[0];
    }
    let sourceType = firstSource ? new Source().runSyntax(firstSource, scope, filename, targetType, write) : undefined;
    let rowType: AbstractType | undefined = undefined;
 
    const concat = node.concatTokens().toUpperCase();
    if (sourceType === undefined) {
      throw new Error("No source type determined");
    } else if (sourceType instanceof UnknownType) {
      throw new Error("Loop, not a table type, " + sourceType.getError());
    } else if (sourceType instanceof TableType
        && target === undefined
        && sourceType.isWithHeader() === false
        && node.getChildren().length === 4) {
      throw new Error("Loop, no header line");
    } else if (!(sourceType instanceof TableType)
        && !(sourceType instanceof AnyType)
        && !(sourceType instanceof DataType)
        && !(sourceType instanceof VoidType)
        && concat.startsWith("LOOP AT GROUP ") === false) {
      throw new Error("Loop, not a table type");
    } else if (loopTarget === undefined
        && sourceType instanceof TableType
        && sourceType.isWithHeader() === false) {
      throw new Error("Loop, no header");
    }
 
    const targetConcat = loopTarget?.concatTokens().toUpperCase();
    if (sourceType instanceof TableType) {
      rowType = sourceType.getRowType();
      sourceType = rowType;
      if (targetConcat?.startsWith("REFERENCE INTO ")) {
        sourceType = new DataReference(sourceType);
      }
    }
 
    if (targetConcat
        && targetConcat.startsWith("TRANSPORTING ")
        && node.findDirectTokenByText("WHERE") === undefined) {
      throw new Error("Loop, TRANSPORTING NO FIELDS only with WHERE");
    }
 
    const inline = target?.findDirectExpression(Expressions.InlineData);
    if (inline) {
      new InlineData().runSyntax(inline, scope, filename, sourceType);
    }
 
    for (const s of sources) {
      if (s === firstSource) {
        continue;
      }
      new Source().runSyntax(s, scope, filename);
    }
 
    const inlinefs = target?.findDirectExpression(Expressions.InlineFS);
    if (inlinefs) {
      new InlineFS().runSyntax(inlinefs, scope, filename, sourceType);
    } else {
      const fstarget = loopTarget?.findDirectExpression(Expressions.FSTarget);
      if (fstarget) {
        new FSTarget().runSyntax(fstarget, scope, filename, sourceType);
      }
    }
 
    for (const t of node.findDirectExpressions(Expressions.ComponentCond)) {
      new ComponentCond().runSyntax(t, scope, filename, rowType);
    }
 
    for (const t of node.findDirectExpressions(Expressions.Dynamic)) {
      new Dynamic().runSyntax(t, scope, filename);
    }
 
    const group = node.findDirectExpression(Expressions.LoopGroupBy);
    if (group) {
      new LoopGroupBy().runSyntax(group, scope, filename);
    }
 
  }
}