Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip var replacement when the type cannot fully be resolved #608

Closed
uhafner opened this issue Nov 19, 2024 · 4 comments · Fixed by #609
Closed

Skip var replacement when the type cannot fully be resolved #608

uhafner opened this issue Nov 19, 2024 · 4 comments · Fixed by #609
Labels
bug Something isn't working

Comments

@uhafner
Copy link

uhafner commented Nov 19, 2024

When a variable is set by the return value of a method with a generic return type, then the type cannot be replaced with var. In such cases the UseVarForObject recipe should skip such replacements.

What version of OpenRewrite are you using?

<rewrite-maven-plugin.version>5.45.0</rewrite-maven-plugin.version>
<rewrite-testing-frameworks.version>2.22.0</rewrite-testing-frameworks.version>
<rewrite-static-analysis.version>1.20.0</rewrite-static-analysis.version>
<rewrite-migrate-java.version>2.29.0</rewrite-migrate-java.version>
<rewrite-recommendations.version>1.13.0</rewrite-recommendations.version>

How are you running OpenRewrite?

Maven Plugin:

        <plugin>
          <groupId>org.openrewrite.maven</groupId>
          <artifactId>rewrite-maven-plugin</artifactId>
          <version>${rewrite-maven-plugin.version}</version>
          <configuration>
            <exclusions>
              <exclusion>**/docker/**</exclusion>
              <exclusion>**/AbstractComparableTest.java</exclusion>
            </exclusions>
            <activeRecipes>
              <recipe>org.openrewrite.maven.BestPractices</recipe>
              <recipe>org.openrewrite.maven.RemoveRedundantDependencyVersions</recipe>
              <recipe>org.openrewrite.staticanalysis.AddSerialAnnotationToSerialVersionUID</recipe>
              <recipe>org.openrewrite.staticanalysis.MissingOverrideAnnotation</recipe>
              <recipe>org.openrewrite.staticanalysis.CodeCleanup</recipe>
              <recipe>org.openrewrite.staticanalysis.CommonStaticAnalysis</recipe>
              <recipe>org.openrewrite.staticanalysis.RemoveExtraSemicolons</recipe>
              <recipe>org.openrewrite.java.migrate.UpgradeToJava17</recipe>
              <recipe>org.openrewrite.java.migrate.util.SequencedCollection</recipe>
              <recipe>org.openrewrite.java.migrate.lang.var.UseVarForObject</recipe>
              <recipe>org.openrewrite.java.migrate.net.JavaNetAPIs</recipe>
              <recipe>org.openrewrite.java.migrate.util.JavaUtilAPIs</recipe>
              <recipe>org.openrewrite.java.migrate.lang.StringRulesRecipes</recipe>
              <recipe>org.openrewrite.java.format.RemoveTrailingWhitespace</recipe>
              <recipe>org.openrewrite.java.format.BlankLines</recipe>
              <recipe>org.openrewrite.java.format.EmptyNewlineAtEndOfFile</recipe>
              <recipe>org.openrewrite.java.testing.assertj.SimplifyChainedAssertJAssertions</recipe>
            </activeRecipes>
          </configuration>
          <dependencies>
            <dependency>
              <groupId>org.openrewrite.recipe</groupId>
              <artifactId>rewrite-testing-frameworks</artifactId>
              <version>${rewrite-testing-frameworks.version}</version>
            </dependency>
            <dependency>
              <groupId>org.openrewrite.recipe</groupId>
              <artifactId>rewrite-static-analysis</artifactId>
              <version>${rewrite-static-analysis.version}</version>
            </dependency>
            <dependency>
              <groupId>org.openrewrite.recipe</groupId>
              <artifactId>rewrite-migrate-java</artifactId>
              <version>${rewrite-migrate-java.version}</version>
            </dependency>
            <dependency>
              <groupId>org.openrewrite.recipe</groupId>
              <artifactId>rewrite-recommendations</artifactId>
              <version>${rewrite-recommendations.version}</version>
            </dependency>
          </dependencies>
        </plugin>

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

    @Test
    void genericTypeInMethod() {
        rewriteRun(
          java(
            """
              package example;

              class Global {
                  static <T> T cast(Object o) {
                      return (T) o;
                  }
              }
              class User {
                  public String test() {
                      Object o = "Hello";
                      String string = Global.cast(o);
                      return string;
                  }
              }
              """,
              """
              package example;

              class Global {
                  static <T> T cast(Object o) {
                      return (T) o;
                  }
              }
              class User {
                  public String test() {
                      var o = "Hello";
                      String string = Global.cast(o);
                      return string;
                  }
              }
              """
          )
        );
    }

What did you see instead?

The currently generated code is not compiling on Java 21:

package example;

class Global {
    static <T> T cast(Object o) {
        return (T) o;
    }
}
class User {
    public String test() {
        var o = "Hello";
        var string = Global.cast(o);
        return string;
    }
}

Are you interested in contributing a fix to OpenRewrite?

No

@uhafner uhafner added the bug Something isn't working label Nov 19, 2024
@timtebeek timtebeek moved this to Backlog in OpenRewrite Nov 19, 2024
@timtebeek
Copy link
Contributor

/cc @MBoegers

@MBoegers
Copy link
Contributor

Good catch! I remember a discussion if it should be migrated to var string = Global.<String>cast(o) which would be correct, but very unusual Java. We decided to not go this far and stick with String string = Global.cast(o)

I'll pick it up soon.

@MBoegers
Copy link
Contributor

Interesting observation here.
If I analyze the J.Initializer of String string = Global.cast(o) the J.MethodInvocation's MethodType is not generic, its example.Global{name=cast,return=java.lang.String,parameters=[java.lang.Object]}.
Global#cast's MethodDeclaration is correctly typed generic J.MethodDeclaration | "MethodDeclaration{example.Global{name=cast,return=Generic{T},parameters=[java.lang.Object]}}".

For non-static methods, they are correctly typed with Generic in the MethodType.
I checked back with some contacts if static generic methods are handled differently by the parser, but I am afraid there is some information lost within OpenRewrits JavaParser.

@MBoegers
Copy link
Contributor

@uhafner the hot fix should prevent your code from breaking by never migrate variables initiated by static methods. I have to check why the OpenRewrite Java parser do not preserve the generic nature of static generic methods. Afterwards we can come back to this and readable migration of not generic method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants