Add UL support for AllOpen compiler plugin

This commit is contained in:
Igor Yakovlev
2019-10-09 18:24:56 +03:00
parent 558a700f51
commit 6ce37fff95
8 changed files with 91 additions and 64 deletions
@@ -90,7 +90,7 @@ internal open class KtLightClassForAnonymousDeclaration(classOrObject: KtClassOr
companion object {
fun KtLightClassForSourceDeclaration.getFirstSupertypeFQNameForAnonymousDeclaration(): String {
val descriptor = getDescriptor() ?: return CommonClassNames.JAVA_LANG_OBJECT
val descriptor = descriptor.value ?: return CommonClassNames.JAVA_LANG_OBJECT
val superTypes = descriptor.typeConstructor.supertypes
@@ -42,7 +42,10 @@ import org.jetbrains.kotlin.asJava.elements.KtLightModifierList
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
import org.jetbrains.kotlin.name.FqNameUnsafe
@@ -53,6 +56,7 @@ 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 org.jetbrains.kotlin.util.isOrdinaryClass
import java.util.*
import javax.swing.Icon
@@ -105,13 +109,12 @@ abstract class KtLightClassForSourceDeclaration(
override val lightClassData: LightClassData
get() = findLightClassData()
protected open fun findLightClassData() = getLightClassDataHolder().
findDataForClassOrObject(classOrObject)
protected open fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
private fun getJavaFileStub(): PsiJavaFileStub = getLightClassDataHolder().javaFileStub
fun getDescriptor(): ClassDescriptor? {
return LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
public val descriptor = lazyPub {
LightClassGenerationSupport.getInstance(project).resolveToDescriptor(classOrObject) as? ClassDescriptor
}
protected fun getLightClassDataHolder(): LightClassDataHolder.ForClass {
@@ -228,7 +231,15 @@ abstract class KtLightClassForSourceDeclaration(
if (isAbstract() || isSealed()) {
psiModifiers.add(PsiModifier.ABSTRACT)
} else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is KtClass && classOrObject.isEnum()))) {
psiModifiers.add(PsiModifier.FINAL)
// 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
}
psiModifiers.add(modifierToAdd)
}
if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) {
@@ -263,13 +274,13 @@ abstract class KtLightClassForSourceDeclaration(
LightClassInheritanceHelper.getService(project).isInheritor(this, baseClass, checkDeep).ifSure { return it }
val qualifiedName: String? = if (baseClass is KtLightClassForSourceDeclaration) {
val baseDescriptor = baseClass.getDescriptor()
val baseDescriptor = baseClass.descriptor.value
if (baseDescriptor != null) DescriptorUtils.getFqName(baseDescriptor).asString() else null
} else {
baseClass.qualifiedName
}
val thisDescriptor = getDescriptor()
val thisDescriptor = descriptor.value
return qualifiedName != null && thisDescriptor != null && checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep)
}
@@ -75,8 +75,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
private val _deprecated by lazyPub { classOrObject.isDeprecated(support) }
private val descriptor = lazyPub { getDescriptor() }
override fun isFinal(isFinalByPsi: Boolean) = if (tooComplex) super.isFinal(isFinalByPsi) else isFinalByPsi
@Volatile
@@ -104,7 +102,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
override fun getModifierList(): PsiModifierList? = _modifierList
private fun allSuperTypes() =
getDescriptor()?.typeConstructor?.supertypes.orEmpty()
descriptor.value?.typeConstructor?.supertypes.orEmpty()
private fun mapSupertype(supertype: KotlinType, kotlinCollectionAsIs: Boolean = false) =
supertype.asPsiType(
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.asJava.classes
import com.intellij.lang.Language
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightMethodBuilder
import com.intellij.psi.impl.light.LightModifierList
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.asJava.elements.convertToLightAnnotationMemberValue
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.REIFIED_KEYWORD
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -26,6 +28,7 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
@@ -35,6 +38,7 @@ import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_
import org.jetbrains.kotlin.resolve.jvm.annotations.STRICTFP_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.annotations.SYNCHRONIZED_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.util.isOrdinaryClass
internal class UltraLightMembersCreator(
private val containingClass: KtLightClass,
@@ -232,6 +236,69 @@ internal class UltraLightMembersCreator(
private fun DeclarationDescriptor.getterIfProperty() =
if (this@getterIfProperty is PropertyDescriptor) this@getterIfProperty.getter else this@getterIfProperty
private inner class UltraLightModifierListForMember(
private val declaration: KtDeclaration,
private val accessedProperty: KtProperty?,
private val outerDeclaration: KtDeclaration,
private val forceStatic: Boolean,
private val forcePrivate: Boolean = false
) : LightModifierList(declaration.manager, declaration.language) {
override fun hasModifierProperty(name: String): Boolean {
val modifierResult = hasModifier(name)
//AllOpen can affect on modality of the member. We ought to check if the extension could override the modality
if (name != PsiModifier.FINAL) return modifierResult
if (!outerDeclaration.isOrdinaryClass) return modifierResult
// Resolver will produce correct descriptor corresponding to modality from AllOpen.
// The easiest way to get new modality is to resolve the descriptor
return (declaration.resolve() as? CallableMemberDescriptor)?.modality == Modality.FINAL
}
private fun hasModifier(name: String): Boolean {
if (name == PsiModifier.PUBLIC || name == PsiModifier.PROTECTED || name == PsiModifier.PRIVATE) {
if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) {
return name == PsiModifier.PRIVATE
}
if (declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || accessedProperty?.hasModifier(KtTokens.PROTECTED_KEYWORD) == true) {
return name == PsiModifier.PROTECTED
}
if (outerDeclaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
when ((outerDeclaration.resolve() as? CallableDescriptor)?.visibility) {
Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC
Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE
Visibilities.PROTECTED -> return name == PsiModifier.PROTECTED
}
}
return name == PsiModifier.PUBLIC
}
return when (name) {
PsiModifier.FINAL -> !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration)
PsiModifier.ABSTRACT -> containingClass.isInterface || outerDeclaration.hasModifier(KtTokens.ABSTRACT_KEYWORD)
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outerDeclaration.isJvmStatic(support) || declaration.isJvmStatic(support))
PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
else -> false
}
}
private fun KtDeclaration.isPrivate() =
hasModifier(KtTokens.PRIVATE_KEYWORD) || this is KtConstructor<*> && containingClassIsSealed || isInlineOnly()
private fun KtDeclaration.isInlineOnly(): Boolean {
if (this !is KtCallableDeclaration || !hasModifier(KtTokens.INLINE_KEYWORD)) return false
if (annotationEntries.isEmpty()) return false
val descriptor = resolve() as? CallableMemberDescriptor ?: return false
return descriptor.isInlineOnly()
}
}
private fun lightMethod(
name: String,
declaration: KtDeclaration,
@@ -247,52 +314,7 @@ internal class UltraLightMembersCreator(
return LightMethodBuilder(
manager, language, name,
LightParameterListBuilder(manager, language),
object : LightModifierList(manager, language) {
override fun hasModifierProperty(name: String): Boolean {
if (name == PsiModifier.PUBLIC || name == PsiModifier.PROTECTED || name == PsiModifier.PRIVATE) {
if (forcePrivate || declaration.isPrivate() || accessedProperty?.isPrivate() == true) {
return name == PsiModifier.PRIVATE
}
if (declaration.hasModifier(KtTokens.PROTECTED_KEYWORD) || accessedProperty?.hasModifier(KtTokens.PROTECTED_KEYWORD) == true) {
return name == PsiModifier.PROTECTED
}
if (outer.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
when ((outer.resolve() as? CallableDescriptor)?.visibility) {
Visibilities.PUBLIC -> return name == PsiModifier.PUBLIC
Visibilities.PRIVATE -> return name == PsiModifier.PRIVATE
Visibilities.PROTECTED -> return name == PsiModifier.PROTECTED
}
}
return name == PsiModifier.PUBLIC
}
return when (name) {
PsiModifier.FINAL -> !containingClass.isInterface && outer !is KtConstructor<*> && isFinal(outer)
PsiModifier.ABSTRACT -> containingClass.isInterface || outer.hasModifier(KtTokens.ABSTRACT_KEYWORD)
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outer.isJvmStatic(support) || declaration.isJvmStatic(
support
))
PsiModifier.STRICTFP -> declaration is KtFunction && declaration.hasAnnotation(STRICTFP_ANNOTATION_FQ_NAME)
PsiModifier.SYNCHRONIZED -> declaration is KtFunction && declaration.hasAnnotation(SYNCHRONIZED_ANNOTATION_FQ_NAME)
else -> false
}
}
fun KtDeclaration.isPrivate() =
hasModifier(KtTokens.PRIVATE_KEYWORD) ||
this is KtConstructor<*> && containingClassIsSealed || isInlineOnly()
private fun KtDeclaration.isInlineOnly(): Boolean {
if (this !is KtCallableDeclaration || !hasModifier(KtTokens.INLINE_KEYWORD)) return false
if (annotationEntries.isEmpty()) return false
val descriptor = resolve() as? CallableMemberDescriptor ?: return false
return descriptor.isInlineOnly()
}
}
UltraLightModifierListForMember(declaration, accessedProperty, outer, forceStatic, forcePrivate)
).setConstructor(declaration is KtConstructor<*>)
}