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 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 486x 1x 1x 310x 310x 1x 1x 309x 309x 1x 1x 306x 306x 1x 1x 1x 1x 486x 486x 486x 486x 442x 442x 44x 486x 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 972x 972x 842x 842x 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;
  }
 
}