diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt index 007f591bb4b..b5f2ac06bb7 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCliJavaFileManagerImpl.kt @@ -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? { - // this method is called from IDEA to resolve dependencies in Java code - // which supposedly shouldn't have errors so the dependencies exist in general - // Most classes are top level classes so we will try to find them fast - // but we must sometimes fallback to support finding inner/nested classes - return qName.toSafeTopLevelClassId()?.let { classId -> findClass(classId, scope) } ?: super.findClass(qName, scope) + // String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin. + // 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", + // or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b". + // 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 + // "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 { diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Baz.java b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Baz.java new file mode 100644 index 00000000000..24bdeb225d2 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Baz.java @@ -0,0 +1,6 @@ +package test; + +public class Baz implements Foo.Bar { + @Override + public void bar() {} +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Foo.java b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Foo.java index 93fc3998747..e67176fcedd 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Foo.java +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/library/test/Foo.java @@ -2,6 +2,6 @@ package test; public class Foo { public interface Bar { - + void bar(); } } diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/source.kt index bc8bfdcee8d..70438e02bd3 100644 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/source.kt +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/innerClassPackageConflict/source.kt @@ -1,3 +1,5 @@ import test.Foo.Bar +import test.Baz val f: Bar? = null +val g: Baz? = Baz().apply { bar() } diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt index 80df674ea75..6111345beaf 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt @@ -277,12 +277,9 @@ class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { assertEquals("Invalid package prefix name is ignored: invalid-prefix.test", warnings.first().messageText) } - fun testSourcePackagePrefixKnownIssueWithInnerClasses() { + fun testSourcePackagePrefixWithInnerClasses() { initProject() - val buildResult = buildAllModules() - 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")) + buildAllModules().assertSuccessful() } fun testKotlinJavaScriptProject() { diff --git a/jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/kotlinProject.iml b/jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/kotlinProject.iml similarity index 100% rename from jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/kotlinProject.iml rename to jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/kotlinProject.iml diff --git a/jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/kotlinProject.ipr b/jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/kotlinProject.ipr similarity index 100% rename from jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/kotlinProject.ipr rename to jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/kotlinProject.ipr diff --git a/jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/src/JavaWithInner.java b/jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/src/JavaWithInner.java similarity index 100% rename from jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/src/JavaWithInner.java rename to jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/src/JavaWithInner.java diff --git a/jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/src/test.kt b/jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/src/test.kt similarity index 100% rename from jps-plugin/testData/general/SourcePackagePrefixKnownIssueWithInnerClasses/src/test.kt rename to jps-plugin/testData/general/SourcePackagePrefixWithInnerClasses/src/test.kt