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

89.05% Statements 122/137
76.59% Branches 36/47
100% Functions 1/1
89.05% Lines 122/137

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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 1371x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 79x 79x 79x 79x 79x 1x 1x 79x 79x 79x       79x 1x 1x 1x 1x 78x 78x 79x 71x 71x 78x 78x 79x 49x 49x 78x 78x 79x 27x 27x 1x 1x 1x 1x 27x 77x 77x 79x 1x 1x         1x 77x 77x 79x 29x 28x 28x 1x 1x 1x 1x 1x 1x 1x 1x 29x 76x 76x 79x 75x 2x 2x 75x 75x 75x 75x 75x 10x 75x 18x 65x 17x 17x 2x 2x 2x 2x 17x 75x 74x 79x 1x 1x 1x 1x 1x 1x 1x 73x 73x 73x 79x 79x 79x 1x         1x 1x 1x       1x 1x 1x 1x 1x 1x   79x 79x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {VoidType, TableType, IntegerType, DataReference, AnyType, UnknownType, StructureType, ObjectReferenceType, StringType} from "../../types/basic";
import {Source} from "../expressions/source";
import {InlineData} from "../expressions/inline_data";
import {Target} from "../expressions/target";
import {FSTarget} from "../expressions/fstarget";
import {ComponentCompareSimple} from "../expressions/component_compare_simple";
import {StatementSyntax} from "../_statement_syntax";
import {AbstractType} from "../../types/basic/_abstract_type";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class ReadTable implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
    const concat = node.concatTokens().toUpperCase();
    const sources = node.findDirectExpressions(Expressions.Source);
 
    let firstSource = node.findDirectExpression(Expressions.SimpleSource2);
    if (firstSource === undefined) {
      firstSource = sources[0];
    }
    const sourceType = firstSource ? new Source().runSyntax(firstSource, input) : undefined;
 
    if (sourceType === undefined) {
      const message = "No source type determined, read table";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    } else if (!(sourceType instanceof TableType) && !(sourceType instanceof VoidType)) {
      const message = "Read table, not a table type";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    let rowType: AbstractType = sourceType;
    if (rowType instanceof TableType) {
      rowType = rowType.getRowType();
    }
 
    const components = node.findDirectExpression(Expressions.ComponentCompareSimple);
    if (components !== undefined) {
      new ComponentCompareSimple().runSyntax(components, input, rowType);
    }
 
    const indexSource = node.findExpressionAfterToken("INDEX");
    if (indexSource) {
      const indexType = new Source().runSyntax(indexSource, input);
      if (new TypeUtils(input.scope).isAssignable(indexType, IntegerType.get()) === false) {
        const message = "READ TABLE, INDEX must be simple, got " + indexType?.constructor.name;
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
    const fromSource = node.findExpressionAfterToken("FROM");
    if (fromSource) {
      const fromType = new Source().runSyntax(fromSource, input);
      if (new TypeUtils(input.scope).isAssignable(fromType, rowType) === false) {
        const message = "READ TABLE, FROM must be compatible";
        input.issues.push(syntaxIssue(input, fromSource.getFirstToken(), message));
        return;
      }
    }
 
    const afterKey = node.findExpressionAfterToken("KEY");
    for (const s of sources) {
      if (s === firstSource || s === indexSource || s === fromSource) {
        continue;
      }
      const type = new Source().runSyntax(s, input);
      if (s === afterKey) {
        if (type instanceof StringType || type instanceof TableType || type instanceof ObjectReferenceType) {
          const message = "Key cannot be string or table or reference";
          input.issues.push(syntaxIssue(input, s.getFirstToken(), message));
          return;
        }
      }
    }
 
    const target = node.findDirectExpression(Expressions.ReadTableTarget);
    if (target) {
      if (concat.includes(" REFERENCE INTO ")) {
        rowType = new DataReference(rowType);
      }
 
      const inline = target.findFirstExpression(Expressions.InlineData);
      const fst = target.findDirectExpression(Expressions.FSTarget);
      const t = target.findFirstExpression(Expressions.Target);
      if (inline) {
        new InlineData().runSyntax(inline, input, rowType);
      } else if (fst) {
        new FSTarget().runSyntax(fst, input, rowType);
      } else if (t) {
        const targetType = new Target().runSyntax(t, input);
        if (new TypeUtils(input.scope).isAssignable(rowType, targetType) === false) {
          const message = "Incompatible types";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    }
 
    if (target === undefined && concat.includes(" TRANSPORTING NO FIELDS ") === false) {
      // if sourceType is void, assume its with header
      if (sourceType instanceof TableType && sourceType.isWithHeader() === false) {
        const message = "READ TABLE, define INTO or TRANSPORTING NO FIELDS";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
    const transporting = node.findDirectExpression(Expressions.TransportingFields);
    if (transporting
        && !(rowType instanceof VoidType)
        && !(rowType instanceof UnknownType)
        && !(rowType instanceof AnyType)) {
      if (!(rowType instanceof StructureType)) {
        const message = "READ TABLE, source not structured";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      for (const t of transporting?.findDirectExpressions(Expressions.FieldSub) || []) {
        const field = t.concatTokens();
        if (field.includes("-")) {
          // todo
          continue;
        }
        if (rowType.getComponentByName(field) === undefined) {
          const message = "READ TABLE, field " + field + " not found in source";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    }
 
  }
}