Support nested classes in KotlinCliJavaFileManagerImpl.findClass
findClass(String, GlobalSearchScope) is invoked for example when we're resolving supertypes of classes in Java libraries. Previously, it never found nested classes and falled back to CoreJavaFileManager's implementation, which lacks a fix for the original issue (KT-12664, which was fixed in JvmDependenciesIndex in5a533a52and164c72e8) #KT-16931 Fixed
This commit is contained in:
+24
-5
@@ -53,12 +53,31 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this method is called from IDEA to resolve dependencies in Java code
|
||||||
|
// which supposedly shouldn't have errors so the dependencies exist in general
|
||||||
override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? {
|
override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? {
|
||||||
// this method is called from IDEA to resolve dependencies in Java code
|
// String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin.
|
||||||
// which supposedly shouldn't have errors so the dependencies exist in general
|
// For example, if qName is "a.b.c.d.e", we should either look for a top level class "e" in the package "a.b.c.d",
|
||||||
// Most classes are top level classes so we will try to find them fast
|
// or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b".
|
||||||
// but we must sometimes fallback to support finding inner/nested classes
|
// Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package
|
||||||
return qName.toSafeTopLevelClassId()?.let { classId -> findClass(classId, scope) } ?: super.findClass(qName, scope)
|
// "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly
|
||||||
|
|
||||||
|
var classId = qName.toSafeTopLevelClassId() ?: return super.findClass(qName, scope)
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
findClass(classId, scope)?.let { return it }
|
||||||
|
|
||||||
|
val packageFqName = classId.packageFqName
|
||||||
|
if (packageFqName.isRoot) break
|
||||||
|
|
||||||
|
classId = ClassId(
|
||||||
|
packageFqName.parent(),
|
||||||
|
FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.findClass(qName, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> {
|
||||||
|
|||||||
compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Baz.java
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public class Baz implements Foo.Bar {
|
||||||
|
@Override
|
||||||
|
public void bar() {}
|
||||||
|
}
|
||||||
compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Foo.java
Vendored
+1
-1
@@ -2,6 +2,6 @@ package test;
|
|||||||
|
|
||||||
public class Foo {
|
public class Foo {
|
||||||
public interface Bar {
|
public interface Bar {
|
||||||
|
void bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,3 +1,5 @@
|
|||||||
import test.Foo.Bar
|
import test.Foo.Bar
|
||||||
|
import test.Baz
|
||||||
|
|
||||||
val f: Bar? = null
|
val f: Bar? = null
|
||||||
|
val g: Baz? = Baz().apply { bar() }
|
||||||
|
|||||||
@@ -277,12 +277,9 @@ class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
|
|||||||
assertEquals("Invalid package prefix name is ignored: invalid-prefix.test", warnings.first().messageText)
|
assertEquals("Invalid package prefix name is ignored: invalid-prefix.test", warnings.first().messageText)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testSourcePackagePrefixKnownIssueWithInnerClasses() {
|
fun testSourcePackagePrefixWithInnerClasses() {
|
||||||
initProject()
|
initProject()
|
||||||
val buildResult = buildAllModules()
|
buildAllModules().assertSuccessful()
|
||||||
buildResult.assertFailed()
|
|
||||||
val errors = buildResult.getMessages(BuildMessage.Kind.ERROR).map { it.messageText }
|
|
||||||
assertTrue("Message wasn't found. $errors", errors.first().contains("class xxx.JavaWithInner.TextRenderer, unresolved supertypes: TableRow"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testKotlinJavaScriptProject() {
|
fun testKotlinJavaScriptProject() {
|
||||||
|
|||||||
Reference in New Issue
Block a user