All files / src/abap/types form_definition.ts

98.04% Statements 100/102
95% Branches 19/20
100% Functions 7/7
98.04% Lines 100/102

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 1021x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 282x 1x 1x 141x 141x 1x 1x 144x 144x 1x 1x 141x 141x 1x 1x 1x 1x 282x 282x 282x 282x 270x 270x 12x 12x 12x 2x 2x 12x 10x 10x 10x 10x 10x 10x 6x 6x 10x 10x 8x 10x     10x 10x 10x 12x 12x 12x 12x 1x 1x 564x 564x 528x 528x 36x 36x 1x 1x 36x 36x 40x 40x 40x 36x 36x 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 {CurrentScope} from "../5_syntax/_current_scope";
import {FormParam} from "../5_syntax/expressions/form_param";
import {IFormDefinition} from "./_form_definition";
import {TableType, UnknownType, VoidType} from "./basic";
 
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, filename: string, scope: CurrentScope) {
    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, filename);
    this.node = st;
 
    this.tableParameters = this.findTables(scope, filename);
    this.usingParameters = this.findType(Expressions.FormUsing, scope);
    this.changingParameters = this.findType(Expressions.FormChanging, scope);
  }
 
  public getTablesParameters(): TypedIdentifier[] {
    return this.tableParameters;
  }
 
  public getUsingParameters(): TypedIdentifier[] {
    return this.usingParameters;
  }
 
  public getChangingParameters(): TypedIdentifier[] {
    return this.changingParameters;
  }
 
///////////////
 
  private findTables(scope: CurrentScope, filename: string): 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(), filename, new VoidType("FORM:UNTYPED"), [IdentifierMeta.FormParameter]));
      } else {
        const p = new FormParam().runSyntax(param, scope, this.filename);
 
        let type = p.getType();
 
        const isStructure = param.findDirectTokenByText("STRUCTURE") !== undefined;
        if (isStructure) {
          type = new TableType(type, {withHeader: true});
        }
 
        if (type instanceof TableType) {
          type = new TableType(type.getRowType(), {withHeader: true});
        } else if (!(type instanceof UnknownType) && !(type instanceof VoidType)) {
          type = new UnknownType("FORM TABLES type must be table type");
        }
 
        ret.push(new TypedIdentifier(p.getToken(), filename, type, [IdentifierMeta.FormParameter]));
      }
    }
 
    return ret;
  }
 
  private findType(type: new () => Expression, scope: CurrentScope): TypedIdentifier[] {
    const found = this.node.findFirstExpression(type);
    if (found === undefined) {
      return [];
    }
    return this.findParams(found, scope);
  }
 
  private findParams(node: ExpressionNode | StatementNode, scope: CurrentScope) {
    const res: TypedIdentifier[] = [];
    for (const param of node.findAllExpressions(Expressions.FormParam)) {
      const p = new FormParam().runSyntax(param, scope, this.filename);
      res.push(p);
    }
    return res;
  }
 
}