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
This commit is contained in:
Denis Zharkov
2018-11-01 11:19:13 +03:00
parent 34e8ce6a48
commit 6fc8c98aea
8 changed files with 61 additions and 11 deletions
@@ -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);
}
@@ -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())
@@ -0,0 +1,11 @@
public abstract class A <T extends A<T>> extends B<java.util.Collection<? extends T>> implements C<T> {
public A() { /* compiled code */ }
public class Inner <D> extends B<java.util.Collection<? extends T>> implements C<D> {
public Inner() { /* compiled code */ }
}
public final class Inner2 <X> extends A<T>.Inner<X> implements C<X> {
public Inner2() { /* compiled code */ }
}
}
@@ -0,0 +1,9 @@
// A
open class B<F>
interface C<E>
abstract class A<T : A<T>> : B<Collection<T>>(), C<T> {
inner open class Inner<D> : B<Collection<T>>(), C<D> {
}
inner class Inner2<X> : Inner<X>(), C<X>
}
@@ -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");
@@ -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");
@@ -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");
@@ -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");