From 5d2d77fb2c6a3248c73e178527d54cf1c111ef77 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 12:39:38 +0100 Subject: [PATCH 1/3] 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. --- ...MockitoJavaAgentToMavenSurefirePlugin.java | 6 +-- ...oreExceptionToTypeNotPresentException.java | 6 +-- ...tExceptionToAlreadyConnectedException.java | 6 +-- .../migrate/JREThrowableFinalMethods.java | 3 +- .../jakarta/JacksonProviderOverrides.java | 10 ++--- .../javax/AddScopeToInjectedClass.java | 5 +-- .../java/migrate/javax/AddTableGenerator.java | 6 +-- .../javax/RemoveTemporalAnnotation.java | 39 +++++++++---------- .../javax/UseJoinColumnForMapping.java | 4 +- .../java/migrate/lombok/LombokUtils.java | 3 +- .../migrate/search/FindInternalJavaxApis.java | 6 +-- .../util/OptionalNotEmptyToIsPresent.java | 7 ++-- .../util/OptionalNotPresentToIsEmpty.java | 7 ++-- 13 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/AddMockitoJavaAgentToMavenSurefirePlugin.java b/src/main/java/org/openrewrite/java/migrate/AddMockitoJavaAgentToMavenSurefirePlugin.java index 3411e16569..77946a893b 100644 --- a/src/main/java/org/openrewrite/java/migrate/AddMockitoJavaAgentToMavenSurefirePlugin.java +++ b/src/main/java/org/openrewrite/java/migrate/AddMockitoJavaAgentToMavenSurefirePlugin.java @@ -57,6 +57,9 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe { private static final String MAVEN_DEPENDENCY_PLUGIN_EXECUTION_TAG = "get-mockito-agent-path" + PROPERTIES_GOAL + ""; + // 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 = "\n%s"; + @Getter final String displayName = "Add Mockito Java Agent to Maven Surefire Plugin"; @@ -69,9 +72,6 @@ public class AddMockitoJavaAgentToMavenSurefirePlugin extends Recipe { @Override public TreeVisitor getVisitor() { return Preconditions.check(new DependencyInsight("org.mockito", "mockito-core", "test", null, false), new MavenIsoVisitor() { - // 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 = "\n%s"; - private String getArgLineJavaAgentArgument() { String mockitoCoreVersion = getResolutionResult().getDependencies().getOrDefault(Scope.Test, emptyList()).stream() .filter(dependency -> "org.mockito".equals(dependency.getGroupId()) && "mockito-core" diff --git a/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java b/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java index bbf1d8653c..48e25abf49 100644 --- a/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java +++ b/src/main/java/org/openrewrite/java/migrate/ArrayStoreExceptionToTypeNotPresentException.java @@ -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()`"; @@ -41,12 +42,11 @@ public class ArrayStoreExceptionToTypeNotPresentException extends Recipe { @Override public TreeVisitor getVisitor() { - String classGetAnnotationPattern = "java.lang.Class getAnnotation(java.lang.Class)"; - return Preconditions.check(new UsesMethod<>(classGetAnnotationPattern), new JavaIsoVisitor() { + return Preconditions.check(new UsesMethod<>(CLASS_GET_ANNOTATION), new JavaIsoVisitor() { @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_ -> { diff --git a/src/main/java/org/openrewrite/java/migrate/IllegalArgumentExceptionToAlreadyConnectedException.java b/src/main/java/org/openrewrite/java/migrate/IllegalArgumentExceptionToAlreadyConnectedException.java index b91682737c..a32350b79a 100644 --- a/src/main/java/org/openrewrite/java/migrate/IllegalArgumentExceptionToAlreadyConnectedException.java +++ b/src/main/java/org/openrewrite/java/migrate/IllegalArgumentExceptionToAlreadyConnectedException.java @@ -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"; @@ -41,12 +42,11 @@ public class IllegalArgumentExceptionToAlreadyConnectedException extends Recipe @Override public TreeVisitor getVisitor() { - String datagramChannelSendMethodPattern = "java.nio.channels.DatagramChannel send(java.nio.ByteBuffer, java.net.SocketAddress)"; - return Preconditions.check(new UsesMethod<>(datagramChannelSendMethodPattern), new JavaIsoVisitor() { + return Preconditions.check(new UsesMethod<>(DATAGRAM_CHANNEL_SEND), new JavaIsoVisitor() { @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_ -> { diff --git a/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java b/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java index 4f71b12e00..61951eeabb 100644 --- a/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java +++ b/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java @@ -34,6 +34,7 @@ @EqualsAndHashCode(callSuper = false) public class JREThrowableFinalMethods extends Recipe { + private static final String JAVA_THROWABLE_CLASS = "java.lang.Throwable"; private final String methodPatternAddSuppressed; private final String methodPatternGetSuppressed; @@ -70,8 +71,6 @@ public TreeVisitor getVisitor() { new UsesMethod<>(METHOD_GETSUPPRESSED)) ), new JavaIsoVisitor() { - 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); diff --git a/src/main/java/org/openrewrite/java/migrate/jakarta/JacksonProviderOverrides.java b/src/main/java/org/openrewrite/java/migrate/jakarta/JacksonProviderOverrides.java index 56a1bf0313..b02429db08 100644 --- a/src/main/java/org/openrewrite/java/migrate/jakarta/JacksonProviderOverrides.java +++ b/src/main/java/org/openrewrite/java/migrate/jakarta/JacksonProviderOverrides.java @@ -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"; @@ -44,12 +47,9 @@ public class JacksonProviderOverrides extends Recipe { @Override public TreeVisitor getVisitor() { return Preconditions.check(new UsesType<>("com.fasterxml.jackson.jaxrs.base.ProviderBase", false), new JavaIsoVisitor() { - 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(), @@ -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); diff --git a/src/main/java/org/openrewrite/java/migrate/javax/AddScopeToInjectedClass.java b/src/main/java/org/openrewrite/java/migrate/javax/AddScopeToInjectedClass.java index 7298d67d6e..abb66a3934 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/AddScopeToInjectedClass.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/AddScopeToInjectedClass.java @@ -31,6 +31,7 @@ public class AddScopeToInjectedClass extends ScanningRecipe> { 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"; @@ -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; } } diff --git a/src/main/java/org/openrewrite/java/migrate/javax/AddTableGenerator.java b/src/main/java/org/openrewrite/java/migrate/javax/AddTableGenerator.java index 0498d2c40f..afd8d8ec43 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/AddTableGenerator.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/AddTableGenerator.java @@ -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."; @@ -45,9 +48,6 @@ public TreeVisitor getVisitor() { return Preconditions.check( new UsesType<>("javax.persistence.GeneratedValue", false), new JavaIsoVisitor() { - 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 generatedValueAnnotations = FindAnnotations.find(multiVariable, "@javax.persistence.GeneratedValue"); diff --git a/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java b/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java index 77b5eddf11..87457a646f 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java @@ -39,6 +39,23 @@ @EqualsAndHashCode(callSuper = false) @Value public class RemoveTemporalAnnotation extends Recipe { + private static final String JAVA_SQL_TIMESTAMP = "java.sql.Timestamp"; + private static final String JAVA_SQL_TIME = "java.sql.Time"; + private static final String JAVA_SQL_DATE = "java.sql.Date"; + private static final Set JAVA_SQL_DATE_TIME_TYPES = Stream.of( + JAVA_SQL_TIMESTAMP, + JAVA_SQL_TIME, + JAVA_SQL_DATE + ).collect(toSet()); + // Combinations of TemporalType and java.sql classes that do not need removal + // TODO: maybe future recipe to handle these by creating a converter class + // https://wiki.eclipse.org/EclipseLink/Examples/JPA/Migration/OpenJPA/Mappings#.40Temporal_on_java.sql.Date.2FTime.2FTimestamp_fields + private static final Map DO_NOT_REMOVE = Stream.of(new String[][]{ + {"DATE", JAVA_SQL_TIMESTAMP}, + {"TIME", JAVA_SQL_TIMESTAMP}, + {"TIMESTAMP", JAVA_SQL_DATE} + }).collect(toMap(data -> data[0], data -> data[1])); + /* * This rule scans for the following annotation-attribute combinations where data does not need to be converted * and the Temporal annotation must be removed to avoid an EclipseLink error: @@ -62,24 +79,6 @@ public class RemoveTemporalAnnotation extends Recipe { @Override public TreeVisitor getVisitor() { Pattern temporalPattern = Pattern.compile(".*TemporalType\\.(TIMESTAMP|DATE|TIME)"); - final String JAVA_SQL_TIMESTAMP = "java.sql.Timestamp"; - final String JAVA_SQL_TIME = "java.sql.Time"; - final String JAVA_SQL_DATE = "java.sql.Date"; - - Set javaSqlDateTimeTypes = Stream.of( - JAVA_SQL_TIMESTAMP, - JAVA_SQL_TIME, - JAVA_SQL_DATE - ).collect(toSet()); - // Combinations of TemporalType and java.sql classes that do not need removal - Map doNotRemove = Stream.of(new String[][]{ - {"DATE", JAVA_SQL_TIMESTAMP}, - {"TIME", JAVA_SQL_TIMESTAMP}, - {"TIMESTAMP", JAVA_SQL_DATE} - }).collect(toMap(data -> data[0], data -> data[1])); - // TODO: maybe future recipe to handle these by creating a converter class - // https://wiki.eclipse.org/EclipseLink/Examples/JPA/Migration/OpenJPA/Mappings#.40Temporal_on_java.sql.Date.2FTime.2FTimestamp_fields - return Preconditions.check( Preconditions.and( new UsesType<>("javax.persistence.Temporal", true), @@ -95,7 +94,7 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m // Exit if no @Temporal annotation, or var is not java.sql.Date/Time/Timestamp String varClass = multiVariable.getType().toString(); Set temporalAnnos = FindAnnotations.find(multiVariable, "javax.persistence.Temporal"); - if (temporalAnnos.isEmpty() || !javaSqlDateTimeTypes.contains(varClass)) { + if (temporalAnnos.isEmpty() || !JAVA_SQL_DATE_TIME_TYPES.contains(varClass)) { return multiVariable; } @@ -109,7 +108,7 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m String temporalType = temporalMatch.group(1); // Check combination of attribute and var's class - if (doNotRemove.get(temporalType).equals(varClass)) { + if (DO_NOT_REMOVE.get(temporalType).equals(varClass)) { return multiVariable; } diff --git a/src/main/java/org/openrewrite/java/migrate/javax/UseJoinColumnForMapping.java b/src/main/java/org/openrewrite/java/migrate/javax/UseJoinColumnForMapping.java index 76611d38b4..b5725ec9ee 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/UseJoinColumnForMapping.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/UseJoinColumnForMapping.java @@ -30,8 +30,8 @@ @EqualsAndHashCode(callSuper = false) public class UseJoinColumnForMapping extends Recipe { - private final String JOIN_COLUMN = "javax.persistence.JoinColumn"; - private final String COLUMN = "javax.persistence.Column"; + private static final String JOIN_COLUMN = "javax.persistence.JoinColumn"; + private static final String COLUMN = "javax.persistence.Column"; @Getter final String displayName = "`@JoinColumn` annotations must be used with relationship mappings"; diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java b/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java index 2ee2ed4cc0..16869b0e2c 100644 --- a/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java +++ b/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java @@ -30,6 +30,7 @@ import static org.openrewrite.java.tree.J.Modifier.Type.*; class LombokUtils { + private static final AnnotationMatcher LOMBOK_NON_NULL = new AnnotationMatcher("@lombok.NonNull"); static boolean isGetter(Cursor cursor) { if (!(cursor.getValue() instanceof J.MethodDeclaration)) { @@ -245,7 +246,7 @@ static List getRequiredFields(J.ClassDecla } boolean isFinal = varDecls.hasModifier(Final); boolean hasNonNull = varDecls.getLeadingAnnotations().stream() - .anyMatch(new AnnotationMatcher("@lombok.NonNull")::matches); + .anyMatch(LOMBOK_NON_NULL::matches); if (!isFinal && !hasNonNull) { continue; } diff --git a/src/main/java/org/openrewrite/java/migrate/search/FindInternalJavaxApis.java b/src/main/java/org/openrewrite/java/migrate/search/FindInternalJavaxApis.java index 4d5860bbfd..4fe4b3de34 100644 --- a/src/main/java/org/openrewrite/java/migrate/search/FindInternalJavaxApis.java +++ b/src/main/java/org/openrewrite/java/migrate/search/FindInternalJavaxApis.java @@ -35,6 +35,7 @@ @EqualsAndHashCode(callSuper = false) @RequiredArgsConstructor public class FindInternalJavaxApis extends Recipe { + private static final TypeMatcher JAVAX_TYPE = new TypeMatcher("javax..*"); private final transient MethodCalls methodCalls = new MethodCalls(this); @@ -55,7 +56,6 @@ public class FindInternalJavaxApis extends Recipe { @Override public TreeVisitor getVisitor() { - TypeMatcher javaxType = new TypeMatcher("javax..*"); return Preconditions.check(new UsesType<>("javax..*", null), (StringUtils.isBlank(methodPattern) ? new MethodAccess.Matcher() : new MethodAccess.Matcher(methodPattern)) .asVisitor((ma, ctx) -> { @@ -65,12 +65,12 @@ public TreeVisitor getVisitor() { if (methodType == null || methodType.getReturnType() == null || methodType.getReturnType() instanceof JavaType.Unknown) { return call; } - if (TypeUtils.isAssignableTo(javaxType::matches, methodType.getReturnType())) { + if (TypeUtils.isAssignableTo(JAVAX_TYPE::matches, methodType.getReturnType())) { insertRow(ma, ctx, methodType); return SearchResult.found(call); } for (JavaType parameterType : methodType.getParameterTypes()) { - if (TypeUtils.isAssignableTo(javaxType::matches, parameterType)) { + if (TypeUtils.isAssignableTo(JAVAX_TYPE::matches, parameterType)) { insertRow(ma, ctx, methodType); return SearchResult.found(call); } diff --git a/src/main/java/org/openrewrite/java/migrate/util/OptionalNotEmptyToIsPresent.java b/src/main/java/org/openrewrite/java/migrate/util/OptionalNotEmptyToIsPresent.java index 1ba14690e3..8f0b112c35 100644 --- a/src/main/java/org/openrewrite/java/migrate/util/OptionalNotEmptyToIsPresent.java +++ b/src/main/java/org/openrewrite/java/migrate/util/OptionalNotEmptyToIsPresent.java @@ -32,6 +32,8 @@ import java.time.Duration; public class OptionalNotEmptyToIsPresent extends Recipe { + private static final MethodMatcher OPTIONAL_IS_EMPTY = new MethodMatcher("java.util.Optional isEmpty()"); + @Getter final String displayName = "Prefer `Optional.isPresent()`"; @@ -43,16 +45,15 @@ public class OptionalNotEmptyToIsPresent extends Recipe { @Override public TreeVisitor getVisitor() { - MethodMatcher optionalIsPresentMatcher = new MethodMatcher("java.util.Optional isEmpty()"); TreeVisitor check = Preconditions.and( new UsesJavaVersion<>(11), - new UsesMethod<>(optionalIsPresentMatcher)); + new UsesMethod<>(OPTIONAL_IS_EMPTY)); return Preconditions.check(check, new JavaVisitor() { @Override public J visitStatement(Statement s, ExecutionContext ctx) { if (s instanceof J.Unary) { J.Unary unary = (J.Unary) s; - if (unary.getOperator() == Type.Not && optionalIsPresentMatcher.matches(unary.getExpression())) { + if (unary.getOperator() == Type.Not && OPTIONAL_IS_EMPTY.matches(unary.getExpression())) { return JavaTemplate.apply("#{any(java.util.Optional)}.isPresent()", getCursor(), unary.getCoordinates().replace(), diff --git a/src/main/java/org/openrewrite/java/migrate/util/OptionalNotPresentToIsEmpty.java b/src/main/java/org/openrewrite/java/migrate/util/OptionalNotPresentToIsEmpty.java index e72d73eec0..d633156ae9 100644 --- a/src/main/java/org/openrewrite/java/migrate/util/OptionalNotPresentToIsEmpty.java +++ b/src/main/java/org/openrewrite/java/migrate/util/OptionalNotPresentToIsEmpty.java @@ -32,6 +32,8 @@ import java.time.Duration; public class OptionalNotPresentToIsEmpty extends Recipe { + private static final MethodMatcher OPTIONAL_IS_PRESENT = new MethodMatcher("java.util.Optional isPresent()"); + @Getter final String displayName = "Prefer `Optional.isEmpty()`"; @@ -43,16 +45,15 @@ public class OptionalNotPresentToIsEmpty extends Recipe { @Override public TreeVisitor getVisitor() { - MethodMatcher optionalIsPresentMatcher = new MethodMatcher("java.util.Optional isPresent()"); TreeVisitor check = Preconditions.and( new UsesJavaVersion<>(11), - new UsesMethod<>(optionalIsPresentMatcher)); + new UsesMethod<>(OPTIONAL_IS_PRESENT)); return Preconditions.check(check, new JavaVisitor() { @Override public J visitStatement(Statement s, ExecutionContext ctx) { if (s instanceof J.Unary) { J.Unary unary = (J.Unary) s; - if (unary.getOperator() == Type.Not && optionalIsPresentMatcher.matches(unary.getExpression())) { + if (unary.getOperator() == Type.Not && OPTIONAL_IS_PRESENT.matches(unary.getExpression())) { return JavaTemplate.apply("#{any(java.util.Optional)}.isEmpty()", getCursor(), unary.getCoordinates().replace(), From 1a2c3f808cc65a9cf9347361c23c532f246331c2 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 12:40:26 +0100 Subject: [PATCH 2/3] 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`. --- .../java/org/openrewrite/java/migrate/UpdateSdkMan.java | 6 +++--- .../openrewrite/java/migrate/UpgradeDockerImageVersion.java | 3 ++- .../java/migrate/guava/NoGuavaCreateTempDir.java | 4 ++-- .../migrate/javax/AddTransientAnnotationToCollections.java | 4 ++-- .../java/migrate/javax/RemoveTemporalAnnotation.java | 4 ++-- .../org/openrewrite/java/migrate/lombok/LombokUtils.java | 6 +++--- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java b/src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java index 9f30faacc7..78df64a5e7 100644 --- a/src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java +++ b/src/main/java/org/openrewrite/java/migrate/UpdateSdkMan.java @@ -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, @@ -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)) { diff --git a/src/main/java/org/openrewrite/java/migrate/UpgradeDockerImageVersion.java b/src/main/java/org/openrewrite/java/migrate/UpgradeDockerImageVersion.java index 07c39abaeb..0dc9e9b4c3 100644 --- a/src/main/java/org/openrewrite/java/migrate/UpgradeDockerImageVersion.java +++ b/src/main/java/org/openrewrite/java/migrate/UpgradeDockerImageVersion.java @@ -54,6 +54,7 @@ public class UpgradeDockerImageVersion extends Recipe { private static final int OLDEST_VERSION = 8; private static final Pattern VERSIONED_TAG = Pattern.compile("(\\d{1,3})(\\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"; @@ -194,7 +195,7 @@ private Docker.From upgradeThroughArgs(Docker.From from, Map 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; } diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java index ac35f62e7a..1f2fb479b4 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java @@ -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) { diff --git a/src/main/java/org/openrewrite/java/migrate/javax/AddTransientAnnotationToCollections.java b/src/main/java/org/openrewrite/java/migrate/javax/AddTransientAnnotationToCollections.java index 937da74e62..736c0d8d6e 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/AddTransientAnnotationToCollections.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/AddTransientAnnotationToCollections.java @@ -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"; @@ -44,7 +45,6 @@ public class AddTransientAnnotationToCollections extends Recipe { @Override public TreeVisitor getVisitor() { - Pattern collection = Pattern.compile("java.util.Collection"); return Preconditions.check( // Only apply to JPA classes Preconditions.or( @@ -56,7 +56,7 @@ public TreeVisitor 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 diff --git a/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java b/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java index 87457a646f..87c980ffde 100644 --- a/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java +++ b/src/main/java/org/openrewrite/java/migrate/javax/RemoveTemporalAnnotation.java @@ -39,6 +39,7 @@ @EqualsAndHashCode(callSuper = false) @Value public class RemoveTemporalAnnotation extends Recipe { + private static final Pattern TEMPORAL_TYPE = Pattern.compile(".*TemporalType\\.(TIMESTAMP|DATE|TIME)"); private static final String JAVA_SQL_TIMESTAMP = "java.sql.Timestamp"; private static final String JAVA_SQL_TIME = "java.sql.Time"; private static final String JAVA_SQL_DATE = "java.sql.Date"; @@ -78,7 +79,6 @@ public class RemoveTemporalAnnotation extends Recipe { @Override public TreeVisitor getVisitor() { - Pattern temporalPattern = Pattern.compile(".*TemporalType\\.(TIMESTAMP|DATE|TIME)"); return Preconditions.check( Preconditions.and( new UsesType<>("javax.persistence.Temporal", true), @@ -101,7 +101,7 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m // Get TemporalType J.Annotation temporal = temporalAnnos.iterator().next(); String temporalArg = temporal.getArguments().iterator().next().toString(); - Matcher temporalMatch = temporalPattern.matcher(temporalArg); + Matcher temporalMatch = TEMPORAL_TYPE.matcher(temporalArg); if (!temporalMatch.find()) { return multiVariable; } diff --git a/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java b/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java index 16869b0e2c..c010e54b62 100644 --- a/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java +++ b/src/main/java/org/openrewrite/java/migrate/lombok/LombokUtils.java @@ -25,12 +25,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; import static lombok.AccessLevel.*; import static org.openrewrite.java.tree.J.Modifier.Type.*; class LombokUtils { private static final AnnotationMatcher LOMBOK_NON_NULL = new AnnotationMatcher("@lombok.NonNull"); + private static final Pattern IS_PREFIX = Pattern.compile("is[A-Z]"); static boolean isGetter(Cursor cursor) { if (!(cursor.getValue() instanceof J.MethodDeclaration)) { @@ -110,9 +112,7 @@ public static boolean isEffectivelyGetter(J.MethodDeclaration method) { public static String deriveGetterMethodName(@Nullable JavaType type, String fieldName) { if (type == JavaType.Primitive.Boolean) { - boolean alreadyStartsWithIs = fieldName.length() >= 3 && - fieldName.substring(0, 3).matches("is[A-Z]"); - if (alreadyStartsWithIs) { + if (IS_PREFIX.matcher(fieldName).lookingAt()) { return fieldName; } return "is" + StringUtils.capitalize(fieldName); From 02c39b8b060c411d47743cc63867c0db95629c31 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Sun, 25 Oct 2026 12:41:05 +0100 Subject: [PATCH 3/3] 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. --- .../migrate/JREThrowableFinalMethods.java | 20 +++++++++---------- .../migrate/guava/NoGuavaCreateTempDir.java | 8 ++++---- .../net/URLConstructorToURICreate.java | 6 +++--- .../migrate/net/URLConstructorsToNewURI.java | 18 ++++++++--------- .../migrate/util/OptionalStreamRecipe.java | 16 +++++++-------- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java b/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java index 61951eeabb..6e9cecaeb5 100644 --- a/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java +++ b/src/main/java/org/openrewrite/java/migrate/JREThrowableFinalMethods.java @@ -59,16 +59,16 @@ public JREThrowableFinalMethods( @Override public TreeVisitor 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() { @Override @@ -78,12 +78,12 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl 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); @@ -98,11 +98,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); diff --git a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java index 1f2fb479b4..42dcde2a06 100644 --- a/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java +++ b/src/main/java/org/openrewrite/java/migrate/guava/NoGuavaCreateTempDir.java @@ -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()`"; @@ -42,12 +44,10 @@ public class NoGuavaCreateTempDir extends Recipe { @Override public TreeVisitor 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 { - 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); @@ -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) { diff --git a/src/main/java/org/openrewrite/java/migrate/net/URLConstructorToURICreate.java b/src/main/java/org/openrewrite/java/migrate/net/URLConstructorToURICreate.java index 74207e53b0..f575bca58d 100644 --- a/src/main/java/org/openrewrite/java/migrate/net/URLConstructorToURICreate.java +++ b/src/main/java/org/openrewrite/java/migrate/net/URLConstructorToURICreate.java @@ -42,7 +42,7 @@ public class URLConstructorToURICreate extends Recipe { private static final String URI_FQN = "java.net.URI"; private static final String URL_FQN = "java.net.URL"; - private static final MethodMatcher methodMatcherSingleArg = new MethodMatcher(URL_FQN + "#(java.lang.String)"); + private static final MethodMatcher SINGLE_ARG_CONSTRUCTOR = new MethodMatcher(URL_FQN + "#(java.lang.String)"); @Getter final String displayName = "Convert `new URL(String)` to `URI.create(String).toURL()`"; @@ -52,11 +52,11 @@ public class URLConstructorToURICreate extends Recipe { @Override public TreeVisitor getVisitor() { - return Preconditions.check(new UsesMethod<>(methodMatcherSingleArg), + return Preconditions.check(new UsesMethod<>(SINGLE_ARG_CONSTRUCTOR), new JavaVisitor() { @Override public J visitNewClass(J.NewClass nc, ExecutionContext ctx) { - if (methodMatcherSingleArg.matches(nc)) { + if (SINGLE_ARG_CONSTRUCTOR.matches(nc)) { String path = extractPath(nc.getArguments().get(0)); if (isNotValidPath(path)) { return nc; diff --git a/src/main/java/org/openrewrite/java/migrate/net/URLConstructorsToNewURI.java b/src/main/java/org/openrewrite/java/migrate/net/URLConstructorsToNewURI.java index e6bb37fec5..b3f7e85641 100644 --- a/src/main/java/org/openrewrite/java/migrate/net/URLConstructorsToNewURI.java +++ b/src/main/java/org/openrewrite/java/migrate/net/URLConstructorsToNewURI.java @@ -31,9 +31,9 @@ public class URLConstructorsToNewURI extends Recipe { private static final String URI_FQN = "java.net.URI"; private static final String URL_FQN = "java.net.URL"; - private static final MethodMatcher methodMatcherThreeArg = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, java.lang.String)"); - private static final MethodMatcher methodMatcherFourArg = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, int, java.lang.String)"); - private static final MethodMatcher methodMatcherFiveArg = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler)"); + private static final MethodMatcher THREE_ARG_CONSTRUCTOR = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, java.lang.String)"); + private static final MethodMatcher FOUR_ARG_CONSTRUCTOR = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, int, java.lang.String)"); + private static final MethodMatcher FIVE_ARG_CONSTRUCTOR = new MethodMatcher(URL_FQN + " (java.lang.String, java.lang.String, int, java.lang.String, java.net.URLStreamHandler)"); @Getter final String displayName = "Convert `new URL(String, ..)` to `new URI(String, ..).toURL()`"; @@ -44,13 +44,13 @@ public class URLConstructorsToNewURI extends Recipe { @Override public TreeVisitor getVisitor() { return Preconditions.check(Preconditions.or( - new UsesMethod<>(methodMatcherThreeArg), - new UsesMethod<>(methodMatcherFourArg), - new UsesMethod<>(methodMatcherFiveArg)), + new UsesMethod<>(THREE_ARG_CONSTRUCTOR), + new UsesMethod<>(FOUR_ARG_CONSTRUCTOR), + new UsesMethod<>(FIVE_ARG_CONSTRUCTOR)), new JavaVisitor() { @Override public J visitNewClass(J.NewClass nc, ExecutionContext ctx) { - if (methodMatcherThreeArg.matches(nc)) { + if (THREE_ARG_CONSTRUCTOR.matches(nc)) { JavaTemplate template = JavaTemplate.builder("new URI(#{any(String)}, null, #{any(String)}, -1, #{any(String)}, null, null).toURL()") .imports(URI_FQN, URL_FQN) .contextSensitive() @@ -63,7 +63,7 @@ public J visitNewClass(J.NewClass nc, ExecutionContext ctx) { nc.getArguments().get(1), nc.getArguments().get(2)); } - if (methodMatcherFourArg.matches(nc)) { + if (FOUR_ARG_CONSTRUCTOR.matches(nc)) { JavaTemplate template = JavaTemplate.builder("new URI(#{any(String)}, null, #{any(String)}, #{any(int)}, #{any(String)}, null, null).toURL()") .imports(URI_FQN, URL_FQN) .contextSensitive() @@ -77,7 +77,7 @@ public J visitNewClass(J.NewClass nc, ExecutionContext ctx) { nc.getArguments().get(2), nc.getArguments().get(3)); } - if (methodMatcherFiveArg.matches(nc)) { + if (FIVE_ARG_CONSTRUCTOR.matches(nc)) { JavaTemplate template = JavaTemplate.builder("URL.of(new URI(#{any(String)}, null, #{any(String)}, #{any(int)}, #{any(String)}, null, null), #{any(java.net.URLStreamHandler)})") .imports(URI_FQN, URL_FQN) .contextSensitive() diff --git a/src/main/java/org/openrewrite/java/migrate/util/OptionalStreamRecipe.java b/src/main/java/org/openrewrite/java/migrate/util/OptionalStreamRecipe.java index 1a7ee6b317..f4a0af60ea 100644 --- a/src/main/java/org/openrewrite/java/migrate/util/OptionalStreamRecipe.java +++ b/src/main/java/org/openrewrite/java/migrate/util/OptionalStreamRecipe.java @@ -37,15 +37,15 @@ public class OptionalStreamRecipe extends Recipe { @Getter final String description = "Migrate Java 8 `Optional.filter(Optional::isPresent).map(Optional::get)` to Java 11 `.flatMap(Optional::stream)`."; - private static final MethodMatcher mapMatcher = new MethodMatcher("java.util.stream.Stream map(java.util.function.Function)"); - private static final MethodMatcher filterMatcher = new MethodMatcher("java.util.stream.Stream filter(java.util.function.Predicate)"); - private static final MethodMatcher optionalGetMatcher = new MethodMatcher("java.util.Optional get()"); - private static final MethodMatcher optionalIsPresentMatcher = new MethodMatcher("java.util.Optional isPresent()"); + private static final MethodMatcher STREAM_MAP = new MethodMatcher("java.util.stream.Stream map(java.util.function.Function)"); + private static final MethodMatcher STREAM_FILTER = new MethodMatcher("java.util.stream.Stream filter(java.util.function.Predicate)"); + private static final MethodMatcher OPTIONAL_GET = new MethodMatcher("java.util.Optional get()"); + private static final MethodMatcher OPTIONAL_IS_PRESENT = new MethodMatcher("java.util.Optional isPresent()"); @Override public TreeVisitor getVisitor() { return Preconditions.check( - Preconditions.and(new UsesJavaVersion<>(9), new UsesMethod<>(optionalIsPresentMatcher)), + Preconditions.and(new UsesJavaVersion<>(9), new UsesMethod<>(OPTIONAL_IS_PRESENT)), new OptionalStreamVisitor()); } @@ -55,17 +55,17 @@ private static class OptionalStreamVisitor extends JavaIsoVisitor