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

93.54% Statements 58/62
90.9% Branches 20/22
100% Functions 1/1
93.54% Lines 58/62

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 621x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 17x 17x 17x 17x 17x 17x 3x 1x 3x 2x 2x 17x 14x 14x 14x 1x 1x 1x 1x 14x 16x 17x 3x 3x 3x         3x 3x 1x 1x 1x 1x 3x 2x 15x 17x 34x 34x 34x 1x 1x 1x 1x 34x 13x 13x 1x
import * as Expressions from "../../2_statements/expressions";
import {StatementNode} from "../../nodes";
import {Source} from "../expressions/source";
import {Target} from "../expressions/target";
import {StringType, StructureType, TableType, UnknownType, VoidType, XStringType} from "../../types/basic";
import {InlineData} from "../expressions/inline_data";
import {StatementSyntax} from "../_statement_syntax";
import {TypeUtils} from "../_type_utils";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class Concatenate implements StatementSyntax {
  public runSyntax(node: StatementNode, input: SyntaxInput): void {
    const byteMode = node.findDirectTokenByText("BYTE") !== undefined;
    const linesMode = node.findDirectTokenByText("LINES") !== undefined;
 
    const target = node.findFirstExpression(Expressions.Target);
    const inline = target?.findDirectExpression(Expressions.InlineData);
    if (inline) {
      if (byteMode) {
        InlineData.runSyntax(inline, input, XStringType.get());
      } else {
        InlineData.runSyntax(inline, input, StringType.get());
      }
    } else if (target) {
      const type = Target.runSyntax(target, input);
      const compatible = byteMode ? new TypeUtils(input.scope).isHexLike(type) : new TypeUtils(input.scope).isCharLikeStrict(type);
      if (compatible === false) {
        const message = "Target type not compatible";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
    if (linesMode) {
      for (const s of node.findDirectExpressions(Expressions.Source)) {
        const type = Source.runSyntax(s, input);
        if (!(type instanceof UnknownType) && !(type instanceof VoidType) && !(type instanceof TableType)) {
          const message = "Source must be an internal table";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
 
        if (linesMode === true && byteMode === true && type instanceof TableType && type.getRowType() instanceof StructureType) {
          const message = "Source row type must not be a structure in BYTE mode";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    }
 
    for (const s of node.findDirectExpressions(Expressions.SimpleSource3)) {
      const type = Source.runSyntax(s, input);
      const compatible = byteMode ? new TypeUtils(input.scope).isHexLike(type) : new TypeUtils(input.scope).isCharLikeStrict(type);
      if (compatible === false) {
        const message = "Source type not compatible";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    }
 
  }
}