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

87.34% Statements 69/79
84.37% Branches 27/32
100% Functions 1/1
87.34% Lines 69/79

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 791x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 309x     309x 309x 309x     309x 309x 309x 309x 95x 79x 79x 3x 3x 79x 309x 214x 214x 163x 157x 1x 157x 1x 1x 157x 161x 163x 155x 155x     155x 156x 155x 155x 155x 156x 163x 6x 6x 161x 163x 160x 160x 154x 154x 163x 163x 163x   163x 37x 37x 214x 37x 51x 14x 14x       309x 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)) {
        if (method.getParameters().getImporting().length === 0) {
          throw new Error("Method \"" + method.getName() + "\" has no importing parameters");
        } else if (method.getParameters().getRequiredParameters().length > 1) {
          throw new Error("Method \"" + method.getName() + "\" has more than one importing or changing parameter");
        }
      }
      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");
    }
  }
}