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

86.66% Statements 65/75
83.33% Branches 25/30
100% Functions 1/1
86.66% Lines 65/75

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 751x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 287x     287x 287x 287x     287x 287x 287x 287x 93x 77x 77x 3x 3x 77x 287x 194x 194x 149x 1x 1x 148x 149x 142x 142x     142x 143x 142x 142x 142x 143x 149x 6x 6x 148x 149x 147x 147x 141x 141x 149x 149x 149x   149x 31x 31x 194x 37x 45x 8x 8x       287x 1x
import {ExpressionNode} from "../../nodes";
import {CurrentScope} from "../_current_scope";
import {StringType, VoidType} from "../../types/basic";
import * as Expressions from "../../2_statements/expressions";
import {IMethodDefinition} from "../../types/_method_definition";
import {MethodParameters} from "./method_parameters";
import {WParenRight, WParenRightW} from "../../1_lexer/tokens";
import {Source} from "./source";
import {AbstractType} from "../../types/basic/_abstract_type";
import {TypeUtils} from "../_type_utils";
 
export class MethodCallParam {
  public runSyntax(node: ExpressionNode, scope: CurrentScope, method: IMethodDefinition | VoidType, filename: string): void {
    if (!(node.get() instanceof Expressions.MethodCallParam)) {
      throw new Error("MethodCallParam, unexpected input");
    }
 
    const children = node.getChildren();
    if (children.length < 2 || children.length > 3) {
      throw new Error("MethodCallParam, unexpected child length");
    }
 
    const child = children[1];
 
    if (child.get() instanceof WParenRight || child.get() instanceof WParenRightW) {
      if (!(method instanceof VoidType)) {
        const required = method.getParameters().getRequiredParameters();
        if (required.length > 0) {
          throw new Error("Parameter \"" + required[0].getName() + "\" must be supplied");
        }
      }
    } else if (child instanceof ExpressionNode
        && (child.get() instanceof Expressions.Source
        || child.get() instanceof Expressions.ConstantString)) {
      if (!(method instanceof VoidType) && method.getParameters().getImporting().length === 0) {
        throw new Error("Method \"" + method.getName() + "\" has no importing parameters");
      }
      let targetType: AbstractType | undefined = undefined;
      if (!(method instanceof VoidType)) {
        const name = method.getParameters().getDefaultImporting();
        if (name === undefined) {
          throw new Error("No default importing parameter");
        }
        for (const i of method.getParameters().getImporting()) {
          if (i.getName().toUpperCase() === name) {
            targetType = i.getType();
            break;
          }
        }
      } else {
        targetType = method;
      }
      let sourceType: AbstractType | undefined = StringType.get();
      if (child.get() instanceof Expressions.Source) {
        sourceType = new Source().runSyntax(child, scope, filename, targetType);
      }
 
      const calculated = child.findFirstExpression(Expressions.MethodCallChain) !== undefined
        || child.findFirstExpression(Expressions.StringTemplate) !== undefined
        || child.findFirstExpression(Expressions.ArithOperator) !== undefined;
      if (sourceType === undefined) {
        throw new Error("No source type determined, method source");
      } else if (new TypeUtils(scope).isAssignableStrict(sourceType, targetType, calculated) === false) {
        throw new Error("Method parameter type not compatible");
      }
    } else if (child instanceof ExpressionNode && child.get() instanceof Expressions.ParameterListS) {
      new MethodParameters().checkExporting(child, scope, method, filename);
    } else if (child.get() instanceof Expressions.MethodParameters) {
      new MethodParameters().runSyntax(child, scope, method, filename);
    } else {
//      console.dir(child);
      throw new Error("MethodCallParam, unexpected child");
    }
  }
}