MoveBodilessDeclarationsToSeparatePlace

This commit is contained in:
Anton Bannykh
2019-12-24 23:28:02 +03:00
committed by Anton Bannykh
parent 09a2c145a9
commit ce625075f6
2 changed files with 59 additions and 72 deletions
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsDeclarationFactory
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
@@ -25,6 +22,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.lower.CallableReferenceKey
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.*
@@ -60,11 +58,34 @@ class JsIrBackendContext(
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
var externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
lateinit var bodilessBuiltInsPackageFragment: IrPackageFragment
val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
val bodilessBuiltInsPackageFragment: IrPackageFragment = run {
val externalNestedClasses = mutableListOf<IrClass>()
val packageLevelJsModules = mutableListOf<IrFile>()
class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
override val descriptor: PackageFragmentDescriptor
get() = error("Operation is unsupported")
private var _owner: IrExternalPackageFragment? = null
override val owner get() = _owner!!
override var uniqId: UniqId
get() = error("Operation is unsupported")
set(value) { error("Operation is unsupported") }
override val isBound get() = _owner != null
override fun bind(owner: IrExternalPackageFragment) {
_owner = owner
}
}
IrExternalPackageFragmentImpl(
DescriptorlessExternalPackageFragmentSymbol(),
FqName("kotlin")
)
}
val packageLevelJsModules = mutableSetOf<IrFile>()
val declarationLevelJsModules = mutableListOf<IrDeclarationWithName>()
val internalPackageFragmentDescriptor = EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))
@@ -5,20 +5,18 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.util.UniqId
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.name.FqName
private val BODILESS_BUILTIN_CLASSES = listOf(
@@ -43,24 +41,6 @@ private val BODILESS_BUILTIN_CLASSES = listOf(
"kotlin.Function"
).map { FqName(it) }.toSet()
private class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
override val descriptor: PackageFragmentDescriptor
get() = error("Operation is unsupported")
private var _owner: IrExternalPackageFragment? = null
override val owner get() = _owner!!
override var uniqId: UniqId
get() = error("Operation is unsupported")
set(value) { error("Operation is unsupported") }
override val isBound get() = _owner != null
override fun bind(owner: IrExternalPackageFragment) {
_owner = owner
}
}
private class DescriptorlessIrFileSymbol : IrFileSymbol {
override fun bind(owner: IrFile) {
_owner = owner
@@ -79,33 +59,22 @@ private class DescriptorlessIrFileSymbol : IrFileSymbol {
override val isBound get() = _owner != null
}
private fun isBuiltInClass(declaration: IrDeclaration): Boolean =
declaration is IrClass && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module: IrModuleFragment) {
val bodilessBuiltInsPackageFragment = IrExternalPackageFragmentImpl(
DescriptorlessExternalPackageFragmentSymbol(),
FqName("kotlin")
)
context.bodilessBuiltInsPackageFragment = bodilessBuiltInsPackageFragment
fun isBuiltInClass(declaration: IrDeclaration): Boolean =
declaration is IrClass && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES
fun collectExternalClasses(container: IrDeclarationContainer, includeCurrentLevel: Boolean): List<IrClass> {
val externalClasses =
container.declarations.filterIsInstance<IrClass>().filter { it.isEffectivelyExternal() }
val nestedExternalClasses =
externalClasses.flatMap { collectExternalClasses(it, true) }
return if (includeCurrentLevel)
externalClasses + nestedExternalClasses
else
nestedExternalClasses
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
MoveBodilessDeclarationsToSeparatePlaceLowering(context).let { moveBodiless ->
moduleFragment.files.forEach {
moveBodiless.lower(it)
}
}
}
class MoveBodilessDeclarationsToSeparatePlaceLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
val irFile = declaration.parent as? IrFile ?: return null
fun lowerFile(irFile: IrFile): IrFile? {
val externalPackageFragment by lazy {
context.externalPackageFragment.getOrPut(irFile.symbol) {
IrFileImpl(fileEntry = irFile.fileEntry, fqName = irFile.fqName, symbol = DescriptorlessIrFileSymbol()).also {
@@ -114,33 +83,30 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module:
}
}
context.externalNestedClasses += collectExternalClasses(irFile, includeCurrentLevel = false)
if (irFile.getJsModule() != null || irFile.getJsQualifier() != null) {
context.packageLevelJsModules.add(irFile)
return null
}
externalPackageFragment.declarations += declaration
declaration.parent = externalPackageFragment
val it = irFile.declarations.iterator()
context.packageLevelJsModules += externalPackageFragment
while (it.hasNext()) {
val d = it.next() as? IrDeclarationWithName ?: continue
return emptyList()
} else {
val d = declaration as? IrDeclarationWithName ?: return null
if (isBuiltInClass(d)) {
it.remove()
bodilessBuiltInsPackageFragment.addChild(d)
context.bodilessBuiltInsPackageFragment.addChild(d)
return emptyList()
} else if (d.isEffectivelyExternal()) {
if (d.getJsModule() != null)
context.declarationLevelJsModules.add(d)
it.remove()
externalPackageFragment.addChild(d)
}
}
return irFile
}
externalPackageFragment.declarations += d
d.parent = externalPackageFragment
module.files.transformFlat { irFile ->
listOfNotNull(lowerFile(irFile))
return emptyList()
}
return null
}
}
}
}