diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/JavaElementFinder.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/JavaElementFinder.java index 403665e81a6..42cd239465c 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/JavaElementFinder.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/JavaElementFinder.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNamesUtilKt; +import org.jetbrains.kotlin.psi.KtClass; import org.jetbrains.kotlin.psi.KtClassOrObject; import org.jetbrains.kotlin.psi.KtEnumEntry; import org.jetbrains.kotlin.psi.KtFile; @@ -146,7 +147,8 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM if (!qualifiedName.shortName().asString().equals(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) return; for (KtClassOrObject classOrObject : lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName.parent(), scope)) { - if (LightClassUtilsKt.getHasInterfaceDefaultImpls(classOrObject)) { + //NOTE: can't filter out more interfaces right away because decompiled declarations do not have member bodies + if (classOrObject instanceof KtClass && ((KtClass) classOrObject).isInterface()) { PsiClass interfaceClass = LightClassUtil.INSTANCE$.getPsiClass(classOrObject); if (interfaceClass != null) { PsiClass implsClass = interfaceClass.findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false); diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt index 890539e5782..6c78ed2ee18 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForExplicitDeclaration.kt @@ -45,6 +45,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import java.util.* import javax.swing.Icon public open class KtLightClassForExplicitDeclaration( @@ -364,12 +365,13 @@ public open class KtLightClassForExplicitDeclaration( override fun toString() = "${KtLightClass::class.java.simpleName}:$classFqName" override fun getOwnInnerClasses(): List { - return getDelegate().innerClasses - .map { - val declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(it) as KtClassOrObject? - if (declaration != null) create(declaration, it) else null - } - .filterNotNull() + val result = ArrayList() + classOrObject.declarations.filterIsInstance().mapTo(result) { create(it) } + + if (classOrObject.hasInterfaceDefaultImpls) { + result.add(KtLightClassForInterfaceDefaultImpls(classFqName.defaultImplsChild(), classOrObject)) + } + return result.filterNotNull() } override fun getUseScope(): SearchScope = getOrigin().useScope @@ -387,11 +389,7 @@ public open class KtLightClassForExplicitDeclaration( FINAL_KEYWORD to PsiModifier.FINAL) - @JvmOverloads - public fun create( - classOrObject: KtClassOrObject, - psiClass: PsiClass? = null - ): KtLightClassForExplicitDeclaration? { + public fun create(classOrObject: KtClassOrObject): KtLightClassForExplicitDeclaration? { if (LightClassUtil.belongsToKotlinBuiltIns(classOrObject.getContainingKtFile())) { return null } @@ -402,13 +400,6 @@ public open class KtLightClassForExplicitDeclaration( return KtLightClassForAnonymousDeclaration(fqName, classOrObject) } - if (classOrObject.hasInterfaceDefaultImpls) { - val implsFqName = fqName.defaultImplsChild() - if (implsFqName.asString() == psiClass?.qualifiedName) { - return KtLightClassForInterfaceDefaultImpls(implsFqName, classOrObject) - } - } - return KtLightClassForExplicitDeclaration(fqName, classOrObject) } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForInterfaceDefaultImpls.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForInterfaceDefaultImpls.kt index 10b28c865bb..daa07e1002f 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForInterfaceDefaultImpls.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KtLightClassForInterfaceDefaultImpls.kt @@ -48,4 +48,6 @@ public open class KtLightClassForInterfaceDefaultImpls( } override fun getContainingClass() = KtLightClassForExplicitDeclaration.create(classOrObject) + + override fun getOwnInnerClasses() = emptyList() } diff --git a/idea/idea-completion/testData/injava/InterfaceDefaultImplsNonImported.java b/idea/idea-completion/testData/injava/InterfaceDefaultImplsNonImported.java new file mode 100644 index 00000000000..1450ed0f319 --- /dev/null +++ b/idea/idea-completion/testData/injava/InterfaceDefaultImplsNonImported.java @@ -0,0 +1,11 @@ +public class Testing { + public static void test() { + DefaultImpl + } +} + +// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractFun)" } +// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractFunWithExpressionBody)" } +// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractProperty)" } +// EXIST: { lookupString: "DefaultImpls", tailText: " (defaultImpls.NonAbstractPropertyWithBody)" } +// ABSENT: { lookupString: "DefaultImpls", tailText: " (defaultImpls.AllAbstract)" } \ No newline at end of file diff --git a/idea/idea-completion/testData/injava/mockLib/defaultImpls.kt b/idea/idea-completion/testData/injava/mockLib/defaultImpls.kt new file mode 100644 index 00000000000..3249376fef9 --- /dev/null +++ b/idea/idea-completion/testData/injava/mockLib/defaultImpls.kt @@ -0,0 +1,30 @@ +package defaultImpls; + +interface AllAbstract { + val c: Int + fun f(t: T): T + + val g: Int + + var g2: String +} + +interface NonAbstractFun { + fun f() { + + } +} + +interface NonAbstractFunWithExpressionBody { + fun f() = 3 +} + +interface NonAbstractProperty { + val c: Int get() = 3 +} + +interface NonAbstractPropertyWithBody { + val c: Int get() { + return 3 + } +} \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompiledKotlinInJavaCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompiledKotlinInJavaCompletionTestGenerated.java index 1045dfa7508..f9b26836a8c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompiledKotlinInJavaCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/CompiledKotlinInJavaCompletionTestGenerated.java @@ -101,6 +101,12 @@ public class CompiledKotlinInJavaCompletionTestGenerated extends AbstractCompile doTest(fileName); } + @TestMetadata("InterfaceDefaultImplsNonImported.java") + public void testInterfaceDefaultImplsNonImported() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/injava/InterfaceDefaultImplsNonImported.java"); + doTest(fileName); + } + @TestMetadata("MultiFileFacade.java") public void testMultiFileFacade() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/injava/MultiFileFacade.java"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinSourceInJavaCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinSourceInJavaCompletionTestGenerated.java index 3fadf2e8549..e1efe1d1f3c 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinSourceInJavaCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/KotlinSourceInJavaCompletionTestGenerated.java @@ -101,6 +101,12 @@ public class KotlinSourceInJavaCompletionTestGenerated extends AbstractKotlinSou doTest(fileName); } + @TestMetadata("InterfaceDefaultImplsNonImported.java") + public void testInterfaceDefaultImplsNonImported() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/injava/InterfaceDefaultImplsNonImported.java"); + doTest(fileName); + } + @TestMetadata("MultiFileFacade.java") public void testMultiFileFacade() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/injava/MultiFileFacade.java");