diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptDependenciesClassFinder.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptDependenciesClassFinder.kt index ca23d4043b9..fd2544e1546 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptDependenciesClassFinder.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/KotlinScriptDependenciesClassFinder.kt @@ -5,14 +5,15 @@ package org.jetbrains.kotlin.idea.core.script -import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.NonClasspathClassFinder import com.intellij.psi.PsiClass +import com.intellij.psi.impl.java.stubs.index.JavaFullClassNameIndex import com.intellij.psi.search.EverythingGlobalScope import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StubIndex import org.jetbrains.kotlin.resolve.jvm.KotlinSafeClassFinder @@ -23,33 +24,46 @@ class KotlinScriptDependenciesClassFinder( .getAllScriptsDependenciesClassFiles().filter { it.isValid }.toList() override fun findClass(qualifiedName: String, scope: GlobalSearchScope): PsiClass? { - tailrec fun findClassInner(parentQualifier: String, inners: List = emptyList()): PsiClass? { - if (parentQualifier.isEmpty()) return null - ProgressManager.checkCanceled() - val parentClass = super.findClass(parentQualifier, scope) - if (parentClass != null) { - if (inners.isNotEmpty()) { - val innerClass = inners.fold(parentClass) { c: PsiClass?, name: String -> - c?.findInnerClassByName(name, false) - } - if (innerClass != null) return innerClass - } else return parentClass - } - return findClassInner( - parentQualifier.substringBeforeLast('.', ""), - listOf(parentQualifier.substringAfterLast('.')) + inners - ) + val scriptDependencies = + ScriptConfigurationManager.getInstance(project).getAllScriptsDependenciesClassFiles() + val firstJarInDependencies = scriptDependencies.firstOrNull() ?: return null + + if (!scope.contains(firstJarInDependencies)) return null + + val classByFileName = super.findClass(qualifiedName, scope) + if (classByFileName != null) { + return classByFileName.isInScope(scope) } - return findClassInner(qualifiedName)?.let { aClass -> - if (scope is EverythingGlobalScope) return aClass - - val file = aClass.containingFile?.virtualFile ?: return null - val index = ProjectFileIndex.SERVICE.getInstance(myProject) - if (index.isInContent(file) || index.isInLibraryClasses(file) || index.isInLibrarySource(file)) { - return null - } - return aClass + // Following code is needed because NonClasspathClassFinder cannot find inner classes + // JavaFullClassNameIndex cannot be used directly, because it filter only classes in source roots + val classes = StubIndex.getElements( + JavaFullClassNameIndex.getInstance().key, + qualifiedName.hashCode(), + project, + scope, + PsiClass::class.java + ).filter { + it.qualifiedName == qualifiedName } + + val found = when (classes.size) { + 0 -> null + 1 -> classes.single() + else -> classes.first() // todo: check when this happens + } + + return found?.isInScope(scope) + } + + private fun PsiClass.isInScope(scope: GlobalSearchScope): PsiClass? { + if (scope is EverythingGlobalScope) return this + + val file = this.containingFile?.virtualFile ?: return null + val index = ProjectFileIndex.SERVICE.getInstance(myProject) + if (index.isInContent(file) || index.isInLibrary(file)) { + return null + } + return this } } \ No newline at end of file diff --git a/idea/testData/script/definition/highlighting/javaNestedClass/lib/lib/JavaInterface.java b/idea/testData/script/definition/highlighting/nestedClass/lib/lib/JavaInterface.java similarity index 100% rename from idea/testData/script/definition/highlighting/javaNestedClass/lib/lib/JavaInterface.java rename to idea/testData/script/definition/highlighting/nestedClass/lib/lib/JavaInterface.java diff --git a/idea/testData/script/definition/highlighting/nestedClass/lib/lib/KotlinInterface.kt b/idea/testData/script/definition/highlighting/nestedClass/lib/lib/KotlinInterface.kt new file mode 100644 index 00000000000..5991b3ea796 --- /dev/null +++ b/idea/testData/script/definition/highlighting/nestedClass/lib/lib/KotlinInterface.kt @@ -0,0 +1,9 @@ +package lib + +interface KotlinInterface { + interface F { + interface I + } + + class G +} \ No newline at end of file diff --git a/idea/testData/script/definition/highlighting/javaNestedClass/script.kts b/idea/testData/script/definition/highlighting/nestedClass/script.kts similarity index 55% rename from idea/testData/script/definition/highlighting/javaNestedClass/script.kts rename to idea/testData/script/definition/highlighting/nestedClass/script.kts index 4a8136003e6..78bb021a2f6 100644 --- a/idea/testData/script/definition/highlighting/javaNestedClass/script.kts +++ b/idea/testData/script/definition/highlighting/nestedClass/script.kts @@ -1,6 +1,6 @@ import lib.* -fun f( +fun javaFun( g: JavaInterface.G, f: JavaInterface.F, i: JavaInterface.F.I @@ -8,4 +8,12 @@ fun f( } +fun kotlinFun( + g: KotlinInterface.G, + f: KotlinInterface.F, + i: KotlinInterface.F.I +) { + +} + // DEPENDENCIES: classpath:lib-classes; imports:custom.library.* \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/script/ScriptConfigurationHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/script/ScriptConfigurationHighlightingTestGenerated.java index 9cb16587202..47b89595b05 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/script/ScriptConfigurationHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/script/ScriptConfigurationHighlightingTestGenerated.java @@ -100,16 +100,16 @@ public class ScriptConfigurationHighlightingTestGenerated extends AbstractScript runTest("idea/testData/script/definition/highlighting/implicitReceiver/"); } - @TestMetadata("javaNestedClass") - public void testJavaNestedClass() throws Exception { - runTest("idea/testData/script/definition/highlighting/javaNestedClass/"); - } - @TestMetadata("multiModule") public void testMultiModule() throws Exception { runTest("idea/testData/script/definition/highlighting/multiModule/"); } + @TestMetadata("nestedClass") + public void testNestedClass() throws Exception { + runTest("idea/testData/script/definition/highlighting/nestedClass/"); + } + @TestMetadata("noResolver") public void testNoResolver() throws Exception { runTest("idea/testData/script/definition/highlighting/noResolver/");