FORM bar.
        cl=>name( 'bar' ).
      ENDFORM.

      PERFORM bar.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("bar");
  });

  it("CREATE OBJECT with dashes/structure", async () => {
    const code = `
      CLASS lcl_bar DEFINITION.
      ENDCLASS.
      CLASS lcl_bar IMPLEMENTATION.
      ENDCLASS.
      TYPES: BEGIN OF ty_structure,
              field TYPE REF TO lcl_bar,
            END OF ty_structure.
      FORM moo.
        DATA ls_structure TYPE ty_structure.
        CREATE OBJECT ls_structure-field.
      ENDFORM.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
  });

  it("class constructor", async () => {
    const code = `
      CLASS lcl_bar DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS class_constructor.
      ENDCLASS.
      CLASS lcl_bar IMPLEMENTATION.
        METHOD class_constructor.
          WRITE 'hello'.
        ENDMETHOD.
      ENDCLASS.

      FORM bar.
        DATA lo_bar TYPE REF TO lcl_bar.
        CREATE OBJECT lo_bar.
      ENDFORM.

      START-OF-SELECTION.
        PERFORM bar.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("hello");
  });

  it("Method with IMPORTING default value", async () => {
    const code = `
      CLASS lcl_bar DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS: moo IMPORTING bar LIKE sy-msgid DEFAULT sy-msgid.
      ENDCLASS.
      CLASS lcl_bar IMPLEMENTATION.
        METHOD moo.
          WRITE bar.
        ENDMETHOD.
      ENDCLASS.
      FORM form.
        sy-msgid = '123'.
        lcl_bar=>moo( ).
      ENDFORM.
      START-OF-SELECTION.
        PERFORM form.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("123");
  });

  it("CALL METHOD", async () => {
    const code = `
      CLASS lcl_bar DEFINITION.
        PUBLIC SECTION.
          METHODS name.
      ENDCLASS.
      CLASS lcl_bar IMPLEMENTATION.
        METHOD name.
          WRITE / 'hello'.
        ENDMETHOD.
      ENDCLASS.
      START-OF-SELECTION.
        PERFORM bar.
      FORM bar.
        DATA bar TYPE REF TO lcl_bar.
        CREATE OBJECT bar.
        CALL METHOD bar->name( ).
        CALL METHOD bar->name.
      ENDFORM.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("hello\nhello");
  });

  it.skip("CALL METHOD with EXPORTING", async () => {
    const code = `
      CLASS lcl_bar DEFINITION.
        PUBLIC SECTION.
          METHODS name IMPORTING foo TYPE i.
      ENDCLASS.
      CLASS lcl_bar IMPLEMENTATION.
        METHOD name.
          WRITE / foo.
        ENDMETHOD.
      ENDCLASS.
      START-OF-SELECTION.
        PERFORM bar.
      FORM bar.
        DATA bar TYPE REF TO lcl_bar.
        CREATE OBJECT bar.
        CALL METHOD bar->name( 1 ).
        CALL METHOD bar->name( foo = 2 ).
        CALL METHOD bar->name EXPORTING foo = 3.
      ENDFORM.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("1\n2\n3");
  });

  it("call method in constructor", async () => {
    const code = `
CLASS lclas DEFINITION.
  PUBLIC SECTION.
    METHODS constructor.
    METHODS foobar.
ENDCLASS.

CLASS lclas IMPLEMENTATION.
  METHOD constructor.
    foobar( ).
  ENDMETHOD.
  METHOD foobar.
    WRITE 'hello'.
  ENDMETHOD.
ENDCLASS.

FORM bar.
  DATA cl TYPE REF TO lclas.
  CREATE OBJECT cl.
  ASSERT NOT cl IS INITIAL.
ENDFORM.

START-OF-SELECTION.
  PERFORM bar.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("hello");
  });

  it("method call chain", async () => {
    const code = `
CLASS clas DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS bar1 RETURNING VALUE(ref) TYPE REF TO clas.
    CLASS-METHODS bar2 RETURNING VALUE(val) TYPE string.
ENDCLASS.
CLASS clas IMPLEMENTATION.
  METHOD bar1.
    CREATE OBJECT ref.
  ENDMETHOD.
  METHOD bar2.
    val = 'hello'.
  ENDMETHOD.
ENDCLASS.

FORM moo.
  WRITE clas=>bar1( )->bar2( ).
ENDFORM.

START-OF-SELECTION.
  PERFORM moo.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("hello");
  });

  it("method parameter uppercase", async () => {
    const code = `
      CLASS cl DEFINITION.
        PUBLIC SECTION.
          CLASS-METHODS name
            IMPORTING
              IV_URL TYPE string.
      ENDCLASS.
      CLASS cl IMPLEMENTATION.
        METHOD name.
          WRITE / iv_url.
          WRITE / IV_URL.
          WRITE / iV_URl.
        ENDMETHOD.
      ENDCLASS.

      FORM bar.
        cl=>name( 'bar' ).
      ENDFORM.

      PERFORM bar.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("bar\nbar\nbar");
  });

  it("testing initialization of variables in constructor, with CALL METHOD", async () => {
    const code = `
      CLASS zcl_super DEFINITION.
        PUBLIC SECTION.
          DATA foo TYPE i.
          METHODS constructor.
      ENDCLASS.

      CLASS zcl_super IMPLEMENTATION.
        METHOD constructor.
          foo = 1.
        ENDMETHOD.
      ENDCLASS.

      CLASS zcl_sub DEFINITION INHERITING FROM zcl_super.
        PUBLIC SECTION.
          METHODS constructor.
      ENDCLASS.

      CLASS zcl_sub IMPLEMENTATION.
        METHOD constructor.
          CALL METHOD super->constructor( ).
          WRITE foo.
        ENDMETHOD.
      ENDCLASS.

      START-OF-SELECTION.
        DATA moo TYPE REF TO zcl_sub.
        CREATE OBJECT moo.`;
    const js = await run(code);
    const f = new AsyncFunction("abap", js);
    await f(abap);
    expect(abap.console.get()).to.equal("1");
  });

  it("testing initialization of variables in constructor, with CALL METHOD 2", async () => {
    const code = `
CLASS zcl_super DEFINITION.
  PUBLIC SECTION.
    DATA foo TYPE i.
    METHODS constructor.
ENDCLASS.

CLASS zcl_super IMPLEMENTATION.
  METHOD constructor.
    foo = 1.