Skip to content

Commit

Permalink
Reorganize Java upgrade to not overreport time savings
Browse files Browse the repository at this point in the history
  • Loading branch information
jkschneider committed Mar 15, 2024
1 parent 3b324fa commit 9c6acfb
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 93 deletions.
114 changes: 38 additions & 76 deletions src/main/java/org/openrewrite/java/migrate/UpgradeJavaVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,29 @@

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.*;
import org.openrewrite.gradle.IsBuildGradle;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Option;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.gradle.UpdateJavaCompatibility;
import org.openrewrite.groovy.tree.G;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.marker.JavaVersion;
import org.openrewrite.maven.MavenVisitor;
import org.openrewrite.xml.XPathMatcher;
import org.openrewrite.xml.tree.Xml;
import org.openrewrite.java.migrate.maven.UpdateMavenProjectPropertyJavaVersion;
import org.openrewrite.java.migrate.maven.UseMavenCompilerPluginReleaseConfiguration;
import org.openrewrite.java.tree.J;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@Value
@EqualsAndHashCode(callSuper = false)
public class UpgradeJavaVersion extends Recipe {

@Option(displayName = "Java version",
description = "The Java version to upgrade to.",
example = "11")
Integer version;

@Override
public String getDisplayName() {
return "Upgrade Java version";
Expand All @@ -46,84 +53,39 @@ public String getDescription() {
"Will not downgrade if the version is newer than the specified version.";
}

@Option(displayName = "Java version",
description = "The Java version to upgrade to.",
example = "11")
Integer version;
@Override
public List<Recipe> getRecipeList() {
return Arrays.asList(
new UseMavenCompilerPluginReleaseConfiguration(version),
new UpdateMavenProjectPropertyJavaVersion(version),
new UpdateJavaCompatibility(version, null, null, false, null)
);
}

/**
* This recipe only updates markers, so it does not correspond to human manual effort.
*
* @return Zero estimated time.
*/
@Override
public Duration getEstimatedEffortPerOccurrence() {
return Duration.ofMinutes(0);
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
String newVersion = version.toString();
Map<JavaVersion, JavaVersion> updatedMarkers = new HashMap<>();

return new TreeVisitor<Tree, ExecutionContext>() {
return new JavaIsoVisitor<ExecutionContext>() {
@Override
public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
if (!(tree instanceof SourceFile)) {
return tree;
}
SourceFile source = (SourceFile) tree;

if (source instanceof G.CompilationUnit && new IsBuildGradle<ExecutionContext>().visit(source, ctx) != source) {
source = (SourceFile) new UpdateJavaCompatibility(version, null, null, false, null).getVisitor().visitNonNull(source, ctx);
} else if (source instanceof Xml.Document) {
source = (SourceFile) new MavenUpdateJavaVersionVisitor().visitNonNull(source, ctx);
}

Optional<JavaVersion> maybeJavaVersion = source.getMarkers().findFirst(JavaVersion.class);
public J preVisit(J tree, ExecutionContext ctx) {
Optional<JavaVersion> maybeJavaVersion = tree.getMarkers().findFirst(JavaVersion.class);
if (maybeJavaVersion.isPresent() && maybeJavaVersion.get().getMajorVersion() < version) {
source = source.withMarkers(source.getMarkers().setByType(updatedMarkers.computeIfAbsent(maybeJavaVersion.get(),
return tree.withMarkers(tree.getMarkers().setByType(updatedMarkers.computeIfAbsent(maybeJavaVersion.get(),
m -> m.withSourceCompatibility(newVersion).withTargetCompatibility(newVersion))));
}
return source;
return tree;
}
};
}

private static final List<String> JAVA_VERSION_XPATHS = Arrays.asList(
"/project/properties/java.version",
"/project/properties/jdk.version",
"/project/properties/javaVersion",
"/project/properties/jdkVersion",
"/project/properties/maven.compiler.source",
"/project/properties/maven.compiler.target",
"/project/properties/maven.compiler.release",
"/project/properties/release.version",
"/project/build//plugins/plugin[artifactId='maven-compiler-plugin']/configuration/source",
"/project/build//plugins/plugin[artifactId='maven-compiler-plugin']/configuration/target",
"/project/build//plugins/plugin[artifactId='maven-compiler-plugin']/configuration/release");

private static final List<XPathMatcher> JAVA_VERSION_XPATH_MATCHERS =
JAVA_VERSION_XPATHS.stream().map(XPathMatcher::new).collect(Collectors.toList());


private class MavenUpdateJavaVersionVisitor extends MavenVisitor<ExecutionContext> {
@Override
public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
tag = (Xml.Tag) super.visitTag(tag, ctx);

if (JAVA_VERSION_XPATH_MATCHERS.stream().anyMatch(matcher -> matcher.matches(getCursor()))) {
Optional<Float> maybeVersion = tag.getValue().flatMap(
value -> {
try {
return Optional.of(Float.parseFloat(value));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
);

if (!maybeVersion.isPresent()) {
return tag;
}
float currentVersion = maybeVersion.get();
if (currentVersion >= version) {
return tag;
}
return tag.withValue(String.valueOf(version));
}

return tag;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.openrewrite.java.migrate.maven;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Option;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.maven.MavenVisitor;
import org.openrewrite.xml.XPathMatcher;
import org.openrewrite.xml.tree.Xml;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Value
@EqualsAndHashCode(callSuper = false)
public class UpdateMavenProjectPropertyJavaVersion extends Recipe {

private static final List<String> JAVA_VERSION_XPATHS = Arrays.asList(
"/project/properties/java.version",
"/project/properties/jdk.version",
"/project/properties/javaVersion",
"/project/properties/jdkVersion",
"/project/properties/maven.compiler.source",
"/project/properties/maven.compiler.target",
"/project/properties/maven.compiler.release",
"/project/properties/release.version");

private static final List<XPathMatcher> JAVA_VERSION_XPATH_MATCHERS =
JAVA_VERSION_XPATHS.stream().map(XPathMatcher::new).collect(Collectors.toList());

@Option(displayName = "Java version",
description = "The Java version to upgrade to.",
example = "11")
Integer version;

@Override
public String getDisplayName() {
return "Update Maven Java project properties";
}

@Override
public String getDescription() {
return "The Java version is determined by several project properties, including:\n\n" +
" * `java.version`\n" +
" * `jdk.version`\n" +
" * `javaVersion`\n" +
" * `jdkVersion`\n" +
" * `maven.compiler.source`\n" +
" * `maven.compiler.target`\n" +
" * `maven.compiler.release`\n" +
" * `release.version`\n\n" +
" These project properties are not added if they are not currently set, but only updated in place.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return new MavenVisitor<ExecutionContext>() {
@Override
public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
tag = (Xml.Tag) super.visitTag(tag, ctx);

if (JAVA_VERSION_XPATH_MATCHERS.stream().anyMatch(matcher -> matcher.matches(getCursor()))) {
Optional<Float> maybeVersion = tag.getValue().flatMap(
value -> {
try {
return Optional.of(Float.parseFloat(value));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
);

if (!maybeVersion.isPresent()) {
return tag;
}
float currentVersion = maybeVersion.get();
if (currentVersion >= version) {
return tag;
}
return tag.withValue(String.valueOf(version));
}

return tag;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ public class UseMavenCompilerPluginReleaseConfiguration extends Recipe {
description = "The new value for the release configuration. This recipe prefers ${java.version} if defined.",
example = "11"
)
String releaseVersion;
Integer releaseVersion;

@Override
public String getDisplayName() {
return "Use Maven Compiler Plugin Release Configuration";
return "Use Maven compiler plugin release configuration";
}

@Override
public String getDescription() {
return "Replaces any explicit `source` or `target` configuration (if present) on the maven-compiler-plugin with " +
"`release`, and updates the `release` value if needed. Will not downgrade the java version if the current version is higher.";
return "Replaces any explicit `source` or `target` configuration (if present) on the `maven-compiler-plugin` with " +
"`release`, and updates the `release` value if needed. Will not downgrade the Java version if the current version is higher.";
}

@Override
Expand Down Expand Up @@ -93,7 +93,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
child -> !("configuration".equals(child.getName()) && child.getChildren().isEmpty()));
}
String releaseVersionValue = hasJavaVersionProperty(getCursor().firstEnclosingOrThrow(Xml.Document.class))
? "${java.version}" : releaseVersion;
? "${java.version}" : releaseVersion.toString();
updated = addOrUpdateChild(updated, compilerPluginConfig,
Xml.Tag.build("<release>" + releaseVersionValue + "</release>"), getCursor().getParentOrThrow());
return updated;
Expand All @@ -108,7 +108,7 @@ private boolean currentNewerThanProposed(@SuppressWarnings("OptionalUsedAsFieldO
}
try {
float currentVersion = Float.parseFloat(maybeRelease.get());
float proposedVersion = Float.parseFloat(releaseVersion);
float proposedVersion = Float.parseFloat(releaseVersion.toString());
return proposedVersion < currentVersion;
} catch (NumberFormatException e) {
return false;
Expand Down
4 changes: 1 addition & 3 deletions src/main/resources/META-INF/rewrite/java-version-11.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ recipeList:
groupId: org.apache.maven.plugins
artifactId: maven-compiler-plugin
newVersion: 3.6.2
- org.openrewrite.java.migrate.maven.UseMavenCompilerPluginReleaseConfiguration:
releaseVersion: 11
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.javax.AddJaxbDependencies
Expand Down Expand Up @@ -219,4 +217,4 @@ recipeList:
- org.openrewrite.java.ChangeType:
oldFullyQualifiedTypeName: com.sun.xml.internal.bind.v2.ContextFactory
newFullyQualifiedTypeName: com.sun.xml.bind.v2.ContextFactory
ignoreDefinition: true
ignoreDefinition: true
2 changes: 0 additions & 2 deletions src/main/resources/META-INF/rewrite/java-version-17.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ tags:
recipeList:
- org.openrewrite.java.migrate.UpgradeJavaVersion:
version: 17
- org.openrewrite.java.migrate.maven.UseMavenCompilerPluginReleaseConfiguration:
releaseVersion: 17
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.DeprecatedJavaxSecurityCert
Expand Down
3 changes: 0 additions & 3 deletions src/main/resources/META-INF/rewrite/java-version-21.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ tags:
recipeList:
- org.openrewrite.java.migrate.UpgradeJavaVersion:
version: 21
- org.openrewrite.java.migrate.maven.UseMavenCompilerPluginReleaseConfiguration:
releaseVersion: 21

---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.migrate.util.SequencedCollection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ void mavenUpgradeFromJava8ToJava17ViaConfiguration() {
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>17</source>
<target>17</target>
<release>17</release>
</configuration>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
class UseMavenCompilerPluginReleaseConfigurationTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new UseMavenCompilerPluginReleaseConfiguration("11"));
spec.recipe(new UseMavenCompilerPluginReleaseConfiguration(11));
}

@DocumentExample
Expand Down

0 comments on commit 9c6acfb

Please sign in to comment.