diff --git a/src/main/java/org/openrewrite/java/migrate/util/IteratorNext.java b/src/main/java/org/openrewrite/java/migrate/util/IteratorNext.java index 2fbb9ef119..65f2b62908 100644 --- a/src/main/java/org/openrewrite/java/migrate/util/IteratorNext.java +++ b/src/main/java/org/openrewrite/java/migrate/util/IteratorNext.java @@ -25,6 +25,7 @@ import org.openrewrite.java.search.UsesMethod; import org.openrewrite.java.tree.Expression; import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; import org.openrewrite.java.tree.TypeUtils; public class IteratorNext extends Recipe { @@ -57,13 +58,13 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu J.MethodInvocation nextInvocation = super.visitMethodInvocation(method, ctx); if (NEXT_MATCHER.matches(nextInvocation) && ITERATOR_MATCHER.matches(nextInvocation.getSelect())) { J.MethodInvocation iteratorInvocation = (J.MethodInvocation) nextInvocation.getSelect(); - if (TypeUtils.isAssignableTo("java.util.SequencedCollection", iteratorInvocation.getSelect().getType())) { - J.MethodInvocation getFirstInvocation = nextInvocation.withSelect(iteratorInvocation.getSelect()) - .withName(nextInvocation.getName().withSimpleName("getFirst")) - .withMethodType(nextInvocation.getMethodType() - .withName("getFirst") - .withDeclaringType(iteratorInvocation.getMethodType().getDeclaringType())); - return getFirstInvocation; + Expression iteratorSelect = iteratorInvocation.getSelect(); + if (TypeUtils.isAssignableTo("java.util.SequencedCollection", iteratorSelect.getType())) { + JavaType.Method getFirst = iteratorInvocation.getMethodType().withName("getFirst"); + return iteratorInvocation + .withName(iteratorInvocation.getName().withSimpleName("getFirst").withType(getFirst)) + .withMethodType(getFirst) + .withPrefix(nextInvocation.getPrefix()); } } return nextInvocation; diff --git a/src/main/java/org/openrewrite/java/migrate/util/ListFirstAndLast.java b/src/main/java/org/openrewrite/java/migrate/util/ListFirstAndLast.java index 00d19aefe4..9056dd53c5 100644 --- a/src/main/java/org/openrewrite/java/migrate/util/ListFirstAndLast.java +++ b/src/main/java/org/openrewrite/java/migrate/util/ListFirstAndLast.java @@ -15,10 +15,7 @@ */ package org.openrewrite.java.migrate.util; -import org.openrewrite.ExecutionContext; -import org.openrewrite.Preconditions; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; +import org.openrewrite.*; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.MethodMatcher; import org.openrewrite.java.search.UsesJavaVersion; @@ -109,7 +106,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu .withParameterNames(null) .withParameterTypes(null); } - return mi.withName(mi.getName().withSimpleName(operation + firstOrLast)) + return mi.withName(mi.getName().withSimpleName(operation + firstOrLast).withType(newMethodType)) .withArguments(arguments) .withMethodType(newMethodType); } diff --git a/src/main/java/org/openrewrite/java/migrate/util/StreamFindFirst.java b/src/main/java/org/openrewrite/java/migrate/util/StreamFindFirst.java new file mode 100644 index 0000000000..dcecf7ad57 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/util/StreamFindFirst.java @@ -0,0 +1,82 @@ +/* + * Copyright 2024 the original author or authors. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * https://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.migrate.util;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.MethodMatcher;
+import org.openrewrite.java.search.UsesJavaVersion;
+import org.openrewrite.java.search.UsesMethod;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.JavaType;
+import org.openrewrite.java.tree.TypeUtils;
+
+public class StreamFindFirst extends Recipe {
+ private static final MethodMatcher COLLECTION_STREAM_MATCHER = new MethodMatcher("java.util.Collection stream()", true);
+ private static final MethodMatcher STREAM_FIND_FIRST_MATCHER = new MethodMatcher("java.util.stream.Stream findFirst()", true);
+ private static final MethodMatcher OPTIONAL_OR_ELSE_THROW_MATCHER = new MethodMatcher("java.util.Optional orElseThrow()", true);
+
+ @Override
+ public String getDisplayName() {
+ return "Use `getFirst()` instead of `stream().findFirst().orElseThrow()`";
+ }
+
+ @Override
+ public String getDescription() {
+ return "For SequencedCollections, use `collection.getFirst()` instead of `collection.stream().findFirst().orElseThrow()`.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ JavaIsoVisitor
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.migrate.util;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+import static org.openrewrite.java.Assertions.javaVersion;
+
+@EnabledForJreRange(min = JRE.JAVA_21)
+class StreamFindFirstTest implements RewriteTest {
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec
+ .recipe(new StreamFindFirst())
+ .parser(JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true))
+ .allSources(src -> src.markers(javaVersion(21)));
+ }
+
+ @Test
+ void sequencedCollection() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import java.util.*;
+
+ class Foo {
+ void bar(SequencedCollection