Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.resolve.calls.ConstructorProcessing.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2019 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.fir.resolve.calls
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.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
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.scope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.Name
private operator fun Pair?.component1() = this?.first
private operator fun Pair<*, T>?.component2() = this?.second
internal fun FirScope.processConstructorsByName(
name: Name,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
includeInnerConstructors: Boolean,
processor: (FirCallableSymbol<*>) -> Unit
) {
// TODO: Handle case with two or more accessible classifiers
val classifierInfo = getFirstClassifierOrNull(name)
if (classifierInfo != null) {
val (matchedClassifierSymbol, substitutor) = classifierInfo
val matchedClassSymbol = matchedClassifierSymbol as? FirClassLikeSymbol<*>
processConstructors(
matchedClassSymbol,
substitutor,
processor,
session,
bodyResolveComponents.scopeSession,
includeInnerConstructors
)
processSyntheticConstructors(
matchedClassSymbol,
processor,
bodyResolveComponents
)
}
}
internal fun FirScope.processFunctionsAndConstructorsByName(
name: Name,
session: FirSession,
bodyResolveComponents: BodyResolveComponents,
includeInnerConstructors: Boolean,
processor: (FirCallableSymbol<*>) -> Unit
) {
processConstructorsByName(
name, session, bodyResolveComponents,
includeInnerConstructors = includeInnerConstructors,
processor
)
processFunctionsByName(name, processor)
}
private fun FirScope.getFirstClassifierOrNull(name: Name): Pair, ConeSubstitutor>? {
var result: Pair, ConeSubstitutor>? = null
processClassifiersByNameWithSubstitution(name) { symbol, substitution ->
if (result == null) {
result = symbol to substitution
}
}
return result
}
private fun processSyntheticConstructors(
matchedSymbol: FirClassLikeSymbol<*>?,
processor: (FirFunctionSymbol<*>) -> Unit,
bodyResolveComponents: BodyResolveComponents
) {
val samConstructor = matchedSymbol.findSAMConstructor(bodyResolveComponents)
if (samConstructor != null) {
processor(samConstructor.symbol)
}
}
private fun FirClassLikeSymbol<*>?.findSAMConstructor(
bodyResolveComponents: BodyResolveComponents
): FirSimpleFunction? {
return when (this) {
is FirRegularClassSymbol -> bodyResolveComponents.samResolver.getSamConstructor(fir)
is FirTypeAliasSymbol -> findSAMConstructorForTypeAlias(bodyResolveComponents)
is FirAnonymousObjectSymbol, null -> null
}
}
private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
bodyResolveComponents: BodyResolveComponents
): FirSimpleFunction? {
val session = bodyResolveComponents.session
val type =
fir.expandedTypeRef.coneTypeUnsafe().fullyExpandedType(session)
val expansionRegularClass = type.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null
val samConstructorForClass = bodyResolveComponents.samResolver.getSamConstructor(expansionRegularClass) ?: return null
if (type.typeArguments.isEmpty()) return samConstructorForClass
val namedSymbol = samConstructorForClass.symbol as? FirNamedFunctionSymbol ?: return null
val substitutor = prepareSubstitutorForTypeAliasConstructors(
this,
type,
session
) { newReturnType, newParameterTypes, newTypeParameters ->
FirClassSubstitutionScope.createFakeOverrideFunction(
session, this, namedSymbol, null,
newReturnType, newParameterTypes, newTypeParameters
).fir
} ?: return null
return substitutor.substitute(samConstructorForClass)
}
private fun processConstructors(
matchedSymbol: FirClassLikeSymbol<*>?,
substitutor: ConeSubstitutor,
processor: (FirFunctionSymbol<*>) -> Unit,
session: FirSession,
scopeSession: ScopeSession,
includeInnerConstructors: Boolean
) {
try {
if (matchedSymbol != null) {
val scope = when (matchedSymbol) {
is FirTypeAliasSymbol -> {
val type = matchedSymbol.fir.expandedTypeRef.coneTypeUnsafe().fullyExpandedType(session)
val basicScope = type.scope(session, scopeSession)
if (basicScope != null && type.typeArguments.isNotEmpty()) {
prepareSubstitutingScopeForTypeAliasConstructors(
matchedSymbol, session, basicScope
) ?: return
} else basicScope
}
is FirClassSymbol ->
(matchedSymbol.fir as FirClass<*>).scope(
substitutor, session, scopeSession, skipPrivateMembers = false,
)
}
//TODO: why don't we use declared member scope at this point?
scope?.processDeclaredConstructors {
if (includeInnerConstructors || !it.fir.isInner) {
processor(it)
}
}
}
} catch (e: Throwable) {
throw RuntimeException("While processing constructors", e)
}
}
private class TypeAliasConstructorsSubstitutingScope(
private val typeAliasSymbol: FirTypeAliasSymbol,
private val copyFactory: ConstructorCopyFactory,
private val delegatingScope: FirScope
) : FirScope() {
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.(newReturnType: ConeKotlinType?, newValueParameterTypes: List?, newTypeParameters: List) -> F
private typealias ConstructorCopyFactory =
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List?, newTypeParameters: List) -> F
private class TypeAliasConstructorsSubstitutor>(
private val typeAliasSymbol: FirTypeAliasSymbol,
private val substitutor: ConeSubstitutor,
private val copyFactory: ConstructorCopyFactory2
) {
fun substitute(baseFunction: F): F {
val typeParameters = typeAliasSymbol.fir.typeParameters
val newReturnType = baseFunction.returnTypeRef.coneType.let(substitutor::substituteOrNull)
val newParameterTypes = baseFunction.valueParameters.map { valueParameter ->
valueParameter.returnTypeRef.coneType.let(substitutor::substituteOrNull)
}
if (newReturnType == null && newParameterTypes.all { it == null }) return baseFunction
return baseFunction.copyFactory(
newReturnType,
newParameterTypes,
typeParameters
)
}
}
private fun prepareSubstitutingScopeForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol,
session: FirSession,
delegatingScope: FirScope
): FirScope? {
val copyFactory2: ConstructorCopyFactory = factory@{ newReturnType, newParameterTypes, newTypeParameters ->
buildConstructor {
source = [email protected]
this.session = session
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = [email protected] (newReturnType)
receiverTypeRef = [email protected]
status = [email protected]
symbol = FirConstructorSymbol([email protected] , overriddenSymbol = [email protected] )
resolvePhase = [email protected]
if (newParameterTypes != null) {
valueParameters +=
[email protected] (
newParameterTypes
) { valueParameter, newParameterType ->
buildValueParameter {
source = valueParameter.source
this.session = session
resolvePhase = valueParameter.resolvePhase
origin = FirDeclarationOrigin.FakeOverride
returnTypeRef = valueParameter.returnTypeRef.withReplacedConeType(newParameterType)
name = valueParameter.name
symbol = FirVariableSymbol(valueParameter.symbol.callableId)
defaultValue = valueParameter.defaultValue
isCrossinline = valueParameter.isCrossinline
isNoinline = valueParameter.isNoinline
isVararg = valueParameter.isVararg
}
}
} else {
valueParameters += [email protected]
}
this.typeParameters += newTypeParameters
}
}
return TypeAliasConstructorsSubstitutingScope(
typeAliasSymbol,
copyFactory2,
delegatingScope
)
}
private fun > prepareSubstitutorForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol,
expandedType: ConeClassLikeType,
session: FirSession,
copyFactory: ConstructorCopyFactory2
): TypeAliasConstructorsSubstitutor? {
val expandedClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null
val resultingTypeArguments = expandedType.typeArguments.map {
// We don't know how to handle cases like yet
// typealias A = ArrayList<*>()
it as? ConeKotlinType ?: return null
}
val substitutor = substitutorByMap(
expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap()
)
return TypeAliasConstructorsSubstitutor(typeAliasSymbol, substitutor, copyFactory)
}