Skip to content

Commit 732b060

Browse files
jkschneiderclaude
andcommitted
Fix K2 PR build failures: classpath resolution and printer stack overflow
- Add jakarta.persistence-api as testRuntimeOnly dep in rewrite-java-test so KotlinParser.classpathFromResources can find the full jar (K2 can't use .tt stubs) - Convert KotlinPrinter.visitBinary to iterative left-chain traversal to avoid StackOverflowError on deeply nested binary expressions (2000+ levels) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d84cf97 commit 732b060

2 files changed

Lines changed: 57 additions & 46 deletions

File tree

rewrite-java-test/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
testImplementation("io.github.classgraph:classgraph:latest.release")
1717
testImplementation("org.junit-pioneer:junit-pioneer:2.0.0")
1818
testRuntimeOnly(project(":rewrite-java-21"))
19+
testRuntimeOnly("jakarta.persistence:jakarta.persistence-api:3.1.0")
1920
testRuntimeOnly("org.apache.hbase:hbase-shaded-client:2.4.11")
2021
testRuntimeOnly("com.google.guava:guava:latest.release")
2122
testRuntimeOnly("org.mapstruct:mapstruct:latest.release")

rewrite-kotlin/src/main/java/org/openrewrite/kotlin/internal/KotlinPrinter.java

Lines changed: 56 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.openrewrite.marker.Marker;
3232
import org.openrewrite.marker.Markers;
3333

34+
import java.util.ArrayList;
3435
import java.util.List;
3536
import java.util.Objects;
3637
import java.util.Optional;
@@ -517,73 +518,82 @@ public J visitAnnotation(J.Annotation annotation, PrintOutputCapture<P> p) {
517518

518519
@Override
519520
public J visitBinary(J.Binary binary, PrintOutputCapture<P> p) {
520-
String keyword = "";
521+
// Collect left-recursive binary chain to avoid StackOverflow on deeply nested expressions.
522+
// For a left-associative tree like ((a + b) + c) + d, this collects [outer, middle, inner]
523+
// and prints them iteratively instead of recursively.
524+
List<J.Binary> chain = new ArrayList<>();
525+
J.Binary current = binary;
526+
while (true) {
527+
chain.add(current);
528+
if (current.getLeft() instanceof J.Binary) {
529+
current = (J.Binary) current.getLeft();
530+
} else {
531+
break;
532+
}
533+
}
534+
535+
// Print beforeSyntax for each binary, outermost first
536+
for (J.Binary b : chain) {
537+
beforeSyntax(b, Space.Location.BINARY_PREFIX, p);
538+
}
539+
540+
// Visit the leftmost non-binary expression
541+
visit(chain.get(chain.size() - 1).getLeft(), p);
542+
543+
// Unwind from innermost to outermost: print operator + right + afterSyntax
544+
for (int i = chain.size() - 1; i >= 0; i--) {
545+
J.Binary b = chain.get(i);
546+
visitSpace(b.getPadding().getOperator().getBefore(), Space.Location.BINARY_OPERATOR, p);
547+
p.append(binaryKeyword(b));
548+
visit(b.getRight(), p);
549+
afterSyntax(b, p);
550+
}
551+
return binary;
552+
}
553+
554+
private String binaryKeyword(J.Binary binary) {
521555
switch (binary.getOperator()) {
522556
case Addition:
523-
keyword = "+";
524-
break;
557+
return "+";
525558
case Subtraction:
526-
keyword = "-";
527-
break;
559+
return "-";
528560
case Multiplication:
529-
keyword = "*";
530-
break;
561+
return "*";
531562
case Division:
532-
keyword = "/";
533-
break;
563+
return "/";
534564
case Modulo:
535-
keyword = "%";
536-
break;
565+
return "%";
537566
case LessThan:
538-
keyword = "<";
539-
break;
567+
return "<";
540568
case GreaterThan:
541-
keyword = ">";
542-
break;
569+
return ">";
543570
case LessThanOrEqual:
544-
keyword = "<=";
545-
break;
571+
return "<=";
546572
case GreaterThanOrEqual:
547-
keyword = ">=";
548-
break;
573+
return ">=";
549574
case Equal:
550-
keyword = "==";
551-
break;
575+
return "==";
552576
case NotEqual:
553-
keyword = "!=";
554-
break;
577+
return "!=";
555578
case BitAnd:
556-
keyword = "and";
557-
break;
579+
return "and";
558580
case BitOr:
559-
keyword = "or";
560-
break;
581+
return "or";
561582
case BitXor:
562-
keyword = "xor";
563-
break;
583+
return "xor";
564584
case LeftShift:
565-
keyword = "shl";
566-
break;
585+
return "shl";
567586
case RightShift:
568-
keyword = "shr";
569-
break;
587+
return "shr";
570588
case UnsignedRightShift:
571-
keyword = "ushr";
572-
break;
589+
return "ushr";
573590
case Or:
574-
keyword = (binary.getMarkers().findFirst(LogicalComma.class).isPresent()) ? "," : "||";
575-
break;
591+
return binary.getMarkers().findFirst(LogicalComma.class).isPresent() ? "," : "||";
576592
case And:
577-
keyword = "&&";
578-
break;
593+
return "&&";
594+
default:
595+
return "";
579596
}
580-
beforeSyntax(binary, Space.Location.BINARY_PREFIX, p);
581-
visit(binary.getLeft(), p);
582-
visitSpace(binary.getPadding().getOperator().getBefore(), Space.Location.BINARY_OPERATOR, p);
583-
p.append(keyword);
584-
visit(binary.getRight(), p);
585-
afterSyntax(binary, p);
586-
return binary;
587597
}
588598

589599
@Override

0 commit comments

Comments
 (0)