Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -57,6 +57,9 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe {
private static final String MAVEN_DEPENDENCY_PLUGIN_EXECUTION_TAG =
"<execution><id>get-mockito-agent-path</id><goals><goal>" + PROPERTIES_GOAL + "</goal></goals></execution>";

// The newline before the comment keeps auto-format from attaching it to a preceding sibling as a trailing comment
private static final String CONFIGURATION_TAG_TEMPLATE = "<configuration>\n<!--suppress MavenModelInspection --><argLine>%s</argLine></configuration>";

@Getter
final String displayName = "Add Mockito Java Agent to Maven Surefire Plugin";

Expand All @@ -69,9 +72,6 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe {
@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new DependencyInsight("org.mockito", "mockito-core", "test", null, false), new MavenIsoVisitor<ExecutionContext>() {
// The newline before the comment keeps auto-format from attaching it to a preceding sibling as a trailing comment
private final String CONFIGURATION_TAG_TEMPLATE = "<configuration>\n<!--suppress MavenModelInspection --><argLine>%s</argLine></configuration>";

private String getArgLineJavaAgentArgument() {
String mockitoCoreVersion = getResolutionResult().getDependencies().getOrDefault(Scope.Test, emptyList()).stream()
.filter(dependency -> "org.mockito".equals(dependency.getGroupId()) && "mockito-core"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class ArrayStoreExceptionToTypeNotPresentException extends Recipe {

private static final String ARRAY_STORE_EXCEPTION = "java.lang.ArrayStoreException";
private static final String TYPE_NOT_PRESENT_EXCEPTION = "java.lang.TypeNotPresentException";
private static final String CLASS_GET_ANNOTATION = "java.lang.Class getAnnotation(java.lang.Class)";

@Getter
final String displayName = "Catch `TypeNotPresentException` thrown by `Class.getAnnotation()`";
Expand All @@ -41,12 +42,11 @@ public class ArrayStoreExceptionToTypeNotPresentException extends Recipe {

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
String classGetAnnotationPattern = "java.lang.Class getAnnotation(java.lang.Class)";
return Preconditions.check(new UsesMethod<>(classGetAnnotationPattern), new JavaIsoVisitor<ExecutionContext>() {
return Preconditions.check(new UsesMethod<>(CLASS_GET_ANNOTATION), new JavaIsoVisitor<ExecutionContext>() {
@Override
public J.Try visitTry(J.Try tryStatement, ExecutionContext ctx) {
J.Try try_ = super.visitTry(tryStatement, ctx);
if (FindMethods.find(try_, classGetAnnotationPattern).isEmpty()) {
if (FindMethods.find(try_, CLASS_GET_ANNOTATION).isEmpty()) {
return try_;
}
return try_.withCatches(ListUtils.map(try_.getCatches(), catch_ -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class IllegalArgumentExceptionToAlreadyConnectedException extends Recipe

private static final String ILLEGAL_ARGUMENT_EXCEPTION = "java.lang.IllegalArgumentException";
private static final String ALREADY_CONNECTED_EXCEPTION = "java.nio.channels.AlreadyConnectedException";
private static final String DATAGRAM_CHANNEL_SEND = "java.nio.channels.DatagramChannel send(java.nio.ByteBuffer, java.net.SocketAddress)";

@Getter
final String displayName = "Replace `IllegalArgumentException` with `AlreadyConnectedException` in `DatagramChannel.send()` method";
Expand All @@ -41,12 +42,11 @@ public class IllegalArgumentExceptionToAlreadyConnectedException extends Recipe

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
String datagramChannelSendMethodPattern = "java.nio.channels.DatagramChannel send(java.nio.ByteBuffer, java.net.SocketAddress)";
return Preconditions.check(new UsesMethod<>(datagramChannelSendMethodPattern), new JavaIsoVisitor<ExecutionContext>() {
return Preconditions.check(new UsesMethod<>(DATAGRAM_CHANNEL_SEND), new JavaIsoVisitor<ExecutionContext>() {
@Override
public J.Try visitTry(J.Try tryStatement, ExecutionContext ctx) {
J.Try try_ = super.visitTry(tryStatement, ctx);
if (FindMethods.find(try_, datagramChannelSendMethodPattern).isEmpty()) {
if (FindMethods.find(try_, DATAGRAM_CHANNEL_SEND).isEmpty()) {
return try_;
}
return try_.withCatches(ListUtils.map(try_.getCatches(), catch_ -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

@EqualsAndHashCode(callSuper = false)
public class JREThrowableFinalMethods extends Recipe {
private static final String JAVA_THROWABLE_CLASS = "java.lang.Throwable";

@Option(displayName = "Method pattern for `addSuppressed`",
description = "A method pattern matching the `addSuppressed(Throwable)` declarations and invocations to rename to `myAddSuppressed`.",
Expand Down Expand Up @@ -68,33 +69,31 @@ public JREThrowableFinalMethods(

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
MethodMatcher METHOD_ADDSUPPRESSED = new MethodMatcher(methodPatternAddSuppressed, false);
MethodMatcher METHOD_GETSUPPRESSED = new MethodMatcher(methodPatternGetSuppressed, false);
MethodMatcher addSuppressed = new MethodMatcher(methodPatternAddSuppressed, false);
MethodMatcher getSuppressed = new MethodMatcher(methodPatternGetSuppressed, false);
return Preconditions.check(
Preconditions.and(
new UsesJavaVersion<>(1, 6),
Preconditions.or(
new DeclaresMethod<>(METHOD_ADDSUPPRESSED),
new DeclaresMethod<>(METHOD_GETSUPPRESSED),
new UsesMethod<>(METHOD_ADDSUPPRESSED),
new UsesMethod<>(METHOD_GETSUPPRESSED))
new DeclaresMethod<>(addSuppressed),
new DeclaresMethod<>(getSuppressed),
new UsesMethod<>(addSuppressed),
new UsesMethod<>(getSuppressed))
),
new JavaIsoVisitor<ExecutionContext>() {
private final String JAVA_THROWABLE_CLASS = "java.lang.Throwable";

@Override
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl, ExecutionContext ctx) {
J.MethodDeclaration md = super.visitMethodDeclaration(methodDecl, ctx);
JavaType.Method mt = md.getMethodType();
if (mt != null && TypeUtils.isAssignableTo(JAVA_THROWABLE_CLASS, mt.getDeclaringType())) {
J.ClassDeclaration classDeclaration = getCursor().firstEnclosing(J.ClassDeclaration.class);
if (classDeclaration != null) {
if (METHOD_ADDSUPPRESSED.matches(md, classDeclaration)) {
if (addSuppressed.matches(md, classDeclaration)) {
JavaType.Method myAddSuppressed = mt.withName("myAddSuppressed");
return md.withName(md.getName().withSimpleName("myAddSuppressed").withType(myAddSuppressed))
.withMethodType(myAddSuppressed);
}
if (METHOD_GETSUPPRESSED.matches(md, classDeclaration)) {
if (getSuppressed.matches(md, classDeclaration)) {
JavaType.Method myGetSuppressed = mt.withName("myGetSuppressed");
return md.withName(md.getName().withSimpleName("myGetSuppressed").withType(myGetSuppressed))
.withMethodType(myGetSuppressed);
Expand All @@ -109,11 +108,11 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation methodInv, Ex
J.MethodInvocation mi = super.visitMethodInvocation(methodInv, ctx);
JavaType.Method mt = mi.getMethodType();
if (mt != null && TypeUtils.isAssignableTo(JAVA_THROWABLE_CLASS, mt.getDeclaringType())) {
if (METHOD_ADDSUPPRESSED.matches(mi)) {
if (addSuppressed.matches(mi)) {
JavaType.Method myAddSuppressed = mt.withName("myAddSuppressed");
mi = mi.withName(mi.getName().withSimpleName("myAddSuppressed").withType(myAddSuppressed))
.withMethodType(myAddSuppressed);
} else if (METHOD_GETSUPPRESSED.matches(mi)) {
} else if (getSuppressed.matches(mi)) {
JavaType.Method myGetSuppressed = mt.withName("myGetSuppressed");
mi = mi.withName(mi.getName().withSimpleName("myGetSuppressed").withType(myGetSuppressed))
.withMethodType(myGetSuppressed);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class UpdateSdkMan extends Recipe {
*/
private static final String BUILD_METADATA = "(\\+[^-]*)?";

private static final Pattern JAVA_VERSION = Pattern.compile("java=(.*?)([.a-z]*-.*)");

@Option(displayName = "Java version",
description = "The Java version to update to. Use `latest.patch` to upgrade to the latest version within the current major version.",
required = false,
Expand Down Expand Up @@ -88,9 +90,7 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
}
PlainText plainText = PlainTextParser.convert(sourceFile);

// Define a regex pattern to extract the version and distribution
Pattern pattern = Pattern.compile("java=(.*?)([.a-z]*-.*)");
Matcher matcher = pattern.matcher(plainText.getText());
Matcher matcher = JAVA_VERSION.matcher(plainText.getText());
if (matcher.find()) {
String ver;
if ("latest.patch".equalsIgnoreCase(newVersion)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class UpgradeDockerImageVersion extends Recipe {
/// `.0.9_9` and `u392-b08` of Temurin, `.0.20.1-17.68` of Zulu or `.0.19-11` of Liberica, then the variant.
private static final Pattern VERSIONED_TAG = Pattern.compile(
"(\\d{1,3})(?:u\\d+(?:-b\\d+)?|(?:\\.\\d+)+(?:_\\d+)?(?:-\\d+(?:\\.\\d+)*)?)?(\\D.*)?");
private static final Pattern MAVEN_TAG = Pattern.compile("(3\\.9)(?:\\.\\d+)?-eclipse-temurin-(\\d+)(.*)");

private static final String ARG_DEFAULTS = "argDefaults";
private static final String ARG_UPGRADES = "argUpgrades";
Expand Down Expand Up @@ -198,7 +199,7 @@ private Docker.From upgradeThroughArgs(Docker.From from, Map<String, String> def

private @Nullable String upgradedTag(String imageName, String tag) {
if ("maven".equals(path(imageName))) {
Matcher mavenTag = Pattern.compile("(3\\.9)(?:\\.\\d+)?-eclipse-temurin-(\\d+)(.*)").matcher(tag);
Matcher mavenTag = MAVEN_TAG.matcher(tag);
if (!mavenTag.matches() || Integer.parseInt(mavenTag.group(2)) >= version) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import java.util.Set;

public class NoGuavaCreateTempDir extends Recipe {
private static final MethodMatcher GUAVA_CREATE_TEMP_DIR = new MethodMatcher("com.google.common.io.Files createTempDir()");

@Getter
final String displayName = "Prefer `Files#createTempDirectory()`";

Expand All @@ -42,12 +44,10 @@ public class NoGuavaCreateTempDir extends Recipe {

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesMethod<>("com.google.common.io.Files createTempDir()"), new NoGuavaTempDirVisitor());
return Preconditions.check(new UsesMethod<>(GUAVA_CREATE_TEMP_DIR), new NoGuavaTempDirVisitor());
}

private static class NoGuavaTempDirVisitor extends JavaIsoVisitor<ExecutionContext> {
private static final MethodMatcher guavaCreateTempDirMatcher = new MethodMatcher("com.google.common.io.Files createTempDir()");

@Override
public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
J.CompilationUnit c = super.visitCompilationUnit(cu, ctx);
Expand All @@ -61,7 +61,7 @@ public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionCon
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
J.MethodInvocation mi = super.visitMethodInvocation(method, ctx);
if (guavaCreateTempDirMatcher.matches(mi)) {
if (GUAVA_CREATE_TEMP_DIR.matches(mi)) {
Cursor parent = getCursor().dropParentUntil(j -> j instanceof J.MethodDeclaration || j instanceof J.Try || j instanceof J.ClassDeclaration);
J parentValue = parent.getValue();
if (parentValue instanceof J.MethodDeclaration) {
Expand All @@ -81,8 +81,8 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu

private boolean isIOExceptionOrException(JavaType.@Nullable FullyQualified fqCatch) {
return fqCatch != null &&
("java.io.IOException".matches(fqCatch.getFullyQualifiedName()) ||
"java.lang.Exception".matches(fqCatch.getFullyQualifiedName()));
("java.io.IOException".equals(fqCatch.getFullyQualifiedName()) ||
"java.lang.Exception".equals(fqCatch.getFullyQualifiedName()));
}

private J.MethodInvocation toFilesCreateTempDir(J.MethodInvocation methodInvocation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
import org.openrewrite.marker.Markers;

public class JacksonProviderOverrides extends Recipe {
private static final MethodMatcher CONFIG_FOR_WRITING = new MethodMatcher(
"com.fasterxml.jackson.jaxrs.base.ProviderBase _configForWriting(com.fasterxml.jackson.databind.ObjectMapper, java.lang.annotation.Annotation[])", true);

@Getter
final String displayName = "Migrate Jackson provider configuration overrides";

Expand All @@ -44,12 +47,9 @@ public class JacksonProviderOverrides extends Recipe {
@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesType<>("com.fasterxml.jackson.jaxrs.base.ProviderBase", false), new JavaIsoVisitor<ExecutionContext>() {
final MethodMatcher oldMethod = new MethodMatcher(
"com.fasterxml.jackson.jaxrs.base.ProviderBase _configForWriting(com.fasterxml.jackson.databind.ObjectMapper, java.lang.annotation.Annotation[])", true);

@Override
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext ctx) {
if (!oldMethod.matches(method.getMethodType()) || method.getParameters().size() != 2) {
if (!CONFIG_FOR_WRITING.matches(method.getMethodType()) || method.getParameters().size() != 2) {
return super.visitMethodDeclaration(method, ctx);
}
String viewName = VariableNameUtils.generateVariableName("defaultView", getCursor(),
Expand All @@ -70,7 +70,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, Ex
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation invocation, ExecutionContext ctx) {
J.MethodInvocation mi = super.visitMethodInvocation(invocation, ctx);
if (!oldMethod.matches(mi)) {
if (!CONFIG_FOR_WRITING.matches(mi)) {
return mi;
}
Cursor methodCursor = getCursor().dropParentUntil(value -> value instanceof J.MethodDeclaration || value instanceof J.CompilationUnit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
public class AddScopeToInjectedClass extends ScanningRecipe<Set<String>> {
private static final String JAVAX_INJECT_INJECT = "javax.inject.Inject";
private static final String JAVAX_ENTERPRISE_CONTEXT_DEPENDENT = "javax.enterprise.context.Dependent";
private static final AnnotationMatcher INJECT = new AnnotationMatcher('@' + JAVAX_INJECT_INJECT);

@Getter
final String displayName = "Add scope annotation to injected classes";
Expand Down Expand Up @@ -59,14 +60,12 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex
return cd;
}

private final AnnotationMatcher matcher = new AnnotationMatcher('@' + JAVAX_INJECT_INJECT);

private boolean variableTypeRequiresScope(JavaType.@Nullable Variable memberVariable) {
if (memberVariable == null) {
return false;
}
for (JavaType.FullyQualified fullYQualifiedAnnotation : memberVariable.getAnnotations()) {
if (matcher.matchesAnnotationOrMetaAnnotation(fullYQualifiedAnnotation)) {
if (INJECT.matchesAnnotationOrMetaAnnotation(fullYQualifiedAnnotation)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
@EqualsAndHashCode(callSuper = false)
@Value
public class AddTableGenerator extends Recipe {
private static final AnnotationMatcher GENERATED_VALUE = new AnnotationMatcher("@javax.persistence.GeneratedValue");
private static final AnnotationMatcher GENERATED_VALUE_AUTO = new AnnotationMatcher("@javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO)");

String displayName = "Attributes with automatically generated values require configuration";

String description = "Adds missing `@TableGenerator` annotation and updates the `@GeneratedValue` annotation values when it uses automatically generated values.";
Expand All @@ -45,9 +48,6 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(
new UsesType<>("javax.persistence.GeneratedValue", false),
new JavaIsoVisitor<ExecutionContext>() {
private final AnnotationMatcher GENERATED_VALUE = new AnnotationMatcher("@javax.persistence.GeneratedValue");
private final AnnotationMatcher GENERATED_VALUE_AUTO = new AnnotationMatcher("@javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO)");

@Override
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) {
Set<J.Annotation> generatedValueAnnotations = FindAnnotations.find(multiVariable, "@javax.persistence.GeneratedValue");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
@EqualsAndHashCode(callSuper = false)
@Value
public class AddTransientAnnotationToCollections extends Recipe {
private static final Pattern COLLECTION = Pattern.compile("java.util.Collection");

String displayName = "Unannotated collection attributes require a Transient annotation";

Expand All @@ -44,7 +45,6 @@ public class AddTransientAnnotationToCollections extends Recipe {

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
Pattern collection = Pattern.compile("java.util.Collection");
return Preconditions.check(
// Only apply to JPA classes
Preconditions.or(
Expand All @@ -56,7 +56,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
@Override
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) {
// Exit if not Collection
if (!multiVariable.getType().isAssignableFrom(collection)) {
if (!multiVariable.getType().isAssignableFrom(COLLECTION)) {
return multiVariable;
}
// Exit if already has JPA annotation
Expand Down
Loading
Loading