openrewrite / rewrite

Automated mass refactoring of source code.
https://docs.openrewrite.org
Apache License 2.0
2.27k stars 340 forks source link

Java recipe `ChangePackage` does not work with Kotlin on non-nested package `mu` #4644

Open molikuner opened 3 weeks ago

molikuner commented 3 weeks ago

What version of OpenRewrite are you using?

I am using

How are you running OpenRewrite?

I'm running a unit test in Java.

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

import org.junit.jupiter.api.Test;
import org.openrewrite.java.ChangePackage;
import org.openrewrite.kotlin.KotlinParser;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.kotlin.Assertions.kotlin;

class ChangePackageImportTest implements RewriteTest {

    @Test
    void checkKotlinPackageImport() {
        rewriteRun(
                spec -> spec.recipes(
                                new ChangePackage(
                                        "mu",
                                        "io.github.oshai.kotlinlogging",
                                        null
                                )
                        )
                        .parser(KotlinParser.builder()),
                kotlin(
                        "import mu.KotlinLogging",
                        "import io.github.oshai.kotlinlogging.KotlinLogging"
                )
        );
    }
}

What did you expect to see?

The test passes

What did you see instead?

The test fails without any changes

Are you interested in contributing a fix to OpenRewrite?

I don't think I have the time at the moment, to look into this issue.

timtebeek commented 3 weeks ago

Thanks for the runnable report @molikuner ! I think I recall seeing a similar issue with Java when there's only a single part to the package declaration. Might be good to double check with a quick matching java(...) entry to know if it's problem specific to Kotlin, or just the recipe in general. I do understand this would be more prevalent within the Kotlin ecosystem, and definitely something to fix.

molikuner commented 3 weeks ago

Thanks for the hint to try it with Java as well, I noticed that it works in Java, but only when adding the correct dependency (io.github.microutils:kotlin-logging-jvm:3.0.5) to the classpath. This was not visible from the error message, so it took some time to figure out.

Anyway, here is a test failing with Kotlin, but working with Java:

import org.junit.jupiter.api.Test;
import org.openrewrite.java.ChangePackage;
import org.openrewrite.java.JavaParser;
import org.openrewrite.kotlin.KotlinParser;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.kotlin.Assertions.kotlin;

class ChangePackageImportTest implements RewriteTest {

    @Test
    void checkKotlinPackageImport() {
        rewriteRun(
                spec -> spec.recipes(
                                new ChangePackage(
                                        "mu",
                                        "io.github.oshai.kotlinlogging",
                                        null
                                )
                        )
                        .parser(KotlinParser.builder().classpath("kotlin-logging"))
                        .parser(JavaParser.fromJavaVersion().classpath("kotlin-logging")),
                kotlin(
                        "import mu.KotlinLogging",
                        "import io.github.oshai.kotlinlogging.KotlinLogging"
                ),
                java(
                        "import mu.KotlinLogging;",
                        "import io.github.oshai.kotlinlogging.KotlinLogging;"
                )
        );
    }
}

I think I recall seeing a similar issue with Java when there's only a single part to the package declaration.

I don't think this is the issue here. The following test also fails with Kotlin, but works with Java:

import org.junit.jupiter.api.Test;
import org.openrewrite.java.ChangePackage;
import org.openrewrite.java.JavaParser;
import org.openrewrite.kotlin.KotlinParser;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.kotlin.Assertions.kotlin;

class ChangePackageImportTest implements RewriteTest {

    @Test
    void checkKotlinPackageImport() {
        rewriteRun(
                spec -> spec.recipes(
                                new ChangePackage(
                                        "io.github.oshai.kotlinlogging",
                                        "com.example",
                                        null
                                )
                        )
                        .parser(KotlinParser.builder().classpath("kotlin-logging"))
                        .parser(JavaParser.fromJavaVersion().classpath("kotlin-logging")),
                kotlin(
                        "import io.github.oshai.kotlinlogging.KotlinLogging",
                        "import com.example.KotlinLogging"
                ),
                java(
                        "import io.github.oshai.kotlinlogging.KotlinLogging;",
                        "import com.example.KotlinLogging;"
                )
        );
    }
}
hojongs commented 2 weeks ago

Hi! Maybe I'm getting a similar issue. Doesn't the ChangePackage recipe work with Kotlin?

I'm following the getting started of OpenRewrite with my Kotlin&Gradle project.

I think ChangePackage doesn't work with Kotlin import statements.

How to reproduce

// build.gradle.kts
plugins {
    id("org.openrewrite.rewrite") version "6.27.1"
}

rewrite {
    activeRecipe(
        "org.openrewrite.java.OrderImports",
        "hojongs.ChangePackageTest",
    )
}
# rewrite.yml
---
type: specs.openrewrite.org/v1beta/recipe
name: hojongs.ChangePackageTest
recipeList:
  - org.openrewrite.java.ChangePackage:
      oldPackageName: hojongs
      newPackageName: com.hojongs
//  Before (Kotlin source code)
package hojongs.controller

import hojongs.controller.dto.ItemResponseDataImpl

// ...
//  After running the `rewriteRun` task (Kotlin source code)
package com.hojongs.controller // moved file & changed package correctly

import hojongs.controller.dto.ItemResponseDataImpl // import statement didn't change

// ...