[FIR] Split functions & constructors processing
This commit is contained in:
+1
-1
@@ -190,7 +190,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() {
|
||||
for (declaration in javaClass.declarations) {
|
||||
if (declaration in renderedDeclarations) continue
|
||||
when (declaration) {
|
||||
is FirJavaConstructor -> enhancementScope.processFunctionsByName(javaClass.name) { symbol ->
|
||||
is FirJavaConstructor -> enhancementScope.processDeclaredConstructors { symbol ->
|
||||
val enhanced = symbol.fir
|
||||
if (enhanced !in renderedDeclarations) {
|
||||
enhanced.accept(renderer, null)
|
||||
|
||||
+14
-5
@@ -82,9 +82,9 @@ class JavaClassEnhancementScope(
|
||||
}
|
||||
|
||||
private fun enhance(
|
||||
original: FirCallableSymbol<*>,
|
||||
original: FirVariableSymbol<*>,
|
||||
name: Name
|
||||
): FirCallableSymbol<*> {
|
||||
): FirVariableSymbol<*> {
|
||||
when (val firElement = original.fir) {
|
||||
is FirField -> {
|
||||
if (firElement.returnTypeRef !is FirJavaTypeRef) return original
|
||||
@@ -139,7 +139,7 @@ class JavaClassEnhancementScope(
|
||||
|
||||
private fun enhance(
|
||||
original: FirFunctionSymbol<*>,
|
||||
name: Name
|
||||
name: Name?
|
||||
): FirFunctionSymbol<*> {
|
||||
val firMethod = original.fir
|
||||
|
||||
@@ -152,7 +152,7 @@ class JavaClassEnhancementScope(
|
||||
private fun enhanceMethod(
|
||||
firMethod: FirFunction<*>,
|
||||
methodId: CallableId,
|
||||
name: Name
|
||||
name: Name?
|
||||
): FirFunctionSymbol<*> {
|
||||
val memberContext = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, jsr305State, firMethod.annotations)
|
||||
|
||||
@@ -241,7 +241,7 @@ class JavaClassEnhancementScope(
|
||||
session = this@JavaClassEnhancementScope.session
|
||||
returnTypeRef = newReturnTypeRef
|
||||
receiverTypeRef = newReceiverTypeRef
|
||||
this.name = name
|
||||
this.name = name!!
|
||||
status = firMethod.status
|
||||
symbol = FirNamedFunctionSymbol(methodId)
|
||||
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
|
||||
@@ -402,4 +402,13 @@ class JavaClassEnhancementScope(
|
||||
)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
|
||||
useSiteMemberScope.processDeclaredConstructors process@{ original ->
|
||||
|
||||
val function = enhancements.getOrPut(original) { enhance(original, name = null) }
|
||||
processor(function as FirConstructorSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -17,11 +18,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
class JvmMappedScope(
|
||||
private val declaredMemberScope: FirScope,
|
||||
private val javaMappedClassUseSiteScope: FirScope,
|
||||
private val whiteListSignaturesByName: Map<Name, List<String>>
|
||||
private val signatures: Signatures
|
||||
) : FirScope() {
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
|
||||
val whiteListSignatures = whiteListSignaturesByName[name]
|
||||
val whiteListSignatures = signatures.whiteListSignaturesByName[name]
|
||||
?: return declaredMemberScope.processFunctionsByName(name, processor)
|
||||
javaMappedClassUseSiteScope.processFunctionsByName(name) { symbol ->
|
||||
val jvmSignature = symbol.fir.computeJvmDescriptor()
|
||||
@@ -36,6 +37,22 @@ class JvmMappedScope(
|
||||
declaredMemberScope.processFunctionsByName(name, processor)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
val constructorBlackList = signatures.constructorBlackList
|
||||
if (constructorBlackList.isNotEmpty()) {
|
||||
javaMappedClassUseSiteScope.processDeclaredConstructors { symbol ->
|
||||
val jvmSignature = symbol.fir.computeJvmDescriptor()
|
||||
.replace("kotlin/Any", "java/lang/Object")
|
||||
.replace("kotlin/String", "java/lang/String")
|
||||
if (jvmSignature !in constructorBlackList) {
|
||||
processor(symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declaredMemberScope.processDeclaredConstructors(processor)
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
declaredMemberScope.processPropertiesByName(name, processor)
|
||||
}
|
||||
@@ -45,15 +62,27 @@ class JvmMappedScope(
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun prepareSignatures(klass: FirRegularClass): Map<Name, List<String>> {
|
||||
data class Signatures(val whiteListSignaturesByName: Map<Name, Set<String>>, val constructorBlackList: Set<String>) {
|
||||
fun isEmpty() = whiteListSignaturesByName.isEmpty() && constructorBlackList.isEmpty()
|
||||
fun isNotEmpty() = !isEmpty()
|
||||
}
|
||||
|
||||
fun prepareSignatures(klass: FirRegularClass): Signatures {
|
||||
val signaturePrefix = klass.symbol.classId.toString()
|
||||
val filteredSignatures = JvmBuiltInsSettings.WHITE_LIST_METHOD_SIGNATURES.filter { signature ->
|
||||
val whiteListSignaturesByName = mutableMapOf<Name, MutableSet<String>>()
|
||||
JvmBuiltInsSettings.WHITE_LIST_METHOD_SIGNATURES.filter { signature ->
|
||||
signature.startsWith(signaturePrefix)
|
||||
}.map { signature ->
|
||||
// +1 to delete dot before function name
|
||||
signature.substring(signaturePrefix.length + 1)
|
||||
}.forEach {
|
||||
whiteListSignaturesByName.getOrPut(Name.identifier(it.substringBefore("("))) { mutableSetOf() }.add(it)
|
||||
}
|
||||
return filteredSignatures.groupBy { Name.identifier(it.substringBefore("(")) }
|
||||
|
||||
val constructorBlackList = JvmBuiltInsSettings.BLACK_LIST_CONSTRUCTOR_SIGNATURES
|
||||
.filter { it.startsWith(signaturePrefix) }
|
||||
.mapTo(mutableSetOf()) { it.substring(signaturePrefix.length + 1) }
|
||||
return Signatures(whiteListSignaturesByName, constructorBlackList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,12 +308,10 @@ class FirCallResolver(
|
||||
val candidateFactory = CandidateFactory(this, callInfo)
|
||||
val candidates = mutableListOf<Candidate>()
|
||||
|
||||
scope.processFunctionsByName(className) {
|
||||
if (it is FirConstructorSymbol) {
|
||||
val candidate = candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
|
||||
candidates += candidate
|
||||
}
|
||||
scope.processDeclaredConstructors {
|
||||
val candidate = candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
|
||||
candidate.typeArgumentMapping = TypeArgumentMapping.Mapped(typeArguments)
|
||||
candidates += candidate
|
||||
}
|
||||
return callResolver.selectDelegatingConstructorCall(delegatedConstructorCall, className, candidates)
|
||||
}
|
||||
|
||||
+73
-59
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructedClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.scopes.scope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
@@ -24,6 +25,9 @@ import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
private operator fun <T> Pair<T, *>?.component1() = this?.first
|
||||
private operator fun <T> Pair<*, T>?.component2() = this?.second
|
||||
|
||||
internal fun FirScope.processFunctionsAndConstructorsByName(
|
||||
name: Name,
|
||||
session: FirSession,
|
||||
@@ -32,34 +36,38 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
|
||||
processor: (FirCallableSymbol<*>) -> Unit
|
||||
) {
|
||||
// TODO: Handle case with two or more accessible classifiers
|
||||
val matchedClassSymbol = getFirstClassifierOrNull(name) as? FirClassLikeSymbol<*>
|
||||
val classifierInfo = getFirstClassifierOrNull(name)
|
||||
if (classifierInfo != null) {
|
||||
val (matchedClassifierSymbol, substitutor) = classifierInfo
|
||||
val matchedClassSymbol = matchedClassifierSymbol as? FirClassLikeSymbol<*>
|
||||
|
||||
processConstructors(
|
||||
matchedClassSymbol,
|
||||
processor,
|
||||
session,
|
||||
bodyResolveComponents.scopeSession,
|
||||
noInnerConstructors
|
||||
)
|
||||
|
||||
processSyntheticConstructors(
|
||||
matchedClassSymbol,
|
||||
processor,
|
||||
bodyResolveComponents
|
||||
)
|
||||
processConstructors(
|
||||
matchedClassSymbol,
|
||||
substitutor,
|
||||
processor,
|
||||
session,
|
||||
bodyResolveComponents.scopeSession,
|
||||
noInnerConstructors
|
||||
)
|
||||
|
||||
processSyntheticConstructors(
|
||||
matchedClassSymbol,
|
||||
processor,
|
||||
bodyResolveComponents
|
||||
)
|
||||
}
|
||||
|
||||
processFunctionsByName(name) {
|
||||
if (it !is FirConstructorSymbol) {
|
||||
processor(it)
|
||||
}
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirScope.getFirstClassifierOrNull(name: Name): FirClassifierSymbol<*>? {
|
||||
var result: FirClassifierSymbol<*>? = null
|
||||
processClassifiersByName(name) {
|
||||
private fun FirScope.getFirstClassifierOrNull(name: Name): Pair<FirClassifierSymbol<*>, ConeSubstitutor>? {
|
||||
var result: Pair<FirClassifierSymbol<*>, ConeSubstitutor>? = null
|
||||
processClassifiersByNameWithSubstitution(name) { symbol, substitution ->
|
||||
if (result == null) {
|
||||
result = it
|
||||
result = symbol to substitution
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +135,7 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
|
||||
|
||||
private fun processConstructors(
|
||||
matchedSymbol: FirClassLikeSymbol<*>?,
|
||||
substitutor: ConeSubstitutor,
|
||||
processor: (FirFunctionSymbol<*>) -> Unit,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
@@ -145,18 +154,15 @@ private fun processConstructors(
|
||||
) ?: return
|
||||
} else basicScope
|
||||
}
|
||||
is FirClassSymbol -> (matchedSymbol.fir as FirClass<*>).unsubstitutedScope(session, scopeSession)
|
||||
}
|
||||
|
||||
val constructorName = when (matchedSymbol) {
|
||||
is FirTypeAliasSymbol -> finalExpansionName(matchedSymbol, session) ?: return
|
||||
is FirRegularClassSymbol -> matchedSymbol.fir.name
|
||||
else -> return
|
||||
is FirClassSymbol ->
|
||||
(matchedSymbol.fir as FirClass<*>).scope(
|
||||
substitutor, session, scopeSession, false,
|
||||
)
|
||||
}
|
||||
|
||||
//TODO: why don't we use declared member scope at this point?
|
||||
scope?.processFunctionsByName(constructorName) {
|
||||
if (!noInner || (it as? FirConstructorSymbol)?.fir?.isInner != true) {
|
||||
scope?.processDeclaredConstructors {
|
||||
if (!noInner || !it.fir.isInner) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
@@ -169,29 +175,37 @@ private fun processConstructors(
|
||||
}
|
||||
|
||||
private class TypeAliasConstructorsSubstitutingScope(
|
||||
private val typeAliasConstructorsSubstitutor: TypeAliasConstructorsSubstitutor<FirConstructor>,
|
||||
private val typeAliasSymbol: FirTypeAliasSymbol,
|
||||
private val copyFactory: ConstructorCopyFactory<FirConstructor>,
|
||||
private val delegatingScope: FirScope
|
||||
) : FirScope() {
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) {
|
||||
delegatingScope.processFunctionsByName(name) {
|
||||
val toProcess = if (it is FirConstructorSymbol) {
|
||||
typeAliasConstructorsSubstitutor.substitute(it.fir).symbol
|
||||
} else {
|
||||
it
|
||||
}
|
||||
|
||||
processor(toProcess)
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
delegatingScope.processDeclaredConstructors {
|
||||
|
||||
val typeParameters = typeAliasSymbol.fir.typeParameters
|
||||
if (typeParameters.isEmpty()) processor(it)
|
||||
else {
|
||||
processor(it.fir.copyFactory(
|
||||
null,
|
||||
null,
|
||||
typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
|
||||
).symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private typealias ConstructorCopyFactory2<F> =
|
||||
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List<ConeKotlinType?>?, newTypeParameters: List<FirTypeParameter>) -> F
|
||||
|
||||
private typealias ConstructorCopyFactory<F> =
|
||||
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List<ConeKotlinType?>, newTypeParameters: List<FirTypeParameter>) -> F
|
||||
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List<ConeKotlinType?>?, newTypeParameters: List<FirTypeParameterRef>) -> F
|
||||
|
||||
private class TypeAliasConstructorsSubstitutor<F : FirFunction<F>>(
|
||||
private val typeAliasSymbol: FirTypeAliasSymbol,
|
||||
private val substitutor: ConeSubstitutor,
|
||||
private val copyFactory: ConstructorCopyFactory<F>
|
||||
private val copyFactory: ConstructorCopyFactory2<F>
|
||||
) {
|
||||
fun substitute(baseFunction: F): F {
|
||||
val typeParameters = typeAliasSymbol.fir.typeParameters
|
||||
@@ -217,20 +231,16 @@ private fun prepareSubstitutingScopeForTypeAliasConstructors(
|
||||
session: FirSession,
|
||||
delegatingScope: FirScope
|
||||
): FirScope? {
|
||||
val typeAliasConstructorsSubstitutor =
|
||||
prepareSubstitutorForTypeAliasConstructors<FirConstructor>(
|
||||
typeAliasSymbol,
|
||||
expandedType,
|
||||
session
|
||||
) factory@{ newReturnType, newParameterTypes, newTypeParameters ->
|
||||
buildConstructor {
|
||||
source = this@factory.source
|
||||
this.session = session
|
||||
returnTypeRef = this@factory.returnTypeRef.withReplacedConeType(newReturnType)
|
||||
receiverTypeRef = this@factory.receiverTypeRef
|
||||
status = this@factory.status
|
||||
symbol = FirConstructorSymbol(this@factory.symbol.callableId, overriddenSymbol = this@factory.symbol)
|
||||
resolvePhase = this@factory.resolvePhase
|
||||
val copyFactory2: ConstructorCopyFactory<FirConstructor> = factory@ { newReturnType, newParameterTypes, newTypeParameters ->
|
||||
buildConstructor {
|
||||
source = this@factory.source
|
||||
this.session = session
|
||||
returnTypeRef = this@factory.returnTypeRef.withReplacedConeType(newReturnType)
|
||||
receiverTypeRef = this@factory.receiverTypeRef
|
||||
status = this@factory.status
|
||||
symbol = FirConstructorSymbol(this@factory.symbol.callableId, overriddenSymbol = this@factory.symbol)
|
||||
resolvePhase = this@factory.resolvePhase
|
||||
if (newParameterTypes != null) {
|
||||
valueParameters +=
|
||||
this@factory.valueParameters.zip(
|
||||
newParameterTypes
|
||||
@@ -247,12 +257,16 @@ private fun prepareSubstitutingScopeForTypeAliasConstructors(
|
||||
isVararg = valueParameter.isVararg
|
||||
}
|
||||
}
|
||||
this.typeParameters += newTypeParameters
|
||||
} else {
|
||||
valueParameters += this@factory.valueParameters
|
||||
}
|
||||
} ?: return null
|
||||
this.typeParameters += newTypeParameters
|
||||
}
|
||||
}
|
||||
|
||||
return TypeAliasConstructorsSubstitutingScope(
|
||||
typeAliasConstructorsSubstitutor,
|
||||
typeAliasSymbol,
|
||||
copyFactory2,
|
||||
delegatingScope
|
||||
)
|
||||
}
|
||||
@@ -261,7 +275,7 @@ private fun <F : FirFunction<F>> prepareSubstitutorForTypeAliasConstructors(
|
||||
typeAliasSymbol: FirTypeAliasSymbol,
|
||||
expandedType: ConeClassLikeType,
|
||||
session: FirSession,
|
||||
copyFactory: ConstructorCopyFactory<F>
|
||||
copyFactory: ConstructorCopyFactory2<F>
|
||||
): TypeAliasConstructorsSubstitutor<F>? {
|
||||
val expandedClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null
|
||||
|
||||
|
||||
+4
-3
@@ -11,9 +11,6 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.FirValueParameterBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
@@ -123,4 +120,8 @@ abstract class AbstractFirUseSiteMemberScope(
|
||||
declaredMemberScope.processClassifiersByNameWithSubstitution(name, processor)
|
||||
superTypesScope.processClassifiersByNameWithSubstitution(name, processor)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
declaredMemberScope.processDeclaredConstructors(processor)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirClassDeclaredMemberScope(
|
||||
@@ -33,7 +30,7 @@ class FirClassDeclaredMemberScope(
|
||||
when (declaration) {
|
||||
is FirCallableMemberDeclaration<*> -> {
|
||||
val name = when (declaration) {
|
||||
is FirConstructor -> if (klass is FirRegularClass) klass.name else continue@loop
|
||||
is FirConstructor -> Name.special("<init>")
|
||||
is FirVariable<*> -> declaration.name
|
||||
is FirSimpleFunction -> declaration.name
|
||||
else -> continue@loop
|
||||
@@ -54,6 +51,15 @@ class FirClassDeclaredMemberScope(
|
||||
}
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
val symbols = callablesIndex[Name.special("<init>")] ?: return
|
||||
for (symbol in symbols) {
|
||||
if (symbol is FirConstructorSymbol) {
|
||||
processor(symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
val symbols = callablesIndex[name] ?: emptyList()
|
||||
for (symbol in symbols) {
|
||||
|
||||
+114
-15
@@ -40,6 +40,7 @@ class FirClassSubstitutionScope(
|
||||
) : FirScope() {
|
||||
|
||||
private val fakeOverrideFunctions = mutableMapOf<FirFunctionSymbol<*>, FirFunctionSymbol<*>>()
|
||||
private val fakeOverrideConstructors = mutableMapOf<FirConstructorSymbol, FirConstructorSymbol>()
|
||||
private val fakeOverrideProperties = mutableMapOf<FirPropertySymbol, FirPropertySymbol>()
|
||||
private val fakeOverrideFields = mutableMapOf<FirFieldSymbol, FirFieldSymbol>()
|
||||
private val fakeOverrideAccessors = mutableMapOf<FirAccessorSymbol, FirAccessorSymbol>()
|
||||
@@ -127,35 +128,66 @@ class FirClassSubstitutionScope(
|
||||
}
|
||||
|
||||
return createFakeOverrideFunction(
|
||||
session, member, original, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, derivedClassId
|
||||
session,
|
||||
member,
|
||||
original,
|
||||
newReceiverType,
|
||||
newReturnType,
|
||||
newParameterTypes,
|
||||
newTypeParameters as List<FirTypeParameter>,
|
||||
derivedClassId
|
||||
)
|
||||
}
|
||||
|
||||
private fun createFakeOverrideConstructor(original: FirConstructorSymbol): FirConstructorSymbol {
|
||||
if (substitutor == ConeSubstitutor.Empty) return original
|
||||
val constructor = original.fir
|
||||
val (newTypeParameters, newSubstitutor) = createNewTypeParametersAndSubstitutor(constructor)
|
||||
|
||||
|
||||
val returnType = constructor.returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
||||
val newReturnType = returnType.substitute(newSubstitutor)
|
||||
|
||||
val newParameterTypes = constructor.valueParameters.map {
|
||||
it.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().substitute(newSubstitutor)
|
||||
}
|
||||
|
||||
if (newReturnType == null && newParameterTypes.all { it == null } && newTypeParameters === constructor.typeParameters) {
|
||||
return original
|
||||
}
|
||||
return createFakeOverrideConstructor(FirConstructorSymbol(original.callableId, overriddenSymbol = original), session, constructor, null, newReturnType, newParameterTypes, newTypeParameters).symbol
|
||||
}
|
||||
|
||||
// Returns a list of type parameters, and a substitutor that should be used for all other types
|
||||
private fun createNewTypeParametersAndSubstitutor(
|
||||
member: FirCallableMemberDeclaration<*>
|
||||
): Pair<List<FirTypeParameter>, ConeSubstitutor> {
|
||||
member: FirTypeParameterRefsOwner
|
||||
): Pair<List<FirTypeParameterRef>, ConeSubstitutor> {
|
||||
if (member.typeParameters.isEmpty()) return Pair(member.typeParameters, substitutor)
|
||||
val newTypeParameters = member.typeParameters.map { originalParameter ->
|
||||
val newTypeParameters = member.typeParameters.map { typeParameter ->
|
||||
if (typeParameter !is FirTypeParameter) return@map null
|
||||
FirTypeParameterBuilder().apply {
|
||||
source = originalParameter.source
|
||||
session = originalParameter.session
|
||||
name = originalParameter.name
|
||||
source = typeParameter.source
|
||||
session = typeParameter.session
|
||||
name = typeParameter.name
|
||||
symbol = FirTypeParameterSymbol()
|
||||
variance = originalParameter.variance
|
||||
isReified = originalParameter.isReified
|
||||
annotations += originalParameter.annotations
|
||||
variance = typeParameter.variance
|
||||
isReified = typeParameter.isReified
|
||||
annotations += typeParameter.annotations
|
||||
}
|
||||
}
|
||||
|
||||
val substitutionMapForNewParameters = member.typeParameters.zip(newTypeParameters).map {
|
||||
Pair(it.first.symbol, ConeTypeParameterTypeImpl(it.second.symbol.toLookupTag(), isNullable = false))
|
||||
val substitutionMapForNewParameters = member.typeParameters.zip(newTypeParameters).mapNotNull { (original, new) ->
|
||||
if (new != null)
|
||||
Pair(original.symbol, ConeTypeParameterTypeImpl(new.symbol.toLookupTag(), isNullable = false))
|
||||
else null
|
||||
}.toMap()
|
||||
|
||||
val additionalSubstitutor = substitutorByMap(substitutionMapForNewParameters)
|
||||
|
||||
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(member.typeParameters)) {
|
||||
for (boundTypeRef in oldTypeParameter.bounds) {
|
||||
if (newTypeParameter == null) continue
|
||||
val original = oldTypeParameter as FirTypeParameter
|
||||
for (boundTypeRef in original.bounds) {
|
||||
val typeForBound = boundTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
||||
val substitutedBound = typeForBound.substitute()
|
||||
newTypeParameter.bounds +=
|
||||
@@ -171,7 +203,10 @@ class FirClassSubstitutionScope(
|
||||
// While common Ir contracts expect them to be different
|
||||
// if (!wereChangesInTypeParameters) return Pair(member.typeParameters, substitutor)
|
||||
|
||||
return Pair(newTypeParameters.map { it.build() }, ChainedSubstitutor(substitutor, additionalSubstitutor))
|
||||
return Pair(
|
||||
newTypeParameters.mapIndexed { index, builder -> builder?.build() ?: member.typeParameters[index] },
|
||||
ChainedSubstitutor(substitutor, additionalSubstitutor)
|
||||
)
|
||||
}
|
||||
|
||||
private fun createFakeOverrideProperty(original: FirPropertySymbol): FirPropertySymbol {
|
||||
@@ -193,7 +228,16 @@ class FirClassSubstitutionScope(
|
||||
return original
|
||||
}
|
||||
|
||||
return createFakeOverrideProperty(session, member, original, newReceiverType, newReturnType, newTypeParameters, derivedClassId)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return createFakeOverrideProperty(
|
||||
session,
|
||||
member,
|
||||
original,
|
||||
newReceiverType,
|
||||
newReturnType,
|
||||
newTypeParameters as List<FirTypeParameter>,
|
||||
derivedClassId
|
||||
)
|
||||
}
|
||||
|
||||
private fun createFakeOverrideField(original: FirFieldSymbol): FirFieldSymbol {
|
||||
@@ -369,6 +413,61 @@ class FirClassSubstitutionScope(
|
||||
delegateGetter = function
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private fun createFakeOverrideConstructor(
|
||||
fakeOverrideSymbol: FirConstructorSymbol,
|
||||
session: FirSession,
|
||||
baseConstructor: FirConstructor,
|
||||
newReceiverType: ConeKotlinType? = null,
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newParameterTypes: List<ConeKotlinType?>? = null,
|
||||
newTypeParameters: List<FirTypeParameterRef>? = null
|
||||
): FirConstructor {
|
||||
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
|
||||
// As second alternative, we can invent some light-weight kind of FirRegularClass
|
||||
return buildConstructor {
|
||||
source = baseConstructor.source
|
||||
this.session = session
|
||||
returnTypeRef = baseConstructor.returnTypeRef.withReplacedReturnType(newReturnType)
|
||||
receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(newReceiverType)
|
||||
status = baseConstructor.status
|
||||
symbol = fakeOverrideSymbol
|
||||
annotations += baseConstructor.annotations
|
||||
resolvePhase = baseConstructor.resolvePhase
|
||||
valueParameters += baseConstructor.valueParameters.zip(
|
||||
newParameterTypes ?: List(baseConstructor.valueParameters.size) { null }
|
||||
) { valueParameter, newType ->
|
||||
buildValueParameter {
|
||||
source = valueParameter.source
|
||||
this.session = session
|
||||
returnTypeRef = valueParameter.returnTypeRef.withReplacedConeType(newType)
|
||||
name = valueParameter.name
|
||||
symbol = FirVariableSymbol(valueParameter.symbol.callableId)
|
||||
defaultValue = valueParameter.defaultValue
|
||||
isCrossinline = valueParameter.isCrossinline
|
||||
isNoinline = valueParameter.isNoinline
|
||||
isVararg = valueParameter.isVararg
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fix the hack for org.jetbrains.kotlin.fir.backend.Fir2IrVisitor.addFakeOverrides
|
||||
// We might have added baseFunction.typeParameters in case new ones are null
|
||||
// But it fails at org.jetbrains.kotlin.ir.AbstractIrTextTestCase.IrVerifier.elementsAreUniqueChecker
|
||||
// because it shares the same declarations of type parameters between two different two functions
|
||||
if (newTypeParameters != null) {
|
||||
typeParameters += newTypeParameters
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
useSiteMemberScope.processDeclaredConstructors process@{ original ->
|
||||
|
||||
val constructor = fakeOverrideConstructors.getOrPut(original) { createFakeOverrideConstructor(original) }
|
||||
processor(constructor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -26,6 +27,10 @@ abstract class FirScope {
|
||||
name: Name,
|
||||
processor: (FirVariableSymbol<*>) -> Unit
|
||||
) {}
|
||||
|
||||
open fun processDeclaredConstructors(
|
||||
processor: (FirConstructorSymbol) -> Unit
|
||||
) {}
|
||||
}
|
||||
|
||||
enum class ProcessorAction {
|
||||
|
||||
Reference in New Issue
Block a user