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

80.85% Statements 38/47
57.14% Branches 8/14
100% Functions 1/1
80.85% Lines 38/47

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 471x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x     5x 5x 5x 5x 5x 5x   5x 2x 5x     5x 5x 3x 3x 1x 3x     2x 2x 2x 3x 5x 5x 5x     5x 5x 5x 1x
import {ExpressionNode} from "../../nodes";
import {CurrentScope} from "../_current_scope";
import {ObjectReferenceType, VoidType} from "../../types/basic";
import * as Expressions from "../../2_statements/expressions";
import {AbstractType} from "../../types/basic/_abstract_type";
import {Source} from "./source";
import {TypeUtils} from "../_type_utils";
 
export class Cast {
  public runSyntax(node: ExpressionNode, scope: CurrentScope, targetType: AbstractType | undefined, filename: string): AbstractType {
    const sourceNode = node.findDirectExpression(Expressions.Source);
    if (sourceNode === undefined) {
      throw new Error("Cast, source node not found");
    }
 
    const sourceType = new Source().runSyntax(sourceNode, scope, filename);
    let tt: AbstractType | undefined = undefined;
 
    const typeName = node.findDirectExpression(Expressions.TypeNameOrInfer)?.getFirstToken().getStr();
    if (typeName === undefined) {
      throw new Error("Cast, child TypeNameOrInfer not found");
    } else if (typeName === "#" && targetType) {
      tt = targetType;
    } else if (typeName === "#") {
      throw new Error("Cast, todo, infer type");
    }
 
    if (tt === undefined) {
      const found = scope.findObjectDefinition(typeName);
      if (found === undefined && scope.getDDIC().inErrorNamespace(typeName) === false) {
        tt = new VoidType(typeName);
      } else if (found === undefined) {
// todo, this should be an UnknownType instead?
        throw new Error("Type \"" + typeName + "\" not found in scope, Cast");
      } else {
        tt = new ObjectReferenceType(found, typeName);
      }
    }
    new Source().addIfInferred(node, scope, filename, tt);
 
    if (new TypeUtils(scope).isCastable(sourceType, tt) === false) {
      throw new Error("Cast, incompatible types");
    }
 
    return tt;
  }
}