From 6fc8c98aea9938d2f35ef62942e0ee85d0f4408f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 1 Nov 2018 11:19:13 +0300 Subject: [PATCH] Avoid calling PsiType::resolve while adding supertype references Otherwise, e.g. in case of inner classes it may lead to StackOverflowError: - Someone tries to resolve supertypes - We're starting building extends/implements lists - Then calling resolve on the type references leads that some logic in Java resolution again is trying to resolve supertype of the same class (only in case of inner ones) Probably, it could be fixed on the side of Java resolve but at the same time it's clear that calling `resolve` while building extends list it's really somewhat not very cool The exception is following: at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration$_extendsList$2.invoke(KtLightClassForSourceDeclaration.kt:77) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration$_extendsList$2.invoke(KtLightClassForSourceDeclaration.kt:73) at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:107) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration.get_extendsList(KtLightClassForSourceDeclaration.kt) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration.getExtendsList(KtLightClassForSourceDeclaration.kt:320) at com.intellij.psi.impl.PsiClassImplUtil.getExtendsListTypes(PsiClassImplUtil.java:1017) at com.intellij.psi.impl.light.AbstractLightClass.getExtendsListTypes(AbstractLightClass.java:137) at com.intellij.psi.impl.ScopedClassHierarchy.getSuperTypes(ScopedClassHierarchy.java:95) at com.intellij.psi.impl.ScopedClassHierarchy.visitType(ScopedClassHierarchy.java:80) at com.intellij.psi.impl.ScopedClassHierarchy.getSuperClassSubstitutor(ScopedClassHierarchy.java:115) at com.intellij.psi.impl.JavaClassSupersImpl.getSuperSubstitutorWithCaching(JavaClassSupersImpl.java:111) at com.intellij.psi.impl.JavaClassSupersImpl.getSuperClassSubstitutor(JavaClassSupersImpl.java:71) at com.intellij.psi.util.TypeConversionUtil.getMaybeSuperClassSubstitutor(TypeConversionUtil.java:1089) at com.intellij.psi.util.TypeConversionUtil.getClassSubstitutor(TypeConversionUtil.java:1055) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl.advancedResolveImpl(ClsJavaCodeReferenceElementImpl.java:143) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl.access$000(ClsJavaCodeReferenceElementImpl.java:43) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl$Resolver.resolve(ClsJavaCodeReferenceElementImpl.java:121) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl$Resolver.resolve(ClsJavaCodeReferenceElementImpl.java:115) at com.intellij.psi.impl.source.resolve.ResolveCache.lambda$resolveWithCaching$1(ResolveCache.java:203) at com.intellij.openapi.util.RecursionManager$2.doPreventingRecursion(RecursionManager.java:99) at com.intellij.psi.impl.source.resolve.ResolveCache.resolveWithCaching(ResolveCache.java:202) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl.multiResolve(ClsJavaCodeReferenceElementImpl.java:223) at com.intellij.psi.impl.compiled.ClsJavaCodeReferenceElementImpl.advancedResolve(ClsJavaCodeReferenceElementImpl.java:213) at com.intellij.psi.impl.source.PsiClassReferenceType.resolveGenerics(PsiClassReferenceType.java:191) at com.intellij.psi.impl.source.PsiClassReferenceType.resolve(PsiClassReferenceType.java:138) at org.jetbrains.kotlin.asJava.classes.LightReferenceListBuilder.addReference(LightReferenceListBuilder.java:53) at org.jetbrains.kotlin.asJava.classes.KtUltraLightClass.createExtendsList(ultraLightPsi.kt:91) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration$_extendsList$2.invoke(KtLightClassForSourceDeclaration.kt:77) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration$_extendsList$2.invoke(KtLightClassForSourceDeclaration.kt:73) at kotlin.SafePublicationLazyImpl.getValue(LazyJVM.kt:107) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration.get_extendsList(KtLightClassForSourceDeclaration.kt) at org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration.getExtendsList(KtLightClassForSourceDeclaration.kt:320) at com.intellij.psi.impl.PsiClassImplUtil.getExtendsListTypes(PsiClassImplUtil.java:1017) at com.intellij.psi.impl.light.AbstractLightClass.getExtendsListTypes(AbstractLightClass.java:137) a --- .../KotlinLightReferenceListBuilder.java | 3 -- .../kotlin/asJava/classes/ultraLightPsi.kt | 29 ++++++++++++++----- .../lightClasses/TypePararametersInClass.java | 11 +++++++ .../lightClasses/TypePararametersInClass.kt | 9 ++++++ .../CompilerLightClassTestGenerated.java | 5 ++++ .../UltraLightClassSanityTestGenerated.java | 5 ++++ .../IdeCompiledLightClassTestGenerated.java | 5 ++++ .../resolve/IdeLightClassTestGenerated.java | 5 ++++ 8 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/asJava/lightClasses/TypePararametersInClass.java create mode 100644 compiler/testData/asJava/lightClasses/TypePararametersInClass.kt diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinLightReferenceListBuilder.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinLightReferenceListBuilder.java index c9da0f0fffd..e1db9618214 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinLightReferenceListBuilder.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KotlinLightReferenceListBuilder.java @@ -47,9 +47,6 @@ public class KotlinLightReferenceListBuilder extends LightReferenceListBuilder i @Override public void addReference(PsiClassType type) { - final PsiClass resolved = type.resolve(); - if (resolved == null) return; - final PsiJavaCodeReferenceElement ref = myFactory.createReferenceElementByType(type); myRefs.add(ref); } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt index ba946436a73..b85bad61ae7 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightPsi.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.asJava.builder.LightClassData import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.codegen.FunctionCodegen +import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.PropertyCodegen import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.* @@ -45,6 +46,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.TRANSIENT_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.annotations.VOLATILE_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: UltraLightSupport) : KtLightClassImpl(classOrObject) { @@ -75,24 +77,35 @@ class KtUltraLightClass(classOrObject: KtClassOrObject, private val support: Ult } private fun allSuperTypes() = - getDescriptor()?.typeConstructor?.supertypes?.mapNotNull { - it.asPsiType(classOrObject, support, TypeMappingMode.SUPER_TYPE, this) as? PsiClassType - }.orEmpty() + getDescriptor()?.typeConstructor?.supertypes.orEmpty().asSequence() + + private fun mapSupertype(supertype: KotlinType) = + supertype.asPsiType(classOrObject, support, TypeMappingMode.SUPER_TYPE, this) as? PsiClassType override fun createExtendsList(): PsiReferenceList? = if (tooComplex) super.createExtendsList() - else LightReferenceListBuilder(manager, language, PsiReferenceList.Role.EXTENDS_LIST).also { list -> + else KotlinLightReferenceListBuilder( + manager, + language, + PsiReferenceList.Role.EXTENDS_LIST + ).also { list -> allSuperTypes() - .filter { (isInterface || it.resolve()?.isInterface == false) && !it.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) } + .filter { (isInterface || !JvmCodegenUtil.isJvmInterface(it)) && !it.isAnyOrNullableAny() } + .map(this::mapSupertype) .forEach(list::addReference) } override fun createImplementsList(): PsiReferenceList? = if (tooComplex) super.createImplementsList() - else LightReferenceListBuilder(manager, language, PsiReferenceList.Role.IMPLEMENTS_LIST).also { list -> + else KotlinLightReferenceListBuilder( + manager, + language, + PsiReferenceList.Role.IMPLEMENTS_LIST + ).also { list -> if (!isInterface) { allSuperTypes() - .filter { it.resolve()?.isInterface == true } + .filter { JvmCodegenUtil.isJvmInterface(it) } + .map(this::mapSupertype) .forEach(list::addReference) } } @@ -579,7 +592,7 @@ internal class KtUltraLightMethod( } private val _throwsList: PsiReferenceList by lazyPub { - val list = LightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST) + val list = KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST) (kotlinOrigin?.resolve() as? FunctionDescriptor)?.let { for (ex in FunctionCodegen.getThrownExceptions(it)) { list.addReference(ex.fqNameSafe.asString()) diff --git a/compiler/testData/asJava/lightClasses/TypePararametersInClass.java b/compiler/testData/asJava/lightClasses/TypePararametersInClass.java new file mode 100644 index 00000000000..137786688ce --- /dev/null +++ b/compiler/testData/asJava/lightClasses/TypePararametersInClass.java @@ -0,0 +1,11 @@ +public abstract class A > extends B> implements C { + public A() { /* compiled code */ } + + public class Inner extends B> implements C { + public Inner() { /* compiled code */ } + } + + public final class Inner2 extends A.Inner implements C { + public Inner2() { /* compiled code */ } + } +} diff --git a/compiler/testData/asJava/lightClasses/TypePararametersInClass.kt b/compiler/testData/asJava/lightClasses/TypePararametersInClass.kt new file mode 100644 index 00000000000..12b084b92cd --- /dev/null +++ b/compiler/testData/asJava/lightClasses/TypePararametersInClass.kt @@ -0,0 +1,9 @@ +// A +open class B +interface C +abstract class A> : B>(), C { + inner open class Inner : B>(), C { + } + + inner class Inner2 : Inner(), C +} diff --git a/compiler/tests/org/jetbrains/kotlin/asJava/CompilerLightClassTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/asJava/CompilerLightClassTestGenerated.java index 7f91cf395e1..378f12a2812 100644 --- a/compiler/tests/org/jetbrains/kotlin/asJava/CompilerLightClassTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/asJava/CompilerLightClassTestGenerated.java @@ -134,6 +134,11 @@ public class CompilerLightClassTestGenerated extends AbstractCompilerLightClassT runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt"); } + @TestMetadata("TypePararametersInClass.kt") + public void testTypePararametersInClass() throws Exception { + runTest("compiler/testData/asJava/lightClasses/TypePararametersInClass.kt"); + } + @TestMetadata("VarArgs.kt") public void testVarArgs() throws Exception { runTest("compiler/testData/asJava/lightClasses/VarArgs.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassSanityTestGenerated.java b/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassSanityTestGenerated.java index 4f561f73c00..f19cfad5386 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassSanityTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassSanityTestGenerated.java @@ -134,6 +134,11 @@ public class UltraLightClassSanityTestGenerated extends AbstractUltraLightClassS runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt"); } + @TestMetadata("TypePararametersInClass.kt") + public void testTypePararametersInClass() throws Exception { + runTest("compiler/testData/asJava/lightClasses/TypePararametersInClass.kt"); + } + @TestMetadata("VarArgs.kt") public void testVarArgs() throws Exception { runTest("compiler/testData/asJava/lightClasses/VarArgs.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeCompiledLightClassTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeCompiledLightClassTestGenerated.java index e0da9dd27e4..ce8576af385 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeCompiledLightClassTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeCompiledLightClassTestGenerated.java @@ -134,6 +134,11 @@ public class IdeCompiledLightClassTestGenerated extends AbstractIdeCompiledLight runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt"); } + @TestMetadata("TypePararametersInClass.kt") + public void testTypePararametersInClass() throws Exception { + runTest("compiler/testData/asJava/lightClasses/TypePararametersInClass.kt"); + } + @TestMetadata("VarArgs.kt") public void testVarArgs() throws Exception { runTest("compiler/testData/asJava/lightClasses/VarArgs.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeLightClassTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeLightClassTestGenerated.java index 5fa215fbfe9..1d494e01a3b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeLightClassTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/caches/resolve/IdeLightClassTestGenerated.java @@ -134,6 +134,11 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest { runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt"); } + @TestMetadata("TypePararametersInClass.kt") + public void testTypePararametersInClass() throws Exception { + runTest("compiler/testData/asJava/lightClasses/TypePararametersInClass.kt"); + } + @TestMetadata("VarArgs.kt") public void testVarArgs() throws Exception { runTest("compiler/testData/asJava/lightClasses/VarArgs.kt");