Skip to content

Commit 8d4a5e6

Browse files
authored
Use the Comments trait instead of hand-built comments (K5 of #1330) (#1355)
* Add `ThreadStopUnsupported` comment through the `Comments` trait * Add `CommentJava24KotlinCap` comment through the `Comments` trait `Placement.FIRST_CHILD` replaces the hand-built `Xml.Comment`. The prefix-based `hasCapComment`/`removeCapComment` stay, as the trait only matches exact comment text and removes comments preceding an element, not a tag's own children. * Leave a persisted `TODO` comment where `AddInputStreamBulkReadMethod` cannot delegate The `SearchResult` marker for complex `read()` bodies is transient and dropped from committed code, so the hint to add a bulk read method by hand was lost. The `Comments` trait adds a real block comment instead, on its own line above a class declaration and inline before an anonymous `new InputStream() {...}`. An equivalent existing comment, including a `// TODO` line comment, is left as is.
1 parent 853047b commit 8d4a5e6

5 files changed

Lines changed: 112 additions & 30 deletions

File tree

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

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
import lombok.EqualsAndHashCode;
1919
import lombok.Value;
2020
import org.jspecify.annotations.Nullable;
21+
import org.openrewrite.Cursor;
2122
import org.openrewrite.ExecutionContext;
2223
import org.openrewrite.Recipe;
23-
import org.openrewrite.Tree;
2424
import org.openrewrite.TreeVisitor;
2525
import org.openrewrite.internal.ListUtils;
26-
import org.openrewrite.marker.Markers;
2726
import org.openrewrite.maven.MavenIsoVisitor;
2827
import org.openrewrite.maven.tree.ResolvedDependency;
2928
import org.openrewrite.semver.LatestRelease;
29+
import org.openrewrite.trait.Comments;
3030
import org.openrewrite.xml.tree.Content;
3131
import org.openrewrite.xml.tree.Xml;
3232

@@ -73,7 +73,8 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
7373
String kotlinStdlibVersion = capsJavaAt24(t) ? findKotlinStdlibVersionBefore23() : null;
7474
if (kotlinStdlibVersion != null) {
7575
if (!hasCapComment(t)) {
76-
return addCommentAsFirstChild(t, comment(kotlinStdlibVersion));
76+
return Comments.of(new Cursor(getCursor().getParentOrThrow(), t))
77+
.comment(comment(kotlinStdlibVersion), Comments.Placement.FIRST_CHILD);
7778
}
7879
} else if (hasCapComment(t)) {
7980
return removeCapComment(t);
@@ -132,13 +133,6 @@ private boolean hasCapComment(Xml.Tag tag) {
132133
return false;
133134
}
134135

135-
private Xml.Tag addCommentAsFirstChild(Xml.Tag tag, String text) {
136-
List<Content> content = (List<Content>) tag.getContent();
137-
String prefix = content == null || content.isEmpty() ? "" : content.get(0).getPrefix();
138-
Xml.Comment comment = new Xml.Comment(Tree.randomId(), prefix, Markers.EMPTY, text);
139-
return tag.withContent(ListUtils.concat(comment, content));
140-
}
141-
142136
@SuppressWarnings("unchecked")
143137
private Xml.Tag removeCapComment(Xml.Tag tag) {
144138
return tag.withContent(ListUtils.filter((List<Content>) tag.getContent(), c ->

‎src/main/java/org/openrewrite/java/migrate/io/AddInputStreamBulkReadMethod.java‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.openrewrite.java.JavaTemplate;
2525
import org.openrewrite.java.search.DeclaresType;
2626
import org.openrewrite.java.tree.*;
27-
import org.openrewrite.marker.SearchResult;
27+
import org.openrewrite.trait.Comments;
2828

2929
import java.util.Arrays;
3030
import java.util.HashSet;
@@ -37,7 +37,7 @@
3737
@EqualsAndHashCode(callSuper = false)
3838
public class AddInputStreamBulkReadMethod extends Recipe {
3939

40-
private static final String MARKER_MESSAGE = "Missing bulk read method may cause significant performance degradation";
40+
private static final String TODO_COMMENT = " TODO: Missing bulk read method may cause significant performance degradation ";
4141
private static final String JAVA_IO_INPUT_STREAM = "java.io.InputStream";
4242

4343
String displayName = "Add bulk read method to `InputStream` implementations";
@@ -46,7 +46,9 @@ public class AddInputStreamBulkReadMethod extends Recipe {
4646
"`read()` method. Java's default `InputStream.read(byte[], int, int)` implementation calls the " +
4747
"single-byte `read()` method in a loop, which can cause severe performance degradation (up to 350x " +
4848
"slower) for bulk reads. This recipe detects `InputStream` implementations that delegate to another " +
49-
"stream and adds the missing bulk read method to delegate bulk reads as well.";
49+
"stream and adds the missing bulk read method to delegate bulk reads as well. Implementations whose " +
50+
"`read()` body is too complex to delegate safely get a `TODO` comment instead, to implement the bulk " +
51+
"read method by hand.";
5052

5153
@Override
5254
public TreeVisitor<?, ExecutionContext> getVisitor() {
@@ -97,9 +99,10 @@ private <T extends J> T processInputStreamClass(T tree, J.Block body) {
9799
return tree;
98100
}
99101

100-
// No delegate found or complex body - add marker for manual implementation
102+
// No delegate found or complex body - add a TODO comment for manual implementation
101103
if (result.getDelegate() == null || result.isComplex()) {
102-
return SearchResult.found(tree, MARKER_MESSAGE);
104+
return Comments.of(new Cursor(getCursor().getParentOrThrow(), tree))
105+
.multilineComment(TODO_COMMENT, Comments.Placement.BEFORE, lineBreakBefore(tree));
103106
}
104107

105108
// Simple delegation - add bulk read method right after the single-byte read method
@@ -116,6 +119,12 @@ private <T extends J> T processInputStreamClass(T tree, J.Block body) {
116119
return tree;
117120
}
118121

122+
private @Nullable String lineBreakBefore(J tree) {
123+
String whitespace = tree.getPrefix().getWhitespace();
124+
int lastNewline = whitespace.lastIndexOf('\n');
125+
return lastNewline < 0 ? null : whitespace.substring(lastNewline);
126+
}
127+
119128
private @Nullable AnalysisResult analyzeClass(List<Statement> statements) {
120129
J.MethodDeclaration readMethod = null;
121130
boolean hasBulkRead = false;

‎src/main/java/org/openrewrite/java/migrate/lang/ThreadStopUnsupported.java‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.openrewrite.java.migrate.lang;
1717

1818
import lombok.Getter;
19+
import org.openrewrite.Cursor;
1920
import org.openrewrite.ExecutionContext;
2021
import org.openrewrite.Preconditions;
2122
import org.openrewrite.Recipe;
@@ -27,10 +28,7 @@
2728
import org.openrewrite.java.search.UsesMethod;
2829
import org.openrewrite.java.tree.J;
2930
import org.openrewrite.java.tree.JavaSourceFile;
30-
import org.openrewrite.java.tree.TextComment;
31-
import org.openrewrite.marker.Markers;
32-
33-
import static java.util.Collections.singletonList;
31+
import org.openrewrite.trait.Comments;
3432

3533
public class ThreadStopUnsupported extends Recipe {
3634
private static final MethodMatcher THREAD_STOP_MATCHER = new MethodMatcher("java.lang.Thread stop()");
@@ -78,7 +76,7 @@ private J getWithComment(J j, String methodName) {
7876
prefixWhitespace + " * For detailed migration instructions see the migration guide available at" +
7977
prefixWhitespace + " * https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html" +
8078
prefixWhitespace + " ";
81-
return j.withComments(singletonList(new TextComment(true, commentText, prefixWhitespace, Markers.EMPTY)));
79+
return Comments.of(new Cursor(getCursor().getParentOrThrow(), j)).multilineComment(commentText);
8280
}
8381
});
8482
}

‎src/main/resources/META-INF/rewrite/recipes.csv‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.g
228228
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.PreferMathMultiplyExact,Prefer `Math#multiplyExact`,Prefer `java.lang.Math#multiplyExact` instead of using `com.google.common.math.IntMath#checkedMultiply`.,3,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
229229
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.PreferMathSubtractExact,Prefer `Math#subtractExact`,Prefer `java.lang.Math#subtractExact` instead of using `com.google.common.math.IntMath#checkedSubtract`.,3,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
230230
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.guava.PreferShortCompare,Prefer `Short#compare`,Prefer `java.lang.Short#compare` instead of using `com.google.common.primitives.Shorts#compare`.,2,,Guava,Modernize,Java,,Recipes for migrating from [Google Guava](https://github.com/google/guava) to Java standard library.,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
231-
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.io.AddInputStreamBulkReadMethod,Add bulk read method to `InputStream` implementations,"Adds a `read(byte[], int, int)` method to `InputStream` subclasses that only override the single-byte `read()` method. Java's default `InputStream.read(byte[], int, int)` implementation calls the single-byte `read()` method in a loop, which can cause severe performance degradation (up to 350x slower) for bulk reads. This recipe detects `InputStream` implementations that delegate to another stream and adds the missing bulk read method to delegate bulk reads as well.",1,,`java.io` APIs,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
231+
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.io.AddInputStreamBulkReadMethod,Add bulk read method to `InputStream` implementations,"Adds a `read(byte[], int, int)` method to `InputStream` subclasses that only override the single-byte `read()` method. Java's default `InputStream.read(byte[], int, int)` implementation calls the single-byte `read()` method in a loop, which can cause severe performance degradation (up to 350x slower) for bulk reads. This recipe detects `InputStream` implementations that delegate to another stream and adds the missing bulk read method to delegate bulk reads as well. Implementations whose `read()` body is too complex to delegate safely get a `TODO` comment instead, to implement the bulk read method by hand.",1,,`java.io` APIs,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
232232
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.io.ReplaceFileInOrOutputStreamFinalizeWithClose,Replace invocations of `finalize()` on `FileInputStream` and `FileOutputStream` with `close()`,Replace invocations of the deprecated `finalize()` method on `FileInputStream` and `FileOutputStream` with `close()`.,1,,`java.io` APIs,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
233233
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.io.ReplaceSystemOutWithIOPrint,Migrate `System.out.print` to Java 25 IO utility class,"Replace `System.out.print()`, `System.out.println()` with `IO.print()` and `IO.println()`. Migrates to the new IO utility class introduced in Java 25.",1,,`java.io` APIs,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
234234
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.jacoco.UpgradeJaCoCo,Upgrade JaCoCo,"This recipe will upgrade JaCoCo to the latest patch version, which traditionally advertises full backwards compatibility for older Java versions.",3,,JaCoCo,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"

0 commit comments

Comments
 (0)