Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.psi2ir.generators.ClassGenerator.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.backend.common.CodegenUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.expressions.putTypeArguments
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
import org.jetbrains.kotlin.ir.util.createIrClassFromDescriptor
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.ir.util.properties
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.startOffsetSkippingComments
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
import org.jetbrains.kotlin.renderer.OverrideRenderingPolicy
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DelegationResolver
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
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
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
class ClassGenerator(
declarationGenerator: DeclarationGenerator
) : DeclarationGeneratorExtension(declarationGenerator) {
companion object {
private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions {
withDefinedIn = false
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OPEN_OVERRIDE
includePropertyConstant = true
classifierNamePolicy = ClassifierNamePolicy.FULLY_QUALIFIED
verbose = true
modifiers = DescriptorRendererModifier.ALL
}
fun List.sortedByRenderer(): List {
val rendered = map(DESCRIPTOR_RENDERER::render)
val sortedIndices = (0 until size).sortedWith(Comparator { i, j -> rendered[i].compareTo(rendered[j]) })
return sortedIndices.map { this[it] }
}
}
fun generateClass(ktClassOrObject: KtPureClassOrObject, visibility_: DescriptorVisibility? = null): IrClass {
val classDescriptor = ktClassOrObject.findClassDescriptor(this.context.bindingContext)
val startOffset = ktClassOrObject.getStartOffsetOfClassDeclarationOrNull() ?: ktClassOrObject.pureStartOffset
val endOffset = ktClassOrObject.pureEndOffset
val visibility = visibility_ ?: classDescriptor.visibility
val modality = getEffectiveModality(ktClassOrObject, classDescriptor)
return context.symbolTable.declareClass(classDescriptor) {
context.irFactory.createIrClassFromDescriptor(
startOffset, endOffset, IrDeclarationOrigin.DEFINED, it, classDescriptor,
context.symbolTable.nameProvider.nameForDeclaration(classDescriptor), visibility, modality
).apply {
metadata = MetadataSource.Class(it.descriptor)
}
}.buildWithScope { irClass ->
declarationGenerator.generateGlobalTypeParametersDeclarations(irClass, classDescriptor.declaredTypeParameters)
irClass.superTypes = classDescriptor.typeConstructor.supertypes.map {
it.toIrType()
}
irClass.thisReceiver = context.symbolTable.declareValueParameter(
startOffset, endOffset,
IrDeclarationOrigin.INSTANCE_RECEIVER,
classDescriptor.thisAsReceiverParameter,
classDescriptor.thisAsReceiverParameter.type.toIrType()
)
val irPrimaryConstructor = generatePrimaryConstructor(irClass, ktClassOrObject)
if (irPrimaryConstructor != null) {
generateDeclarationsForPrimaryConstructorParameters(irClass, irPrimaryConstructor, ktClassOrObject)
}
if (ktClassOrObject is KtClassOrObject) //todo: supertype list for synthetic declarations
generateMembersDeclaredInSupertypeList(irClass, ktClassOrObject)
generateMembersDeclaredInClassBody(irClass, ktClassOrObject)
generateFakeOverrideMemberDeclarations(irClass, ktClassOrObject)
if (irClass.isInline && ktClassOrObject is KtClassOrObject) {
generateAdditionalMembersForInlineClasses(irClass, ktClassOrObject)
}
if (irClass.isData && ktClassOrObject is KtClassOrObject) {
generateAdditionalMembersForDataClass(irClass, ktClassOrObject)
}
if (DescriptorUtils.isEnumClass(classDescriptor)) {
generateAdditionalMembersForEnumClass(irClass)
}
}
}
private fun getEffectiveModality(ktClassOrObject: KtPureClassOrObject, classDescriptor: ClassDescriptor): Modality =
when {
!DescriptorUtils.isEnumClass(classDescriptor) ->
classDescriptor.modality
DescriptorUtils.hasAbstractMembers(classDescriptor) ->
Modality.ABSTRACT
ktClassOrObject.hasEnumEntriesWithClassMembers() ->
Modality.OPEN
else ->
Modality.FINAL
}
private fun KtPureClassOrObject.hasEnumEntriesWithClassMembers(): Boolean {
val body = this.body ?: return false
return body.enumEntries.any { it.hasMemberDeclarations() }
}
private fun KtEnumEntry.hasMemberDeclarations() = declarations.isNotEmpty()
private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtPureClassOrObject) {
val classDescriptor = irClass.descriptor
classDescriptor.unsubstitutedMemberScope.getContributedDescriptors()
.filterIsInstance()
.filter {
it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
}
.sortedByRenderer()
.forEach { fakeOverride ->
declarationGenerator.generateFakeOverrideDeclaration(fakeOverride, ktClassOrObject)?.let { irClass.declarations.add(it) }
}
context.extensions.getParentClassStaticScope(classDescriptor)?.run {
getContributedDescriptors()
.filterIsInstance()
.filter {
DescriptorVisibilities.isVisibleIgnoringReceiver(it, classDescriptor)
}
.sortedByRenderer()
.forEach { parentStaticMember ->
val fakeOverride = createFakeOverrideDescriptorForParentStaticMember(classDescriptor, parentStaticMember)
declarationGenerator.generateFakeOverrideDeclaration(fakeOverride, ktClassOrObject)?.let {
irClass.declarations.add(it)
}
}
}
}
private fun createFakeOverrideDescriptorForParentStaticMember(
classDescriptor: ClassDescriptor,
parentStaticMember: FunctionDescriptor
): FunctionDescriptor =
parentStaticMember.copy(
classDescriptor, parentStaticMember.modality, parentStaticMember.visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false
).apply {
setSingleOverridden(parentStaticMember)
}
private fun generateMembersDeclaredInSupertypeList(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return
var delegateNumber = 0
for (ktEntry in ktSuperTypeList.entries) {
if (ktEntry is KtDelegatedSuperTypeEntry) {
generateDelegatedImplementationMembers(irClass, ktEntry, delegateNumber++)
}
}
}
private fun generateDelegatedImplementationMembers(
irClass: IrClass,
ktEntry: KtDelegatedSuperTypeEntry,
delegateNumber: Int
) {
val ktDelegateExpression = ktEntry.delegateExpression!!
val delegateType = getTypeInferredByFrontendOrFail(ktDelegateExpression)
val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!)
val superTypeConstructorDescriptor = superType.constructor.declarationDescriptor
val superClass = superTypeConstructorDescriptor as? ClassDescriptor
?: throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor")
val propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(ktDelegateExpression, irClass.descriptor, context.bindingContext)
val irDelegateField: IrField = if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, context.bindingContext)) {
irClass.properties.first { it.descriptor == propertyDescriptor }.backingField!!
} else {
val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType, delegateNumber)
context.symbolTable.declareField(
ktDelegateExpression.startOffsetSkippingComments, ktDelegateExpression.endOffset,
IrDeclarationOrigin.DELEGATE,
delegateDescriptor, delegateDescriptor.type.toIrType(),
createBodyGenerator(irClass.symbol).generateExpressionBody(ktDelegateExpression)
).apply {
irClass.addMember(this)
}
}
val delegatesMap = DelegationResolver.getDelegates(irClass.descriptor, superClass, delegateType)
val delegatedMembers = delegatesMap.keys.toList().sortedByRenderer()
for (delegatedMember in delegatedMembers) {
val overriddenMember = delegatedMember.overriddenDescriptors.find { it.containingDeclaration.original == superClass.original }
if (overriddenMember != null) {
val delegateToMember = delegatesMap[delegatedMember]
?: throw AssertionError(
"No corresponding member in delegate type $delegateType for $delegatedMember overriding $overriddenMember"
)
generateDelegatedMember(irClass, irDelegateField, delegatedMember, delegateToMember)
}
}
}
private fun generateDelegatedMember(
irClass: IrClass,
irDelegate: IrField,
delegatedMember: CallableMemberDescriptor,
delegateToMember: CallableMemberDescriptor
) {
when (delegatedMember) {
is FunctionDescriptor -> generateDelegatedFunction(irClass, irDelegate, delegatedMember, delegateToMember as FunctionDescriptor)
is PropertyDescriptor -> generateDelegatedProperty(irClass, irDelegate, delegatedMember, delegateToMember as PropertyDescriptor)
}
}
private fun generateDelegatedProperty(
irClass: IrClass,
irDelegate: IrField,
delegatedDescriptor: PropertyDescriptor,
delegateToDescriptor: PropertyDescriptor
) {
irClass.addMember(generateDelegatedProperty(irDelegate, delegatedDescriptor, delegateToDescriptor))
}
private fun generateDelegatedProperty(
irDelegate: IrField,
delegatedDescriptor: PropertyDescriptor,
delegateToDescriptor: PropertyDescriptor
): IrProperty {
val startOffset = irDelegate.startOffset
val endOffset = irDelegate.endOffset
val irProperty = context.symbolTable.declareProperty(
startOffset, endOffset, IrDeclarationOrigin.DELEGATED_MEMBER,
delegatedDescriptor
)
irProperty.getter = generateDelegatedFunction(irDelegate, delegatedDescriptor.getter!!, delegateToDescriptor.getter!!)
if (delegatedDescriptor.isVar) {
irProperty.setter = generateDelegatedFunction(irDelegate, delegatedDescriptor.setter!!, delegateToDescriptor.setter!!)
}
irProperty.linkCorrespondingPropertySymbol()
return irProperty
}
private fun generateDelegatedFunction(
irClass: IrClass,
irDelegate: IrField,
delegatedDescriptor: FunctionDescriptor,
delegateToDescriptor: FunctionDescriptor
) {
irClass.addMember(generateDelegatedFunction(irDelegate, delegatedDescriptor, delegateToDescriptor))
}
private fun generateDelegatedFunction(
irDelegate: IrField,
delegatedDescriptor: FunctionDescriptor,
delegateToDescriptor: FunctionDescriptor
): IrSimpleFunction =
context.symbolTable.declareSimpleFunctionWithOverrides(
irDelegate.startOffset, irDelegate.endOffset,
IrDeclarationOrigin.DELEGATED_MEMBER,
delegatedDescriptor
).buildWithScope { irFunction ->
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
// TODO could possibly refer to scoped type parameters for property accessors
irFunction.returnType = delegatedDescriptor.returnType!!.toIrType()
irFunction.body = generateDelegateFunctionBody(irDelegate, delegatedDescriptor, delegateToDescriptor, irFunction)
}
private fun generateDelegateFunctionBody(
irDelegate: IrField,
delegatedDescriptor: FunctionDescriptor,
delegateToDescriptor: FunctionDescriptor,
irDelegatedFunction: IrSimpleFunction
): IrBlockBody {
val startOffset = irDelegate.startOffset
val endOffset = irDelegate.endOffset
val irBlockBody = context.irFactory.createBlockBody(startOffset, endOffset)
val substitutedDelegateTo = substituteDelegateToDescriptor(delegatedDescriptor, delegateToDescriptor)
val returnType = substitutedDelegateTo.returnType!!
val delegateToSymbol = context.symbolTable.referenceSimpleFunction(delegateToDescriptor.original)
val irCall = IrCallImpl(
startOffset, endOffset,
returnType.toIrType(),
delegateToSymbol,
substitutedDelegateTo.typeParametersCount
).apply {
context.callToSubstitutedDescriptorMap[this] = substitutedDelegateTo
val typeArguments = getTypeArgumentsForOverriddenDescriptorDelegatingCall(delegatedDescriptor, delegateToDescriptor)
putTypeArguments(typeArguments) { it.toIrType() }
val dispatchReceiverParameter = irDelegatedFunction.dispatchReceiverParameter!!
dispatchReceiver =
IrGetFieldImpl(
startOffset, endOffset,
irDelegate.symbol,
irDelegate.type,
IrGetValueImpl(
startOffset, endOffset,
dispatchReceiverParameter.type,
dispatchReceiverParameter.symbol
)
)
extensionReceiver =
irDelegatedFunction.extensionReceiverParameter?.let { extensionReceiver ->
IrGetValueImpl(startOffset, endOffset, extensionReceiver.type, extensionReceiver.symbol)
}
mapValueParameters { overriddenValueParameter ->
val delegatedValueParameter = delegatedDescriptor.valueParameters[overriddenValueParameter.index]
val irDelegatedValueParameter = irDelegatedFunction.getIrValueParameter(delegatedValueParameter)
IrGetValueImpl(startOffset, endOffset, irDelegatedValueParameter.type, irDelegatedValueParameter.symbol)
}
}
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
irBlockBody.statements.add(irCall)
} else {
val irReturn = IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, irDelegatedFunction.symbol, irCall)
irBlockBody.statements.add(irReturn)
}
return irBlockBody
}
@Suppress("UNCHECKED_CAST")
private fun substituteDelegateToDescriptor(delegated: D, overridden: D): D =
// PropertyAccessorDescriptor doesn't support 'substitute', so we substitute the corresponding property instead.
when (overridden) {
is PropertyGetterDescriptor -> substituteDelegateToDescriptor(
(delegated as PropertyGetterDescriptor).correspondingProperty,
overridden.correspondingProperty
).getter as D
is PropertySetterDescriptor -> substituteDelegateToDescriptor(
(delegated as PropertySetterDescriptor).correspondingProperty,
overridden.correspondingProperty
).setter as D
else -> {
val delegatedTypeParameters = delegated.typeParameters
val substitutor =
TypeSubstitutor.create(
overridden.typeParameters.associate {
val delegatedDefaultType = delegatedTypeParameters[it.index].defaultType
it.typeConstructor to TypeProjectionImpl(delegatedDefaultType)
}
)
overridden.substitute(substitutor)!! as D
}
}
private fun getTypeArgumentsForOverriddenDescriptorDelegatingCall(
delegatedDescriptor: FunctionDescriptor,
delegateToDescriptor: FunctionDescriptor
): Map? {
val keys = delegateToDescriptor.propertyIfAccessor.original.typeParameters
if (keys.isEmpty()) return null
val values = delegatedDescriptor.propertyIfAccessor.typeParameters
val typeArguments = newHashMapWithExpectedSize(keys.size)
for ((i, overriddenTypeParameter) in keys.withIndex()) {
typeArguments[overriddenTypeParameter] = values[i].defaultType
}
return typeArguments
}
private fun generateAdditionalMembersForInlineClasses(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
DataClassMembersGenerator(declarationGenerator).generateInlineClassMembers(ktClassOrObject, irClass)
}
private fun generateAdditionalMembersForDataClass(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
DataClassMembersGenerator(declarationGenerator).generateDataClassMembers(ktClassOrObject, irClass)
}
private fun generateAdditionalMembersForEnumClass(irClass: IrClass) {
EnumClassMembersGenerator(declarationGenerator).generateSpecialMembers(irClass)
}
private fun generatePrimaryConstructor(irClass: IrClass, ktClassOrObject: KtPureClassOrObject): IrConstructor? {
val classDescriptor = irClass.descriptor
val primaryConstructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return null
return FunctionGenerator(declarationGenerator)
.generatePrimaryConstructor(primaryConstructorDescriptor, ktClassOrObject)
.also {
irClass.addMember(it)
}
}
private fun generateDeclarationsForPrimaryConstructorParameters(
irClass: IrClass,
irPrimaryConstructor: IrConstructor,
ktClassOrObject: KtPureClassOrObject
) {
ktClassOrObject.primaryConstructor?.let { ktPrimaryConstructor ->
irPrimaryConstructor.valueParameters.forEach {
context.symbolTable.introduceValueParameter(it)
}
ktPrimaryConstructor.valueParameters.forEachIndexed { i, ktParameter ->
val irValueParameter = irPrimaryConstructor.valueParameters[i]
if (ktParameter.hasValOrVar()) {
val irProperty = PropertyGenerator(declarationGenerator)
.generatePropertyForPrimaryConstructorParameter(ktParameter, irValueParameter)
irClass.addMember(irProperty)
}
}
}
}
private fun generateMembersDeclaredInClassBody(irClass: IrClass, ktClassOrObject: KtPureClassOrObject) {
// generate real body declarations
ktClassOrObject.body?.let { ktClassBody ->
ktClassBody.declarations.mapNotNullTo(irClass.declarations) { ktDeclaration ->
declarationGenerator.generateClassMemberDeclaration(ktDeclaration, irClass)
}
}
// generate synthetic nested classes (including companion)
irClass.descriptor
.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)
.asSequence()
.filterIsInstance()
.mapTo(irClass.declarations) { declarationGenerator.generateSyntheticClassOrObject(it.syntheticDeclaration) }
// synthetic functions and properties to classes must be contributed by corresponding lowering
}
fun generateEnumEntry(ktEnumEntry: KtEnumEntry): IrEnumEntry {
val enumEntryDescriptor = getOrFail(BindingContext.CLASS, ktEnumEntry)
// TODO this is a hack, pass declaration parent through generator chain instead
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
val enumClassSymbol = context.symbolTable.referenceClass(enumClassDescriptor)
val irEnumClass = enumClassSymbol.owner
return context.symbolTable.declareEnumEntry(
ktEnumEntry.startOffsetSkippingComments,
ktEnumEntry.endOffset,
IrDeclarationOrigin.DEFINED,
enumEntryDescriptor
).buildWithScope { irEnumEntry ->
irEnumEntry.parent = irEnumClass
if (!enumEntryDescriptor.isExpect) {
irEnumEntry.initializerExpression =
context.irFactory.createExpressionBody(createBodyGenerator(irEnumEntry.symbol)
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor))
}
if (ktEnumEntry.hasMemberDeclarations()) {
irEnumEntry.correspondingClass = generateClass(ktEnumEntry, DescriptorVisibilities.PRIVATE)
}
}
}
}