Remove fallbacking of UL (to LightClasses) by complexity checking

This commit is contained in:
Igor Yakovlev
2019-10-09 21:52:26 +03:00
parent 3f9bffcc5f
commit 58b8d8868a
14 changed files with 46 additions and 145 deletions
@@ -90,7 +90,7 @@ internal open class KtLightClassForAnonymousDeclaration(classOrObject: KtClassOr
companion object {
fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String {
val descriptor = descriptor.value ?: return CommonClassNames.JAVA_LANG_OBJECT
val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT
val superTypes = descriptor.typeConstructor.supertypes
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.asJava.classes
import com.google.common.annotations.VisibleForTesting
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.TextRange
@@ -53,21 +52,7 @@ open class KtLightClassForFacade constructor(
files: Collection<KtFile>
) : KtLazyLightClass(manager) {
@Volatile
@VisibleForTesting
var isClsDelegateLoaded = false
override val clsDelegate: PsiClass
get() {
isClsDelegateLoaded = true
return super.clsDelegate
}
protected open val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade> = myLightClassDataCache
get() {
isClsDelegateLoaded = true
return field
}
val files: Collection<KtFile> = files.toSet()
@@ -113,9 +113,8 @@ abstract class KtLightClassForSourceDeclaration(
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
public val descriptor = lazyPub {
fun getDescriptor() =
LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
}
protected fun getLightClassDataHolder(): LightClassDataHolder.ForClass {
val lightClassData = getLightClassDataHolder(classOrObject)
@@ -234,12 +233,9 @@ abstract class KtLightClassForSourceDeclaration(
// AllOpen can affect on modality of the member. We ought to check if the extension could override the modality
// Resolver will produce correct descriptor corresponding to modality from AllOpen.
// The easiest way to get new modality is to resolve the descriptor
val modifierToAdd = if (kotlinOrigin.isOrdinaryClass && descriptor.value?.modality == Modality.OPEN) {
PsiModifier.OPEN
} else {
PsiModifier.FINAL
if (!kotlinOrigin.isOrdinaryClass || getDescriptor()?.modality != Modality.OPEN) {
psiModifiers.add(PsiModifier.FINAL)
}
psiModifiers.add(modifierToAdd)
}
if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) {
@@ -274,13 +270,13 @@ abstract class KtLightClassForSourceDeclaration(
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val qualifiedName: String? = if (baseClass is KtLightClassForSourceDeclaration) {
val baseDescriptor = baseClass.descriptor.value
val baseDescriptor = baseClass.getDescriptor()
if (baseDescriptor != null) DescriptorUtils.getFqName(baseDescriptor).asString() else null
} else {
baseClass.qualifiedName
}
val thisDescriptor = descriptor.value
val thisDescriptor = getDescriptor()
return qualifiedName != null && thisDescriptor != null && checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep)
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.HierarchicalMethodSignature
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.PsiSuperMethodImplUtil
import org.jetbrains.kotlin.asJava.elements.KtLightField
@@ -71,7 +70,7 @@ class KtUltraLightInlineClass(
override fun getOwnFields(): List<KtLightField> = emptyList()
override fun getOwnMethods() = if (tooComplex) super.getOwnMethods() else _ownMethods
override fun getOwnMethods() = _ownMethods
override fun getVisibleSignatures(): MutableCollection<HierarchicalMethodSignature> = PsiSuperMethodImplUtil.getVisibleSignatures(this)
@@ -24,28 +24,13 @@ class KtUltraLightClassForFacade(
private val filesWithSupports: Collection<Pair<KtFile, KtUltraLightSupport>>
) : KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files) {
private inline fun <T> forTooComplex(getter: () -> T): T {
check(tooComplex) {
"Cls delegate shouldn't be loaded for not too complex ultra-light classes! Qualified name: $qualifiedName"
}
return getter()
}
override fun getDelegate(): PsiClass = invalidAccess()
override fun getDelegate(): PsiClass = forTooComplex { super.getDelegate() }
override val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade> get() = invalidAccess()
override val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>
get() = forTooComplex { super.lightClassDataCache }
override val clsDelegate: PsiClass get() = invalidAccess()
override val clsDelegate: PsiClass
get() = forTooComplex { super.clsDelegate }
override fun getScope(): PsiElement? = if (!tooComplex) parent else super.getScope()
private val tooComplex: Boolean by lazyPub {
filesWithSupports.any { (file, support) ->
file.declarations.any { support.isTooComplexForUltraLightGeneration(it) }
}
}
override fun getScope(): PsiElement? = parent
private val filesWithSupportsWithCreators by lazyPub {
filesWithSupports.map { (file, support) ->
@@ -86,7 +71,7 @@ class KtUltraLightClassForFacade(
}
}
private val ownMethodsForNotTooComplex: List<KtLightMethod> by lazyPub {
private val _ownMethods: List<KtLightMethod> by lazyPub {
mutableListOf<KtLightMethod>().also { result ->
for ((file, support, creator) in filesWithSupportsWithCreators) {
loadMethodsFromFile(file, support, creator, result)
@@ -94,7 +79,7 @@ class KtUltraLightClassForFacade(
}
}
private val ownFieldsForNotTooComplex: List<KtLightField> by lazyPub {
private val _ownFields: List<KtLightField> by lazyPub {
hashSetOf<String>().let { nameCache ->
filesWithSupportsWithCreators.flatMap { (file, _, creator) ->
file.declarations.filterIsInstance<KtProperty>().mapNotNull {
@@ -104,9 +89,9 @@ class KtUltraLightClassForFacade(
}
}
override fun getOwnFields() = if (!tooComplex) ownFieldsForNotTooComplex else super.getOwnFields()
override fun getOwnFields() = _ownFields
override fun getOwnMethods() = if (!tooComplex) ownMethodsForNotTooComplex else super.getOwnMethods()
override fun getOwnMethods() = _ownMethods
override fun getVisibleSignatures(): MutableCollection<HierarchicalMethodSignature> = PsiSuperMethodImplUtil.getVisibleSignatures(this)
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.asJava.classes
import com.google.common.annotations.VisibleForTesting
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.PsiClassImplUtil
@@ -23,7 +22,6 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.codegen.kotlinType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -71,38 +69,22 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
)
}
protected val tooComplex: Boolean by lazyPub { support.isTooComplexForUltraLightGeneration(classOrObject) }
private val _deprecated by lazyPub { classOrObject.isDeprecated(support) }
override fun isFinal(isFinalByPsi: Boolean) = if (tooComplex) super.isFinal(isFinalByPsi) else isFinalByPsi
override fun isFinal(isFinalByPsi: Boolean) = isFinalByPsi
@Volatile
@VisibleForTesting
var isClsDelegateLoaded = false
override fun findLightClassData(): LightClassData = invalidAccess()
private inline fun <T> forTooComplex(getter: () -> T): T {
if (!isClsDelegateLoaded) {
isClsDelegateLoaded = true
check(tooComplex) {
"Cls delegate shouldn't be loaded for not too complex ultra-light classes! Qualified name: $qualifiedName"
}
}
return getter()
}
override fun findLightClassData(): LightClassData = forTooComplex { super.findLightClassData() }
override fun getDelegate(): PsiClass = forTooComplex { super.getDelegate() }
override fun getDelegate(): PsiClass = invalidAccess()
private val _modifierList: PsiModifierList? by lazyPub {
if (tooComplex) super.getModifierList() else KtUltraLightClassModifierList(this, support) { computeModifiers() }
KtUltraLightClassModifierList(this, support) { computeModifiers() }
}
override fun getModifierList(): PsiModifierList? = _modifierList
private fun allSuperTypes() =
descriptor.value?.typeConstructor?.supertypes.orEmpty()
getDescriptor()?.typeConstructor?.supertypes.orEmpty()
private fun mapSupertype(supertype: KotlinType, kotlinCollectionAsIs: Boolean = false) =
supertype.asPsiType(
@@ -121,8 +103,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
if (isAnnotationType) return KotlinLightReferenceListBuilder(manager, language, role)
if (tooComplex) return if (forExtendsList) super.createExtendsList() else super.createImplementsList()
val superTypes = allSuperTypes().filter {
isTypeForInheritanceList(it, forExtendsList)
}
@@ -180,8 +160,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
return forExtendsList == !JvmCodegenUtil.isJvmInterface(supertype)
}
override fun buildTypeParameterList(): PsiTypeParameterList =
if (tooComplex) super.buildTypeParameterList() else buildTypeParameterList(classOrObject, this, support)
override fun buildTypeParameterList(): PsiTypeParameterList = buildTypeParameterList(classOrObject, this, support)
// the following logic should be in the platform (super), overrides can be removed once that happens
override fun getInterfaces(): Array<PsiClass> = PsiClassImplUtil.getInterfaces(this)
@@ -217,10 +196,11 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
}
fun ArrayList<KtLightField>.updateWithCompilerPlugins() = also {
val lazyDescriptor = lazy { getDescriptor() }
applyCompilerPlugins {
it.interceptFieldsBuilding(
declaration = kotlinOrigin,
descriptor = descriptor,
descriptor = lazyDescriptor,
containingDeclaration = this@KtUltraLightClass,
fieldsList = result
)
@@ -275,7 +255,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
private fun isNamedObject() = classOrObject is KtObjectDeclaration && !classOrObject.isCompanion()
override fun getOwnFields(): List<KtLightField> = if (tooComplex) super.getOwnFields() else _ownFields
override fun getOwnFields(): List<KtLightField> = _ownFields
private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() }
@@ -328,10 +308,11 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
addMethodsFromDataClass(result)
addDelegatesToInterfaceMethods(result)
val lazyDescriptor = lazy { getDescriptor() }
applyCompilerPlugins {
it.interceptMethodsBuilding(
declaration = kotlinOrigin,
descriptor = descriptor,
descriptor = lazyDescriptor,
containingDeclaration = this,
methodsList = result
)
@@ -467,7 +448,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
private fun isJvmStatic(declaration: KtAnnotated): Boolean = declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
override fun getOwnMethods(): List<KtLightMethod> = if (tooComplex) super.getOwnMethods() else _ownMethods.value
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
@@ -478,13 +459,15 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
override fun getInitializers(): Array<PsiClassInitializer> = emptyArray()
override fun getContainingClass(): PsiClass? =
if (tooComplex) super.getContainingClass()
else ((classOrObject.parent as? KtClassBody)?.parent as? KtClassOrObject)?.let(KtLightClassForSourceDeclaration::create)
override fun getContainingClass(): PsiClass? {
val containingBody = classOrObject.parent as? KtClassBody
val containingClass = containingBody?.parent as? KtClassOrObject
return containingClass?.let { create(it) }
}
override fun getParent(): PsiElement? = if (tooComplex) super.getParent() else containingClass ?: containingFile
override fun getParent(): PsiElement? = containingClass ?: containingFile
override fun getScope(): PsiElement? = if (tooComplex) super.getScope() else parent
override fun getScope(): PsiElement? = parent
override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean =
baseClass?.let { InheritanceImplUtil.isInheritorDeep(this, it, classToByPass) } ?: false
@@ -144,8 +144,7 @@ internal open class KtUltraLightFieldImpl protected constructor(
override val kotlinOrigin = declaration
override val clsDelegate: PsiField
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
override val clsDelegate: PsiField get() = invalidAccess()
override val lightMemberOrigin = LightMemberOriginForDeclaration(declaration, JvmDeclarationOriginKind.OTHER)
@@ -30,8 +30,7 @@ internal class KtUltraLightSuspendContinuationParameter(
override val kotlinTypeForNullabilityAnnotation: KotlinType? get() = ktType
override val psiTypeForNullabilityAnnotation: PsiType? get() = psiType
override val kotlinOrigin: KtParameter? = null
override val clsDelegate: PsiParameter
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
override val clsDelegate: PsiParameter get() = invalidAccess()
private val ktType by lazyPub {
val descriptor = ktFunction.resolve() as? FunctionDescriptor
@@ -79,8 +78,7 @@ internal abstract class KtUltraLightParameter(
override fun isEquivalentTo(another: PsiElement?): Boolean = kotlinOrigin == another
override val clsDelegate: PsiParameter
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
override val clsDelegate: PsiParameter get() = invalidAccess()
private val lightModifierList by lazyPub { KtLightSimpleModifierList(this, emptySet()) }
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
interface KtUltraLightSupport {
val moduleName: String
fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>?
fun isTooComplexForUltraLightGeneration(element: KtDeclaration): Boolean
val deprecationResolver: DeprecationResolver
val typeMapper: KotlinTypeMapper
val moduleDescriptor: ModuleDescriptor
@@ -388,4 +388,7 @@ fun KotlinType.tryResolveMarkerInterfaceFQName(): String? {
}
return null
}
}
internal fun <L : Any> L.invalidAccess(): Nothing =
error("Cls delegate shouldn't be loaded for not too complex ultra-light classes! Qualified name: ${javaClass.name}")
@@ -102,8 +102,7 @@ abstract class KtUltraLightModifierList<out T : KtLightElement<KtModifierListOwn
private val support: KtUltraLightSupport
) : KtLightModifierList<T>(owner) {
override val clsDelegate: PsiModifierList
get() = throw IllegalStateException("Cls delegate shouldn't be loaded for ultra-light PSI!")
override val clsDelegate: PsiModifierList get() = invalidAccess()
private fun throwInvalidOperation(): Nothing = throw IncorrectOperationException()