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.backend.js.JsDeclarationFactory
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement 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.lower.CallableReferenceKey
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.* 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.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
@@ -60,11 +58,34 @@ class JsIrBackendContext(
val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false val devMode = configuration[JSConfigurationKeys.DEVELOPER_MODE] ?: false
var externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>() val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
lateinit var bodilessBuiltInsPackageFragment: IrPackageFragment val bodilessBuiltInsPackageFragment: IrPackageFragment = run {
val externalNestedClasses = mutableListOf<IrClass>() class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
val packageLevelJsModules = mutableListOf<IrFile>() 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 declarationLevelJsModules = mutableListOf<IrDeclarationWithName>()
val internalPackageFragmentDescriptor = EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")) val internalPackageFragmentDescriptor = EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))
@@ -5,20 +5,18 @@
package org.jetbrains.kotlin.ir.backend.js.lower 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.backend.common.ir.addChild
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext 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.getJsModule
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
import org.jetbrains.kotlin.ir.declarations.* 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.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.util.UniqId import org.jetbrains.kotlin.ir.util.UniqId
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
private val BODILESS_BUILTIN_CLASSES = listOf( private val BODILESS_BUILTIN_CLASSES = listOf(
@@ -43,24 +41,6 @@ private val BODILESS_BUILTIN_CLASSES = listOf(
"kotlin.Function" "kotlin.Function"
).map { FqName(it) }.toSet() ).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 { private class DescriptorlessIrFileSymbol : IrFileSymbol {
override fun bind(owner: IrFile) { override fun bind(owner: IrFile) {
_owner = owner _owner = owner
@@ -79,33 +59,22 @@ private class DescriptorlessIrFileSymbol : IrFileSymbol {
override val isBound get() = _owner != null 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) { fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, moduleFragment: IrModuleFragment) {
MoveBodilessDeclarationsToSeparatePlaceLowering(context).let { moveBodiless ->
val bodilessBuiltInsPackageFragment = IrExternalPackageFragmentImpl( moduleFragment.files.forEach {
DescriptorlessExternalPackageFragmentSymbol(), moveBodiless.lower(it)
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
} }
}
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 { val externalPackageFragment by lazy {
context.externalPackageFragment.getOrPut(irFile.symbol) { context.externalPackageFragment.getOrPut(irFile.symbol) {
IrFileImpl(fileEntry = irFile.fileEntry, fqName = irFile.fqName, symbol = DescriptorlessIrFileSymbol()).also { 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) { if (irFile.getJsModule() != null || irFile.getJsQualifier() != null) {
context.packageLevelJsModules.add(irFile) externalPackageFragment.declarations += declaration
return null declaration.parent = externalPackageFragment
}
val it = irFile.declarations.iterator() context.packageLevelJsModules += externalPackageFragment
while (it.hasNext()) { return emptyList()
val d = it.next() as? IrDeclarationWithName ?: continue } else {
val d = declaration as? IrDeclarationWithName ?: return null
if (isBuiltInClass(d)) { if (isBuiltInClass(d)) {
it.remove() context.bodilessBuiltInsPackageFragment.addChild(d)
bodilessBuiltInsPackageFragment.addChild(d) return emptyList()
} else if (d.isEffectivelyExternal()) { } else if (d.isEffectivelyExternal()) {
if (d.getJsModule() != null) if (d.getJsModule() != null)
context.declarationLevelJsModules.add(d) context.declarationLevelJsModules.add(d)
it.remove() externalPackageFragment.declarations += d
externalPackageFragment.addChild(d) d.parent = externalPackageFragment
}
}
return irFile
}
module.files.transformFlat { irFile -> return emptyList()
listOfNotNull(lowerFile(irFile)) }
return null
}
} }
} }