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

82.85% Statements 87/105
76.31% Branches 29/38
100% Functions 1/1
82.85% Lines 87/105

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 1051x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 96x 96x 96x 96x 96x 96x 96x 96x 96x 96x 6x         6x 6x 6x 96x 96x 96x 3x         3x 3x 3x 96x 96x 96x 41x 41x 96x 68x 68x 68x 68x 68x         68x 68x 68x 65x 68x 1x 1x 68x 68x 68x 7x 7x 5x 7x 1x 1x 1x 1x 6x 6x 6x 7x         68x 61x 1x 1x 1x 1x 61x 68x 94x 94x 96x 1x 1x 94x 96x     96x 96x 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, UnknownType, 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 = Target.runSyntax(target, input);
    }
 
    const fsTarget = node.findExpressionAfterToken("ASSIGNING");
    if (fsTarget && fsTarget.get() instanceof Expressions.FSTarget) {
      if (!(targetType instanceof TableType) && !(targetType instanceof VoidType) && !(targetType instanceof UnknownType)) {
        const message = "APPEND to non table type, " + targetType?.constructor.name;
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      const rowType = targetType instanceof TableType ? targetType.getRowType() : targetType;
      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) && !(targetType instanceof UnknownType)) {
        const message = "APPEND to non table type, " + targetType?.constructor.name;
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
      const rowType = targetType instanceof TableType ? targetType.getRowType() : targetType;
      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)
          && !(targetType instanceof UnknownType)
          && dataTarget !== target
          && !(targetType instanceof VoidType)) {
        const message = `Append, target not a table type (${targetType.constructor.name})`;
        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 = 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();
        } else if (!(sourceType instanceof VoidType) && !(sourceType instanceof UnknownType)) {
          const message = "LINES OF must be a table type";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
        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) {
      Source.runSyntax(from, input);
    }
    const to = node.findExpressionAfterToken("TO");
    if (to && to.get() instanceof Expressions.Source) {
      Source.runSyntax(to, input);
    }
 
  }
}