openrewrite / rewrite-migrate-java

OpenRewrite recipes for migrating to newer versions of Java.
Apache License 2.0
92 stars 65 forks source link

Exception thrown when matching for `NoGuavaImmutableListOf` on `ImmutableList.of(1, 2).stream()` #489

Open olayinkasf opened 1 month ago

olayinkasf commented 1 month ago

What version of OpenRewrite are you using?

I am using

How are you running OpenRewrite?

I am using the Maven plugin, and my project is a single module project.

<plugin>
  <groupId>org.openrewrite.maven</groupId>
  <artifactId>rewrite-maven-plugin</artifactId>
  <version>5.32.1</version>
  <configuration>
    ... 
  </configuration>
</plugin>

What is the smallest, simplest way to reproduce the problem?

class A {
    void foo(String bar) {
        final List<Integer> list = ImmutableList.of(1, 2).stream().toList();
    }
}

What did you expect to see?

class A {
    void foo(String bar) {
        final List<Integer> list = List.of(1, 2).stream().toList();
    }
}

What did you see instead?

Nothing. Exception thrown.

What is the full stack trace of any errors you encountered?

Error while visiting path/to/myclass/A.java: java.lang.IndexOutOfBoundsException: Index: 1
  java.base/java.util.Collections$EmptyList.get(Collections.java:4807)
  org.openrewrite.java.migrate.guava.AbstractNoGuavaImmutableOf$1.isParentTypeDownCast(AbstractNoGuavaImmutableOf.java:149)
  org.openrewrite.java.migrate.guava.AbstractNoGuavaImmutableOf$1.visitMethodInvocation(AbstractNoGuavaImmutableOf.java:71)
  org.openrewrite.java.migrate.guava.AbstractNoGuavaImmutableOf$1.visitMethodInvocation(AbstractNoGuavaImmutableOf.java:68)
  org.openrewrite.java.tree.J$MethodInvocation.acceptJava(J.java:3921)
  org.openrewrite.java.tree.J.accept(J.java:59)
  org.openrewrite.TreeVisitor.visit(TreeVisitor.java:250)
  org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:324)
  org.openrewrite.java.JavaVisitor.visitRightPadded(JavaVisitor.java:1375)
  org.openrewrite.java.JavaVisitor.visitMethodInvocation(JavaVisitor.java:915)
  org.openrewrite.java.migrate.guava.AbstractNoGuavaImmutableOf$1.visitMethodInvocation(AbstractNoGuavaImmutableOf.java:115)
  org.openrewrite.java.migrate.guava.AbstractNoGuavaImmutableOf$1.visitMethodInvocation(AbstractNoGuavaImmutableOf.java:68)
  org.openrewrite.java.tree.J$MethodInvocation.acceptJava(J.java:3921)
  org.openrewrite.java.tree.J.accept(J.java:59)
  org.openrewrite.TreeVisitor.visit(TreeVisitor.java:250)
  org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:324)
  ...

Additional details

My understanding is that the matcher to pick up the segment to be rewritten failed pick the right method. Instead of picking up ImmutableList.of(1, 2), it picked up ImmutableList.of(1, 2).stream() and then tried to access the arguments of stream() and since stream doesn't have any argument, an IndexOutOfBoundsException was thrown.

Are you interested in contributing a fix to OpenRewrite?

I can fix it when I have time but I don't know when I will so please feel free to do that.

timtebeek commented 1 month ago

Thanks for the detailed report and links to the implementation. Indeed an odd case that we should cover. I'll add this to the backlog for now & we'll see who gets to it first. :)