openclover / clover

This repository contains source code of OpenClover Core as well as its integrations: Clover-for-Ant, Clover-for-Eclipse and Clover-for-IDEA plugins. Sources are licensed under Apache 2.0 license.
Other
57 stars 14 forks source link

Istrumentation of generic instanceof pattern matching produces invalid Java code #253

Closed matic277 closed 3 months ago

matic277 commented 3 months ago

Instrumentation produces invalid Java code, if generics are used in instanceof pattern matching. Example:

public class Main
{
  public static void main(String[] args)
  {
    // ok
    final var generic = Generic.get();
    if (!(generic instanceof Generic g))
    {
      System.out.println();
    }
    else
    {
      System.out.println(g.someObj);
    }

    // not ok
    if (!(generic instanceof Generic<?> g))
    {
      System.out.println();
    }
    else
    {
      System.out.println(g.someObj);
    }
  }

  public static class Generic<T>
  {
    T someObj = null;

    public static Object get() { return new Generic<>(); }
  }
}

Produces:

public class Main
{public static class __CLR4_5_21b1blty2xw21{...}
  public static void main(String[] args)
  {__CLR4_5_21b1blty2xw21.R.inc(47);
    // ok
    __CLR4_5_21b1blty2xw21.R.inc(48);final var generic = Generic.get();
    __CLR4_5_21b1blty2xw21.R.inc(49);if (!(generic instanceof Generic g))
    {{
      __CLR4_5_21b1blty2xw21.R.inc(52);System.out.println();
    }
    }else
    {{
      __CLR4_5_21b1blty2xw21.R.inc(53);System.out.println(g.someObj);
    }

    // not ok
    }__CLR4_5_21b1blty2xw21.R.inc(54);if ((((!(generic instanceof Generic<?> g))&&(__CLR4_5_21b1blty2xw21.R.iget(55)!=0|true))||(__CLR4_5_21b1blty2xw21.R.iget(56)==0&false)))
    {{
      __CLR4_5_21b1blty2xw21.R.inc(57);System.out.println();
    }
    }else
    {{
      __CLR4_5_21b1blty2xw21.R.inc(58);System.out.println(g.someObj); // ERROR HERE, g is out of scope
    }
  }}

  public static class Generic<T>
  {
    T someObj = null;

    public static Object get() {__CLR4_5_21b1blty2xw21.R.inc(59); __CLR4_5_21b1blty2xw21.R.inc(60);return new Generic<>(); }
  }
}

Note how clover adds more conditions to the second if-statement, which uses generics <?> on instanceof matching. Which I assume put the variable "g" out of scope in the else block.

Using Java 17 with OpenClover 4.5.2

marek-parfianowicz commented 3 months ago

Thank you for reporting this. I think this is a duplicate of https://github.com/openclover/clover/issues/237, in which I fixed two problems - the "final" keyword in instanceof and the "<?>" generic signature. This is implemented but waiting for next release, 4.6.0.