All files / src/abap/types form_definition.ts

98.05% Statements 101/103
95.45% Branches 21/22
100% Functions 7/7
98.05% Lines 101/103

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 101 102 1031x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 520x 1x 1x 327x 327x 1x 1x 326x 326x 1x 1x 323x 323x 1x 1x 1x 1x 520x 520x 520x 520x 476x 476x 44x 520x 46x 12x 12x 46x 34x 34x 34x 34x 34x 34x 30x 30x 34x 34x 32x 34x     34x 34x 34x 34x 46x 44x 44x 44x 1x 1x 1040x 1040x 910x 910x 130x 130x 1x 1x 130x 130x 142x 142x 142x 130x 130x 1x 1x
import * as Statements from "../2_statements/statements";
import * as Expressions from "../2_statements/expressions";
import * as Tokens from "../1_lexer/tokens";
import {Identifier} from "../4_file_information/_identifier";
import {StructureNode, StatementNode, ExpressionNode} from "../nodes";
import {Expression} from "../2_statements/combi";
import {TypedIdentifier, IdentifierMeta} from "./_typed_identifier";
import {FormParam} from "../5_syntax/expressions/form_param";
import {IFormDefinition} from "./_form_definition";
import {TableKeyType, TableType, UnknownType, VoidType} from "./basic";
import {SyntaxInput} from "../5_syntax/_syntax_input";
 
export class FormDefinition extends Identifier implements IFormDefinition {
  private readonly node: StatementNode;
  private readonly tableParameters: TypedIdentifier[];
  private readonly usingParameters: TypedIdentifier[];
  private readonly changingParameters: TypedIdentifier[];
 
  public constructor(node: StructureNode | StatementNode, input: SyntaxInput) {
    const st = node instanceof StructureNode ? node.findFirstStatement(Statements.Form)! : node;
 
    // FORMs can contain a dash in the name
    const formName = st.findFirstExpression(Expressions.FormName);
    const pos = formName!.getFirstToken().getStart();
    const name = formName!.concatTokens();
    const nameToken = new Tokens.Identifier(pos, name);
 
    super(nameToken, input.filename);
    this.node = st;
 
    this.tableParameters = this.findTables(input);
    this.usingParameters = this.findType(Expressions.FormUsing, input);
    this.changingParameters = this.findType(Expressions.FormChanging, input);
  }
 
  public getTablesParameters(): TypedIdentifier[] {
    return this.tableParameters;
  }
 
  public getUsingParameters(): TypedIdentifier[] {
    return this.usingParameters;
  }
 
  public getChangingParameters(): TypedIdentifier[] {
    return this.changingParameters;
  }
 
///////////////
 
  private findTables(input: SyntaxInput): TypedIdentifier[] {
    const ret: TypedIdentifier[] = [];
 
    const tables = this.node.findFirstExpression(Expressions.FormTables);
    if (tables === undefined) {
      return [];
    }
 
    for (const param of tables.findAllExpressions(Expressions.FormParam)) {
      if (param.getChildren().length === 1) {
        // untyped TABLES parameter
        ret.push(new TypedIdentifier(param.getFirstToken(), input.filename, VoidType.get("FORM:UNTYPED"), [IdentifierMeta.FormParameter]));
      } else {
        const p = FormParam.runSyntax(param, input);
 
        let type = p.getType();
 
        const isStructure = param.findDirectTokenByText("STRUCTURE") !== undefined;
        if (isStructure) {
          type = new TableType(type, {withHeader: true, keyType: TableKeyType.default});
        }
 
        if (type instanceof TableType) {
          type = new TableType(type.getRowType(), {withHeader: true, keyType: TableKeyType.default});
        } else if (!(type instanceof UnknownType) && !(type instanceof VoidType)) {
          type = new UnknownType("FORM TABLES type must be table type");
        }
 
        // keep the meta from FormParam, so STRUCTURE typing can be recognized later
        ret.push(new TypedIdentifier(p.getToken(), input.filename, type, p.getMeta()));
      }
    }
 
    return ret;
  }
 
  private findType(type: new () => Expression, input: SyntaxInput): TypedIdentifier[] {
    const found = this.node.findFirstExpression(type);
    if (found === undefined) {
      return [];
    }
    return this.findParams(found, input);
  }
 
  private findParams(node: ExpressionNode | StatementNode, input: SyntaxInput) {
    const res: TypedIdentifier[] = [];
    for (const param of node.findAllExpressions(Expressions.FormParam)) {
      const p = FormParam.runSyntax(param, input);
      res.push(p);
    }
    return res;
  }
 
}