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

Use Tree.randomId() to construct LST elements, not UUID.randomUUID() #3784

Merged
merged 14 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from 11 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
@@ -0,0 +1,111 @@
package org.openrewrite.java;
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
timtebeek marked this conversation as resolved.
Show resolved Hide resolved

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.*;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import org.openrewrite.internal.lang.NonNull;

@Value
@EqualsAndHashCode(callSuper = true)
public class ReplaceUUIDRandomId extends Recipe {
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
/**
* A method pattern that is used to find matching LST constructor invocations.
* See {@link MethodMatcher} for details on the expression's syntax.
*/
@Option(displayName = "LST Constructor pattern",
description = "A method pattern that is used to find matching LST constructor invocations.",
example = "com.example.LST *.*(..)")
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
String constructorPattern;
timtebeek marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String getDisplayName() {
return "Replace UUID.randomUUID() with Tree.randomId() in LST constructor call";
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public String getDescription() {
return "This recipe replaces occurrences of UUID.randomUUID() with Tree.randomId() when passed as an argument inside a constructor call for an LST class.";
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
}

@JsonCreator
public ReplaceUUIDRandomId(@NonNull @JsonProperty("fullyQualifiedClassName") String constructorPattern) {
this.constructorPattern = constructorPattern;
}

@Override
public Set<String> getTags() {
return Collections.singleton("uuid-replacement");
}

@Override
public Duration getEstimatedEffortPerOccurrence() {
return Duration.ofMinutes(2);
}

@Override
public RecipeDescriptor createRecipeDescriptor() {
// Customize if needed
return super.createRecipeDescriptor();
}

@Override
public @NotNull List<Recipe> getRecipeList() {
return Collections.emptyList();
}
timtebeek marked this conversation as resolved.
Show resolved Hide resolved

@Override
public @NotNull TreeVisitor<J, ExecutionContext> getVisitor() {
MethodMatcher lstConstructorMatcher = new MethodMatcher(constructorPattern);
return new ReplaceUUIDRandomIdVisitor(lstConstructorMatcher);
}

private static class ReplaceUUIDRandomIdVisitor extends JavaIsoVisitor<ExecutionContext> {
private final MethodMatcher methodMatcher;

public ReplaceUUIDRandomIdVisitor(MethodMatcher methodMatcher) {
this.methodMatcher = methodMatcher;
}

@Override
public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext ctx) {
J.NewClass n = super.visitNewClass(newClass, ctx);
if (methodMatcher.matches(n)) {
List<Expression> arguments = n.getArguments();
if (!arguments.isEmpty()) {
Expression firstArgument = arguments.get(0);
if (firstArgument instanceof J.MethodInvocation &&
((J.MethodInvocation) firstArgument).getSelect() instanceof J.Identifier &&
"UUID".equals(((J.Identifier) ((J.MethodInvocation) firstArgument).getSelect()).getSimpleName()) &&
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
"randomUUID".equals(((J.MethodInvocation) firstArgument).getSimpleName())) {

Expression replacement = JavaTemplate.builder("Tree.randomId()")
.imports("org.openrewrite.java.tree.Tree")
.build()
.matcher(new Cursor(getCursor(), arguments.get(0)))
.find()
? (Expression) JavaTemplate.builder("ListUtils.mapFirst(arguments, __ -> Tree.randomId())")
.imports("org.openrewrite.java.tree.Tree", "org.openrewrite.java.tree.ListUtils")
.build()
: null;

n = n.withArguments(ListUtils.mapFirst(arguments, a -> replacement));
}
}
}
return n;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.openrewrite.java;
timtebeek marked this conversation as resolved.
Show resolved Hide resolved

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

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

public class ReplaceUUIDRandomIdTest implements RewriteTest {
@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new ReplaceUUIDRandomId("com.youorg.Test;"));
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
void replacesUUIDRandomId() {
rewriteRun(
java(
"""
package com.youorg;

import org.openrewrite.java.tree.J;
import java.util.UUID;

class Test {
J.Literal literal = new J.Literal(UUID.randomUUID(), Space.EMPTY, Markers.EMPTY, null, null, null, JavaType.Primitive.Boolean);
}
""",
"""
package com.youorg;

import org.openrewrite.Tree;import org.openrewrite.java.tree.J;
import java.util.UUID;

class Test {
J.Literal literal = new J.Literal(Tree.randomId(), Space.EMPTY, Markers.EMPTY, null, null, null, JavaType.Primitive.Boolean);
}
""")
);
}

@Test
void notReplaceUUIDRandomID() {
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
rewriteRun(
java(
"""
package com.youorg;

import java.util.UUID;

class Test {
UUID uuid = UUID.randomUUID();
}
""",
"""
package com.youorg;

import java.util.UUID;

class Test {
UUID uuid = UUID.randomUUID();
}
""")
timtebeek marked this conversation as resolved.
Show resolved Hide resolved
);
}
}
Loading