From d29a47ec7f2fac9d0f604025e67d61a74635c266 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 16 Feb 2018 15:15:19 +0300 Subject: [PATCH] Generate references to superclasses --- .../psi2ir/generators/ClassGenerator.kt | 14 +++++--- .../psi2ir/generators/DeclarationGenerator.kt | 2 +- .../kotlin/ir/declarations/IrClass.kt | 3 ++ .../ir/declarations/impl/IrClassImpl.kt | 2 ++ .../ir/util/DeclarationStubGenerator.kt | 28 ++++++++++------ .../kotlin/ir/util/DeepCopyIrTree.kt | 14 ++++++++ .../ir/util/DeepCopyIrTreeWithSymbols.kt | 3 ++ .../kotlin/ir/util/DependenciesCollector.kt | 9 +++++ .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 33 +++++++++++++------ 9 files changed, 83 insertions(+), 25 deletions(-) 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 c0d304e39fd..da21c4cfd47 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 @@ -38,14 +38,20 @@ import java.lang.AssertionError class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) { fun generateClass(ktClassOrObject: KtClassOrObject): IrClass { val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject) + val startOffset = ktClassOrObject.startOffset + val endOffset = ktClassOrObject.endOffset return context.symbolTable.declareClass( - ktClassOrObject.startOffset, ktClassOrObject.endOffset, - IrDeclarationOrigin.DEFINED, - descriptor + startOffset, endOffset, IrDeclarationOrigin.DEFINED, descriptor ).buildWithScope { irClass -> + descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superClasses) { + it.constructor.declarationDescriptor?.safeAs()?.let { + context.symbolTable.referenceClass(it) + } + } + irClass.thisReceiver = context.symbolTable.declareValueParameter( - ktClassOrObject.startOffset, ktClassOrObject.endOffset, + startOffset, endOffset, IrDeclarationOrigin.INSTANCE_RECEIVER, irClass.descriptor.thisAsReceiverParameter ) 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 56c8517f868..a53cc0506c3 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 @@ -68,7 +68,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass = ClassGenerator(this).generateClass(ktClassOrObject) - fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration = + private fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration = IrTypeAliasImpl( ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED, getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt index 972d5eddc98..0e99e98be99 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt @@ -36,6 +36,9 @@ interface IrClass : IrSymbolDeclaration, IrDeclarationContainer, val isCompanion: Boolean val isData: Boolean + // NB type parameters can't be top-level classifiers in supetypes of a class + val superClasses: MutableList + var thisReceiver: IrValueParameter? } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt index bb38bdabeef..1b40222ef7e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrClassImpl.kt @@ -73,6 +73,8 @@ class IrClassImpl( override val typeParameters: MutableList = SmartList() + override val superClasses: MutableList = SmartList() + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitClass(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index d630a768b4d..a90600449a8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.utils.addToStdlib.safeAs class DeclarationStubGenerator( val symbolTable: SymbolTable, @@ -56,7 +57,7 @@ class DeclarationStubGenerator( throw AssertionError("Unexpected member descriptor: $descriptor") } - fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty = + private fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty = IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty -> val getterDescriptor = descriptor.getter if (getterDescriptor == null) { @@ -75,16 +76,16 @@ class DeclarationStubGenerator( generateValueParametersStubs(descriptor.valueParameters, irFunction) } - fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor = + private fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor = symbolTable.declareConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original).also { irConstructor -> generateValueParametersStubs(descriptor.valueParameters, irConstructor) } - fun generateValueParametersStubs(valueParameters: Collection, function: IrFunction) { + private fun generateValueParametersStubs(valueParameters: Collection, function: IrFunction) { valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) } } - fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter = + private fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter = IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irValueParameter -> if (descriptor.declaresDefaultValue()) { irValueParameter.defaultValue = @@ -97,29 +98,36 @@ class DeclarationStubGenerator( } } - fun generateClassStub(descriptor: ClassDescriptor): IrClass = + private fun generateClassStub(descriptor: ClassDescriptor): IrClass = symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irClass -> + // TODO get rid of code duplication, see ClassGenerator#generateClass + descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superClasses) { + it.constructor.declarationDescriptor?.safeAs()?.let { + symbolTable.referenceClass(it) + } + } + generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass) generateChildStubs(descriptor.constructors, irClass) generateMemberStubs(descriptor.defaultType.memberScope, irClass) generateMemberStubs(descriptor.staticScope, irClass) } - fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry = + private fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry = symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) - fun generateTypeParameterStubs(typeParameters: List, container: IrTypeParametersContainer) { + private fun generateTypeParameterStubs(typeParameters: List, container: IrTypeParametersContainer) { typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) } } - fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter = + private fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter = IrTypeParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) - fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) { + private fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) { generateChildStubs(memberScope.getContributedDescriptors(), container) } - fun generateChildStubs(descriptors: Collection, container: IrDeclarationContainer) { + private fun generateChildStubs(descriptors: Collection, container: IrDeclarationContainer) { descriptors.sortedWith(StableDescriptorsComparator).mapTo(container.declarations) { generateMemberStub(it) } } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt index 9e14c6307d9..87a872ee4e5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl @@ -96,6 +97,19 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { ).apply { thisReceiver = declaration.thisReceiver?.withDescriptor(descriptor.thisAsReceiverParameter) transformTypeParameters(declaration, descriptor.declaredTypeParameters) + + descriptor.typeConstructor.supertypes.forEachIndexed { index, supertype -> + val superclassDescriptor = supertype.constructor.declarationDescriptor + if (superclassDescriptor is ClassDescriptor) { + val oldSuperclassSymbol = declaration.superClasses.getOrNull(index) + val newSuperclassSymbol = + if (superclassDescriptor == oldSuperclassSymbol?.descriptor) + oldSuperclassSymbol + else + IrClassSymbolImpl(superclassDescriptor) + superClasses.add(newSuperclassSymbol) + } + } } private fun IrValueParameter.withDescriptor(newDescriptor: ParameterDescriptor) = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index bbdede9e893..a063aafa82d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -88,6 +88,9 @@ open class DeepCopyIrTreeWithSymbols(private val symbolRemapper: SymbolRemapper) mapDeclarationOrigin(declaration.origin), symbolRemapper.getDeclaredClass(declaration.symbol) ).apply { + declaration.superClasses.mapTo(superClasses) { + symbolRemapper.getReferencedClass(it) + } thisReceiver = declaration.thisReceiver?.transform() declaration.typeParameters.transformTo(typeParameters) declaration.transformDeclarationsTo(this) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DependenciesCollector.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DependenciesCollector.kt index 044654b2eca..b60791a5bdb 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DependenciesCollector.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DependenciesCollector.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers class DependenciesCollector { private val modulesForDependencyDescriptors = LinkedHashSet() @@ -41,6 +42,14 @@ class DependenciesCollector { assert(symbolTable.unboundValueParameters.isEmpty()) { "Unbound value parameters: ${symbolTable.unboundValueParameters}" } assert(symbolTable.unboundVariables.isEmpty()) { "Unbound variables: ${symbolTable.unboundVariables}" } + for (unboundClass in symbolTable.unboundClasses.toTypedArray()) { + for (superClassifier in unboundClass.descriptor.getAllSuperClassifiers()) { + if (superClassifier is ClassDescriptor) { + symbolTable.referenceClass(superClassifier) + } + } + } + symbolTable.unboundClasses.addTopLevelDeclarations() symbolTable.unboundConstructors.addTopLevelDeclarations() symbolTable.unboundEnumEntries.addTopLevelDeclarations() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index a2116a6876a..bf61c81b99f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -16,10 +16,12 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid @@ -78,6 +80,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor { override fun visitClass(declaration: IrClass, data: String) { declaration.dumpLabeledElementWith(data) { declaration.thisReceiver?.accept(this, "\$this") + declaration.superClasses.renderDeclarationElementsOrDescriptors("superClasses") declaration.typeParameters.dumpElements() declaration.declarations.dumpElements() } @@ -85,16 +88,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor { override fun visitSimpleFunction(declaration: IrSimpleFunction, data: String) { declaration.dumpLabeledElementWith(data) { - if (declaration.overriddenSymbols.isNotEmpty()) { - indented("overridden") { - for (overriddenSymbol in declaration.overriddenSymbols) { - if (overriddenSymbol.isBound) - overriddenSymbol.owner.render() - else - printer.println("UNBOUND: ", DescriptorRenderer.COMPACT.render(overriddenSymbol.descriptor)) - } - } - } + declaration.overriddenSymbols.renderDeclarationElementsOrDescriptors("overridden") declaration.typeParameters.dumpElements() declaration.dispatchReceiverParameter?.accept(this, "\$this") declaration.extensionReceiverParameter?.accept(this, "\$receiver") @@ -103,6 +97,25 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor { } } + private fun Collection>.renderDeclarationElementsOrDescriptors( + caption: String + ) { + if (isNotEmpty()) { + indented(caption) { + for (symbol in this) { + symbol.renderDeclarationElementOrDescriptor() + } + } + } + } + + private fun IrBindableSymbol.renderDeclarationElementOrDescriptor() { + if (isBound) + owner.render() + else + printer.println("UNBOUND: ", DescriptorRenderer.COMPACT.render(descriptor)) + } + override fun visitConstructor(declaration: IrConstructor, data: String) { declaration.dumpLabeledElementWith(data) { declaration.typeParameters.dumpElements()