smallrye / jandex

Java Annotation Indexer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Not a parameterized type!" when indexing a record with a compact constructor and an annotated parameterized types

nithril opened this issue · comments

Hello,

Considering this java record with a compact constructor:

public record MyRecord(List<@NotEmpty String> list) {
    public MyRecord {
        list = null;
    }
}

When indexing the record

Indexer indexer = new Indexer();
indexer.indexClass(MyRecord.class);

Jandex throws a java.lang.IllegalArgumentException: Not a parameterized type!

The error occurs when parsing a type annotation on the record constructor. If the constructor is removed, the class file is parsed just fine. This is how javap -v -p shows the constructor:

  public test.MyRecord(java.util.List<java.lang.String>);
    descriptor: (Ljava/util/List;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Record."<init>":()V
         4: aload_0
         5: aload_1
         6: putfield      #7                  // Field list:Ljava/util/List;
         9: return
      LineNumberTable:
        line 6: 0
        line 7: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Ltest/MyRecord;
            0      10     1  list   Ljava/util/List;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      10     1  list   Ljava/util/List<Ljava/lang/String;>;
    MethodParameters:
      Name                           Flags
      list
    Signature: #37                          // (Ljava/util/List<Ljava/lang/String;>;)V
    RuntimeVisibleTypeAnnotations:
      0: #28(): FIELD, location=[TYPE_ARGUMENT(0)]
        test.NotEmpty

It seems to me that the target_type value of the type annotation is wrong -- it's FIELD (0x13), but it should be METHOD_PARAMETER (0x16). Congrats, you found a bug in javac :-)

Jandex should be able to ignore that. I'll try to figure something out.

Also, it seems the problem only appears with a compact constructor. As a workaround, you can use a normal constructor instead of a compact one:

public record MyRecord(List<@NotEmpty String> list) {
    public MyRecord(List<@NotEmpty String> list) {
        this.list = list;
    }
}

It seems to me that the target_type value of the type annotation is wrong -- it's FIELD (0x13), but it should be METHOD_PARAMETER (0x16). Congrats, you found a bug in javac :-)

The merit goes to you :)

Are you sure it should be METHOD_PARAMETER? AFAIU compact constructor is operating on the fields of the class

Actually a compact constructor has implicitly declared parameters, per the JLS (8.10.4.2. Compact Canonical Constructors). In this case, there's just one parameter, and its type contains a type annotation.

The record also implicitly declares a component field (8.10.3. Record Members). That field's type also contains a type annotation, and it seems to me that javac simply takes the type of the field it generated and pushes it into the constructor parameter list. Which is fine, until there are type annotations :-)

EDIT: the record also implicitly declares an accessor method, but type annotations on its return type seem to be correct.

In any case, I have a workaround for Jandex that will just drop the invalid type annotation.

Done in #219. Thanks for the report!