From 82b9270d748ce825468755842e52b304b50103e8 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Thu, 10 Jul 2025 09:56:39 +0200 Subject: [PATCH 1/9] RemoveUnusedImports --- .../src/main/java/org/openrewrite/java/RemoveUnusedImports.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java b/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java index 087134868e..da50065ef7 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java @@ -48,7 +48,7 @@ public class RemoveUnusedImports extends Recipe { @Override public String getDisplayName() { - return "Remove unused imports"; + return "Remove unused imports fix"; } @Override From d59a97426c88df4ab8410492a8dcb01616db8b83 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Thu, 10 Jul 2025 10:12:39 +0200 Subject: [PATCH 2/9] RemoveUnusedImports --- .../java/RemoveUnusedImportsTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index 0269fa74b4..ff8339387a 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -132,6 +132,62 @@ public abstract class MyMapEntry implements Entry { ); } + @Issue("https://github.com/openrewrite/rewrite/issues/1798") + @Test + void doNotDocRemoval() { + rewriteRun( + java( +""" +/* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.platform.suite.api; + +import static org.apiguardian.api.API.Status.STABLE; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Set; + +import org.apiguardian.api.API; + +/** + * {@code @SelectModules} specifies the modules to select when running + * a test suite on the JUnit Platform. + * + * @since 1.8 + * @see Suite + * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +@Documented +@API(status = STABLE, since = "1.10") +public @interface SelectModules { + + /** + * One or more modules to select. + */ + String[] value(); + +} +""" + ) + ); + } + @Issue("https://github.com/openrewrite/rewrite/issues/1052") @Test void usedInJavadocWithThrows() { From a13540e5152e75329f4f5d0c20c35e3d40edd7c4 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Thu, 10 Jul 2025 10:12:52 +0200 Subject: [PATCH 3/9] RemoveUnusedImports --- .../java/RemoveUnusedImportsTest.java | 94 +++++++++---------- .../openrewrite/java/RemoveUnusedImports.java | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index ff8339387a..8899791771 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -137,53 +137,53 @@ public abstract class MyMapEntry implements Entry { void doNotDocRemoval() { rewriteRun( java( -""" -/* - * Copyright 2015-2025 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - -package org.junit.platform.suite.api; - -import static org.apiguardian.api.API.Status.STABLE; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Set; - -import org.apiguardian.api.API; - -/** - * {@code @SelectModules} specifies the modules to select when running - * a test suite on the JUnit Platform. - * - * @since 1.8 - * @see Suite - * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Inherited -@Documented -@API(status = STABLE, since = "1.10") -public @interface SelectModules { - - /** - * One or more modules to select. - */ - String[] value(); - -} -""" + """ + /* + * Copyright 2015-2025 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + + package org.junit.platform.suite.api; + + import static org.apiguardian.api.API.Status.STABLE; + + import java.lang.annotation.Documented; + import java.lang.annotation.ElementType; + import java.lang.annotation.Inherited; + import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; + import java.lang.annotation.Target; + import java.util.Set; + + import org.apiguardian.api.API; + + /** + * {@code @SelectModules} specifies the modules to select when running + * a test suite on the JUnit Platform. + * + * @since 1.8 + * @see Suite + * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @Inherited + @Documented + @API(status = STABLE, since = "1.10") + public @interface SelectModules { + + /** + * One or more modules to select. + */ + String[] value(); + + } + """ ) ); } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java b/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java index da50065ef7..087134868e 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/RemoveUnusedImports.java @@ -48,7 +48,7 @@ public class RemoveUnusedImports extends Recipe { @Override public String getDisplayName() { - return "Remove unused imports fix"; + return "Remove unused imports"; } @Override From 8d68bb3f042f85b8cb0278de8266a61143fc1a24 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Sun, 13 Jul 2025 14:57:03 +0200 Subject: [PATCH 4/9] RemoveUnusedImports --- .../java/RemoveUnusedImportsTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index 8899791771..5150b24dfd 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -186,6 +186,56 @@ void doNotDocRemoval() { """ ) ); + rewriteRun( + java( + """ + /** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + package net.sourceforge.pmd.lang.java.ast; + + import net.sourceforge.pmd.lang.ast.Node; + + /** + * The declaration of an annotation type. + * This is a {@linkplain Node#isFindBoundary() find boundary} for tree traversal methods. + * + *

Note that in contrast to interface types, no {@linkplain ASTExtendsList extends clause} + * is permitted, and an annotation type cannot be generic. + * + *

+               *
+               * AnnotationTypeDeclaration ::= {@link ASTModifierList ModifierList}
+               *                               "@" "interface"
+               *                               <IDENTIFIER>
+               *                               {@link ASTAnnotationTypeBody AnnotationTypeBody}
+               *
+               * 
+ * + */ + public final class ASTAnnotationTypeDeclaration extends AbstractTypeDeclaration { + + + ASTAnnotationTypeDeclaration(int id) { + super(id); + } + + + @Override + protected R acceptVisitor(JavaVisitor visitor, P data) { + return visitor.visit(this, data); + } + + + @Override + public boolean isInterface() { + return true; + } + } + """ + ) + ); } @Issue("https://github.com/openrewrite/rewrite/issues/1052") From f5c2f757ed6438404fa431424a5fd04e5c1847e5 Mon Sep 17 00:00:00 2001 From: Vincent Potucek Date: Sun, 13 Jul 2025 14:59:15 +0200 Subject: [PATCH 5/9] RemoveUnusedImports --- .../java/RemoveUnusedImportsTest.java | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index 5150b24dfd..11b82628da 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -200,38 +200,15 @@ void doNotDocRemoval() { /** * The declaration of an annotation type. * This is a {@linkplain Node#isFindBoundary() find boundary} for tree traversal methods. - * - *

Note that in contrast to interface types, no {@linkplain ASTExtendsList extends clause} - * is permitted, and an annotation type cannot be generic. - * - *

-               *
-               * AnnotationTypeDeclaration ::= {@link ASTModifierList ModifierList}
-               *                               "@" "interface"
-               *                               <IDENTIFIER>
-               *                               {@link ASTAnnotationTypeBody AnnotationTypeBody}
-               *
                * 
* */ - public final class ASTAnnotationTypeDeclaration extends AbstractTypeDeclaration { + public final class ASTAnnotationTypeDeclaration { ASTAnnotationTypeDeclaration(int id) { - super(id); } - - @Override - protected R acceptVisitor(JavaVisitor visitor, P data) { - return visitor.visit(this, data); - } - - - @Override - public boolean isInterface() { - return true; - } } """ ) From a3050540f1497e295645fc247c28d2818d51421c Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Wed, 20 Aug 2025 11:55:51 +0200 Subject: [PATCH 6/9] Reduce test --- .../java/RemoveUnusedImportsTest.java | 89 ++++++------------- 1 file changed, 27 insertions(+), 62 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index 11b82628da..9cbc3d4a0b 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -132,85 +132,50 @@ public abstract class MyMapEntry implements Entry { ); } - @Issue("https://github.com/openrewrite/rewrite/issues/1798") @Test - void doNotDocRemoval() { + void retainImportIfUsedInJavaDoc() { rewriteRun( java( """ - /* - * Copyright 2015-2025 the original author or authors. - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v2.0 which - * accompanies this distribution and is available at - * - * https://www.eclipse.org/legal/epl-v20.html - */ - - package org.junit.platform.suite.api; - - import static org.apiguardian.api.API.Status.STABLE; - - import java.lang.annotation.Documented; - import java.lang.annotation.ElementType; - import java.lang.annotation.Inherited; - import java.lang.annotation.Retention; - import java.lang.annotation.RetentionPolicy; - import java.lang.annotation.Target; - import java.util.Set; - - import org.apiguardian.api.API; - + import java.util.Date; + import java.util.List; + /** - * {@code @SelectModules} specifies the modules to select when running - * a test suite on the JUnit Platform. - * - * @since 1.8 - * @see Suite - * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) + * referencing {@link Date} only in doc */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @Inherited - @Documented - @API(status = STABLE, since = "1.10") - public @interface SelectModules { - - /** - * One or more modules to select. - */ - String[] value(); - + class Test { + List list; } - """ + """ ) ); + } + + @Test + void removeImportIfFullyQualifiedInJavaDoc() { rewriteRun( java( """ + import java.util.Date; + import java.util.List; + /** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + * referencing {@link java.util.Date} only in doc */ - - package net.sourceforge.pmd.lang.java.ast; - - import net.sourceforge.pmd.lang.ast.Node; - + class Test2 { + List list; + } + """, + """ + import java.util.List; + /** - * The declaration of an annotation type. - * This is a {@linkplain Node#isFindBoundary() find boundary} for tree traversal methods. - * - * + * referencing {@link java.util.Date} only in doc */ - public final class ASTAnnotationTypeDeclaration { - - - ASTAnnotationTypeDeclaration(int id) { - } - + class Test2 { + List list; } - """ + """ ) ); } From 6b62f8676753f64d13f41052df2569c611f2172c Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Wed, 20 Aug 2025 12:50:13 +0200 Subject: [PATCH 7/9] Remove fully qualified JavaDoc references from TypesInUse --- .../org/openrewrite/java/internal/TypesInUse.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java b/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java index ceb3d78773..65e32f2d41 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java @@ -24,6 +24,7 @@ import org.openrewrite.java.tree.J; import org.openrewrite.java.tree.JavaSourceFile; import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.Javadoc; import java.util.IdentityHashMap; import java.util.Objects; @@ -87,12 +88,20 @@ public J.Identifier visitIdentifier(J.Identifier identifier, Integer p) { } else { usedMethods.add((JavaType.Method) javaType); } - } else if (!(cursor.getValue() instanceof J.ClassDeclaration) && !(cursor.getValue() instanceof J.Lambda)) { - // ignore type representing class declaration itself and inferred lambda types + } else if (!(cursor.getValue() instanceof J.ClassDeclaration) && + !(cursor.getValue() instanceof J.Lambda) && + !isFullyQualifiedJavaDocReference(cursor)) { types.add(javaType); } } return javaType; } + + private boolean isFullyQualifiedJavaDocReference(Cursor cursor) { + // Fully qualified Javadoc references are _using_ those types as much as they are just references; + // TypesInUse also determines what imports are retained, and for fully qualified these can be dropped + return cursor.getValue() instanceof J.FieldAccess && + cursor.getPathAsStream().anyMatch(o -> o instanceof Javadoc.Reference); + } } } From 48ea627386015d5abb5b00de53dd46d22cf2430c Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Wed, 20 Aug 2025 13:00:42 +0200 Subject: [PATCH 8/9] Apply formatter to text blocks --- .../java/org/openrewrite/java/RemoveUnusedImportsTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java index 7633713cb8..2101b473ac 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/RemoveUnusedImportsTest.java @@ -146,7 +146,7 @@ void retainImportIfUsedInJavaDoc() { class Test { List list; } - """ + """ ) ); } @@ -165,7 +165,7 @@ void removeImportIfFullyQualifiedInJavaDoc() { class Test2 { List list; } - """, + """, """ import java.util.List; @@ -175,7 +175,7 @@ class Test2 { class Test2 { List list; } - """ + """ ) ); } From 05c0e2923744dd622a4a14f0ebd384c4f3dab9ed Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Wed, 20 Aug 2025 19:36:59 +0200 Subject: [PATCH 9/9] Also break `isFullyQualifiedJavaDocReference` on J.Block --- .../openrewrite/java/internal/TypesInUse.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java b/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java index 94ec5c6797..a507a4ad60 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/internal/TypesInUse.java @@ -27,6 +27,7 @@ import org.openrewrite.java.tree.Javadoc; import java.util.IdentityHashMap; +import java.util.Iterator; import java.util.Objects; import java.util.Set; @@ -112,9 +113,20 @@ public J.Lambda.Parameters visitLambdaParameters(J.Lambda.Parameters parameters, private boolean isFullyQualifiedJavaDocReference(Cursor cursor) { // Fully qualified Javadoc references are _using_ those types as much as they are just references; - // TypesInUse also determines what imports are retained, and for fully qualified these can be dropped - return cursor.getValue() instanceof J.FieldAccess && - cursor.getPathAsStream().anyMatch(o -> o instanceof Javadoc.Reference); + // TypesInUse entries determines what imports are retained, and for fully qualified these can be dropped + if (cursor.getValue() instanceof J.FieldAccess) { + Iterator path = cursor.getPath(); + while (path.hasNext()) { + Object o = path.next(); + if (o instanceof Javadoc.Reference) { + return true; + } + if (o instanceof J.Block) { + return false; + } + } + } + return false; } } }