Minor: DeclarationsGenerator can take care of secondary constructor delegating to 'super'.

This commit is contained in:
Dmitry Petrov
2016-08-30 13:14:31 +03:00
committed by Dmitry Petrov
parent a140d75016
commit f83237498f
4 changed files with 32 additions and 27 deletions
@@ -20,6 +20,10 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi2ir.generators.getResolvedCall
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
@@ -56,3 +60,10 @@ fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean {
return false
}
fun KtSecondaryConstructor.isConstructorDelegatingToSuper(bindingContext: BindingContext): Boolean {
val delegatingResolvedCall = getDelegationCall().getResolvedCall(bindingContext) ?: return false
val constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, this) ?: return false
val ownerClassDescriptor = constructorDescriptor.containingDeclaration
val targetClassDescriptor = delegatingResolvedCall.resultingDescriptor.containingDeclaration
return targetClassDescriptor != ownerClassDescriptor
}
@@ -130,13 +130,13 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
return irBlockBody
}
fun generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor: KtSecondaryConstructor, ktClassOrObject: KtClassOrObject): IrBody {
val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset)
fun generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor: KtSecondaryConstructor): IrBody {
val irBlockBody = IrBlockBodyImpl(ktConstructor.startOffset, ktConstructor.endOffset)
generateDelegatingConstructorCall(irBlockBody, ktConstructor)
irBlockBody.addStatement(IrNestedInitializersCallImpl(ktConstructor.startOffset, ktConstructor.endOffset,
getOrFail(BindingContext.CLASS, ktClassOrObject)))
val classDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor).containingDeclaration
irBlockBody.addStatement(IrNestedInitializersCallImpl(ktConstructor.startOffset, ktConstructor.endOffset, classDescriptor))
ktConstructor.bodyExpression?.let { ktBody ->
createStatementGenerator().generateBlockBodyStatements(irBlockBody, ktBody)
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl
@@ -27,6 +26,7 @@ import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper
import org.jetbrains.kotlin.resolve.BindingContext
class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator {
@@ -40,15 +40,21 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
generatePropertiesDeclaredInPrimaryConstructor(irClass, ktClassOrObject)
val shouldGenerateNestedInitializers = generateMembersDeclaredInClassBody(irClass, ktClassOrObject)
generateMembersDeclaredInClassBody(irClass, ktClassOrObject)
if (shouldGenerateNestedInitializers) {
if (shouldGenerateNestedInitializers(ktClassOrObject)) {
irClass.nestedInitializers = BodyGenerator(descriptor, context).generateNestedInitializersBody(ktClassOrObject)
}
return irClass
}
private fun shouldGenerateNestedInitializers(ktClassOrObject: KtClassOrObject): Boolean {
val ktClassBody = ktClassOrObject.getBody() ?: return false
return ktClassBody.declarations.any { it is KtSecondaryConstructor && it.isConstructorDelegatingToSuper(context.bindingContext) }
}
private fun generatePrimaryConstructor(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
val primaryConstructorDescriptor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: return
@@ -70,20 +76,12 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
}
}
private fun generateMembersDeclaredInClassBody(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject): Boolean {
var hasConstructorsWithNestedInitializersCall = false
private fun generateMembersDeclaredInClassBody(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) {
ktClassOrObject.getBody()?.let { ktClassBody ->
for (ktDeclaration in ktClassBody.declarations) {
if (ktDeclaration is KtAnonymousInitializer) continue
val irMember =
if (ktDeclaration is KtSecondaryConstructor && isConstructorDelegatingToSuper(ktDeclaration, irClass.descriptor)) {
hasConstructorsWithNestedInitializersCall = true
declarationGenerator.generateSecondaryConstructorWithNestedInitializers(ktDeclaration, ktClassOrObject)
}
else
declarationGenerator.generateMemberDeclaration(ktDeclaration)
val irMember = declarationGenerator.generateMemberDeclaration(ktDeclaration)
irClass.addMember(irMember)
if (irMember is IrProperty) {
@@ -92,14 +90,6 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator
}
}
}
return hasConstructorsWithNestedInitializersCall
}
private fun isConstructorDelegatingToSuper(ktConstructor: KtSecondaryConstructor, classOwner: ClassDescriptor): Boolean {
val delegatingResolvedCall = getResolvedCall(ktConstructor.getDelegationCall())!!
val calleeOwner = delegatingResolvedCall.resultingDescriptor.containingDeclaration as ClassDescriptor
return calleeOwner != classOwner
}
private fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter): IrDeclaration {
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper
import org.jetbrains.kotlin.resolve.BindingContext
class DeclarationGenerator(override val context: GeneratorContext) : Generator {
@@ -59,6 +60,9 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
}
fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor) : IrFunction {
if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext)) {
return generateSecondaryConstructorWithNestedInitializers(ktConstructor)
}
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor)
val body = createBodyGenerator(constructorDescriptor).generateSecondaryConstructorBody(ktConstructor)
return IrFunctionImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED,
@@ -66,9 +70,9 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
}
fun generateSecondaryConstructorWithNestedInitializers(ktConstructor: KtSecondaryConstructor, ktClassOrObject: KtClassOrObject): IrDeclaration {
private fun generateSecondaryConstructorWithNestedInitializers(ktConstructor: KtSecondaryConstructor): IrFunction {
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor)
val body = createBodyGenerator(constructorDescriptor).generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor, ktClassOrObject)
val body = createBodyGenerator(constructorDescriptor).generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor)
return IrFunctionImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED,
constructorDescriptor, body)
}