Skip to content

Commit 39006a6

Browse files
Fix Kotlin parser handling of unresolved callable references (#7469)
`visitCallableReferenceExpression` looked up the FIR for the callable reference's right-hand side (`expression.getCallableReference()`) to decide whether to accept the reference. When the type is unresolved (e.g. `JavaLanguageVersion::of` in a `.gradle.kts` parsed without the full Gradle classpath), the RHS maps to `FirErrorNamedReferenceImpl` even though the whole expression still maps cleanly to `FirCallableReferenceAccess`. The visitor then threw, the declaration bubbled up into `J.Unknown`, and its PSI text range (which includes the trailing newline) got duplicated against the file's EOF space, causing a print idempotency failure. Check the FIR mapping of the whole expression for validity instead, and use the reference-level FIR only for optional type resolution. Types simply remain `null` when the reference cannot be resolved, which matches how other unresolved-type scenarios are handled. Re-enables the previously `@Disabled` `firCallableReferenceAccess` regression test.
1 parent 305085c commit 39006a6

4 files changed

Lines changed: 29 additions & 6 deletions

File tree

rewrite-gradle/src/test/java/org/openrewrite/gradle/GradleParserTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,17 @@ void kotlinDsl() {
275275
);
276276
}
277277

278+
@Test
279+
void kotlinDslWithUnresolvedCallableReference() {
280+
rewriteRun(
281+
buildGradleKts(
282+
"""
283+
kotlin { jvmToolchain { languageVersion.set(libs.versions.jdk.map(JavaLanguageVersion::of)) } }
284+
"""
285+
)
286+
);
287+
}
288+
278289
@Test
279290
void escapedAndNonEscapedDollarSignsInSingleDoubleQuotes() {
280291
var gradleParser = new GradleParser(new GradleParser.Builder());

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,14 @@ public J visitBreakExpression(KtBreakExpression expression, ExecutionContext dat
269269

270270
@Override
271271
public J visitCallableReferenceExpression(KtCallableReferenceExpression expression, ExecutionContext data) {
272-
FirElement firElement = psiElementAssociations.primary(expression.getCallableReference());
273-
if (!(firElement instanceof FirResolvedCallableReference || firElement instanceof FirCallableReferenceAccess)) {
272+
FirElement exprFir = psiElementAssociations.primary(expression);
273+
if (!(exprFir instanceof FirCallableReferenceAccess)) {
274274
throw new UnsupportedOperationException(java.lang.String.format("Unsupported callable reference: fir class: %s, fir: %s, psi class: %s.",
275-
firElement == null ? "null" : firElement.getClass().getName(),
276-
PsiTreePrinter.print(psiElementAssociations.primary(expression)),
275+
exprFir == null ? "null" : exprFir.getClass().getName(),
276+
PsiTreePrinter.print(exprFir),
277277
expression.getClass().getName()));
278278
}
279+
FirElement firElement = psiElementAssociations.primary(expression.getCallableReference());
279280
JavaType.Method methodReferenceType = null;
280281
JavaType.Variable fieldReferenceType = null;
281282
if (firElement instanceof FirResolvedCallableReference) {

rewrite-kotlin/src/test/java/org/openrewrite/kotlin/tree/CompilationUnitTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.openrewrite.test.SourceSpec;
2323

2424
import static org.openrewrite.kotlin.Assertions.kotlin;
25+
import static org.openrewrite.kotlin.Assertions.kotlinScript;
2526

2627
class CompilationUnitTest implements RewriteTest {
2728

@@ -69,6 +70,18 @@ class A /*C1*/
6970
);
7071
}
7172

73+
@Test
74+
void unresolvedCallableReference() {
75+
rewriteRun(
76+
spec -> spec.typeValidationOptions(org.openrewrite.test.TypeValidation.none()),
77+
kotlinScript(
78+
"""
79+
kotlin { jvmToolchain { languageVersion.set(libs.versions.jdk.map(JavaLanguageVersion::of)) } }
80+
"""
81+
)
82+
);
83+
}
84+
7285
@ParameterizedTest
7386
@ValueSource(strings = {
7487
"class Foo",

rewrite-kotlin/src/test/java/org/openrewrite/kotlin/tree/MemberReferenceTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.openrewrite.kotlin.tree;
1717

18-
import org.junit.jupiter.api.Disabled;
1918
import org.junit.jupiter.api.Test;
2019
import org.openrewrite.Issue;
2120
import org.openrewrite.test.RewriteTest;
@@ -142,7 +141,6 @@ fun method ( s: List<String ? > ) {
142141
);
143142
}
144143

145-
@Disabled("K2 produces J.Unknown for unresolved callable references (::unresolved)")
146144
@Issue("https://github.com/openrewrite/rewrite-kotlin/issues/386")
147145
@Test
148146
void firCallableReferenceAccess() {

0 commit comments

Comments
 (0)