[light classes] drop descriptors from KtLightClassForSourceDeclaration

^KT-53097
This commit is contained in:
Dmitry Gridin
2022-07-07 20:31:58 +02:00
committed by Space
parent 30c378edc2
commit bac592c2db
4 changed files with 129 additions and 123 deletions
+1 -1
View File
@@ -4,11 +4,11 @@ plugins {
}
dependencies {
api(project(":compiler:light-classes-base"))
api(project(":compiler:util"))
api(project(":compiler:backend"))
api(project(":compiler:frontend"))
api(project(":compiler:frontend.java"))
api(project(":compiler:light-classes-base"))
compileOnly(intellijCore())
compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all"))
compileOnly(commonDependency("org.jetbrains.intellij.deps:trove4j"))
@@ -6,11 +6,9 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.InheritanceImplUtil
import com.intellij.psi.impl.source.PsiImmediateClassType
import com.intellij.psi.impl.source.tree.TreeUtil
import com.intellij.psi.scope.PsiScopeProcessor
@@ -30,18 +28,14 @@ import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.resolve.DescriptorUtils
import javax.swing.Icon
private class KtLightClassModifierList(containingClass: KtLightClassForSourceDeclaration, computeModifiers: () -> Set<String>) :
@@ -92,9 +86,6 @@ abstract class KtLightClassForSourceDeclaration(
abstract override fun getParent(): PsiElement?
abstract override fun getQualifiedName(): String?
fun getDescriptor() =
LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
private val _containingFile: PsiFile by lazyPub {
object : FakeFileForLightClass(
classOrObject.containingKtFile,
@@ -175,59 +166,7 @@ abstract class KtLightClassForSourceDeclaration(
override fun getModifierList(): PsiModifierList? = _modifierList
protected open fun computeModifiers(): Set<String> {
val psiModifiers = hashSetOf<String>()
// PUBLIC, PROTECTED, PRIVATE, ABSTRACT, FINAL
//noinspection unchecked
for (tokenAndModifier in jetTokenToPsiModifier) {
if (classOrObject.hasModifier(tokenAndModifier.first)) {
psiModifiers.add(tokenAndModifier.second)
}
}
if (classOrObject.hasModifier(PRIVATE_KEYWORD)) {
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE)
} else if (!psiModifiers.contains(PsiModifier.PROTECTED)) {
psiModifiers.add(PsiModifier.PUBLIC)
}
// ABSTRACT | FINAL
when {
isAbstract() || isSealed() -> {
psiModifiers.add(PsiModifier.ABSTRACT)
}
isEnum -> {
// Enum class should not be `final`, since its enum entries extend it.
// It could be either `abstract` w/o ctor, or empty modality w/ private ctor.
}
!(classOrObject.hasModifier(OPEN_KEYWORD)) -> {
val descriptor = lazy { getDescriptor() }
var modifier = PsiModifier.FINAL
project.applyCompilerPlugins {
modifier = it.interceptModalityBuilding(kotlinOrigin, descriptor, modifier)
}
if (modifier == PsiModifier.FINAL) {
psiModifiers.add(PsiModifier.FINAL)
}
}
}
if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) {
psiModifiers.add(PsiModifier.STATIC)
}
return psiModifiers
}
private fun isAbstract(): Boolean = classOrObject.hasModifier(ABSTRACT_KEYWORD) || isInterface
private fun isSealed(): Boolean = classOrObject.hasModifier(SEALED_KEYWORD)
protected abstract fun computeModifiers(): Set<String>
override fun hasModifierProperty(@NonNls name: String): Boolean = modifierList?.hasModifierProperty(name) ?: false
@@ -242,29 +181,11 @@ abstract class KtLightClassForSourceDeclaration(
override fun isEnum(): Boolean = classOrObject is KtClass && classOrObject.isEnum()
override fun hasTypeParameters(): Boolean = classOrObject is KtClass && !classOrObject.typeParameters.isEmpty()
override fun hasTypeParameters(): Boolean = classOrObject is KtClass && classOrObject.typeParameters.isNotEmpty()
override fun isValid(): Boolean = classOrObject.isValid
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val qualifiedName: String? = if (baseClass is KtLightClassForSourceDeclaration) {
baseClass.getDescriptor()?.let(DescriptorUtils::getFqName)?.asString()
} else {
baseClass.qualifiedName
}
val thisDescriptor = getDescriptor()
return if (qualifiedName != null && thisDescriptor != null) {
qualifiedName != DescriptorUtils.getFqName(thisDescriptor).asString() &&
checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep)
} else {
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
}
}
abstract override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean
@Throws(IncorrectOperationException::class)
override fun setName(@NonNls name: String): PsiElement {
@@ -305,13 +226,6 @@ abstract class KtLightClassForSourceDeclaration(
override fun getImplementsList(): PsiReferenceList? = _implementsList
companion object {
private val jetTokenToPsiModifier = listOf(
PUBLIC_KEYWORD to PsiModifier.PUBLIC,
INTERNAL_KEYWORD to PsiModifier.PUBLIC,
PROTECTED_KEYWORD to PsiModifier.PROTECTED,
FINAL_KEYWORD to PsiModifier.FINAL
)
fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? =
CachedValuesManager.getCachedValue(classOrObject) {
CachedValueProvider.Result.create(
@@ -335,38 +249,6 @@ abstract class KtLightClassForSourceDeclaration(
createUltraLightClass(classOrObject)
}
}
private fun checkSuperTypeByFQName(classDescriptor: ClassDescriptor, qualifiedName: String, deep: Boolean): Boolean {
if (CommonClassNames.JAVA_LANG_OBJECT == qualifiedName) return true
if (qualifiedName == DescriptorUtils.getFqName(classDescriptor).asString()) return true
val fqName = FqNameUnsafe(qualifiedName)
val mappedQName =
if (fqName.isSafe)
JavaToKotlinClassMap.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
else null
if (qualifiedName == mappedQName) return true
for (superType in classDescriptor.typeConstructor.supertypes) {
val superDescriptor = superType.constructor.declarationDescriptor
if (superDescriptor is ClassDescriptor) {
val superQName = DescriptorUtils.getFqName(superDescriptor).asString()
if (superQName == qualifiedName || superQName == mappedQName) return true
if (deep) {
if (checkSuperTypeByFQName(superDescriptor, qualifiedName, true)) {
return true
}
}
}
}
return false
}
private val LOG = Logger.getInstance(KtLightClassForSourceDeclaration::class.java)
}
abstract override fun getSupers(): Array<PsiClass>
@@ -5,9 +5,19 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.CommonClassNames
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiModifier
import com.intellij.psi.impl.InheritanceImplUtil
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
// light class for top level or (inner/nested of top level) source declarations
abstract class KtLightClassImpl @JvmOverloads constructor(
@@ -15,6 +25,83 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
jvmDefaultMode: JvmDefaultMode,
forceUsingOldLightClasses: Boolean = false
) : KtLightClassForSourceDeclaration(classOrObject, jvmDefaultMode, forceUsingOldLightClasses) {
fun getDescriptor() =
LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
override fun computeModifiers(): Set<String> {
val psiModifiers = hashSetOf<String>()
// PUBLIC, PROTECTED, PRIVATE, ABSTRACT, FINAL
//noinspection unchecked
for (tokenAndModifier in jetTokenToPsiModifier) {
if (classOrObject.hasModifier(tokenAndModifier.first)) {
psiModifiers.add(tokenAndModifier.second)
}
}
if (classOrObject.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
// Top-level private class has PACKAGE_LOCAL visibility in Java
// Nested private class has PRIVATE visibility
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE)
} else if (!psiModifiers.contains(PsiModifier.PROTECTED)) {
psiModifiers.add(PsiModifier.PUBLIC)
}
// ABSTRACT | FINAL
when {
isAbstract() || isSealed() -> {
psiModifiers.add(PsiModifier.ABSTRACT)
}
isEnum -> {
// Enum class should not be `final`, since its enum entries extend it.
// It could be either `abstract` w/o ctor, or empty modality w/ private ctor.
}
!(classOrObject.hasModifier(KtTokens.OPEN_KEYWORD)) -> {
val descriptor = lazy { getDescriptor() }
var modifier = PsiModifier.FINAL
project.applyCompilerPlugins {
modifier = it.interceptModalityBuilding(kotlinOrigin, descriptor, modifier)
}
if (modifier == PsiModifier.FINAL) {
psiModifiers.add(PsiModifier.FINAL)
}
}
}
if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(KtTokens.INNER_KEYWORD)) {
psiModifiers.add(PsiModifier.STATIC)
}
return psiModifiers
}
private fun isAbstract(): Boolean = classOrObject.hasModifier(KtTokens.ABSTRACT_KEYWORD) || isInterface
private fun isSealed(): Boolean = classOrObject.hasModifier(KtTokens.SEALED_KEYWORD)
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean {
if (manager.areElementsEquivalent(baseClass, this)) return false
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val qualifiedName: String? = if (baseClass is KtLightClassImpl) {
baseClass.getDescriptor()?.let(DescriptorUtils::getFqName)?.asString()
} else {
baseClass.qualifiedName
}
val thisDescriptor = getDescriptor()
return if (qualifiedName != null && thisDescriptor != null) {
qualifiedName != DescriptorUtils.getFqName(thisDescriptor).asString() &&
checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep)
} else {
InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
}
}
override fun getQualifiedName() = classOrObject.fqName?.asString()
override fun getParent() = if (classOrObject.isTopLevel())
@@ -24,3 +111,40 @@ abstract class KtLightClassImpl @JvmOverloads constructor(
abstract override fun copy(): PsiElement
}
private fun checkSuperTypeByFQName(classDescriptor: ClassDescriptor, qualifiedName: String, deep: Boolean): Boolean {
if (CommonClassNames.JAVA_LANG_OBJECT == qualifiedName) return true
if (qualifiedName == DescriptorUtils.getFqName(classDescriptor).asString()) return true
val fqName = FqNameUnsafe(qualifiedName)
val mappedQName =
if (fqName.isSafe)
JavaToKotlinClassMap.mapJavaToKotlin(fqName.toSafe())?.asSingleFqName()?.asString()
else null
if (qualifiedName == mappedQName) return true
for (superType in classDescriptor.typeConstructor.supertypes) {
val superDescriptor = superType.constructor.declarationDescriptor
if (superDescriptor is ClassDescriptor) {
val superQName = DescriptorUtils.getFqName(superDescriptor).asString()
if (superQName == qualifiedName || superQName == mappedQName) return true
if (deep) {
if (checkSuperTypeByFQName(superDescriptor, qualifiedName, true)) {
return true
}
}
}
}
return false
}
private val jetTokenToPsiModifier = listOf(
KtTokens.PUBLIC_KEYWORD to PsiModifier.PUBLIC,
KtTokens.INTERNAL_KEYWORD to PsiModifier.PUBLIC,
KtTokens.PROTECTED_KEYWORD to PsiModifier.PROTECTED,
KtTokens.FINAL_KEYWORD to PsiModifier.FINAL,
)
@@ -65,7 +65,7 @@ open class KtUltraLightClassForAnonymousDeclaration(classOrObject: KtClassOrObje
override fun copy() = KtUltraLightClassForAnonymousDeclaration(classOrObject, support)
}
private fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String {
private fun KtLightClassImpl.getFirstSupertypeFQNameForAnonymousDeclaration(): String {
val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT
val superTypes = descriptor.typeConstructor.supertypes