Skip to content

Commit 3d47629

Browse files
timtebeekTim te Beek
andauthored
Fix TypeTable support for Kotlin K2 by restoring annotation escape sequences (#6779)
The K2 upgrade bypass of TypeTable was unnecessary. The real issue was a bug in the annotation deserializer that corrupted Kotlin metadata: missing escape sequence handlers for \b (backspace) and \f (form feed) caused these control characters to be converted to literal 'b' and 'f' in @kotlin.Metadata annotations, making them unreadable by K2's FIR compiler. Fixed by adding the missing cases in TypeTableAnnotationSupport.parseStringValue(), restored classpathFromResources() in KotlinParser to use TypeTable, and added a test verifying TypeTable stubs work with K2. Co-authored-by: Tim te Beek <tim@mac.home>
1 parent f2a013b commit 3d47629

3 files changed

Lines changed: 54 additions & 9 deletions

File tree

rewrite-java/src/main/java/org/openrewrite/java/internal/parser/TypeTableAnnotationSupport.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,12 @@ private Object parseStringValue() {
536536
case 't':
537537
sb.append('\t');
538538
break;
539+
case 'b':
540+
sb.append('\b');
541+
break;
542+
case 'f':
543+
sb.append('\f');
544+
break;
539545
case '|':
540546
sb.append('|');
541547
break; // TypeTable-specific escape

rewrite-kotlin/src/main/java/org/openrewrite/kotlin/KotlinParser.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,8 @@ public Builder classpath(String... artifactNames) {
300300
}
301301

302302
public Builder classpathFromResources(ExecutionContext ctx, String... classpath) {
303-
// K2 requires full class files; the type-transformed (.tt) stubs from
304-
// JavaParser.dependenciesFromResources are not readable by K2's FIR compiler.
305-
// Strip version suffixes and resolve full jars from the classpath instead.
306-
List<String> stripped = new ArrayList<>(classpath.length);
307-
for (String name : classpath) {
308-
stripped.add(name.replaceAll("-\\d+$", ""));
309-
}
310-
this.artifactNames = stripped;
311-
this.classpath = null;
303+
this.artifactNames = null;
304+
this.classpath = JavaParser.dependenciesFromResources(ctx, classpath);
312305
return this;
313306
}
314307

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.kotlin;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.InMemoryExecutionContext;
20+
import org.openrewrite.test.RewriteTest;
21+
22+
import static org.openrewrite.kotlin.Assertions.kotlin;
23+
24+
/**
25+
* Verifies that TypeTable-sourced classpath entries work with the Kotlin K2 compiler.
26+
*/
27+
class KotlinParserTypeTableTest implements RewriteTest {
28+
29+
@Test
30+
void typeTableClasspathWithCoroutinesViaClasspathFromResources() {
31+
rewriteRun(
32+
spec -> spec.parser(KotlinParser.builder()
33+
.classpathFromResources(new InMemoryExecutionContext(), "kotlinx-coroutines-core-jvm")),
34+
kotlin(
35+
"""
36+
import kotlinx.coroutines.channels.ReceiveChannel
37+
38+
fun <T> pollChannel(channel: ReceiveChannel<T>): T? {
39+
@Suppress("DEPRECATION")
40+
return channel.poll()
41+
}
42+
"""
43+
)
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)