All files / src/abap/5_syntax/expressions value_body.ts

97.61% Statements 82/84
94.73% Branches 36/38
100% Functions 1/1
97.61% Lines 82/84

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 841x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 120x 120x 120x 120x 120x 120x 29x 29x 91x 91x 120x 31x 31x 29x 29x 31x 89x 89x 89x 120x 7x 7x 89x 120x 36x 36x 86x 86x 120x 16x 16x 86x 120x 61x 61x 61x 61x 61x     61x 61x 49x 49x 61x 61x 4x 5x 5x 4x 61x 34x 34x 61x 36x 36x 59x 84x 120x 7x 7x 84x 120x 29x 29x 84x 120x 1x 1x 120x 120x 1x
import {ExpressionNode} from "../../nodes";
import {CurrentScope} from "../_current_scope";
import * as Expressions from "../../2_statements/expressions";
import {For} from "./for";
import {Source} from "./source";
import {AbstractType} from "../../types/basic/_abstract_type";
import {Let} from "./let";
import {FieldAssignment} from "./field_assignment";
import {AnyType, TableType, UnknownType, VoidType} from "../../types/basic";
 
export class ValueBody {
  public runSyntax(
    node: ExpressionNode | undefined,
    scope: CurrentScope,
    filename: string,
    targetType: AbstractType | undefined): AbstractType | undefined {
 
    if (node === undefined) {
      return targetType;
    }
 
    let forScopes = 0;
    for (const forNode of node.findDirectExpressions(Expressions.For) || []) {
      const scoped = new For().runSyntax(forNode, scope, filename);
      if (scoped === true) {
        forScopes++;
      }
    }
 
    let letScoped = false;
    const letNode = node.findDirectExpression(Expressions.Let);
    if (letNode) {
      letScoped = new Let().runSyntax(letNode, scope, filename);
    }
 
    for (const s of node.findDirectExpressions(Expressions.FieldAssignment)) {
      new FieldAssignment().runSyntax(s, scope, filename, targetType);
    }
 
    let type: AbstractType | undefined = undefined; // todo, this is only correct if there is a single source in the body
    for (const s of node.findDirectExpressions(Expressions.Source)) {
      type = new Source().runSyntax(s, scope, filename);
    }
 
    for (const foo of node.findDirectExpressions(Expressions.ValueBodyLine)) {
      if (!(targetType instanceof TableType)
          && !(targetType instanceof UnknownType)
          && !(targetType instanceof AnyType)
          && targetType !== undefined
          && !(targetType instanceof VoidType)) {
        throw new Error("Value, not a table type");
      }
      let rowType: AbstractType | undefined = targetType;
      if (targetType instanceof TableType) {
        rowType = targetType.getRowType();
      }
 
      for (const l of foo.findDirectExpressions(Expressions.ValueBodyLines)) {
        for (const s of l.findDirectExpressions(Expressions.Source)) {
          new Source().runSyntax(s, scope, filename);
        }
      }
      for (const s of foo.findDirectExpressions(Expressions.FieldAssignment)) {
        new FieldAssignment().runSyntax(s, scope, filename, rowType);
      }
      for (const s of foo.findDirectExpressions(Expressions.Source)) {
        new Source().runSyntax(s, scope, filename);
      }
    }
 
    if (letScoped === true) {
      scope.pop(node.getLastToken().getEnd());
    }
 
    for (let i = 0; i < forScopes; i++) {
      scope.pop(node.getLastToken().getEnd());
    }
 
    if (targetType?.isGeneric() && type) {
      return type;
    }
    return targetType ? targetType : type;
  }
}