Move AllOpen UL support to separate extension

This commit is contained in:
Igor Yakovlev
2019-10-17 23:28:44 +03:00
parent 58b8d8868a
commit 8c65a9a2aa
10 changed files with 100 additions and 25 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.asJava
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
@@ -32,4 +33,10 @@ interface UltraLightClassModifierExtension {
containingDeclaration: KtUltraLightClass,
fieldsList: MutableList<KtLightField>
) = Unit
fun interceptModalityBuilding(
declaration: KtDeclaration,
descriptor: Lazy<DeclarationDescriptor?>,
modifier: String
) = modifier
}
@@ -42,10 +42,7 @@ 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
@@ -230,10 +227,12 @@ abstract class KtLightClassForSourceDeclaration(
if (isAbstract() || isSealed()) {
psiModifiers.add(PsiModifier.ABSTRACT)
} else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is KtClass && classOrObject.isEnum()))) {
// 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
if (!kotlinOrigin.isOrdinaryClass || getDescriptor()?.modality != Modality.OPEN) {
val descriptor = lazy { getDescriptor() }
var modifier = PsiModifier.FINAL
project.applyCompilerPlugins {
modifier = it.interceptModalityBuilding(kotlinOrigin, descriptor, modifier)
}
if (modifier == PsiModifier.FINAL) {
psiModifiers.add(PsiModifier.FINAL)
}
}
@@ -197,7 +197,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
fun ArrayList<KtLightField>.updateWithCompilerPlugins() = also {
val lazyDescriptor = lazy { getDescriptor() }
applyCompilerPlugins {
project.applyCompilerPlugins {
it.interceptFieldsBuilding(
declaration = kotlinOrigin,
descriptor = lazyDescriptor,
@@ -309,7 +309,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
addDelegatesToInterfaceMethods(result)
val lazyDescriptor = lazy { getDescriptor() }
applyCompilerPlugins {
project.applyCompilerPlugins {
it.interceptMethodsBuilding(
declaration = kotlinOrigin,
descriptor = lazyDescriptor,
@@ -321,10 +321,6 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
return result
}
private inline fun applyCompilerPlugins(body: (UltraLightClassModifierExtension) -> Unit) {
UltraLightClassModifierExtension.getInstances(project).forEach { body(it) }
}
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
{
CachedValueProvider.Result.create(
@@ -246,14 +246,15 @@ internal class UltraLightMembersCreator(
override fun hasModifierProperty(name: String): Boolean {
val modifierResult = hasModifier(name)
if (name != PsiModifier.FINAL || !outerDeclaration.isOrdinaryClass) return 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
val descriptor = lazy { declaration.resolve() }
var modifier = PsiModifier.FINAL
project.applyCompilerPlugins {
modifier = it.interceptModalityBuilding(declaration, descriptor, modifier)
}
return modifier == PsiModifier.FINAL
}
private fun hasModifier(name: String): Boolean {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.asJava.classes
import com.google.common.collect.Lists
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.cache.ModifierFlags
import com.intellij.psi.impl.cache.TypeInfo
@@ -16,6 +17,7 @@ import com.intellij.psi.impl.light.*
import com.intellij.util.BitUtil.isSet
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
@@ -390,5 +392,9 @@ fun KotlinType.tryResolveMarkerInterfaceFQName(): String? {
return null
}
internal inline fun Project.applyCompilerPlugins(body: (UltraLightClassModifierExtension) -> Unit) {
UltraLightClassModifierExtension.getInstances(this).forEach { body(it) }
}
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}")