openrewrite / rewrite-templating

Automated templating using code snippets.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`IndexOutOfBoundsException` on `matcher.parameter(0)` when matching `str.getBytes(UTF_8).length`

timtebeek opened this issue · comments

What version of OpenRewrite are you using?

  • rewrite-templating v1.3.11

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

The following Refaster rule

class Utf8EncodedLength {
  @BeforeTemplate
  int before(String str) {
    return str.getBytes(UTF_8).length;
  }

  @AfterTemplate
  int after(String str) {
    return Utf8.encodedLength(str);
  }
}

Generates a Rewrite recipe

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
    JavaVisitor<ExecutionContext> javaVisitor = new AbstractRefasterJavaVisitor() {
        final JavaTemplate before = Semantics.expression(this, "before", (String str) -> str.getBytes(UTF_8).length).build();
        final JavaTemplate after = Semantics.expression(this, "after", (String str) -> com.google.common.base.Utf8.encodedLength(str)).build();

        @Override
        public J visitFieldAccess(J.FieldAccess elem, ExecutionContext ctx) {
            JavaTemplate.Matcher matcher;
            if ((matcher = before.matcher(getCursor())).find()) {
                maybeRemoveImport("java.nio.charset.StandardCharsets.UTF_8");
                return embed(
                        after.apply(getCursor(), elem.getCoordinates().replace(), matcher.parameter(0)), // FIXME IndexOutOfBoundsException
                        getCursor(),
                        ctx,
                        SHORTEN_NAMES
                );
            }
            return super.visitFieldAccess(elem, ctx);
        }
...

Which uses template

public static JavaTemplate.Builder getTemplate() {
    return JavaTemplate
            .builder("#{str:any(java.lang.String)}.getBytes(UTF_8).length")
            .staticImports("java.nio.charset.StandardCharsets.UTF_8");
}

Which produces an IndexOutOfBoundsException when run against the reference input/output test:
https://github.com/timtebeek/error-prone-support/blob/e0c795d248e5a7c434b9a95c08e6e060af942136/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StringRulesTestInput.java#L19

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

java.lang.AssertionError: Failed to parse sources or run recipe

	at org.openrewrite.test.RewriteTest.lambda$defaultExecutionContext$10(RewriteTest.java:591)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.handleError(RecipeScheduler.java:308)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.lambda$editSources$4(RecipeScheduler.java:250)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.lambda$mapForRecipeRecursively$5(RecipeScheduler.java:334)
	at org.openrewrite.internal.InMemoryLargeSourceSet.lambda$edit$0(InMemoryLargeSourceSet.java:62)
	at org.openrewrite.internal.ListUtils.map(ListUtils.java:176)
	at org.openrewrite.internal.InMemoryLargeSourceSet.edit(InMemoryLargeSourceSet.java:61)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.mapForRecipeRecursively(RecipeScheduler.java:327)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.editSources(RecipeScheduler.java:200)
	at org.openrewrite.RecipeScheduler.scheduleRun(RecipeScheduler.java:76)
	at org.openrewrite.Recipe.run(Recipe.java:281)
	at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:346)
	at org.openrewrite.test.RewriteTest.rewriteRun(RewriteTest.java:132)
	at tech.picnic.errorprone.refasterrules.StringRulesRecipesTest.reuseStringRulesTestInputOutput(StringRulesRecipesTest.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: org.openrewrite.internal.RecipeRunException: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:329)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.visitReturn(JavaVisitor.java:1067)
	at org.openrewrite.java.tree.J$Return.acceptJava(J.java:4830)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.visitRightPadded(JavaVisitor.java:1340)
	at org.openrewrite.java.JavaVisitor.lambda$visitBlock$4(JavaVisitor.java:386)
	at org.openrewrite.internal.ListUtils.map(ListUtils.java:176)
	at org.openrewrite.java.JavaVisitor.visitBlock(JavaVisitor.java:385)
	at org.openrewrite.java.tree.J$Block.acceptJava(J.java:767)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.visitMethodDeclaration(JavaVisitor.java:868)
	at org.openrewrite.java.tree.J$MethodDeclaration.acceptJava(J.java:3594)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.visitRightPadded(JavaVisitor.java:1340)
	at org.openrewrite.java.JavaVisitor.lambda$visitBlock$4(JavaVisitor.java:386)
	at org.openrewrite.internal.ListUtils.map(ListUtils.java:176)
	at org.openrewrite.java.JavaVisitor.visitBlock(JavaVisitor.java:385)
	at org.openrewrite.java.tree.J$Block.acceptJava(J.java:767)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.visitClassDeclaration(JavaVisitor.java:473)
	at org.openrewrite.java.tree.J$ClassDeclaration.acceptJava(J.java:1219)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visitAndCast(TreeVisitor.java:361)
	at org.openrewrite.java.JavaVisitor.lambda$visitCompilationUnit$10(JavaVisitor.java:486)
	at org.openrewrite.internal.ListUtils.map(ListUtils.java:176)
	at org.openrewrite.java.JavaVisitor.visitCompilationUnit(JavaVisitor.java:486)
	at org.openrewrite.java.tree.J$CompilationUnit.acceptJava(J.java:1517)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:184)
	at org.openrewrite.Preconditions$1.visit(Preconditions.java:51)
	at org.openrewrite.Preconditions$1.visit(Preconditions.java:31)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.lambda$editSources$3(RecipeScheduler.java:230)
	at io.micrometer.core.instrument.AbstractTimer.recordCallable(AbstractTimer.java:147)
	at org.openrewrite.table.RecipeRunStats.recordEdit(RecipeRunStats.java:68)
	at org.openrewrite.RecipeScheduler$RecipeRunCycle.lambda$editSources$4(RecipeScheduler.java:227)
	... 14 more
Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
	at java.base/java.util.Objects.checkIndex(Objects.java:385)
	at java.base/java.util.ArrayList.get(ArrayList.java:427)
	at org.openrewrite.java.JavaTemplate$Matcher.parameter(JavaTemplate.java:103)
	at tech.picnic.errorprone.refasterrules.StringRulesRecipes$Utf8EncodedLengthRecipe$1.visitFieldAccess(StringRulesRecipes.java:172)
	at tech.picnic.errorprone.refasterrules.StringRulesRecipes$Utf8EncodedLengthRecipe$1.visitFieldAccess(StringRulesRecipes.java:162)
	at org.openrewrite.java.tree.J$FieldAccess.acceptJava(J.java:1906)
	at org.openrewrite.java.tree.J.accept(J.java:59)
	at org.openrewrite.TreeVisitor.visit(TreeVisitor.java:278)
	... 59 more