IR: extract FakeOverrideBuilderStrategy to separate file
This commit is contained in:
+110
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.ir.overrides
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.StandardNames
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||||
|
import org.jetbrains.kotlin.ir.types.extractTypeParameters
|
||||||
|
import org.jetbrains.kotlin.ir.util.getPackageFragment
|
||||||
|
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
|
abstract class FakeOverrideBuilderStrategy(
|
||||||
|
private val friendModules: Map<String, Collection<String>>,
|
||||||
|
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
|
||||||
|
) {
|
||||||
|
fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember =
|
||||||
|
buildFakeOverrideMember(superType, member, clazz, friendModules, unimplementedOverridesStrategy)
|
||||||
|
|
||||||
|
fun postProcessGeneratedFakeOverride(fakeOverride: IrOverridableMember, clazz: IrClass) {
|
||||||
|
unimplementedOverridesStrategy.postProcessGeneratedFakeOverride(fakeOverride as IrOverridableDeclaration<*>, clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun linkFakeOverride(fakeOverride: IrOverridableMember, compatibilityMode: Boolean) {
|
||||||
|
when (fakeOverride) {
|
||||||
|
is IrFunctionWithLateBinding -> linkFunctionFakeOverride(fakeOverride, compatibilityMode)
|
||||||
|
is IrPropertyWithLateBinding -> linkPropertyFakeOverride(fakeOverride, compatibilityMode)
|
||||||
|
else -> error("Unexpected fake override: $fakeOverride")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun linkFunctionFakeOverride(function: IrFunctionWithLateBinding, manglerCompatibleMode: Boolean)
|
||||||
|
protected abstract fun linkPropertyFakeOverride(property: IrPropertyWithLateBinding, manglerCompatibleMode: Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ObsoleteDescriptorBasedAPI::class) // Because of the LazyIR, have to use descriptors here.
|
||||||
|
private fun IrOverridableMember.isPrivateToThisModule(
|
||||||
|
thisClass: IrClass, memberClass: IrClass, friendModules: Map<String, Collection<String>>,
|
||||||
|
): Boolean {
|
||||||
|
if (visibility != DescriptorVisibilities.INTERNAL) return false
|
||||||
|
|
||||||
|
val thisModule = thisClass.getPackageFragment().packageFragmentDescriptor.containingDeclaration
|
||||||
|
val memberModule = memberClass.getPackageFragment().packageFragmentDescriptor.containingDeclaration
|
||||||
|
|
||||||
|
return thisModule != memberModule && !isInFriendModules(thisModule, memberModule, friendModules)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isInFriendModules(
|
||||||
|
fromModule: ModuleDescriptor,
|
||||||
|
toModule: ModuleDescriptor,
|
||||||
|
friendModules: Map<String, Collection<String>>,
|
||||||
|
): Boolean {
|
||||||
|
if (friendModules.isEmpty()) return false
|
||||||
|
|
||||||
|
val fromModuleName = fromModule.name.asStringStripSpecialMarkers()
|
||||||
|
|
||||||
|
val fromFriends = friendModules[fromModuleName] ?: return false
|
||||||
|
|
||||||
|
val toModuleName = toModule.name.asStringStripSpecialMarkers()
|
||||||
|
|
||||||
|
return toModuleName in fromFriends
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildFakeOverrideMember(
|
||||||
|
superType: IrType,
|
||||||
|
member: IrOverridableMember,
|
||||||
|
clazz: IrClass,
|
||||||
|
friendModules: Map<String, Collection<String>> = emptyMap(),
|
||||||
|
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy = IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides,
|
||||||
|
): IrOverridableMember {
|
||||||
|
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
|
||||||
|
val classifier = superType.classifier
|
||||||
|
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
|
||||||
|
|
||||||
|
val typeParameters = extractTypeParameters(classifier.owner)
|
||||||
|
val superArguments = superType.arguments
|
||||||
|
require(typeParameters.size == superArguments.size) {
|
||||||
|
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
|
||||||
|
}
|
||||||
|
|
||||||
|
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
|
||||||
|
|
||||||
|
for (i in typeParameters.indices) {
|
||||||
|
val tp = typeParameters[i]
|
||||||
|
val ta = superArguments[i]
|
||||||
|
require(ta is IrTypeProjection) { "Unexpected super type argument: ${ta.render()} @ $i" }
|
||||||
|
require(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
|
||||||
|
substitutionMap[tp.symbol] = ta.type
|
||||||
|
}
|
||||||
|
|
||||||
|
return CopyIrTreeWithSymbolsForFakeOverrides(member, substitutionMap, clazz, unimplementedOverridesStrategy)
|
||||||
|
.copy()
|
||||||
|
.apply {
|
||||||
|
val isInvisible = isPrivateToThisModule(clazz, classifier.owner, friendModules)
|
||||||
|
if (isInvisible && !member.annotations.hasAnnotation(StandardNames.FqNames.publishedApi))
|
||||||
|
visibility = DescriptorVisibilities.INVISIBLE_FAKE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,110 +5,27 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.overrides
|
package org.jetbrains.kotlin.ir.overrides
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy
|
import org.jetbrains.kotlin.ir.linkage.partial.IrUnimplementedOverridesStrategy
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.collectAndFilterRealOverrides
|
||||||
|
import org.jetbrains.kotlin.ir.util.isReal
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
|
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.*
|
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
|
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
|
||||||
import org.jetbrains.kotlin.utils.memoryOptimizedMap
|
import org.jetbrains.kotlin.utils.memoryOptimizedMap
|
||||||
import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
|
import org.jetbrains.kotlin.utils.memoryOptimizedMapNotNull
|
||||||
|
|
||||||
abstract class FakeOverrideBuilderStrategy(
|
|
||||||
private val friendModules: Map<String, Collection<String>>,
|
|
||||||
private val unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy
|
|
||||||
) {
|
|
||||||
fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember =
|
|
||||||
buildFakeOverrideMember(superType, member, clazz, friendModules, unimplementedOverridesStrategy)
|
|
||||||
|
|
||||||
fun postProcessGeneratedFakeOverride(fakeOverride: IrOverridableMember, clazz: IrClass) {
|
|
||||||
unimplementedOverridesStrategy.postProcessGeneratedFakeOverride(fakeOverride as IrOverridableDeclaration<*>, clazz)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun linkFakeOverride(fakeOverride: IrOverridableMember, compatibilityMode: Boolean) {
|
|
||||||
when (fakeOverride) {
|
|
||||||
is IrFunctionWithLateBinding -> linkFunctionFakeOverride(fakeOverride, compatibilityMode)
|
|
||||||
is IrPropertyWithLateBinding -> linkPropertyFakeOverride(fakeOverride, compatibilityMode)
|
|
||||||
else -> error("Unexpected fake override: $fakeOverride")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun linkFunctionFakeOverride(function: IrFunctionWithLateBinding, manglerCompatibleMode: Boolean)
|
|
||||||
protected abstract fun linkPropertyFakeOverride(property: IrPropertyWithLateBinding, manglerCompatibleMode: Boolean)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class) // Because of the LazyIR, have to use descriptors here.
|
|
||||||
private fun IrOverridableMember.isPrivateToThisModule(thisClass: IrClass, memberClass: IrClass, friendModules: Map<String, Collection<String>>): Boolean {
|
|
||||||
if (visibility != DescriptorVisibilities.INTERNAL) return false
|
|
||||||
|
|
||||||
val thisModule = thisClass.getPackageFragment().packageFragmentDescriptor.containingDeclaration
|
|
||||||
val memberModule = memberClass.getPackageFragment().packageFragmentDescriptor.containingDeclaration
|
|
||||||
|
|
||||||
return thisModule != memberModule && !isInFriendModules(thisModule, memberModule, friendModules)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isInFriendModules(
|
|
||||||
fromModule: ModuleDescriptor,
|
|
||||||
toModule: ModuleDescriptor,
|
|
||||||
friendModules: Map<String, Collection<String>>
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
if (friendModules.isEmpty()) return false
|
|
||||||
|
|
||||||
val fromModuleName = fromModule.name.asStringStripSpecialMarkers()
|
|
||||||
|
|
||||||
val fromFriends = friendModules[fromModuleName] ?: return false
|
|
||||||
|
|
||||||
val toModuleName = toModule.name.asStringStripSpecialMarkers()
|
|
||||||
|
|
||||||
return toModuleName in fromFriends
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildFakeOverrideMember(
|
|
||||||
superType: IrType,
|
|
||||||
member: IrOverridableMember,
|
|
||||||
clazz: IrClass,
|
|
||||||
friendModules: Map<String, Collection<String>> = emptyMap(),
|
|
||||||
unimplementedOverridesStrategy: IrUnimplementedOverridesStrategy = IrUnimplementedOverridesStrategy.ProcessAsFakeOverrides
|
|
||||||
): IrOverridableMember {
|
|
||||||
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
|
|
||||||
val classifier = superType.classifier
|
|
||||||
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
|
|
||||||
|
|
||||||
val typeParameters = extractTypeParameters(classifier.owner)
|
|
||||||
val superArguments = superType.arguments
|
|
||||||
require(typeParameters.size == superArguments.size) {
|
|
||||||
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
|
|
||||||
|
|
||||||
for (i in typeParameters.indices) {
|
|
||||||
val tp = typeParameters[i]
|
|
||||||
val ta = superArguments[i]
|
|
||||||
require(ta is IrTypeProjection) { "Unexpected super type argument: ${ta.render()} @ $i" }
|
|
||||||
require(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
|
|
||||||
substitutionMap[tp.symbol] = ta.type
|
|
||||||
}
|
|
||||||
|
|
||||||
return CopyIrTreeWithSymbolsForFakeOverrides(member, substitutionMap, clazz, unimplementedOverridesStrategy)
|
|
||||||
.copy()
|
|
||||||
.apply {
|
|
||||||
val isInvisible = isPrivateToThisModule(clazz, classifier.owner, friendModules)
|
|
||||||
if (isInvisible && !member.annotations.hasAnnotation(StandardNames.FqNames.publishedApi))
|
|
||||||
visibility = DescriptorVisibilities.INVISIBLE_FAKE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// The below pile of code is basically half of OverridingUtil.java
|
// The below pile of code is basically half of OverridingUtil.java
|
||||||
// adapted to IR and converted to Kotlin.
|
// adapted to IR and converted to Kotlin.
|
||||||
|
|||||||
Reference in New Issue
Block a user