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

82% Statements 82/100
77.41% Branches 24/31
100% Functions 1/1
82% Lines 82/100

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 1001x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 92x 92x 92x 92x 92x 92x 92x 92x 92x 92x 6x         6x 6x 6x 92x 92x 92x 3x         3x 3x 3x 92x 92x 92x 38x 38x 92x 64x 64x 64x 64x         64x 64x 64x 62x 64x 1x 1x 64x 64x 64x 6x 6x 5x 5x 6x 6x 6x 6x         64x 58x 1x 1x 1x 1x 58x 64x 91x 91x 92x 1x 1x 91x 92x     92x 92x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {Source} from "../expressions/source";
import {Target} from "../expressions/target";
import {DataReference, TableType, VoidType} from "../../types/basic";
import {AbstractType} from "../../types/basic/_abstract_type";
import {FSTarget} from "../expressions/fstarget";
import {StatementSyntax} from "../_statement_syntax";
import {InlineData} from "../expressions/inline_data";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
// todo: issue error for short APPEND if the source is without header line
export class Append implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
 
    let targetType: AbstractType | undefined = undefined;
 
    const target = node.findDirectExpression(Expressions.Target);
    if (target) {
      targetType = new Target().runSyntax(target, input);
    }
 
    const fsTarget = node.findExpressionAfterToken("ASSIGNING");
    if (fsTarget && fsTarget.get() instanceof Expressions.FSTarget) {
      if (!(targetType instanceof TableType) && !(targetType instanceof VoidType)) {
        const message = "APPEND to non table type";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      const rowType = targetType instanceof TableType ? targetType.getRowType() : targetType;
      new FSTarget().runSyntax(fsTarget, input, rowType);
    }
 
    const dataTarget = node.findExpressionAfterToken("INTO");
    if (dataTarget && node.concatTokens().toUpperCase().includes(" REFERENCE INTO DATA(")) {
      if (!(targetType instanceof TableType) && !(targetType instanceof VoidType)) {
        const message = "APPEND to non table type";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      const rowType = targetType instanceof TableType ? targetType.getRowType() : targetType;
      new InlineData().runSyntax(dataTarget, input, new DataReference(rowType));
    }
 
    let source = node.findDirectExpression(Expressions.SimpleSource4);
    if (source === undefined) {
      source = node.findDirectExpression(Expressions.Source);
    }
    if (source) {
      if (targetType !== undefined
          && !(targetType instanceof TableType)
          && dataTarget !== target
          && !(targetType instanceof VoidType)) {
        const message = "Append, target not a table type";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
 
      let rowType: AbstractType | undefined = undefined;
      if (targetType instanceof TableType) {
        rowType = targetType.getRowType();
      } else if (targetType instanceof VoidType) {
        rowType = targetType;
      }
      let sourceType = new Source().runSyntax(source, input, rowType);
 
      if (node.findDirectTokenByText("LINES")) {
        // hmm, checking only the row types are compatible will not check the table type, e.g. sorted or hashed
        if (sourceType instanceof TableType) {
          sourceType = sourceType.getRowType();
        }
        if (targetType instanceof TableType) {
          targetType = targetType.getRowType();
        }
        if (new TypeUtils(input.scope).isAssignable(sourceType, targetType) === false) {
          const message = "Incompatible types";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      } else {
        if (new TypeUtils(input.scope).isAssignable(sourceType, rowType) === false) {
          const message = "Incompatible types";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    }
 
    const from = node.findExpressionAfterToken("FROM");
    if (from && from.get() instanceof Expressions.Source) {
      new Source().runSyntax(from, input);
    }
    const to = node.findExpressionAfterToken("TO");
    if (to && to.get() instanceof Expressions.Source) {
      new Source().runSyntax(to, input);
    }
 
  }
}