Get rid of 'externalPackageFragments' and 'dependencyModules' in IrModuleFragment

This commit is contained in:
Mikhael Bogdanov
2018-07-31 15:06:34 +02:00
parent 0df6fddd0a
commit b22352a60d
8 changed files with 3 additions and 186 deletions
@@ -43,7 +43,7 @@ fun compile(
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext)
val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files).removeDuplicates()
val moduleFragment = psi2IrTranslator.generateModuleFragment(psi2IrContext, files)
val context = JsIrBackendContext(
analysisResult.moduleDescriptor,
@@ -113,18 +113,3 @@ private fun DeclarationContainerLoweringPass.runOnFilePostfix(files: List<IrFile
private fun BodyLoweringPass.runOnFilePostfix(files: List<IrFile>) = files.forEach { runOnFilePostfix(it) }
private fun FunctionLoweringPass.runOnFilePostfix(files: List<IrFile>) = files.forEach { runOnFilePostfix(it) }
private fun ClassLoweringPass.runOnFilePostfix(files: List<IrFile>) = files.forEach { runOnFilePostfix(it) }
// TODO find out why duplicates occur
private fun IrModuleFragment.removeDuplicates(): IrModuleFragment {
fun <T> MutableList<T>.removeDuplicates() {
val tmp = toSet()
clear()
addAll(tmp)
}
dependencyModules.removeDuplicates()
dependencyModules.forEach { it.externalPackageFragments.removeDuplicates() }
return this
}
@@ -59,42 +59,6 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: JsIrBackendContext)
symbolTable = context.symbolTable,
irBuiltIns = context.irBuiltIns
).generateUnboundSymbolsAsDependencies(this)
// Merge duplicated module and package declarations:
this.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {}
override fun visitModuleFragment(declaration: IrModuleFragment) {
declaration.dependencyModules.forEach { it.acceptVoid(this) }
val dependencyModules = declaration.dependencyModules.toSet().groupBy { it.descriptor }.map { (_, fragments) ->
fragments.reduce { firstModule, nextModule ->
firstModule.apply {
mergeFrom(nextModule)
}
}
}
declaration.dependencyModules.clear()
declaration.dependencyModules.addAll(dependencyModules)
}
})
}
private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit {
assert(this.files.isEmpty())
assert(other.files.isEmpty())
val thisPackages = this.externalPackageFragments.groupBy { it.packageFragmentDescriptor }
other.externalPackageFragments.forEach {
val thisPackage = thisPackages[it.packageFragmentDescriptor]?.toSet()?.single()
if (thisPackage == null) {
this.externalPackageFragments.add(it)
} else {
thisPackage.addChildren(it.declarations)
}
}
}
private class DeclarationSymbolCollector : IrElementVisitorVoid {
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -26,7 +27,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/irasdescriptors/NewIrUtils.kt
fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTable) {
fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: ReferenceSymbolTable) {
val moduleDescriptor = this.descriptor
fun KotlinType.referenceAllClassifiers() {
@@ -126,9 +127,4 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl
}
this.acceptVoid(visitor)
this.dependencyModules.forEach { module ->
module.externalPackageFragments.forEach {
it.acceptVoid(visitor)
}
}
}
@@ -28,8 +28,6 @@ interface IrModuleFragment : IrElement {
val descriptor: ModuleDescriptor
val irBuiltins: IrBuiltIns
val files: MutableList<IrFile>
val externalPackageFragments: MutableList<IrExternalPackageFragment>
val dependencyModules: MutableList<IrModuleFragment>
override val startOffset: Int get() = UNDEFINED_OFFSET
override val endOffset: Int get() = UNDEFINED_OFFSET
@@ -38,10 +38,6 @@ class IrModuleFragmentImpl(
override val files: MutableList<IrFile> = ArrayList()
override val externalPackageFragments: MutableList<IrExternalPackageFragment> = ArrayList()
override val dependencyModules: MutableList<IrModuleFragment> = ArrayList()
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitModuleFragment(this, data)
@@ -1,108 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
class DependenciesCollector {
private val modulesForDependencyDescriptors = LinkedHashSet<ModuleDescriptor>()
private val packageFragmentsForDependencyDescriptors = LinkedHashMap<ModuleDescriptor, MutableSet<PackageFragmentDescriptor>>()
private val topLevelDescriptors = LinkedHashMap<PackageFragmentDescriptor, MutableSet<DeclarationDescriptor>>()
val dependencyModules: Collection<ModuleDescriptor> get() = modulesForDependencyDescriptors
fun getPackageFragments(moduleDescriptor: ModuleDescriptor): Collection<PackageFragmentDescriptor> =
packageFragmentsForDependencyDescriptors[moduleDescriptor] ?: emptyList()
fun getTopLevelDescriptors(packageFragmentDescriptor: PackageFragmentDescriptor): Collection<DeclarationDescriptor> =
topLevelDescriptors[packageFragmentDescriptor] ?: emptyList()
val isEmpty get() = topLevelDescriptors.isEmpty()
fun collectTopLevelDescriptorsForUnboundSymbols(symbolTable: SymbolTable) {
assert(symbolTable.unboundTypeParameters.isEmpty()) { "Unbound type parameters: ${symbolTable.unboundTypeParameters}" }
assert(symbolTable.unboundValueParameters.isEmpty()) { "Unbound value parameters: ${symbolTable.unboundValueParameters}" }
assert(symbolTable.unboundVariables.isEmpty()) { "Unbound variables: ${symbolTable.unboundVariables}" }
symbolTable.markOverriddenFunctionsForUnboundFunctionsReferenced()
symbolTable.markSuperClassesForUnboundClassesReferenced()
symbolTable.unboundClasses.addTopLevelDeclarations()
symbolTable.unboundConstructors.addTopLevelDeclarations()
symbolTable.unboundEnumEntries.addTopLevelDeclarations()
symbolTable.unboundFields.addTopLevelDeclarations()
symbolTable.unboundSimpleFunctions.addTopLevelDeclarations()
}
private fun SymbolTable.markOverriddenFunctionsForUnboundFunctionsReferenced() {
for (unboundFunction in unboundSimpleFunctions.toTypedArray()) {
markOverriddenFunctionsReferenced(unboundFunction.descriptor, HashSet())
}
}
private fun SymbolTable.markOverriddenFunctionsReferenced(
function: FunctionDescriptor,
visitedFunctions: MutableSet<FunctionDescriptor>
) {
for (overridden in function.overriddenDescriptors) {
if (overridden !in visitedFunctions) {
visitedFunctions.add(overridden)
referenceFunction(overridden.original)
markOverriddenFunctionsReferenced(overridden, visitedFunctions)
}
}
}
private fun SymbolTable.markSuperClassesForUnboundClassesReferenced() {
for (unboundClass in unboundClasses.toTypedArray()) {
for (superClassifier in unboundClass.descriptor.getAllSuperClassifiers()) {
if (superClassifier is ClassDescriptor) {
referenceClass(superClassifier)
}
}
}
}
private fun Collection<IrSymbol>.addTopLevelDeclarations() {
forEach {
getTopLevelDeclaration(it.descriptor)?.let { addTopLevelDescriptor(it) }
}
}
private fun DeclarationDescriptor.isSyntheticJavaProperties() =
this is PropertyAccessorDescriptor &&
this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED &&
containingDeclaration is ModuleDescriptor
private fun getTopLevelDeclaration(descriptor: DeclarationDescriptor): DeclarationDescriptor? {
val containingDeclaration = descriptor.containingDeclaration
return when (containingDeclaration) {
is PackageFragmentDescriptor -> descriptor
is ClassDescriptor -> getTopLevelDeclaration(containingDeclaration)
else ->
if (descriptor.isDynamic() || descriptor.isSyntheticJavaProperties()) {
//skip
null
} else {
throw AssertionError("Package or class expected: $containingDeclaration; for $descriptor")
}
}
}
private fun addTopLevelDescriptor(descriptor: DeclarationDescriptor) {
val packageFragmentDescriptor = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor::class.java)!!
val moduleDescriptor = packageFragmentDescriptor.containingDeclaration
modulesForDependencyDescriptors.add(moduleDescriptor)
packageFragmentsForDependencyDescriptors.getOrPut(moduleDescriptor) { LinkedHashSet() }.add(packageFragmentDescriptor)
topLevelDescriptors.getOrPut(packageFragmentDescriptor) { LinkedHashSet() }.add(descriptor)
}
}
@@ -65,7 +65,6 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor<Unit, String> {
override fun visitModuleFragment(declaration: IrModuleFragment, data: String) {
declaration.dumpLabeledElementWith(data) {
declaration.files.dumpElements()
declaration.externalPackageFragments.dumpElements()
}
}
@@ -42,19 +42,6 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() {
for ((testFile, irFile) in ktFiles.zip(irModule.files)) {
doTestIrFileAgainstExpectations(dir, testFile, irFile)
}
if (shouldDumpDependencies(wholeFile)) {
doTestIrModuleDependencies(wholeFile, irModule)
}
}
private fun doTestIrModuleDependencies(wholeFile: File, irModule: IrModuleFragment) {
irModule.dependencyModules.forEach { irDependencyModule ->
val actual = irDependencyModule.dump()
val sanitizedModuleName = StringUtil.sanitizeJavaIdentifier(irDependencyModule.descriptor.name.asString())
val expectedFileName = wholeFile.absolutePath.replace(".kt", "__$sanitizedModuleName.txt")
KotlinTestUtils.assertEqualsToFile(File(expectedFileName), actual)
}
}
protected fun doTestIrFileAgainstExpectations(dir: File, testFile: TestFile, irFile: IrFile) {