Support delegating to interfaces in ultra-light classes

This commit is contained in:
Denis Zharkov
2018-12-04 11:15:56 +03:00
parent dbf9ff29a9
commit 52d5143dd7
4 changed files with 34 additions and 5 deletions
@@ -18,9 +18,11 @@ import org.jetbrains.kotlin.asJava.builder.LightClassData
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
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.kotlinType
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
@@ -33,6 +35,7 @@ import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DelegationResolver
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
@@ -293,6 +296,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
}
addMethodsFromDataClass(result)
addDelegatesToInterfaceMethods(result)
result
}
@@ -332,6 +336,28 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
}.generate()
}
private fun addDelegatesToInterfaceMethods(result: MutableList<KtLightMethod>) {
classOrObject.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>().forEach {
addDelegatesToInterfaceMethods(it, result)
}
}
private fun addDelegatesToInterfaceMethods(superTypeEntry: KtDelegatedSuperTypeEntry, result: MutableList<KtLightMethod>) {
val classDescriptor = classOrObject.resolve() as? ClassDescriptor ?: return
val typeReference = superTypeEntry.typeReference ?: return
val bindingContext = typeReference.analyze()
val superClassDescriptor = CodegenUtil.getSuperClassBySuperTypeListEntry(superTypeEntry, bindingContext) ?: return
val delegationType = superTypeEntry.delegateExpression.kotlinType(bindingContext) ?: return
for (delegate in DelegationResolver.getDelegates(classDescriptor, superClassDescriptor, delegationType).keys) {
when (delegate) {
is PropertyDescriptor -> delegate.accessors.mapTo(result, this::createGeneratedMethodFromDescriptor)
is FunctionDescriptor -> result.add(createGeneratedMethodFromDescriptor(delegate))
}
}
}
private fun createConstructors(): List<KtLightMethod> {
val result = arrayListOf<KtLightMethod>()
val constructors = classOrObject.allConstructors
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.resolve.BindingContext
@@ -130,7 +131,7 @@ internal fun KtDeclaration.getKotlinType(): KotlinType? {
}
internal fun KtDeclaration.resolve() = LightClassGenerationSupport.getInstance(project).resolveToDescriptor(this)
internal fun KtDeclaration.analyze() = LightClassGenerationSupport.getInstance(project).analyze(this)
internal fun KtElement.analyze() = LightClassGenerationSupport.getInstance(project).analyze(this)
// copy-pasted from kotlinInternalUastUtils.kt and post-processed
internal fun KotlinType.asPsiType(
@@ -233,7 +234,7 @@ fun KtUltraLightClass.createGeneratedMethodFromDescriptor(
private fun KtUltraLightClass.lightMethod(
descriptor: FunctionDescriptor
): LightMethodBuilder {
val name = descriptor.name.asString()
val name = typeMapper(support).mapFunctionName(descriptor, OwnerKind.IMPLEMENTATION)
val accessFlags: Int by lazyPub {
val asmFlags = AsmUtil.getMethodAsmFlags(descriptor, OwnerKind.IMPLEMENTATION, support.deprecationResolver)
@@ -2,6 +2,11 @@
interface Base {
fun printMessage()
fun printMessageLine()
val x: Int
var y: Int
fun String.foo(y: Any?): Int
}
class BaseImpl(val x: Int) : Base {
@@ -9,7 +14,6 @@ class BaseImpl(val x: Int) : Base {
override fun printMessageLine() { println(x) }
}
/** should load cls */
class Derived(b: Base) : Base by b {
override fun printMessage() { print("abc") }
}
@@ -122,8 +122,6 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
if (declaration is KtClassOrObject) {
declaration.superTypeListEntries.find { it is KtDelegatedSuperTypeEntry }?.let { return it }
declaration.primaryConstructor?.let { findTooComplexDeclaration(it) }?.let { return it }
for (d in declaration.declarations) {