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

81% Statements 81/100
84.37% Branches 27/32
100% Functions 1/1
81% Lines 81/100

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 97 98 99 100 1011x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 385x         385x 385x 385x         385x 385x 385x 385x 111x 85x 85x 4x 4x 4x 4x 85x 385x 274x 274x 205x 197x 1x 1x 1x 197x 1x 1x 1x 1x 197x 203x 205x 195x 195x         195x 196x 195x 195x 195x 196x 205x 8x 8x 203x 205x 201x 201x 3x 3x 205x 2x 2x 200x 205x       205x 45x 45x 45x 45x 274x 42x 69x 27x 27x         385x 1x  
import {ExpressionNode} from "../../nodes";
import {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";
import {Constant} from "./constant";
import {checkOffsetLength} from "./_check_offset_length";
 
export class MethodCallParam {
  public static 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 = undefined;
      if (child.get() instanceof Expressions.Source) {
        sourceType = Source.runSyntax(child, input, targetType);
        if (checkOffsetLength(child, sourceType, method, input)) {
          return;
        }
      } else if (child.get() instanceof Expressions.ConstantString) {
        sourceType = Constant.runSyntax(child);
      }
 
      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, child) === 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 {
      const message = "MethodCallParam, unexpected child";
      input.issues.push(syntaxIssue(input, node.getFirstToken(), message));
      return;
    }
  }
}