Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
*/
package org.openrewrite.java.migrate.joda;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Preconditions;
import org.openrewrite.ScanningRecipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.*;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.VariableDeclarations.NamedVariable;
Expand All @@ -30,7 +30,23 @@

import static java.util.Collections.emptyList;

@EqualsAndHashCode(callSuper = false)
@Value
public class JodaTimeRecipe extends ScanningRecipe<JodaTimeRecipe.Accumulator> {

/**
* Controls whether additional safety checks are performed during the migration process.
* When enabled, the recipe will verify that expressions are safe to migrate before performing the migration.
* This helps prevent potential issues or bugs that might arise from automatic migration.
*/
@Option(displayName = "Enable safe migration",
description = "When enabled, performs additional safety checks to verify that expressions are safe to migrate before converting them. " +
"Safety checks include analyzing method parameters, return values, and variable usages across class boundaries.",
required = false
)
@Nullable
Boolean safeMigration;

@Override
public String getDisplayName() {
return "Migrate Joda-Time to Java time";
Expand All @@ -48,12 +64,12 @@ public Accumulator getInitialValue(ExecutionContext ctx) {

@Override
public TreeVisitor<?, ExecutionContext> getScanner(Accumulator acc) {
return new JodaTimeScanner(acc);
return new JodaTimeScanner(acc, Boolean.TRUE.equals(safeMigration));
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor(Accumulator acc) {
JodaTimeVisitor jodaTimeVisitor = new JodaTimeVisitor(acc, true, new LinkedList<>());
JodaTimeVisitor jodaTimeVisitor = new JodaTimeVisitor(acc, Boolean.TRUE.equals(safeMigration), new LinkedList<>());
return Preconditions.check(new UsesType<>("org.joda.time.*", true), jodaTimeVisitor);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ class JodaTimeScanner extends ScopeAwareVisitor {

@Getter
private final JodaTimeRecipe.Accumulator acc;
private final boolean safeMigration;

private final Map<NamedVariable, Set<NamedVariable>> varDependencies = new HashMap<>();
private final Map<JavaType, Set<String>> unsafeVarsByType = new HashMap<>();
private final Map<JavaType.Method, Set<NamedVariable>> methodReferencedVars = new HashMap<>();
private final Map<JavaType.Method, Set<UnresolvedVar>> methodUnresolvedReferencedVars = new HashMap<>();

public JodaTimeScanner(JodaTimeRecipe.Accumulator acc) {
this(acc, true);
}

public JodaTimeScanner(JodaTimeRecipe.Accumulator acc, boolean safeMigration) {
super(new LinkedList<>());
this.acc = acc;
this.safeMigration = safeMigration;
}

@Override
Expand All @@ -67,6 +73,9 @@ public Javadoc visitReference(Javadoc.Reference reference, ExecutionContext ctx)

@Override
public J visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
if (!safeMigration) { // skip scan if safe mode is disabled
return cu;
}
super.visitCompilationUnit(cu, ctx);
Set<NamedVariable> allReachable = new HashSet<>();
for (NamedVariable var : acc.getUnsafeVars()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void document() {
.afterRecipe(doc -> assertThat(doc.getMarkers().findFirst(MavenResolutionResult.class)
.get().getDependencies().get(Scope.Compile))
.filteredOn(rd -> rd.getDepth() == 0)
.satisfiesExactly(
.satisfiesExactlyInAnyOrder(
rd -> {
assertThat(rd.getGroupId()).isEqualTo("org.bouncycastle");
assertThat(rd.getArtifactId()).isEqualTo("bcprov-jdk18on");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class JodaTimeRecipeTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
spec
.recipe(new JodaTimeRecipe())
.recipe(new JodaTimeRecipe(true))
.parser(JavaParser.fromJavaVersion().classpath("joda-time"));
}

Expand Down