From f83237498f64e51d4c18fac4b42fcfa82d5e7cb4 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 30 Aug 2016 13:14:31 +0300 Subject: [PATCH] Minor: DeclarationsGenerator can take care of secondary constructor delegating to 'super'. --- .../jetbrains/kotlin/psi2ir/KotlinUtils.kt | 11 +++++++ .../kotlin/psi2ir/generators/BodyGenerator.kt | 8 ++--- .../psi2ir/generators/ClassGenerator.kt | 32 +++++++------------ .../psi2ir/generators/DeclarationGenerator.kt | 8 +++-- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt index 0e6ba89d8a5..c460465d04d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt @@ -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 +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index 5a59bdc5d58..dd79af5570c 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -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) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index e03c6b4a1e3..662b95120e5 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -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 { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index 2b655b4a9e1..12941ff62bb 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -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) }