Always take java source before class files.

Also when searching for inner classes.

^Fixes KT-51025
This commit is contained in:
Mads Ager
2022-05-04 15:00:10 +02:00
committed by Alexander Udalov
parent 84b0e0b934
commit c6d7c23940
2 changed files with 46 additions and 6 deletions
@@ -174,6 +174,15 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
val result = ArrayList<PsiClass>(1)
forEachClassId(qName) { classId ->
val relativeClassName = classId.relativeClassName.asString()
// Search java sources first. For build tools, it makes sense to build new files passing all the
// class files for the previous build on the class path.
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType ->
val psiClass =
findVirtualFileGivenPackage(dir, relativeClassName, rootType)
@@ -186,12 +195,6 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
true
}
result.addIfNotNull(
singleJavaFileRootsIndex.findJavaSourceClass(classId)
?.takeIf { it in scope }
?.findPsiClassInVirtualFile(relativeClassName)
)
if (result.isNotEmpty()) {
return@time result.toTypedArray()
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.cli
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
class JavaSourceInnerClassInClassPathTest : TestCaseWithTmpdir() {
// Test that a java source file for a class is taken before a class file for the same
// class on the class path.
fun test() {
val aJava = tmpdir.resolve("A.java").also {
it.writeText("class A { interface AInner { int foo(); } }")
}
val bJava = tmpdir.resolve("B.java").also {
it.writeText("class B implements A.AInner { public int foo() { return 42; } }")
}
val cKt = tmpdir.resolve("C.kt").also {
it.writeText("fun main() { B().foo() }")
}
val (output, exit) = AbstractCliTest.executeCompilerGrabOutput(
K2JVMCompiler(),
listOf(aJava.path, bJava.path, cKt.path, "-d", tmpdir.path, "-Xcompile-java", "-Xuse-javac")
)
assert(exit == ExitCode.OK) { output }
val (output2, exit2) = AbstractCliTest.executeCompilerGrabOutput(
K2JVMCompiler(),
listOf(aJava.path, bJava.path, cKt.path, "-cp", tmpdir.path)
)
assert(exit2 == ExitCode.OK) { output2 }
}
}