Skip to content

Commit 4c56260

Browse files
authored
Hoist visitor matchers and regexes into private static final constants (K4 of #1330) (#1357)
* Hoist visitor matchers and FQNs into `private static final` constants Matchers, type patterns and FQN strings that were instance fields of anonymous visitors or locals in `getVisitor()` are now constants on the recipe class, so they are built once rather than per visitor. Matchers built from recipe options stay per instance. * Precompile regex `Pattern`s into static constants `LombokUtils`, `UpgradeDockerImageVersion`, `UpdateSdkMan`, `RemoveTemporalAnnotation` and `AddTransientAnnotationToCollections` compiled constant regexes per call or per visitor. `NoGuavaCreateTempDir` used `String.matches` to compare fully qualified names, which compiles a regex on every call; it now uses `equals`. * Rename camelCase matcher constants to UPPER_SNAKE `static final` matchers in `URLConstructorsToNewURI`, `URLConstructorToURICreate`, `OptionalStreamRecipe` and `NoGuavaCreateTempDir` now follow constant naming; the latter's matcher moves to the recipe class so the precondition reuses it. `JREThrowableFinalMethods` builds its matchers from recipe options, so those stay locals and lose their constant-style names instead.
1 parent e64ee57 commit 4c56260

20 files changed

Lines changed: 101 additions & 101 deletions

‎src/main/java/org/openrewrite/java/migrate/AddMockitoJavaAgentToMavenSurefirePlugin.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe {
5757
private static final String MAVEN_DEPENDENCY_PLUGIN_EXECUTION_TAG =
5858
"<execution><id>get-mockito-agent-path</id><goals><goal>" + PROPERTIES_GOAL + "</goal></goals></execution>";
5959

60+
// The newline before the comment keeps auto-format from attaching it to a preceding sibling as a trailing comment
61+
private static final String CONFIGURATION_TAG_TEMPLATE = "<configuration>\n<!--suppress MavenModelInspection --><argLine>%s</argLine></configuration>";
62+
6063
@Getter
6164
final String displayName = "Add Mockito Java Agent to Maven Surefire Plugin";
6265

@@ -69,9 +72,6 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe {
6972
@Override
7073
public TreeVisitor<?, ExecutionContext> getVisitor() {
7174
return Preconditions.check(new DependencyInsight("org.mockito", "mockito-core", "test", null, false), new MavenIsoVisitor<ExecutionContext>() {
72-
// The newline before the comment keeps auto-format from attaching it to a preceding sibling as a trailing comment
73-
private final String CONFIGURATION_TAG_TEMPLATE = "<configuration>\n<!--suppress MavenModelInspection --><argLine>%s</argLine></configuration>";
74-
7575
private String getArgLineJavaAgentArgument() {
7676
String mockitoCoreVersion = getResolutionResult().getDependencies().getOrDefault(Scope.Test, emptyList()).stream()
7777
.filter(dependency -> "org.mockito".equals(dependency.getGroupId()) && "mockito-core"

‎src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class ArrayStoreExceptionToTypeNotPresentException extends Recipe {
3232

3333
private static final String ARRAY_STORE_EXCEPTION = "java.lang.ArrayStoreException";
3434
private static final String TYPE_NOT_PRESENT_EXCEPTION = "java.lang.TypeNotPresentException";
35+
private static final String CLASS_GET_ANNOTATION = "java.lang.Class getAnnotation(java.lang.Class)";
3536

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

4243
@Override
4344
public TreeVisitor<?, ExecutionContext> getVisitor() {
44-
String classGetAnnotationPattern = "java.lang.Class getAnnotation(java.lang.Class)";
45-
return Preconditions.check(new UsesMethod<>(classGetAnnotationPattern), new JavaIsoVisitor<ExecutionContext>() {
45+
return Preconditions.check(new UsesMethod<>(CLASS_GET_ANNOTATION), new JavaIsoVisitor<ExecutionContext>() {
4646
@Override
4747
public J.Try visitTry(J.Try tryStatement, ExecutionContext ctx) {
4848
J.Try try_ = super.visitTry(tryStatement, ctx);
49-
if (FindMethods.find(try_, classGetAnnotationPattern).isEmpty()) {
49+
if (FindMethods.find(try_, CLASS_GET_ANNOTATION).isEmpty()) {
5050
return try_;
5151
}
5252
return try_.withCatches(ListUtils.map(try_.getCatches(), catch_ -> {

‎src/main/java/org/openrewrite/java/migrate/IllegalArgumentExceptionToAlreadyConnectedException.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class IllegalArgumentExceptionToAlreadyConnectedException extends Recipe
3232

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

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

4243
@Override
4344
public TreeVisitor<?, ExecutionContext> getVisitor() {
44-
String datagramChannelSendMethodPattern = "java.nio.channels.DatagramChannel send(java.nio.ByteBuffer, java.net.SocketAddress)";
45-
return Preconditions.check(new UsesMethod<>(datagramChannelSendMethodPattern), new JavaIsoVisitor<ExecutionContext>() {
45+
return Preconditions.check(new UsesMethod<>(DATAGRAM_CHANNEL_SEND), new JavaIsoVisitor<ExecutionContext>() {
4646
@Override
4747
public J.Try visitTry(J.Try tryStatement, ExecutionContext ctx) {
4848
J.Try try_ = super.visitTry(tryStatement, ctx);
49-
if (FindMethods.find(try_, datagramChannelSendMethodPattern).isEmpty()) {
49+
if (FindMethods.find(try_, DATAGRAM_CHANNEL_SEND).isEmpty()) {
5050
return try_;
5151
}
5252
return try_.withCatches(ListUtils.map(try_.getCatches(), catch_ -> {

‎src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java‎

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

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

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

6970
@Override
7071
public TreeVisitor<?, ExecutionContext> getVisitor() {
71-
MethodMatcher METHOD_ADDSUPPRESSED = new MethodMatcher(methodPatternAddSuppressed, false);
72-
MethodMatcher METHOD_GETSUPPRESSED = new MethodMatcher(methodPatternGetSuppressed, false);
72+
MethodMatcher addSuppressed = new MethodMatcher(methodPatternAddSuppressed, false);
73+
MethodMatcher getSuppressed = new MethodMatcher(methodPatternGetSuppressed, false);
7374
return Preconditions.check(
7475
Preconditions.and(
7576
new UsesJavaVersion<>(1, 6),
7677
Preconditions.or(
77-
new DeclaresMethod<>(METHOD_ADDSUPPRESSED),
78-
new DeclaresMethod<>(METHOD_GETSUPPRESSED),
79-
new UsesMethod<>(METHOD_ADDSUPPRESSED),
80-
new UsesMethod<>(METHOD_GETSUPPRESSED))
78+
new DeclaresMethod<>(addSuppressed),
79+
new DeclaresMethod<>(getSuppressed),
80+
new UsesMethod<>(addSuppressed),
81+
new UsesMethod<>(getSuppressed))
8182
),
8283
new JavaIsoVisitor<ExecutionContext>() {
83-
private final String JAVA_THROWABLE_CLASS = "java.lang.Throwable";
84-
8584
@Override
8685
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl, ExecutionContext ctx) {
8786
J.MethodDeclaration md = super.visitMethodDeclaration(methodDecl, ctx);
8887
JavaType.Method mt = md.getMethodType();
8988
if (mt != null && TypeUtils.isAssignableTo(JAVA_THROWABLE_CLASS, mt.getDeclaringType())) {
9089
J.ClassDeclaration classDeclaration = getCursor().firstEnclosing(J.ClassDeclaration.class);
9190
if (classDeclaration != null) {
92-
if (METHOD_ADDSUPPRESSED.matches(md, classDeclaration)) {
91+
if (addSuppressed.matches(md, classDeclaration)) {
9392
JavaType.Method myAddSuppressed = mt.withName("myAddSuppressed");
9493
return md.withName(md.getName().withSimpleName("myAddSuppressed").withType(myAddSuppressed))
9594
.withMethodType(myAddSuppressed);
9695
}
97-
if (METHOD_GETSUPPRESSED.matches(md, classDeclaration)) {
96+
if (getSuppressed.matches(md, classDeclaration)) {
9897
JavaType.Method myGetSuppressed = mt.withName("myGetSuppressed");
9998
return md.withName(md.getName().withSimpleName("myGetSuppressed").withType(myGetSuppressed))
10099
.withMethodType(myGetSuppressed);
@@ -109,11 +108,11 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation methodInv, Ex
109108
J.MethodInvocation mi = super.visitMethodInvocation(methodInv, ctx);
110109
JavaType.Method mt = mi.getMethodType();
111110
if (mt != null && TypeUtils.isAssignableTo(JAVA_THROWABLE_CLASS, mt.getDeclaringType())) {
112-
if (METHOD_ADDSUPPRESSED.matches(mi)) {
111+
if (addSuppressed.matches(mi)) {
113112
JavaType.Method myAddSuppressed = mt.withName("myAddSuppressed");
114113
mi = mi.withName(mi.getName().withSimpleName("myAddSuppressed").withType(myAddSuppressed))
115114
.withMethodType(myAddSuppressed);
116-
} else if (METHOD_GETSUPPRESSED.matches(mi)) {
115+
} else if (getSuppressed.matches(mi)) {
117116
JavaType.Method myGetSuppressed = mt.withName("myGetSuppressed");
118117
mi = mi.withName(mi.getName().withSimpleName("myGetSuppressed").withType(myGetSuppressed))
119118
.withMethodType(myGetSuppressed);

‎src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class UpdateSdkMan extends Recipe {
4949
*/
5050
private static final String BUILD_METADATA = "(\\+[^-]*)?";
5151

52+
private static final Pattern JAVA_VERSION = Pattern.compile("java=(.*?)([.a-z]*-.*)");
53+
5254
@Option(displayName = "Java version",
5355
description = "The Java version to update to. Use `latest.patch` to upgrade to the latest version within the current major version.",
5456
required = false,
@@ -88,9 +90,7 @@ public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
8890
}
8991
PlainText plainText = PlainTextParser.convert(sourceFile);
9092

91-
// Define a regex pattern to extract the version and distribution
92-
Pattern pattern = Pattern.compile("java=(.*?)([.a-z]*-.*)");
93-
Matcher matcher = pattern.matcher(plainText.getText());
93+
Matcher matcher = JAVA_VERSION.matcher(plainText.getText());
9494
if (matcher.find()) {
9595
String ver;
9696
if ("latest.patch".equalsIgnoreCase(newVersion)) {

‎src/main/java/org/openrewrite/java/migrate/UpgradeDockerImageVersion.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class UpgradeDockerImageVersion extends Recipe {
5757
/// `.0.9_9` and `u392-b08` of Temurin, `.0.20.1-17.68` of Zulu or `.0.19-11` of Liberica, then the variant.
5858
private static final Pattern VERSIONED_TAG = Pattern.compile(
5959
"(\\d{1,3})(?:u\\d+(?:-b\\d+)?|(?:\\.\\d+)+(?:_\\d+)?(?:-\\d+(?:\\.\\d+)*)?)?(\\D.*)?");
60+
private static final Pattern MAVEN_TAG = Pattern.compile("(3\\.9)(?:\\.\\d+)?-eclipse-temurin-(\\d+)(.*)");
6061

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

199200
private @Nullable String upgradedTag(String imageName, String tag) {
200201
if ("maven".equals(path(imageName))) {
201-
Matcher mavenTag = Pattern.compile("(3\\.9)(?:\\.\\d+)?-eclipse-temurin-(\\d+)(.*)").matcher(tag);
202+
Matcher mavenTag = MAVEN_TAG.matcher(tag);
202203
if (!mavenTag.matches() || Integer.parseInt(mavenTag.group(2)) >= version) {
203204
return null;
204205
}

‎src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import java.util.Set;
3232

3333
public class NoGuavaCreateTempDir extends Recipe {
34+
private static final MethodMatcher GUAVA_CREATE_TEMP_DIR = new MethodMatcher("com.google.common.io.Files createTempDir()");
35+
3436
@Getter
3537
final String displayName = "Prefer `Files#createTempDirectory()`";
3638

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

4345
@Override
4446
public TreeVisitor<?, ExecutionContext> getVisitor() {
45-
return Preconditions.check(new UsesMethod<>("com.google.common.io.Files createTempDir()"), new NoGuavaTempDirVisitor());
47+
return Preconditions.check(new UsesMethod<>(GUAVA_CREATE_TEMP_DIR), new NoGuavaTempDirVisitor());
4648
}
4749

4850
private static class NoGuavaTempDirVisitor extends JavaIsoVisitor<ExecutionContext> {
49-
private static final MethodMatcher guavaCreateTempDirMatcher = new MethodMatcher("com.google.common.io.Files createTempDir()");
50-
5151
@Override
5252
public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
5353
J.CompilationUnit c = super.visitCompilationUnit(cu, ctx);
@@ -61,7 +61,7 @@ public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionCon
6161
@Override
6262
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
6363
J.MethodInvocation mi = super.visitMethodInvocation(method, ctx);
64-
if (guavaCreateTempDirMatcher.matches(mi)) {
64+
if (GUAVA_CREATE_TEMP_DIR.matches(mi)) {
6565
Cursor parent = getCursor().dropParentUntil(j -> j instanceof J.MethodDeclaration || j instanceof J.Try || j instanceof J.ClassDeclaration);
6666
J parentValue = parent.getValue();
6767
if (parentValue instanceof J.MethodDeclaration) {
@@ -81,8 +81,8 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
8181

8282
private boolean isIOExceptionOrException(JavaType.@Nullable FullyQualified fqCatch) {
8383
return fqCatch != null &&
84-
("java.io.IOException".matches(fqCatch.getFullyQualifiedName()) ||
85-
"java.lang.Exception".matches(fqCatch.getFullyQualifiedName()));
84+
("java.io.IOException".equals(fqCatch.getFullyQualifiedName()) ||
85+
"java.lang.Exception".equals(fqCatch.getFullyQualifiedName()));
8686
}
8787

8888
private J.MethodInvocation toFilesCreateTempDir(J.MethodInvocation methodInvocation) {

‎src/main/java/org/openrewrite/java/migrate/jakarta/JacksonProviderOverrides.java‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
import org.openrewrite.marker.Markers;
3636

3737
public class JacksonProviderOverrides extends Recipe {
38+
private static final MethodMatcher CONFIG_FOR_WRITING = new MethodMatcher(
39+
"com.fasterxml.jackson.jaxrs.base.ProviderBase _configForWriting(com.fasterxml.jackson.databind.ObjectMapper, java.lang.annotation.Annotation[])", true);
40+
3841
@Getter
3942
final String displayName = "Migrate Jackson provider configuration overrides";
4043

@@ -44,12 +47,9 @@ public class JacksonProviderOverrides extends Recipe {
4447
@Override
4548
public TreeVisitor<?, ExecutionContext> getVisitor() {
4649
return Preconditions.check(new UsesType<>("com.fasterxml.jackson.jaxrs.base.ProviderBase", false), new JavaIsoVisitor<ExecutionContext>() {
47-
final MethodMatcher oldMethod = new MethodMatcher(
48-
"com.fasterxml.jackson.jaxrs.base.ProviderBase _configForWriting(com.fasterxml.jackson.databind.ObjectMapper, java.lang.annotation.Annotation[])", true);
49-
5050
@Override
5151
public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext ctx) {
52-
if (!oldMethod.matches(method.getMethodType()) || method.getParameters().size() != 2) {
52+
if (!CONFIG_FOR_WRITING.matches(method.getMethodType()) || method.getParameters().size() != 2) {
5353
return super.visitMethodDeclaration(method, ctx);
5454
}
5555
String viewName = VariableNameUtils.generateVariableName("defaultView", getCursor(),
@@ -70,7 +70,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, Ex
7070
@Override
7171
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation invocation, ExecutionContext ctx) {
7272
J.MethodInvocation mi = super.visitMethodInvocation(invocation, ctx);
73-
if (!oldMethod.matches(mi)) {
73+
if (!CONFIG_FOR_WRITING.matches(mi)) {
7474
return mi;
7575
}
7676
Cursor methodCursor = getCursor().dropParentUntil(value -> value instanceof J.MethodDeclaration || value instanceof J.CompilationUnit);

‎src/main/java/org/openrewrite/java/migrate/javax/AddScopeToInjectedClass.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
public class AddScopeToInjectedClass extends ScanningRecipe<Set<String>> {
3232
private static final String JAVAX_INJECT_INJECT = "javax.inject.Inject";
3333
private static final String JAVAX_ENTERPRISE_CONTEXT_DEPENDENT = "javax.enterprise.context.Dependent";
34+
private static final AnnotationMatcher INJECT = new AnnotationMatcher('@' + JAVAX_INJECT_INJECT);
3435

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

62-
private final AnnotationMatcher matcher = new AnnotationMatcher('@' + JAVAX_INJECT_INJECT);
63-
6463
private boolean variableTypeRequiresScope(JavaType.@Nullable Variable memberVariable) {
6564
if (memberVariable == null) {
6665
return false;
6766
}
6867
for (JavaType.FullyQualified fullYQualifiedAnnotation : memberVariable.getAnnotations()) {
69-
if (matcher.matchesAnnotationOrMetaAnnotation(fullYQualifiedAnnotation)) {
68+
if (INJECT.matchesAnnotationOrMetaAnnotation(fullYQualifiedAnnotation)) {
7069
return true;
7170
}
7271
}

‎src/main/java/org/openrewrite/java/migrate/javax/AddTableGenerator.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
@EqualsAndHashCode(callSuper = false)
3737
@Value
3838
public class AddTableGenerator extends Recipe {
39+
private static final AnnotationMatcher GENERATED_VALUE = new AnnotationMatcher("@javax.persistence.GeneratedValue");
40+
private static final AnnotationMatcher GENERATED_VALUE_AUTO = new AnnotationMatcher("@javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO)");
41+
3942
String displayName = "Attributes with automatically generated values require configuration";
4043

4144
String description = "Adds missing `@TableGenerator` annotation and updates the `@GeneratedValue` annotation values when it uses automatically generated values.";
@@ -45,9 +48,6 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
4548
return Preconditions.check(
4649
new UsesType<>("javax.persistence.GeneratedValue", false),
4750
new JavaIsoVisitor<ExecutionContext>() {
48-
private final AnnotationMatcher GENERATED_VALUE = new AnnotationMatcher("@javax.persistence.GeneratedValue");
49-
private final AnnotationMatcher GENERATED_VALUE_AUTO = new AnnotationMatcher("@javax.persistence.GeneratedValue(strategy=javax.persistence.GenerationType.AUTO)");
50-
5151
@Override
5252
public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) {
5353
Set<J.Annotation> generatedValueAnnotations = FindAnnotations.find(multiVariable, "@javax.persistence.GeneratedValue");

0 commit comments

Comments
 (0)