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

84.72% Statements 61/72
87.09% Branches 27/31
100% Functions 1/1
84.72% Lines 61/72

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 731x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7856x 7856x     7856x 7856x 4x 4x 7856x 7856x 80x 80x 80x 80x 80x 80x 77x 77x 80x     80x 80x 80x 7776x 7776x 7776x 7856x 26x 26x 26x 7750x 7750x 7856x 7856x 7856x 7856x 7856x 7750x 12x 7750x 2x 7738x 4x 7736x 2x 2x 7750x 7750x 7856x 7750x 7750x               1x  
import {ExpressionNode} from "../../nodes";
import {TypedIdentifier, IdentifierMeta} from "../../types/_typed_identifier";
import {AnyType, CGenericType, CharacterType, HexType, NGenericType, NumericType, PackedType, PGenericType, UnknownType, XGenericType} from "../../types/basic";
import {ConstantFieldLength, FormParamName, Length, SimpleFieldChain, TypeName} from "../../2_statements/expressions";
import {BasicTypes} from "../basic_types";
import {AbstractType} from "../../types/basic/_abstract_type";
import {SyntaxInput} from "../_syntax_input";
import {AssertError} from "../assert_error";
import {Identifier} from "../../1_lexer/tokens";
 
export class FormParam {
  public static runSyntax(node: ExpressionNode, input: SyntaxInput): TypedIdentifier {
    const formParamName = node.findFirstExpression(FormParamName);
    if (formParamName === undefined) {
      throw new AssertError("FormParam, could not find FormParamName");
    }
    let nameToken = formParamName.getFirstToken();
    if (formParamName.getChildren().length > 1) {
      nameToken = new Identifier(nameToken.getStart(), formParamName.concatTokens());
    }
 
    if (node.findDirectTokenByText("STRUCTURE") && nameToken) {
      // STRUCTURES typing
      const typeName = node.findDirectExpression(SimpleFieldChain)?.getFirstToken().getStr();
      let type: AbstractType | TypedIdentifier | undefined;
      if (typeName) {
        type = input.scope.findType(typeName)?.getType();
        if (type === undefined) {
          type = input.scope.getDDIC().lookupTableOrView(typeName).type;
        }
      } else {
        type = new UnknownType("todo, FORM STRUCTURES typing");
      }
      return new TypedIdentifier(nameToken, input.filename, type,
                                 [IdentifierMeta.FormParameter, IdentifierMeta.FormParameterStructure]);
    }
 
 
 
    if (node.getChildren().length === 1 && nameToken) {
      // untyped FORM parameter
      return new TypedIdentifier(nameToken, input.filename, AnyType.get(), [IdentifierMeta.FormParameter]);
    }
 
    let bfound = new BasicTypes(input).parseType(node);
    const typeName = node.findFirstExpression(TypeName)?.concatTokens().toUpperCase();
    const hasExplicitLength = node.findFirstExpression(Length) !== undefined
      || node.findFirstExpression(ConstantFieldLength) !== undefined;
    // the length cannot be specified for FORM parameters, so these types are generic
    if (hasExplicitLength === false) {
      if (typeName === "C" && bfound instanceof CharacterType) {
        bfound = CGenericType.get();
      } else if (typeName === "X" && bfound instanceof HexType) {
        bfound = XGenericType.get();
      } else if (typeName === "P" && bfound instanceof PackedType) {
        bfound = PGenericType.get();
      } else if (typeName === "N" && bfound instanceof NumericType) {
        bfound = NGenericType.get();
      }
    }
 
    if (nameToken && bfound) {
      return new TypedIdentifier(nameToken, input.filename, bfound, [IdentifierMeta.FormParameter]);
    }

    if (nameToken) {
      return new TypedIdentifier(nameToken, input.filename, new UnknownType("FormParam, todo"), [IdentifierMeta.FormParameter]);
    }

    throw new AssertError("FormParam, unexpected node");
  }
}