[FIR] Split functions & constructors processing

This commit is contained in:
simon.ogorodnik
2020-04-09 22:34:23 +03:00
parent 7a1ecabe0a
commit c2ea0676e4
9 changed files with 260 additions and 99 deletions
@@ -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)
@@ -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)
}
@@ -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
@@ -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)
}
}
@@ -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) {
@@ -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 {