FIR: Re-implement call resolver with proper architecture

This commit is contained in:
Simon Ogorodnik
2019-03-18 21:51:51 +03:00
parent 33b44870d6
commit a562f3db3c
3 changed files with 341 additions and 332 deletions
@@ -7,9 +7,8 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
@@ -22,70 +21,294 @@ import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction
import org.jetbrains.kotlin.fir.service import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.* import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.utils.addToStdlib.cast
import java.util.*
import kotlin.collections.LinkedHashSet
class CallResolver(val typeCalculator: ReturnTypeCalculator) {
lateinit var checkers: List<ApplicabilityChecker> class CallInfo(
lateinit var scopes: List<FirScope> val variableAccess: Boolean,
val explicitReceiver: FirExpression?,
val argumentCount: Int
) {
private val names = LinkedHashSet<Name>() }
private val newNames = mutableSetOf<Name>()
fun pushName(name: Name) { interface CheckerSink {
newNames += name fun reportApplicability(new: CandidateApplicability)
}
class CheckerSinkImpl : CheckerSink {
var current = CandidateApplicability.RESOLVED
override fun reportApplicability(new: CandidateApplicability) {
if (new < current) current = new
}
}
private abstract class Checker {
abstract fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo)
}
private object MapArguments : Checker() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol as? FirFunctionSymbol ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
if (symbol.firUnsafe<FirFunction>().valueParameters.size != callInfo.argumentCount) {
return sink.reportApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
}
} }
fun runTowerResolver(): ApplicabilityChecker? { }
processedScopes.clear()
newNames.clear()
names.clear()
var successChecker: ApplicabilityChecker? = null
checkers.forEach { class Candidate(val symbol: ConeSymbol) {}
it.initNames(this.names)
enum class TowerDataKind {
EMPTY,
TOWER_LEVEL
}
interface TowerScopeLevel {
sealed class Token<out T : ConeSymbol> {
object Properties : Token<ConePropertySymbol>()
object Functions : Token<ConeFunctionSymbol>()
object Objects : Token<ConeClassifierSymbol>()
}
fun <T : ConeSymbol> processElementsByName(
token: Token<T>,
name: Name,
extensionReceiver: ReceiverValueWithPossibleTypes?,
processor: TowerScopeLevelProcessor<T>
): ProcessorAction
interface TowerScopeLevelProcessor<T : ConeSymbol> {
fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction
}
object Empty : TowerScopeLevel {
override fun <T : ConeSymbol> processElementsByName(
token: Token<T>,
name: Name,
extensionReceiver: ReceiverValueWithPossibleTypes?,
processor: TowerScopeLevelProcessor<T>
): ProcessorAction = ProcessorAction.NEXT
}
}
interface ReceiverValue {
val type: ConeKotlinType
}
interface ReceiverValueWithPossibleTypes : ReceiverValue
class MemberScopeTowerLevel(
val session: FirSession,
val dispatchReceiver: ReceiverValueWithPossibleTypes
) : TowerScopeLevel {
private fun <T : ConeSymbol> processMembers(
output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
takeMembers: FirScope.(processor: (T) -> ProcessorAction) -> ProcessorAction
): ProcessorAction {
return dispatchReceiver.type.scope(session)?.takeMembers { output.consumeCandidate(it, dispatchReceiver) } ?: ProcessorAction.NEXT
}
override fun <T : ConeSymbol> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
extensionReceiver: ReceiverValueWithPossibleTypes?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
return when (token) {
TowerScopeLevel.Token.Properties -> processMembers(processor) { this.processPropertiesByName(name, it.cast()) }
TowerScopeLevel.Token.Functions -> processMembers(processor) { this.processFunctionsByName(name, it.cast()) }
TowerScopeLevel.Token.Objects -> ProcessorAction.NEXT
} }
}
for ((index, scope) in scopes.asReversed().withIndex()) { }
names.addAll(newNames)
newNames.clear()
processedScopes.add(scope) class ScopeTowerLevel(
val session: FirSession,
val scope: FirScope
) : TowerScopeLevel {
override fun <T : ConeSymbol> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
extensionReceiver: ReceiverValueWithPossibleTypes?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
return when (token) {
names.forEach { name -> TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { processor.consumeCandidate(it as T, null) }
fun process(symbol: ConeSymbol): ProcessorAction { TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { processor.consumeCandidate(it as T, null) }
for (checker in checkers) { TowerScopeLevel.Token.Objects -> scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) {
checker.consumeCandidate(index, symbol, this) processor.consumeCandidate(
it as T,
null
)
}
}
}
}
abstract class TowerDataConsumer {
abstract fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
): ProcessorAction
}
fun createVariableConsumer(
session: FirSession,
name: Name,
explicitReceiver: FirExpression?,
explicitReceiverType: FirTypeRef?
): TowerDataConsumer {
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, explicitReceiver, explicitReceiverType)
}
fun createFunctionConsumer(
session: FirSession,
name: Name,
explicitReceiver: FirExpression?,
explicitReceiverType: FirTypeRef?
): TowerDataConsumer {
return createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, explicitReceiver, explicitReceiverType)
}
fun createSimpleConsumer(
session: FirSession,
name: Name,
token: TowerScopeLevel.Token<*>,
explicitReceiver: FirExpression?,
explicitReceiverType: FirTypeRef?
): TowerDataConsumer {
return if (explicitReceiver != null) {
ExplicitReceiverTowerDataConsumer(session, name, token, object : ReceiverValueWithPossibleTypes {
override val type: ConeKotlinType
get() = explicitReceiverType!!.coneTypeUnsafe()
})
} else {
NoExplicitReceiverTowerDataConsumer(session, name, token)
}
}
class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val explicitReceiver: ReceiverValueWithPossibleTypes
) : TowerDataConsumer() {
var groupId = 0
override fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
): ProcessorAction {
groupId++
return when (kind) {
TowerDataKind.EMPTY ->
MemberScopeTowerLevel(session, explicitReceiver).processElementsByName(
token,
name,
null,
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
resultCollector.consumeCandidate(groupId, symbol)
return ProcessorAction.NEXT
}
} }
return ProcessorAction.NEXT )
} TowerDataKind.TOWER_LEVEL ->
towerScopeLevel.processElementsByName(
scope.processClassifiersByNameWithAction(name, FirPosition.OTHER, ::process) token,
scope.processPropertiesByName(name, ::process) name,
scope.processFunctionsByName(name, ::process) explicitReceiver,
} object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
successChecker = checkers.maxBy { it.currentApplicability } resultCollector.consumeCandidate(groupId, symbol)
return ProcessorAction.NEXT
if (successChecker?.currentApplicability == CandidateApplicability.RESOLVED) { }
break }
} )
} }
return successChecker
} }
lateinit var session: FirSession }
val processedScopes = mutableListOf<FirScope>()
class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>
) : TowerDataConsumer() {
var groupId = 0
override fun consume(
kind: TowerDataKind,
implicitReceiverType: ConeKotlinType?,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector
): ProcessorAction {
groupId++
return when (kind) {
TowerDataKind.TOWER_LEVEL -> {
towerScopeLevel.processElementsByName(
token,
name,
null,
object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, boundDispatchReceiver: ReceiverValueWithPossibleTypes?): ProcessorAction {
resultCollector.consumeCandidate(groupId, symbol)
return ProcessorAction.NEXT
}
}
)
}
else -> ProcessorAction.NEXT
}
}
}
class CallResolver(val typeCalculator: ReturnTypeCalculator, val session: FirSession) {
var callInfo: CallInfo? = null
var scopes: List<FirScope>? = null
fun runTowerResolver(towerDataConsumer: TowerDataConsumer): CandidateCollector {
val collector = CandidateCollector(callInfo!!)
towerDataConsumer.consume(TowerDataKind.EMPTY, null, TowerScopeLevel.Empty, collector)
for (scope in scopes!!) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, null, ScopeTowerLevel(session, scope), collector)
}
return collector
}
} }
@@ -99,9 +322,7 @@ enum class CandidateApplicability {
RESOLVED RESOLVED
} }
class CandidateCollector(val callInfo: CallInfo) {
// TODO: Extract from this transformer
abstract class ApplicabilityChecker {
val groupNumbers = mutableListOf<Int>() val groupNumbers = mutableListOf<Int>()
val candidates = mutableListOf<ConeSymbol>() val candidates = mutableListOf<ConeSymbol>()
@@ -109,35 +330,27 @@ abstract class ApplicabilityChecker {
var currentApplicability = CandidateApplicability.HIDDEN var currentApplicability = CandidateApplicability.HIDDEN
var expectedType: FirTypeRef? = null
var explicitReceiverType: FirTypeRef? = null
fun newDataSet() { fun newDataSet() {
groupNumbers.clear() groupNumbers.clear()
candidates.clear() candidates.clear()
expectedType = null
currentApplicability = CandidateApplicability.HIDDEN currentApplicability = CandidateApplicability.HIDDEN
} }
protected open fun getApplicability( protected fun getApplicability(
group: Int, group: Int,
symbol: ConeSymbol, symbol: ConeSymbol
resolver: CallResolver
): CandidateApplicability { ): CandidateApplicability {
val declaration = (symbol as? FirBasedSymbol<*>)?.fir
?: return CandidateApplicability.HIDDEN
declaration as FirDeclaration
if (declaration is FirCallableDeclaration) { val sink = CheckerSinkImpl()
if ((declaration.receiverTypeRef == null) != (explicitReceiverType == null)) return CandidateApplicability.PARAMETER_MAPPING_ERROR
}
return CandidateApplicability.RESOLVED MapArguments.check(Candidate(symbol), sink, callInfo)
return sink.current
} }
open fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) { fun consumeCandidate(group: Int, symbol: ConeSymbol) {
val applicability = getApplicability(group, symbol, resolver) val applicability = getApplicability(group, symbol)
if (applicability > currentApplicability) { if (applicability > currentApplicability) {
groupNumbers.clear() groupNumbers.clear()
@@ -152,19 +365,13 @@ abstract class ApplicabilityChecker {
} }
} }
abstract fun initNames(names: LinkedHashSet<Name>)
open fun isSuccessful(index: Int, candidate: ConeSymbol): Boolean { fun successCandidates(): List<ConeSymbol> {
return true
}
open fun successCandidates(): List<ConeSymbol> {
if (groupNumbers.isEmpty()) return emptyList() if (groupNumbers.isEmpty()) return emptyList()
val result = mutableListOf<ConeSymbol>() val result = mutableListOf<ConeSymbol>()
var bestGroup = groupNumbers.first() var bestGroup = groupNumbers.first()
for ((index, candidate) in candidates.withIndex()) { for ((index, candidate) in candidates.withIndex()) {
val group = groupNumbers[index] val group = groupNumbers[index]
if (!isSuccessful(index, candidate)) continue
if (bestGroup > group) { if (bestGroup > group) {
bestGroup = group bestGroup = group
result.clear() result.clear()
@@ -177,195 +384,6 @@ abstract class ApplicabilityChecker {
} }
} }
open class VariableApplicabilityChecker(val name: Name) : ApplicabilityChecker() {
override fun initNames(names: LinkedHashSet<Name>) {
names.add(name)
}
override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
if (symbol !is ConeVariableSymbol) return
if (symbol.callableId.callableName != name) return
super.consumeCandidate(group, symbol, resolver)
}
}
class VariableInvokeApplicabilityChecker(val variableName: Name) : FunctionApplicabilityChecker(invoke) {
val variableChecker = object : VariableApplicabilityChecker(variableName) {
override fun isSuccessful(index: Int, candidate: ConeSymbol): Boolean {
return matchedProperties[index]
}
}
private var matchedProperties = BitSet()
private var lookupInvoke = false
override fun initNames(names: LinkedHashSet<Name>) {
names.add(variableName)
// if (lookupInvoke) {
// names.add(name)
// }
}
private fun isInvokeApplicableOn(propertySymbol: ConeSymbol, invokeSymbol: ConeCallableSymbol): Boolean {
return true //TODO: Actual type-check here
}
override fun getApplicability(
group: Int,
symbol: ConeSymbol,
resolver: CallResolver
): CandidateApplicability {
symbol as ConeCallableSymbol
val declaration = (symbol as? FirBasedSymbol<*>)?.fir
?: return CandidateApplicability.HIDDEN
declaration as FirDeclaration
if (declaration is FirFunction) {
if (declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR
}
var applicable = false
fun processCandidates(candidates: Iterable<IndexedValue<ConeSymbol>>) {
for ((index, candidate) in candidates) {
val invokeApplicableOn = isInvokeApplicableOn(candidate, symbol)
if (invokeApplicableOn) {
applicable = true
}
matchedProperties[index] = invokeApplicableOn
}
}
if (group == -1) {
processCandidates(listOf(variableChecker.candidates.withIndex().last()))
} else {
processCandidates(variableChecker.candidates.withIndex())
}
if (applicable) {
return CandidateApplicability.RESOLVED
}
return CandidateApplicability.PARAMETER_MAPPING_ERROR
}
private fun checkSuccess(): Boolean {
return currentApplicability == CandidateApplicability.RESOLVED
}
override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
if (symbol is ConeVariableSymbol && symbol.callableId.callableName == variableName) {
variableChecker.consumeCandidate(group, symbol, resolver)
val lastCandidate = variableChecker.candidates.lastOrNull()
if (variableChecker.currentApplicability == CandidateApplicability.RESOLVED && lastCandidate == symbol) {
val receiverScope =
resolver.typeCalculator.tryCalculateReturnType(lastCandidate.firUnsafe()).type
.scope(resolver.session)
if (!lookupInvoke) resolver.pushName(invoke)
lookupInvoke = true
receiverScope?.processFunctionsByName(invoke) { candidate ->
this.consumeCandidate(-1, candidate, resolver)
ProcessorAction.NEXT
}
if (checkSuccess()) return
for ((index, scope) in resolver.processedScopes.withIndex()) {
scope.processFunctionsByName(invoke) { candidate ->
this.consumeCandidate(index, candidate, resolver)
ProcessorAction.NEXT
}
if (checkSuccess()) return
}
}
}
super.consumeCandidate(group, symbol, resolver)
}
companion object {
val invoke = Name.identifier("invoke")
}
}
class ClassifierApplicabilityChecker(val name: Name) : ApplicabilityChecker() {
override fun initNames(names: LinkedHashSet<Name>) {
names.add(name)
}
override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
if (symbol !is ConeClassifierSymbol) return
if (symbol.toLookupTag().name != name) return
super.consumeCandidate(group, symbol, resolver)
}
}
open class FunctionApplicabilityChecker(val name: Name) : ApplicabilityChecker() {
var parameterCount = 0
override fun initNames(names: LinkedHashSet<Name>) {
names.add(name)
}
lateinit var session: FirSession
override fun getApplicability(
group: Int,
symbol: ConeSymbol,
resolver: CallResolver
): CandidateApplicability {
val declaration = symbol.firUnsafe<FirCallableDeclaration>()
if (declaration is FirFunction && declaration.valueParameters.size != parameterCount) return CandidateApplicability.PARAMETER_MAPPING_ERROR
var extensionReceiver = declaration.receiverTypeRef?.coneTypeUnsafe()
var dispatchReceiver = declaration.dispatchReceiverType(session)
val explicitReceiverType = explicitReceiverType?.coneTypeUnsafe()
if (explicitReceiverType != null) {
if (dispatchReceiver != null && explicitReceiverType.isSubtypeOf(dispatchReceiver, session)) {
dispatchReceiver = null
}
if (extensionReceiver != null && explicitReceiverType.isSubtypeOf(extensionReceiver, session)) {
extensionReceiver = null
}
if (extensionReceiver != null || dispatchReceiver != null) return CandidateApplicability.WRONG_RECEIVER
}
return CandidateApplicability.RESOLVED
}
fun ConeKotlinType.isSubtypeOf(type: ConeKotlinType, session: FirSession): Boolean {
return try {
AbstractTypeChecker.isSubtypeOf(ConeTypeCheckerContext(true, session), this, type)
} catch (e: IllegalStateException) {
throw RuntimeException("Sub-typing error: subType = ${this.render()}, superType = ${type.render()}", e)
}
}
override fun consumeCandidate(group: Int, symbol: ConeSymbol, resolver: CallResolver) {
if (symbol !is ConeFunctionSymbol) return
if (symbol.callableId.callableName != name) return
session = resolver.session
super.consumeCandidate(group, symbol, resolver)
}
}
fun FirCallableDeclaration.dispatchReceiverType(session: FirSession): ConeKotlinType? { fun FirCallableDeclaration.dispatchReceiverType(session: FirSession): ConeKotlinType? {
val id = (this.symbol as ConeCallableSymbol).callableId.classId ?: return null val id = (this.symbol as ConeCallableSymbol).callableId.classId ?: return null
val symbol = session.service<FirSymbolProvider>().getClassLikeSymbolByFqName(id) as? FirClassSymbol ?: return null val symbol = session.service<FirSymbolProvider>().getClassLikeSymbolByFqName(id) as? FirClassSymbol ?: return null
@@ -9,8 +9,6 @@ import com.google.common.collect.LinkedHashMultimap
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
@@ -101,7 +99,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
} }
FirOperation.SAFE_AS -> { FirOperation.SAFE_AS -> {
bindingContext[resolved] = bindingContext[resolved] =
resolved.typeRef.withReplacedConeType( resolved.typeRef.withReplacedConeType(
session, session,
resolved.typeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE) resolved.typeRef.coneTypeUnsafe().withNullability(ConeNullability.NULLABLE)
) )
@@ -130,26 +128,15 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
val jump = ReturnTypeCalculatorWithJump(session) val jump = ReturnTypeCalculatorWithJump(session)
private fun runTowerResolver(
checkers: List<ApplicabilityChecker>
): ApplicabilityChecker? {
val callResolver = CallResolver(jump)
callResolver.scopes = (scopes + localScopes)
callResolver.checkers = checkers
callResolver.session = session
return callResolver.runTowerResolver()
}
private fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { private fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression {
bindingContext[access] = bindingContext[access] =
when (val newCallee = access.calleeReference) { when (val newCallee = access.calleeReference) {
is FirErrorNamedReference -> is FirErrorNamedReference ->
FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason) FirErrorTypeRefImpl(session, access.psi, newCallee.errorReason)
is FirResolvedCallableReference -> is FirResolvedCallableReference ->
jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe()) jump.tryCalculateReturnType(newCallee.callableSymbol.firUnsafe())
else -> return else -> return
} }
} }
override fun transformQualifiedAccessExpression( override fun transformQualifiedAccessExpression(
@@ -170,18 +157,21 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
qualifiedAccessExpression.explicitReceiver?.visitNoTransform(this, null) qualifiedAccessExpression.explicitReceiver?.visitNoTransform(this, null)
val checkers = listOf(VariableApplicabilityChecker(callee.name).apply { val receiver = qualifiedAccessExpression.explicitReceiver
expectedType = data as FirTypeRef?
explicitReceiverType = qualifiedAccessExpression.explicitReceiver?.resultType
})
val result = runTowerResolver(checkers) //val checkers = listOf(VariableApplicabilityChecker(callee.name))
if (result != null) {
val resultExpression = qualifiedAccessExpression.transformCalleeReference(this, result.successCandidates()) val info = CallInfo(true, receiver, 0)
storeTypeFromCallee(resultExpression as FirQualifiedAccessExpression) val resolver = CallResolver(jump, session)
return resultExpression.compose() resolver.callInfo = info
} resolver.scopes = (scopes + localScopes).asReversed()
return qualifiedAccessExpression.compose()
val consumer = createVariableConsumer(session, callee.name, qualifiedAccessExpression.explicitReceiver, qualifiedAccessExpression.explicitReceiver?.resultType)
val result = resolver.runTowerResolver(consumer)
val successCandidates = result.successCandidates()
val resultExpression = qualifiedAccessExpression.transformCalleeReference(this, successCandidates)
storeTypeFromCallee(resultExpression as FirQualifiedAccessExpression)
return resultExpression.compose()
} }
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult<FirStatement> { override fun transformFunctionCall(functionCall: FirFunctionCall, data: Any?): CompositeTransformResult<FirStatement> {
@@ -197,46 +187,47 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
val receiver = functionCall.explicitReceiver val receiver = functionCall.explicitReceiver
val arguments = functionCall.arguments val arguments = functionCall.arguments
val checkers = listOf(FunctionApplicabilityChecker(name).apply {
expectedType = expectedTypeRef val info = CallInfo(false, receiver, arguments.size)
explicitReceiverType = receiver?.resultType val resolver = CallResolver(jump, session)
parameterCount = arguments.size resolver.callInfo = info
}, VariableInvokeApplicabilityChecker(name).apply { resolver.scopes = (scopes + localScopes).asReversed()
expectedType = expectedTypeRef
variableChecker.apply {
expectedType = expectedTypeRef
explicitReceiverType = receiver?.resultType
}
parameterCount = arguments.size
})
val result = runTowerResolver(checkers)
val resultExpression = when (result) { val consumer = createFunctionConsumer(session, name, receiver, receiver?.resultType)
is VariableInvokeApplicabilityChecker -> { val result = resolver.runTowerResolver(consumer)
FirFunctionCallImpl(functionCall.session, functionCall.psi, safe = functionCall.safe).apply { val successCandidates = result.successCandidates()
calleeReference =
functionCall.calleeReference.transformSingle(this@FirBodyResolveTransformer, result.successCandidates()) // fun isInvoke()
explicitReceiver = //
FirQualifiedAccessExpressionImpl( // val resultExpression =
functionCall.session, //
functionCall.calleeReference.psi, // when {
functionCall.safe // successCandidates.singleOrNull() as? ConeCallableSymbol -> {
).apply { // FirFunctionCallImpl(functionCall.session, functionCall.psi, safe = functionCall.safe).apply {
calleeReference = createResolvedNamedReference( // calleeReference =
functionCall.calleeReference, // functionCall.calleeReference.transformSingle(this@FirBodyResolveTransformer, result.successCandidates())
result.variableChecker.successCandidates() as List<ConeCallableSymbol> // explicitReceiver =
) // FirQualifiedAccessExpressionImpl(
explicitReceiver = functionCall.explicitReceiver // functionCall.session,
} // functionCall.calleeReference.psi,
} // functionCall.safe
} // ).apply {
is ApplicabilityChecker -> { // calleeReference = createResolvedNamedReference(
functionCall.transformCalleeReference(this, result.successCandidates()) // functionCall.calleeReference,
} // result.variableChecker.successCandidates() as List<ConeCallableSymbol>
else -> functionCall // )
} // explicitReceiver = functionCall.explicitReceiver
// }
// }
// }
// is ApplicabilityChecker -> {
// functionCall.transformCalleeReference(this, result.successCandidates())
// }
// else -> functionCall
// }
val resultExpression = functionCall.transformCalleeReference(this, successCandidates)
storeTypeFromCallee(resultExpression as FirFunctionCall) storeTypeFromCallee(resultExpression as FirFunctionCall)
return resultExpression.compose() return resultExpression.compose()
@@ -10,8 +10,8 @@ FILE: dispatchReceiver.kt
public get(): R|Base| public get(): R|Base|
public set(value: R|Base|): R|kotlin/Unit| public set(value: R|Base|): R|kotlin/Unit|
public final fun check(): <ERROR TYPE REF: cycle> { public final fun check(): R|kotlin/Unit| {
^check R|/My.delegate|.R|/My.check|() ^check R|/My.delegate|.R|/Base.check|()
} }
} }