[light classes] support DefaultImpls in ulc

^KT-48773
This commit is contained in:
Dmitry Gridin
2022-06-13 21:28:00 +02:00
committed by Space
parent 20a9314b0b
commit f42528e354
8 changed files with 245 additions and 33 deletions
@@ -227,10 +227,12 @@ abstract class KtLightClassForSourceDeclaration(
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
@@ -314,11 +316,14 @@ abstract class KtLightClassForSourceDeclaration(
}
if (classOrObject.hasInterfaceDefaultImpls && jvmDefaultMode != JvmDefaultMode.ALL_INCOMPATIBLE) {
result.add(KtLightClassForInterfaceDefaultImpls(classOrObject))
result.add(createClassForInterfaceDefaultImpls())
}
return result
}
protected open fun createClassForInterfaceDefaultImpls(): PsiClass = KtLightClassForInterfaceDefaultImpls(classOrObject)
override fun getUseScope(): SearchScope = kotlinOrigin.useScope
override fun getElementType(): IStubElementType<out StubElement<*>, *>? = classOrObject.elementType
@@ -398,6 +403,7 @@ abstract class KtLightClassForSourceDeclaration(
return when {
!classOrObject.safeIsLocal() && containingScript != null ->
KtLightClassForScript.getLightClassCachedValue(containingScript).value
else ->
getLightClassCachedValue(classOrObject).value
}
@@ -0,0 +1,153 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.*
import com.intellij.psi.impl.PsiClassImplUtil
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.util.IncorrectOperationException
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KtUltraLightClassForInterfaceDefaultImpls(classOrObject: KtClassOrObject, support: KtUltraLightSupport) :
KtUltraLightClass(classOrObject, support) {
override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { "$it.${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" }
override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME
override fun getParent() = containingClass
override fun copy(): KtUltraLightClassForInterfaceDefaultImpls = KtUltraLightClassForInterfaceDefaultImpls(
classOrObject.copy() as KtClassOrObject,
support,
)
override fun getInterfaces(): Array<PsiClass> = emptyArray()
override fun createExtendsList(): PsiReferenceList? = null
override fun createImplementsList(): PsiReferenceList? = null
override fun getSuperClass(): PsiClass? = PsiClassImplUtil.getSuperClass(this)
override fun getSupers(): Array<PsiClass> = PsiClassImplUtil.getSuperClass(this)?.let { arrayOf(it) } ?: emptyArray()
override fun getSuperTypes(): Array<PsiClassType> = arrayOf(PsiType.getJavaLangObject(manager, resolveScope))
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
override fun computeModifiers(): Set<String> = publicStaticFinal
override fun getOwnFields(): List<KtLightField> = emptyList()
override fun isInterface(): Boolean = false
override fun isDeprecated(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isEnum(): Boolean = false
override fun isFinal(isFinalByPsi: Boolean): Boolean = true
override fun hasTypeParameters(): Boolean = false
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean =
baseClass.qualifiedName == CommonClassNames.JAVA_LANG_OBJECT
override fun setName(name: String): PsiElement =
throw IncorrectOperationException("Impossible to rename ${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}")
override fun getContainingClass(): KtLightClassForSourceDeclaration? = create(classOrObject, jvmDefaultMode)
override fun getOwnInnerClasses() = emptyList<PsiClass>()
override fun getOwnMethods(): List<KtLightMethod> = _ownMethods.value
private val membersBuilder by lazyPub {
UltraLightMembersCreator(
this,
false,
classOrObject.hasModifier(KtTokens.SEALED_KEYWORD),
mangleInternalFunctions = true,
support = support,
)
}
private fun ownMethods(): List<KtLightMethod> {
val interfaceType by lazy {
JavaPsiFacade.getElementFactory(project).createType(containingClass!!)
}
val result = mutableListOf<KtLightMethod>()
fun processClass(psiClass: PsiClass) {
val declarations = psiClass.safeAs<KtUltraLightClass>()
?.kotlinOrigin
?.declarations
?.filterNot { it.isHiddenByDeprecation(support) }
.orEmpty()
for (declaration in declarations) {
when (declaration) {
is KtNamedFunction -> {
if (declaration.hasBody()) {
result.addAll(
membersBuilder.createMethods(declaration, forceStatic = true, forceNonFinal = true) {
KtUltraLightReceiverParameterForDefaultImpls(support, it) { interfaceType }
}
)
}
}
is KtProperty -> {
if (declaration.accessors.any(KtPropertyAccessor::hasBody)) {
result.addAll(
membersBuilder.propertyAccessors(
declaration,
declaration.isVar,
forceStatic = true,
onlyJvmStatic = false,
forceNonFinal = true,
) {
KtUltraLightReceiverParameterForDefaultImpls(support, it) { interfaceType }
}
)
}
}
}
}
for (superClass in psiClass.interfaces) {
processClass(superClass)
}
}
containingClass?.let { processClass(it) }
return result
}
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
/* provider = */
{
CachedValueProvider.Result.create(
ownMethods(),
classOrObject.getExternalDependencies()
)
},
/* trackValue = */ false,
)
}
internal class KtUltraLightReceiverParameterForDefaultImpls(
support: KtUltraLightSupport,
method: KtUltraLightMethod,
private val typeGetter: () -> PsiType,
) : KtUltraLightParameter(AsmUtil.THIS_IN_DEFAULT_IMPLS, null, support, method) {
override fun getType(): PsiType = typeGetter()
override fun isVarArgs(): Boolean = false
override val qualifiedNameForNullabilityAnnotation: String = NotNull::class.java.name
}
private val publicStaticFinal = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -521,6 +521,8 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
superOwnInnerClasses
}
override fun createClassForInterfaceDefaultImpls(): PsiClass = KtUltraLightClassForInterfaceDefaultImpls(classOrObject, support)
private val shouldGenerateRepeatableAnnotationContainer: Boolean
get() = isAnnotationType &&
classOrObject.hasAnnotation(StandardNames.FqNames.repeatable) &&
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.convertToLightAnnotationMemberValue
import org.jetbrains.kotlin.builtins.StandardNames.DEFAULT_VALUE_PARAMETER
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
@@ -80,6 +79,7 @@ internal class UltraLightMembersCreator(
val declaration = property?.setter ?: variable
declaration.simpleVisibility()
}
else -> PsiModifier.PRIVATE
}
val modifiers = hashSetOf(visibility)
@@ -115,7 +115,9 @@ internal class UltraLightMembersCreator(
fun createMethods(
ktFunction: KtFunction,
forceStatic: Boolean,
forcePrivate: Boolean = false
forcePrivate: Boolean = false,
forceNonFinal: Boolean = false,
additionalReceiverParameter: ((KtUltraLightMethod) -> KtUltraLightParameter)? = null,
): Collection<KtLightMethod> {
if (ktFunction.hasExpectModifier()
@@ -124,7 +126,14 @@ internal class UltraLightMembersCreator(
) return emptyList()
var methodIndex = METHOD_INDEX_BASE
val basicMethod = asJavaMethod(ktFunction, forceStatic, forcePrivate, methodIndex = methodIndex)
val basicMethod = asJavaMethod(
ktFunction,
forceStatic,
forcePrivate,
methodIndex = methodIndex,
forceNonFinal = forceNonFinal,
additionalReceiverParameter = additionalReceiverParameter,
)
val result = mutableListOf(basicMethod)
@@ -138,7 +147,9 @@ internal class UltraLightMembersCreator(
forceStatic,
forcePrivate,
numberOfDefaultParametersToAdd = numberOfDefaultParametersToAdd,
methodIndex = methodIndex
methodIndex = methodIndex,
forceNonFinal = forceNonFinal,
additionalReceiverParameter = additionalReceiverParameter,
)
)
}
@@ -174,7 +185,9 @@ internal class UltraLightMembersCreator(
forceStatic: Boolean,
forcePrivate: Boolean,
numberOfDefaultParametersToAdd: Int = -1,
methodIndex: Int
methodIndex: Int,
forceNonFinal: Boolean = false,
additionalReceiverParameter: ((KtUltraLightMethod) -> KtUltraLightParameter)? = null,
): KtLightMethod {
ProgressManager.checkCanceled()
val isConstructor = ktFunction is KtConstructor<*>
@@ -182,8 +195,13 @@ internal class UltraLightMembersCreator(
if (isConstructor) containingClass.name
else computeMethodName(ktFunction, ktFunction.name ?: SpecialNames.NO_NAME_PROVIDED.asString(), MethodType.REGULAR)
val method = lightMethod(name.orEmpty(), ktFunction, forceStatic, forcePrivate)
val method = lightMethod(name.orEmpty(), ktFunction, forceStatic, forcePrivate, forceNonFinal)
val wrapper = KtUltraLightMethodForSourceDeclaration(method, ktFunction, support, containingClass, methodIndex)
additionalReceiverParameter?.let {
val receiver = it(wrapper)
method.addParameter(receiver)
}
addReceiverParameter(ktFunction, wrapper, method)
var remainingNumberOfDefaultParametersToAdd =
@@ -259,7 +277,8 @@ internal class UltraLightMembersCreator(
private val accessedProperty: KtProperty?,
private val outerDeclaration: KtDeclaration,
private val forceStatic: Boolean,
private val forcePrivate: Boolean = false
private val forcePrivate: Boolean = false,
private val forceNonFinal: Boolean = false,
) : LightModifierList(declaration.manager, declaration.language) {
override fun hasModifierProperty(name: String): Boolean {
@@ -301,10 +320,13 @@ internal class UltraLightMembersCreator(
}
return when (name) {
PsiModifier.FINAL -> !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration)
PsiModifier.FINAL ->
!forceNonFinal && !containingClass.isInterface && outerDeclaration !is KtConstructor<*> && isFinal(outerDeclaration)
PsiModifier.ABSTRACT -> containingClass.isInterface || outerDeclaration.hasModifier(ABSTRACT_KEYWORD)
PsiModifier.STATIC -> forceStatic || containingClassIsNamedObject && (outerDeclaration.isJvmStatic(support) || declaration
.isJvmStatic(support))
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)
PsiModifier.NATIVE -> declaration is KtFunction && declaration.hasModifier(EXTERNAL_KEYWORD)
@@ -329,7 +351,8 @@ internal class UltraLightMembersCreator(
name: String,
declaration: KtDeclaration,
forceStatic: Boolean,
forcePrivate: Boolean = false
forcePrivate: Boolean = false,
forceNonFinal: Boolean = false,
): LightMethodBuilder {
val accessedProperty = if (declaration is KtPropertyAccessor) declaration.property else null
val outer = accessedProperty ?: declaration
@@ -340,7 +363,7 @@ internal class UltraLightMembersCreator(
return LightMethodBuilder(
manager, language, name,
LightParameterListBuilder(manager, language),
UltraLightModifierListForMember(declaration, accessedProperty, outer, forceStatic, forcePrivate)
UltraLightModifierListForMember(declaration, accessedProperty, outer, forceStatic, forcePrivate, forceNonFinal)
).setConstructor(declaration is KtConstructor<*>)
}
@@ -410,6 +433,8 @@ internal class UltraLightMembersCreator(
onlyJvmStatic: Boolean,
createAsAnnotationMethod: Boolean = false,
isJvmRecord: Boolean = false,
forceNonFinal: Boolean = false,
additionalReceiverParameter: ((KtUltraLightMethod) -> KtUltraLightParameter)? = null,
): List<KtLightMethod> {
val propertyName = declaration.name ?: return emptyList()
@@ -460,18 +485,28 @@ internal class UltraLightMembersCreator(
val defaultGetterName = if (createAsAnnotationMethod || isJvmRecord) propertyName else JvmAbi.getterName(propertyName)
val getterName = computeMethodName(auxiliaryOrigin, defaultGetterName, MethodType.GETTER)
val getterPrototype = lightMethod(getterName, auxiliaryOrigin, forceStatic = onlyJvmStatic || forceStatic)
val getterPrototype = lightMethod(
getterName,
auxiliaryOrigin,
forceStatic = onlyJvmStatic || forceStatic,
forceNonFinal = forceNonFinal,
)
val getterWrapper = KtUltraLightMethodForSourceDeclaration(
getterPrototype,
lightMemberOrigin,
support,
containingClass,
forceToSkipNullabilityAnnotation = createAsAnnotationMethod,
methodIndex = METHOD_INDEX_FOR_GETTER
methodIndex = METHOD_INDEX_FOR_GETTER,
)
val getterType: PsiType by lazyPub { methodReturnType(declaration, getterWrapper, isSuspendFunction = false) }
getterPrototype.setMethodReturnType { getterType }
additionalReceiverParameter?.invoke(getterWrapper)?.let {
getterPrototype.addParameter(it)
}
addReceiverParameter(declaration, getterWrapper, getterPrototype)
val defaultExpression = if (createAsAnnotationMethod && declaration is KtParameter) declaration.defaultValue else null
@@ -491,16 +526,25 @@ internal class UltraLightMembersCreator(
)
val setterName = computeMethodName(auxiliaryOrigin, JvmAbi.setterName(propertyName), MethodType.SETTER)
val setterPrototype = lightMethod(setterName, auxiliaryOrigin, forceStatic = onlyJvmStatic || forceStatic)
.setMethodReturnType(PsiType.VOID)
val setterPrototype = lightMethod(
setterName,
auxiliaryOrigin,
forceStatic = onlyJvmStatic || forceStatic,
forceNonFinal = forceNonFinal,
).setMethodReturnType(PsiType.VOID)
val setterWrapper = KtUltraLightMethodForSourceDeclaration(
setterPrototype,
lightMemberOrigin,
support,
containingClass,
methodIndex = METHOD_INDEX_FOR_SETTER
methodIndex = METHOD_INDEX_FOR_SETTER,
)
additionalReceiverParameter?.invoke(setterWrapper)?.let {
setterPrototype.addParameter(it)
}
addReceiverParameter(declaration, setterWrapper, setterPrototype)
val setterParameter = ktSetter?.parameter
setterPrototype.addParameter(
@@ -1,10 +1,10 @@
public abstract interface B /* p.B*/ extends p.A {
public abstract interface C /* p.C*/ extends p.B {
@org.jetbrains.annotations.NotNull()
public abstract java.lang.String b();// b()
public abstract java.lang.String c();// c()
public static final class DefaultImpls /* p.B.DefaultImpls*/ extends p.A {
public static final class DefaultImpls /* p.C.DefaultImpls*/ extends p.B {
@org.jetbrains.annotations.NotNull()
public java.lang.String b();// b()
public java.lang.String c();// c()
}}
}}
@@ -1,13 +1,16 @@
public abstract interface B /* p.B*/ extends p.A {
public abstract interface C /* p.C*/ extends p.B {
@org.jetbrains.annotations.NotNull()
public abstract java.lang.String b();// b()
public abstract java.lang.String c();// c()
public static final class DefaultImpls /* p.B.DefaultImpls*/ {
public static final class DefaultImpls /* p.C.DefaultImpls*/ {
@org.jetbrains.annotations.NotNull()
public static java.lang.String a(@org.jetbrains.annotations.NotNull() p.B);// a(p.B)
public static java.lang.String a(@org.jetbrains.annotations.NotNull() p.C);// a(p.C)
@org.jetbrains.annotations.NotNull()
public static java.lang.String b(@org.jetbrains.annotations.NotNull() p.B);// b(p.B)
public static java.lang.String b(@org.jetbrains.annotations.NotNull() p.C);// b(p.C)
@org.jetbrains.annotations.NotNull()
public static java.lang.String c(@org.jetbrains.annotations.NotNull() p.C);// c(p.C)
}}
@@ -1,4 +1,4 @@
// p.B
// p.C
package p
interface A {
@@ -9,6 +9,10 @@ interface B: A {
fun b() = "b"
}
interface C : B {
fun c() = "c"
}
// TODO: could be lazy
// see KT-22819
// LAZINESS:NoLaziness
@@ -1,10 +1,10 @@
public abstract interface PrivateInTrait /* PrivateInTrait*/ {
public static final class DefaultImpls /* PrivateInTrait.DefaultImpls*/ {
private static java.lang.String getN(PrivateInTrait);// getN(PrivateInTrait)
private static java.lang.String getN(@org.jetbrains.annotations.NotNull() PrivateInTrait);// getN(PrivateInTrait)
private static java.lang.String getNn(PrivateInTrait);// getNn(PrivateInTrait)
private static java.lang.String getNn(@org.jetbrains.annotations.NotNull() PrivateInTrait);// getNn(PrivateInTrait)
private static void setNn(PrivateInTrait, java.lang.String);// setNn(PrivateInTrait, java.lang.String)
private static void setNn(@org.jetbrains.annotations.NotNull() PrivateInTrait, java.lang.String);// setNn(PrivateInTrait, java.lang.String)
}}