Generate IR for synthetic nested classes directly in class generator

This commit is contained in:
Leonid Startsev
2018-07-09 17:07:43 +03:00
parent c3f66cda65
commit ba9b7547b0
9 changed files with 87 additions and 50 deletions
@@ -164,6 +164,7 @@ class SyntheticClassOrObjectDescriptor(
// in theory `containingKtFile` is `@NotNull` but in practice EA-114080
_parent.containingKtFile ?: throw IllegalStateException("containingKtFile was null for $_parent of ${_parent.javaClass}")
override fun getBody(): KtClassBody? = null
}
}
@@ -22,10 +22,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.name.Name
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.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
@@ -85,3 +82,6 @@ val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor?
val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor?
get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter
val KtPureElement?.pureStartOffsetOrUndefined get() = this?.psiOrParent?.startOffset ?: UNDEFINED_OFFSET
val KtPureElement?.pureEndOffsetOrUndefined get() = this?.psiOrParent?.endOffset ?: UNDEFINED_OFFSET
@@ -25,7 +25,10 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -176,15 +179,15 @@ class BodyGenerator(
fun getLoop(expression: KtExpression): IrLoop? =
loopTable[expression]
fun generatePrimaryConstructorBody(ktClassOrObject: KtClassOrObject): IrBody {
val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset)
fun generatePrimaryConstructorBody(ktClassOrObject: KtPureClassOrObject): IrBody {
val irBlockBody = IrBlockBodyImpl(ktClassOrObject.pureStartOffset, ktClassOrObject.pureEndOffset)
generateSuperConstructorCall(irBlockBody, ktClassOrObject)
val classDescriptor = (scopeOwner as ClassConstructorDescriptor).containingDeclaration
irBlockBody.statements.add(
IrInstanceInitializerCallImpl(
ktClassOrObject.startOffset, ktClassOrObject.endOffset,
ktClassOrObject.pureStartOffset, ktClassOrObject.pureEndOffset,
context.symbolTable.referenceClass(classDescriptor),
context.irBuiltIns.unitType
)
@@ -214,11 +217,12 @@ class BodyGenerator(
return irBlockBody
}
private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) {
val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtPureClassOrObject) {
val classDescriptor = ktClassOrObject.findClassDescriptor(context.bindingContext)
when (classDescriptor.kind) {
ClassKind.ENUM_CLASS -> generateEnumSuperConstructorCall(irBlockBody, ktClassOrObject, classDescriptor)
// enums can't be synthetic
ClassKind.ENUM_CLASS -> generateEnumSuperConstructorCall(irBlockBody, ktClassOrObject as KtClassOrObject, classDescriptor)
ClassKind.ENUM_ENTRY -> {
irBlockBody.statements.add(
@@ -229,7 +233,8 @@ class BodyGenerator(
else -> {
val statementGenerator = createStatementGenerator()
ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList ->
// synthetic inheritance is not supported yet
(ktClassOrObject as? KtClassOrObject)?.getSuperTypeList()?.let { ktSuperTypeList ->
for (ktSuperTypeListEntry in ktSuperTypeList.entries) {
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!)
@@ -253,11 +258,11 @@ class BodyGenerator(
}
}
private fun generateAnySuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) {
private fun generateAnySuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtPureElement) {
val anyConstructor = context.builtIns.any.constructors.single()
irBlockBody.statements.add(
IrDelegatingConstructorCallImpl(
ktElement.startOffset, ktElement.endOffset,
ktElement.pureStartOffset, ktElement.pureEndOffset,
context.irBuiltIns.unitType,
context.symbolTable.referenceConstructor(anyConstructor),
anyConstructor
@@ -31,11 +31,17 @@ import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -47,10 +53,10 @@ class ClassGenerator(
declarationGenerator: DeclarationGenerator
) : DeclarationGeneratorExtension(declarationGenerator) {
fun generateClass(ktClassOrObject: KtClassOrObject): IrClass {
val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
val startOffset = ktClassOrObject.startOffset
val endOffset = ktClassOrObject.endOffset
fun generateClass(ktClassOrObject: KtPureClassOrObject): IrClass {
val classDescriptor = ktClassOrObject.findClassDescriptor(this.context.bindingContext)
val startOffset = ktClassOrObject.pureStartOffset
val endOffset = ktClassOrObject.pureEndOffset
return context.symbolTable.declareClass(
startOffset, endOffset, IrDeclarationOrigin.DEFINED, classDescriptor
@@ -73,13 +79,14 @@ class ClassGenerator(
generateDeclarationsForPrimaryConstructorParameters(irClass, irPrimaryConstructor, ktClassOrObject)
}
generateMembersDeclaredInSupertypeList(irClass, ktClassOrObject)
if (ktClassOrObject is KtClassOrObject) //todo: supertype list for synthetic declarations
generateMembersDeclaredInSupertypeList(irClass, ktClassOrObject)
generateMembersDeclaredInClassBody(irClass, ktClassOrObject)
generateFakeOverrideMemberDeclarations(irClass, ktClassOrObject)
if (irClass.isData) {
if (irClass.isData && ktClassOrObject is KtClassOrObject) {
generateAdditionalMembersForDataClass(irClass, ktClassOrObject)
}
@@ -89,7 +96,7 @@ class ClassGenerator(
}
}
private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtPureClassOrObject) {
irClass.descriptor.unsubstitutedMemberScope.getContributedDescriptors()
.mapNotNull {
it.safeAs<CallableMemberDescriptor>().takeIf {
@@ -317,7 +324,7 @@ class ClassGenerator(
EnumClassMembersGenerator(declarationGenerator).generateSpecialMembers(irClass)
}
private fun generatePrimaryConstructor(irClass: IrClass, ktClassOrObject: KtClassOrObject): IrConstructor? {
private fun generatePrimaryConstructor(irClass: IrClass, ktClassOrObject: KtPureClassOrObject): IrConstructor? {
val classDescriptor = irClass.descriptor
val primaryConstructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return null
@@ -331,7 +338,7 @@ class ClassGenerator(
private fun generateDeclarationsForPrimaryConstructorParameters(
irClass: IrClass,
irPrimaryConstructor: IrConstructor,
ktClassOrObject: KtClassOrObject
ktClassOrObject: KtPureClassOrObject
) {
ktClassOrObject.primaryConstructor?.let { ktPrimaryConstructor ->
irPrimaryConstructor.valueParameters.forEach {
@@ -349,12 +356,23 @@ class ClassGenerator(
}
}
private fun generateMembersDeclaredInClassBody(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
private fun generateMembersDeclaredInClassBody(irClass: IrClass, ktClassOrObject: KtPureClassOrObject) {
// generate real body declarations
ktClassOrObject.getBody()?.let { ktClassBody ->
ktClassBody.declarations.mapTo(irClass.declarations) { ktDeclaration ->
declarationGenerator.generateClassMemberDeclaration(ktDeclaration, irClass.descriptor)
}
}
// generate synthetic nested classes (including companion)
irClass.descriptor
.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)
.asSequence()
.filterIsInstance<SyntheticClassOrObjectDescriptor>()
.mapTo(irClass.declarations) { declarationGenerator.generateSyntheticClassOrObject(it.syntheticDeclaration) }
// synthetic functions and properties to classes must be contributed by corresponding lowering
}
fun generateEnumEntry(ktEnumEntry: KtEnumEntry): IrEnumEntry {
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.endOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.pureEndOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.pureStartOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.startOffsetOrUndefined
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -56,6 +58,10 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
)
}
fun generateSyntheticClassOrObject(syntheticDeclaration: KtPureClassOrObject): IrClass {
return generateClassOrObjectDeclaration(syntheticDeclaration)
}
fun generateClassMemberDeclaration(ktDeclaration: KtDeclaration, classDescriptor: ClassDescriptor): IrDeclaration =
when (ktDeclaration) {
is KtAnonymousInitializer ->
@@ -71,7 +77,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
private fun generateEnumEntryDeclaration(ktEnumEntry: KtEnumEntry): IrEnumEntry =
ClassGenerator(this).generateEnumEntry(ktEnumEntry)
fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass =
fun generateClassOrObjectDeclaration(ktClassOrObject: KtPureClassOrObject): IrClass =
ClassGenerator(this).generateClass(ktClassOrObject)
private fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration =
@@ -135,7 +141,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
fun generateInitializerBody(scopeOwnerSymbol: IrSymbol, ktBody: KtExpression): IrExpressionBody =
createBodyGenerator(scopeOwnerSymbol).generateExpressionBody(ktBody)
fun generateFakeOverrideDeclaration(memberDescriptor: CallableMemberDescriptor, ktElement: KtElement): IrDeclaration {
fun generateFakeOverrideDeclaration(memberDescriptor: CallableMemberDescriptor, ktElement: KtPureElement): IrDeclaration {
assert(memberDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
"Fake override expected: $memberDescriptor"
}
@@ -149,9 +155,9 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
}
}
private fun generateFakeOverrideProperty(propertyDescriptor: PropertyDescriptor, ktElement: KtElement): IrProperty {
val startOffset = ktElement.startOffset
val endOffset = ktElement.endOffset
private fun generateFakeOverrideProperty(propertyDescriptor: PropertyDescriptor, ktElement: KtPureElement): IrProperty {
val startOffset = ktElement.pureStartOffsetOrUndefined
val endOffset = ktElement.pureEndOffsetOrUndefined
val backingField =
if (propertyDescriptor.getter == null)
@@ -173,7 +179,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
)
}
private fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrSimpleFunction =
private fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtPureElement): IrSimpleFunction =
FunctionGenerator(this).generateFakeOverrideFunction(functionDescriptor, ktElement)
}
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset
import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.endOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper
import org.jetbrains.kotlin.psi2ir.startOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -58,7 +58,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
generateLambdaBody(ktFunction)
}
fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrSimpleFunction =
fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtPureElement): IrSimpleFunction =
declareSimpleFunctionInner(functionDescriptor, ktElement, IrDeclarationOrigin.FAKE_OVERRIDE).buildWithScope { irFunction ->
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null)
}
@@ -77,17 +77,17 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun declareSimpleFunctionInner(
descriptor: FunctionDescriptor,
ktElement: KtElement,
ktElement: KtPureElement,
origin: IrDeclarationOrigin
): IrSimpleFunction =
context.symbolTable.declareSimpleFunctionWithOverrides(
ktElement.startOffset, ktElement.endOffset, origin,
ktElement.pureStartOffset, ktElement.pureEndOffset, origin,
descriptor
)
fun generateFunctionParameterDeclarationsAndReturnType(
irFunction: IrFunction,
ktParameterOwner: KtElement?,
ktParameterOwner: KtPureElement?,
ktReceiverParameterElement: KtElement?
) {
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, irFunction.descriptor.propertyIfAccessor.typeParameters)
@@ -208,7 +208,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
fun generatePrimaryConstructor(
primaryConstructorDescriptor: ClassConstructorDescriptor,
ktClassOrObject: KtClassOrObject
ktClassOrObject: KtPureClassOrObject
): IrConstructor =
declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) {
if (
@@ -233,13 +233,13 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private inline fun declareConstructor(
ktConstructorElement: KtElement,
ktParametersElement: KtElement,
ktConstructorElement: KtPureElement,
ktParametersElement: KtPureElement,
constructorDescriptor: ClassConstructorDescriptor,
generateBody: BodyGenerator.() -> IrBody?
): IrConstructor =
context.symbolTable.declareConstructor(
ktConstructorElement.startOffset, ktConstructorElement.endOffset, IrDeclarationOrigin.DEFINED,
ktConstructorElement.pureStartOffset, ktConstructorElement.pureEndOffset, IrDeclarationOrigin.DEFINED,
constructorDescriptor
).buildWithScope { irConstructor ->
generateValueParameterDeclarations(irConstructor, ktParametersElement, null)
@@ -254,8 +254,8 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun generateValueParameterDeclarations(
irFunction: IrFunction,
ktParameterOwner: KtElement?,
ktReceiverParameterElement: KtElement?,
ktParameterOwner: KtPureElement?,
ktReceiverParameterElement: KtPureElement?,
withDefaultValues: Boolean = true
) {
val functionDescriptor = irFunction.descriptor
@@ -291,13 +291,13 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
private fun generateReceiverParameterDeclaration(
receiverParameterDescriptor: ReceiverParameterDescriptor,
ktElement: KtElement?
ktElement: KtPureElement?
): IrValueParameter =
declareParameter(receiverParameterDescriptor, ktElement)
private fun declareParameter(descriptor: ParameterDescriptor, ktElement: KtElement?) =
private fun declareParameter(descriptor: ParameterDescriptor, ktElement: KtPureElement?) =
context.symbolTable.declareValueParameter(
ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined,
ktElement.pureStartOffsetOrUndefined, ktElement.pureEndOffsetOrUndefined,
IrDeclarationOrigin.DEFINED,
descriptor, descriptor.type.toIrType(),
(descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType()
@@ -67,7 +67,7 @@ abstract class KtClassOrObject :
fun getAnonymousInitializers(): List<KtAnonymousInitializer> = getBody()?.anonymousInitializers.orEmpty()
fun getBody(): KtClassBody? = getStubOrPsiChild(KtStubElementTypes.CLASS_BODY)
override fun getBody(): KtClassBody? = getStubOrPsiChild(KtStubElementTypes.CLASS_BODY)
inline fun <reified T : KtDeclaration> addDeclaration(declaration: T): T {
val body = getOrCreateBody()
@@ -57,5 +57,8 @@ public interface KtPureClassOrObject extends KtPureElement, KtDeclarationContain
@NotNull
@ReadOnly
List<KtSecondaryConstructor> getSecondaryConstructors();
@Nullable
KtClassBody getBody();
}
@@ -26,10 +26,7 @@ import com.intellij.psi.search.SearchScope
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtFileAnnotationList
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.*
import java.util.*
// NOTE: in this file we collect only LANGUAGE INDEPENDENT methods working with PSI and not modifying it
@@ -294,6 +291,13 @@ val PsiElement.startOffset: Int
val PsiElement.endOffset: Int
get() = textRange.endOffset
val KtPureElement.pureStartOffset: Int
get() = psiOrParent.textRange.startOffset
val KtPureElement.pureEndOffset: Int
get() = psiOrParent.textRange.endOffset
fun PsiElement.getStartOffsetIn(ancestor: PsiElement): Int {
var offset = 0
var parent = this