From 5ea309d5781fcededa302099bccc7a84142e3e6b Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Fri, 17 Apr 2020 12:35:23 +0300 Subject: [PATCH] [PSi2IR] Generate synthetic declaration during psi2ir - Make sure any declaration from currently generating module is bound. - Implement standalone declaration generator --- .../kotlin/psi2ir/Psi2IrTranslator.kt | 11 +- .../IrSyntheticDeclarationGenerator.kt | 52 +++++ .../StandaloneDeclarationGenerator.kt | 181 +++++++++++++++++ .../SyntheticDeclarationsGenerator.kt | 182 ++++++++++++++++++ .../ir/util/ExternalDependenciesGenerator.kt | 16 -- .../jetbrains/kotlin/ir/util/SymbolTable.kt | 74 ++++++- .../org/jetbrains/kotlin/ir/util/overrides.kt | 2 +- 7 files changed, 498 insertions(+), 20 deletions(-) create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrSyntheticDeclarationGenerator.kt create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt create mode 100644 compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index b6c08e25728..59719c9961e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.generators.* @@ -83,11 +84,13 @@ class Psi2IrTranslator( expectDescriptorToSymbol?.let { referenceExpectsForUsedActuals(it, context.symbolTable, irModule) } postprocess(context, irModule) - irProviders.filterIsInstance().forEach { it.init(irModule, pluginExtensions) } + irProviders.filterIsInstance().forEach { it.init(irModule, emptyList()) } moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) + assert(context.symbolTable.allUnbound.isEmpty()) postprocessingSteps.forEach { it.invoke(irModule) } +// assert(context.symbolTable.allUnbound.isEmpty()) // TODO: fix IrPluginContext to make it not produce additional external reference // TODO: remove it once plugin API improved moduleGenerator.generateUnboundSymbolsAsDependencies(irProviders) @@ -96,6 +99,7 @@ class Psi2IrTranslator( } private fun postprocess(context: GeneratorContext, irElement: IrModuleFragment) { + generateSyntheticDeclarations(irElement, context) insertImplicitCasts(irElement, context) generateAnnotationsForDeclarations(context, irElement) @@ -106,4 +110,9 @@ class Psi2IrTranslator( val annotationGenerator = AnnotationGenerator(context) irElement.acceptVoid(annotationGenerator) } + + private fun generateSyntheticDeclarations(moduleFragment: IrModuleFragment, context: GeneratorContext) { + val generator = IrSyntheticDeclarationGenerator(context) + moduleFragment.acceptChildrenVoid(generator) + } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrSyntheticDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrSyntheticDeclarationGenerator.kt new file mode 100644 index 00000000000..5d5e74bdd8e --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrSyntheticDeclarationGenerator.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.util.withScope +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils + +class IrSyntheticDeclarationGenerator(context: GeneratorContext) : IrElementVisitorVoid { + + private val descriptorGenerator = SyntheticDeclarationsGenerator(context, emptyList()) + private val symbolTable = context.symbolTable + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + private fun collectDescriptors(descriptor: ClassDescriptor): MutableList { + val result = mutableListOf() + result.addAll(DescriptorUtils.getAllDescriptors(descriptor.unsubstitutedMemberScope)) + result.addAll(descriptor.constructors) + result.addAll(descriptor.sealedSubclasses) + descriptor.companionObjectDescriptor?.let { result.add(it) } + + return result + } + + private fun ensureMemberScope(irClass: IrClass) { + val declaredDescriptors = irClass.declarations.map { it.descriptor } + val contributedDescriptors = collectDescriptors(irClass.descriptor) + + contributedDescriptors.removeAll(declaredDescriptors) + + symbolTable.withScope(irClass.descriptor) { + contributedDescriptors.forEach { it.accept(descriptorGenerator, irClass) } + } + } + + override fun visitClass(declaration: IrClass) { + ensureMemberScope(declaration) + declaration.acceptChildrenVoid(this) + } + +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt new file mode 100644 index 00000000000..128209121e1 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StandaloneDeclarationGenerator.kt @@ -0,0 +1,181 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType +import org.jetbrains.kotlin.ir.util.withScope +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtPureElement +import org.jetbrains.kotlin.psi.psiUtil.pureEndOffset +import org.jetbrains.kotlin.psi.psiUtil.pureStartOffset +import org.jetbrains.kotlin.psi2ir.endOffsetOrUndefined +import org.jetbrains.kotlin.psi2ir.startOffsetOrUndefined +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.types.KotlinType + +class StandaloneDeclarationGenerator(private val context: GeneratorContext) { + private val typeTranslator = context.typeTranslator + private val symbolTable = context.symbolTable + + // TODO: use this generator in psi2ir too + + fun KotlinType.toIrType() = typeTranslator.translateType(this) + + protected fun generateGlobalTypeParametersDeclarations( + irTypeParametersOwner: IrTypeParametersContainer, + from: List + ) { + generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor -> + symbolTable.declareGlobalTypeParameter(startOffset, endOffset, IrDeclarationOrigin.DEFINED, typeParameterDescriptor) + } + } + + fun generateScopedTypeParameterDeclarations( + irTypeParametersOwner: IrTypeParametersContainer, + from: List + ) { + generateTypeParameterDeclarations(irTypeParametersOwner, from) { startOffset, endOffset, typeParameterDescriptor -> + symbolTable.declareScopedTypeParameter(startOffset, endOffset, IrDeclarationOrigin.DEFINED, typeParameterDescriptor) + } + } + + private fun generateTypeParameterDeclarations( + irTypeParametersOwner: IrTypeParametersContainer, + from: List, + declareTypeParameter: (Int, Int, TypeParameterDescriptor) -> IrTypeParameter + ) { + irTypeParametersOwner.typeParameters += from.map { typeParameterDescriptor -> + val ktTypeParameterDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameterDescriptor) + val startOffset = ktTypeParameterDeclaration.startOffsetOrUndefined + val endOffset = ktTypeParameterDeclaration.endOffsetOrUndefined + declareTypeParameter( + startOffset, + endOffset, + typeParameterDescriptor + ).also { + it.parent = irTypeParametersOwner + } + } + + for (irTypeParameter in irTypeParametersOwner.typeParameters) { + irTypeParameter.descriptor.upperBounds.mapTo(irTypeParameter.superTypes) { + it.toIrType() + } + } + } + + fun generateClass(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, symbol: IrClassSymbol): IrClass { + + val irClass = IrClassImpl(startOffset, endOffset, origin, symbol) + + symbolTable.withScope(descriptor) { + irClass.metadata = MetadataSource.Class(descriptor) + + generateGlobalTypeParametersDeclarations(irClass, descriptor.declaredTypeParameters) + irClass.superTypes = descriptor.typeConstructor.supertypes.map { + it.toIrType() + } + + irClass.thisReceiver = context.symbolTable.declareValueParameter( + startOffset, endOffset, + IrDeclarationOrigin.INSTANCE_RECEIVER, + descriptor.thisAsReceiverParameter, + descriptor.thisAsReceiverParameter.type.toIrType() + ).also { it.parent = irClass } + } + + return irClass + } + + fun generateEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor, symbol: IrEnumEntrySymbol): IrEnumEntry { + // TODO: corresponging class? + val irEntry = IrEnumEntryImpl(startOffset, endOffset, origin, symbol) + + return irEntry + } + + fun generateTypeAlias(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: TypeAliasDescriptor, symbol: IrTypeAliasSymbol): IrTypeAlias { + val irAlias = IrTypeAliasImpl.fromSymbolDescriptor(startOffset, endOffset, symbol, descriptor.expandedType.toIrType(), origin) + + generateGlobalTypeParametersDeclarations(irAlias, descriptor.declaredTypeParameters) + + return irAlias + } + + protected fun declareParameter(descriptor: ParameterDescriptor, ktElement: KtPureElement?, irOwnerElement: IrElement): IrValueParameter { + return symbolTable.declareValueParameter( + ktElement?.pureStartOffset ?: irOwnerElement.startOffset, + ktElement?.pureEndOffset ?: irOwnerElement.endOffset, + IrDeclarationOrigin.DEFINED, + descriptor, descriptor.type.toIrType(), + (descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType() + ) + } + + protected fun generateValueParameterDeclarations(irFunction: IrFunction, functionDescriptor: FunctionDescriptor) { + + // TODO: KtElements + + irFunction.dispatchReceiverParameter = functionDescriptor.dispatchReceiverParameter?.let { + declareParameter(it, null, irFunction) + } + + irFunction.extensionReceiverParameter = functionDescriptor.extensionReceiverParameter?.let { + declareParameter(it, null, irFunction) + } + + // Declare all the value parameters up first. + irFunction.valueParameters = functionDescriptor.valueParameters.map { valueParameterDescriptor -> + val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter + declareParameter(valueParameterDescriptor, ktParameter, irFunction) + } + } + + fun generateConstructor(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassConstructorDescriptor, symbol: IrConstructorSymbol): IrConstructor { + val irConstructor = IrConstructorImpl(startOffset, endOffset, origin, symbol, IrUninitializedType) + irConstructor.metadata = MetadataSource.Function(descriptor) + + symbolTable.withScope(descriptor) { + val ctorTypeParameters = descriptor.typeParameters.filter { it.containingDeclaration === descriptor } + generateScopedTypeParameterDeclarations(irConstructor, ctorTypeParameters) + generateValueParameterDeclarations(irConstructor, descriptor) + irConstructor.returnType = descriptor.returnType.toIrType() + } + + return irConstructor + } + + protected fun generateOverridenSymbols(irFunction: IrSimpleFunction, overridens: Collection) { + irFunction.overriddenSymbols = overridens.map { symbolTable.referenceSimpleFunction(it.original) } + } + + fun generateSimpleFunction(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: FunctionDescriptor, symbol: IrSimpleFunctionSymbol): IrSimpleFunction { + val irFunction = IrFunctionImpl(startOffset, endOffset, origin, symbol, IrUninitializedType) + irFunction.metadata = MetadataSource.Function(descriptor) + + symbolTable.withScope(descriptor) { + generateOverridenSymbols(irFunction, descriptor.overriddenDescriptors) + generateScopedTypeParameterDeclarations(irFunction, descriptor.typeParameters) + generateValueParameterDeclarations(irFunction, descriptor) + irFunction.returnType = descriptor.returnType?.toIrType() ?: error("Expected return type $descriptor") + } + + return irFunction + } + + fun generateProperty(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: PropertyDescriptor, symbol: IrPropertySymbol): IrProperty { + val irProperty = IrPropertyImpl(startOffset, endOffset, origin, symbol, isDelegated = false) + + irProperty.metadata = MetadataSource.Property(descriptor) + + return irProperty + } +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt new file mode 100644 index 00000000000..0414483a21d --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/SyntheticDeclarationsGenerator.kt @@ -0,0 +1,182 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.IrExtensionGenerator +import org.jetbrains.kotlin.resolve.DescriptorUtils + +class SyntheticDeclarationsGenerator( + private val context: GeneratorContext, + private val pluginProviders: Collection +) : DeclarationDescriptorVisitor { + + private val generator = StandaloneDeclarationGenerator(context) + private val symbolTable = context.symbolTable + + companion object { + private const val offset = UNDEFINED_OFFSET + } + + private fun D.insertDeclaration(declarationContainer: IrDeclarationContainer): D { + parent = declarationContainer + declarationContainer.declarations.add(this) + return this + } + + private inline fun generateOrDefault(symbol: S, onDefault: (S) -> R): R { + for (p in pluginProviders) { + p.declare(symbol)?.let { + @Suppress("UNCHECKED_CAST") + return it as R + } + } + + return onDefault(symbol) + } + + override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: IrDeclarationContainer?) { + error("Unexpected declaration descriptor $descriptor") + } + + override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: IrDeclarationContainer?) { + error("Unexpected declaration descriptor $descriptor") + } + + override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: IrDeclarationContainer?) { + error("Unexpected declaration descriptor $descriptor") + } + + private fun createFunctionStub(descriptor: FunctionDescriptor, symbol: IrSimpleFunctionSymbol): IrSimpleFunction { + return generateOrDefault(symbol) { + generator.generateSimpleFunction(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: IrDeclarationContainer?) { + require(data != null) + if (descriptor.visibility != Visibilities.INVISIBLE_FAKE) { + symbolTable.declareSimpleFunctionIfNotExists(descriptor) { + createFunctionStub(descriptor, it).insertDeclaration(data) + } + } + } + + override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: IrDeclarationContainer?) { + error("Unexpected declaration descriptor $descriptor") + } + + private fun createClassStub(descriptor: ClassDescriptor, symbol: IrClassSymbol): IrClass { + assert(!DescriptorUtils.isEnumEntry(descriptor)) + return generateOrDefault(symbol) { + generator.generateClass(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + private fun createEnumEntruStub(descriptor: ClassDescriptor, symbol: IrEnumEntrySymbol): IrEnumEntry { + assert(DescriptorUtils.isEnumEntry(descriptor)) + return generateOrDefault(symbol) { + generator.generateEnumEntry(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, data: IrDeclarationContainer?) { + require(data != null) + + if (DescriptorUtils.isEnumEntry(descriptor)) { + symbolTable.declareEnumEntryIfNotExists(descriptor) { + createEnumEntruStub(descriptor, it).insertDeclaration(data) + } + } else { + symbolTable.declareClassIfNotExists(descriptor) { + createClassStub(descriptor, it).insertDeclaration(data) + } + } + } + + private fun declareTypeAliasStub(descriptor: TypeAliasDescriptor, symbol: IrTypeAliasSymbol): IrTypeAlias { + return generateOrDefault(symbol) { + generator.generateTypeAlias(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: IrDeclarationContainer?) { + require(data != null) + + symbolTable.declareTypeAliasIfNotExists(descriptor) { + declareTypeAliasStub(descriptor, it).insertDeclaration(data) + } + } + + override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: IrDeclarationContainer?) { + error("Unreachable execution $descriptor") + } + + private fun createConstructorStub(descriptor: ClassConstructorDescriptor, symbol: IrConstructorSymbol): IrConstructor { + return generateOrDefault(symbol) { + generator.generateConstructor(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: IrDeclarationContainer?) { + require(data != null) + assert(constructorDescriptor is ClassConstructorDescriptor) + symbolTable.declareConstructorIfNotExists(constructorDescriptor as ClassConstructorDescriptor) { + createConstructorStub(constructorDescriptor, it).insertDeclaration(data) + } + } + + override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: IrDeclarationContainer?) { + assert(symbolTable.referenceScript(scriptDescriptor).isBound) { "Script $scriptDescriptor isn't declared" } + } + + private fun createPropertyStub(descriptor: PropertyDescriptor, symbol: IrPropertySymbol): IrProperty { + return generateOrDefault(symbol) { + generator.generateProperty(offset, offset, IrDeclarationOrigin.DEFINED, descriptor, symbol) + } + } + + private fun declareAccessor(accessorDescriptor: PropertyAccessorDescriptor, property: IrProperty): IrSimpleFunction { + // TODO: type parameters + return symbolTable.declareSimpleFunctionIfNotExists(accessorDescriptor) { + createFunctionStub(accessorDescriptor, it).also { acc -> + acc.parent = property.parent + acc.correspondingPropertySymbol = property.symbol + } + } + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: IrDeclarationContainer?) { + require(data != null) + if (descriptor.visibility != Visibilities.INVISIBLE_FAKE) { + symbolTable.declarePropertyIfNotExists(descriptor) { + createPropertyStub(descriptor, it).insertDeclaration(data).also { p -> + descriptor.getter?.let { g -> p.getter = declareAccessor(g, p) } + descriptor.setter?.let { s -> p.setter = declareAccessor(s, p) } + } + } + } + } + + override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: IrDeclarationContainer?) { + error("Unreachable execution $descriptor") + } + + override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: IrDeclarationContainer?) { + error("Unreachable execution $descriptor") + } + + override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: IrDeclarationContainer?) { + error("Unreachable execution $descriptor") + } + + override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: IrDeclarationContainer?) { + error("Unreachable execution $descriptor") + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt index 97bc836e9f8..42385b40180 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ExternalDependenciesGenerator.kt @@ -55,22 +55,6 @@ class ExternalDependenciesGenerator( } } while (unbound.isNotEmpty()) } - - private val SymbolTable.allUnbound: List - get() { - val r = mutableListOf() - r.addAll(unboundClasses) - r.addAll(unboundConstructors) - r.addAll(unboundEnumEntries) - r.addAll(unboundFields) - r.addAll(unboundSimpleFunctions) - r.addAll(unboundProperties) - r.addAll(unboundTypeAliases) - if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) { - r.addAll(unboundTypeParameters) - } - return r - } } fun List.getDeclaration(symbol: IrSymbol): IrDeclaration = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index f38ba87ad4a..e9b2c85a4fc 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.util +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* @@ -61,6 +62,8 @@ interface ReferenceSymbolTable { fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol fun referenceField(descriptor: PropertyDescriptor): IrFieldSymbol + fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol + fun referenceProperty(descriptor: PropertyDescriptor, generate: () -> IrProperty): IrProperty fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol @@ -119,6 +122,24 @@ open class SymbolTable( return createOwner(symbol) } + inline fun declareIfNotExists(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { + @Suppress("UNCHECKED_CAST") + val d0 = d.original as D + assert(d0 === d) { + "Non-original descriptor in declaration: $d\n\tExpected: $d0" + } + val existing = get(d0) + val symbol = if (existing == null) { + val new = createSymbol() + set(d0, new) + new + } else { + if (!existing.isBound) unboundSymbols.remove(existing) + existing + } + return if (symbol.isBound) symbol.owner else createOwner(symbol) + } + inline fun declare(sig: IdSignature, d: D, createSymbol: () -> S, createOwner: (S) -> B): B { @Suppress("UNCHECKED_CAST") val d0 = d.original as D @@ -393,6 +414,10 @@ open class SymbolTable( ) } + fun declareClassIfNotExists(descriptor: ClassDescriptor, classFactory: (IrClassSymbol) -> IrClass): IrClass { + return classSymbolTable.declareIfNotExists(descriptor, { createClassSymbol(descriptor) }, classFactory) + } + fun declareClassFromLinker(descriptor: ClassDescriptor, sig: IdSignature, factory: (IrClassSymbol) -> IrClass): IrClass { return classSymbolTable.run { if (sig.isPublic) { @@ -441,6 +466,13 @@ open class SymbolTable( constructorFactory ) + fun declareConstructorIfNotExists(descriptor: ClassConstructorDescriptor, constructorFactory: (IrConstructorSymbol) -> IrConstructor): IrConstructor = + constructorSymbolTable.declareIfNotExists( + descriptor, + { createConstructorSymbol(descriptor) }, + constructorFactory + ) + override fun referenceConstructor(descriptor: ClassConstructorDescriptor) = constructorSymbolTable.referenced(descriptor) { createConstructorSymbol(descriptor) } @@ -483,6 +515,10 @@ open class SymbolTable( factory ) + fun declareEnumEntryIfNotExists(descriptor: ClassDescriptor, factory: (IrEnumEntrySymbol) -> IrEnumEntry): IrEnumEntry { + return enumEntrySymbolTable.declareIfNotExists(descriptor, { createEnumEntrySymbol(descriptor) }, factory) + } + fun declareEnumEntryFromLinker( descriptor: ClassDescriptor, sig: IdSignature, @@ -599,6 +635,9 @@ open class SymbolTable( propertyFactory ) + fun declarePropertyIfNotExists(descriptor: PropertyDescriptor, propertyFactory: (IrPropertySymbol) -> IrProperty): IrProperty = + propertySymbolTable.declareIfNotExists(descriptor, { createPropertySymbol(descriptor) }, propertyFactory) + fun declarePropertyFromLinker(descriptor: PropertyDescriptor, sig: IdSignature, factory: (IrPropertySymbol) -> IrProperty): IrProperty { return propertySymbolTable.run { if (sig.isPublic) { @@ -609,7 +648,7 @@ open class SymbolTable( } } - fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol = + override fun referenceProperty(descriptor: PropertyDescriptor): IrPropertySymbol = propertySymbolTable.referenced(descriptor) { createPropertySymbol(descriptor) } override fun referencePropertyFromLinker(descriptor: PropertyDescriptor, sig: IdSignature): IrPropertySymbol = @@ -652,6 +691,9 @@ open class SymbolTable( fun declareTypeAlias(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias = typeAliasSymbolTable.declare(descriptor, { createTypeAliasSymbol(descriptor) }, factory) + fun declareTypeAliasIfNotExists(descriptor: TypeAliasDescriptor, factory: (IrTypeAliasSymbol) -> IrTypeAlias): IrTypeAlias = + typeAliasSymbolTable.declareIfNotExists(descriptor, { createTypeAliasSymbol(descriptor) }, factory) + val unboundTypeAliases: Set get() = typeAliasSymbolTable.unboundSymbols private fun createSimpleFunctionSymbol(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol { @@ -681,6 +723,13 @@ open class SymbolTable( ) } + fun declareSimpleFunctionIfNotExists( + descriptor: FunctionDescriptor, + functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction + ): IrSimpleFunction { + return simpleFunctionSymbolTable.declareIfNotExists(descriptor, { createSimpleFunctionSymbol(descriptor) }, functionFactory) + } + fun declareSimpleFunctionFromLinker( descriptor: FunctionDescriptor, sig: IdSignature, @@ -913,4 +962,25 @@ inline fun SymbolTable.withScope(owner: D, block: val result = block(owner) leaveScope(owner) return result -} \ No newline at end of file +} + +inline fun ReferenceSymbolTable.withReferenceScope(owner: D, block: ReferenceSymbolTable.(D) -> T): T { + enterScope(owner) + val result = block(owner) + leaveScope(owner) + return result +} + +val SymbolTable.allUnbound: List + get() { + val r = mutableListOf() + r.addAll(unboundClasses) + r.addAll(unboundConstructors) + r.addAll(unboundEnumEntries) + r.addAll(unboundFields) + r.addAll(unboundSimpleFunctions) + r.addAll(unboundProperties) + r.addAll(unboundTypeAliases) + r.addAll(unboundTypeParameters) + return r.filter { !it.isBound } + } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/overrides.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/overrides.kt index e082d7e1751..902a50c5ce9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/overrides.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/overrides.kt @@ -25,7 +25,7 @@ fun SymbolTable.declareSimpleFunctionWithOverrides( fun generateOverriddenFunctionSymbols( declaration: IrSimpleFunction, - symbolTable: SymbolTable + symbolTable: ReferenceSymbolTable ) { declaration.overriddenSymbols = declaration.descriptor.overriddenDescriptors.map { symbolTable.referenceSimpleFunction(it.original)