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

79.38% Statements 77/97
84.37% Branches 27/32
100% Functions 1/1
79.38% Lines 77/97

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 971x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 325x         325x 325x 325x         325x 325x 325x 325x 107x 81x 81x 3x 3x 3x 3x 81x 325x 218x 218x 166x 158x 1x 1x 1x 158x 1x 1x 1x 1x 158x 164x 166x 156x 156x         156x 157x 156x 156x 156x 157x 166x 8x 8x 164x 166x 163x 163x 164x 164x 166x 166x 166x       166x 38x 38x 38x 38x 218x 37x 52x 15x 15x           325x 1x
import {ExpressionNode} from "../../nodes";
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";
import {SyntaxInput, syntaxIssue} from "../_syntax_input";
 
export class MethodCallParam {
  public runSyntax(node: ExpressionNode, input: SyntaxInput, method: IMethodDefinition | VoidType): void {
    if (!(node.get() instanceof Expressions.MethodCallParam)) {
      const message = "MethodCallParam, unexpected input";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    const children = node.getChildren();
    if (children.length < 2 || children.length > 3) {
      const message = "MethodCallParam, unexpected child length";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
 
    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) {
          const message = "Parameter \"" + required[0].getName() + "\" must be supplied";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
    } 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) {
          const message = "Method \"" + method.getName() + "\" has no importing parameters";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        } else if (method.getParameters().getRequiredParameters().length > 1) {
          const message = "Method \"" + method.getName() + "\" has more than one importing or changing parameter";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
      }
      let targetType: AbstractType | undefined = undefined;
      if (!(method instanceof VoidType)) {
        const name = method.getParameters().getDefaultImporting();
        if (name === undefined) {
          const message = "No default importing parameter";
          input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
          return;
        }
        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, input, targetType);
      }
 
      const calculated = child.findFirstExpression(Expressions.MethodCallChain) !== undefined
        || child.findFirstExpression(Expressions.StringTemplate) !== undefined
        || child.findFirstExpression(Expressions.ArithOperator) !== undefined;
      if (sourceType === undefined) {
        const message = "No source type determined, method source";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      } else if (new TypeUtils(input.scope).isAssignableStrict(sourceType, targetType, calculated) === false) {
        const message = "Method parameter type not compatible";
        input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
        return;
      }
    } else if (child instanceof ExpressionNode && child.get() instanceof Expressions.ParameterListS) {
      new MethodParameters().checkExporting(child, input, method);
    } else if (child.get() instanceof Expressions.MethodParameters) {
      new MethodParameters().runSyntax(child, input, method);
    } else {
//      console.dir(child);
      const message = "MethodCallParam, unexpected child";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
  }
}