Refactoring & clarification: implement new FIR tower resolver
This commit is contained in:
@@ -209,9 +209,7 @@ class FirCallResolver(
|
||||
typeArguments.addAll(qualifiedAccess.typeArguments)
|
||||
resultType = if (classId.isLocal) {
|
||||
typeForQualifierByDeclaration(referencedSymbol.fir, resultType, session)
|
||||
?: resultType.resolvedTypeFromPrototype(
|
||||
session.builtinTypes.unitType.type//StandardClassIds.Unit(symbolProvider).constructType(emptyArray(), isNullable = false)
|
||||
)
|
||||
?: session.builtinTypes.unitType
|
||||
} else {
|
||||
typeForQualifier(this)
|
||||
}
|
||||
@@ -252,7 +250,8 @@ class FirCallResolver(
|
||||
val result = towerResolver.runResolver(
|
||||
implicitReceiverStack.receiversAsReversed(),
|
||||
info,
|
||||
collector = CandidateCollector(this, resolutionStageRunner)
|
||||
collector = CandidateCollector(this, resolutionStageRunner),
|
||||
manager = TowerResolveManager(towerResolver)
|
||||
)
|
||||
val bestCandidates = result.bestCandidates()
|
||||
val noSuccessfulCandidates = result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED
|
||||
@@ -316,7 +315,7 @@ class FirCallResolver(
|
||||
|
||||
fun <T> selectCandidateFromGivenCandidates(call: T, name: Name, candidates: Collection<Candidate>): T where T : FirResolvable, T : FirCall {
|
||||
val result = CandidateCollector(this, resolutionStageRunner)
|
||||
candidates.forEach { result.consumeCandidate(0, it) }
|
||||
candidates.forEach { result.consumeCandidate(TowerGroup.Start, it) }
|
||||
val bestCandidates = result.bestCandidates()
|
||||
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
bestCandidates.toSet()
|
||||
|
||||
@@ -325,9 +325,7 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
|
||||
}
|
||||
}
|
||||
// TODO: Handle no value type here
|
||||
return resultType.resolvedTypeFromPrototype(
|
||||
session.builtinTypes.unitType.type
|
||||
)
|
||||
return session.builtinTypes.unitType
|
||||
}
|
||||
|
||||
internal fun typeForReifiedParameterReference(parameterReference: FirResolvedReifiedParameterReference): FirTypeRef {
|
||||
@@ -361,7 +359,8 @@ internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultTy
|
||||
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
|
||||
val makeNullable: Boolean by lazy {
|
||||
if (access is FirQualifiedAccess && access.safe) {
|
||||
val explicitReceiver = access.explicitReceiver!!
|
||||
val explicitReceiver = access.explicitReceiver
|
||||
?: throw AssertionError("Safe call without explicit receiver: ${access.render()}")
|
||||
val receiverResultType = explicitReceiver.resultType
|
||||
if (receiverResultType is FirResolvedTypeRef) {
|
||||
receiverResultType.type.isNullable
|
||||
|
||||
@@ -46,22 +46,28 @@ data class CallInfo(
|
||||
) {
|
||||
val argumentCount get() = arguments.size
|
||||
|
||||
fun noStubReceiver(): CallInfo =
|
||||
if (stubReceiver == null) this else CallInfo(
|
||||
callKind, name, explicitReceiver, arguments,
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, null
|
||||
)
|
||||
|
||||
fun replaceWithVariableAccess(): CallInfo =
|
||||
CallInfo(
|
||||
CallKind.VariableAccess, name, explicitReceiver, emptyList(),
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
|
||||
)
|
||||
|
||||
fun replaceExplicitReceiver(explicitReceiver: FirExpression): CallInfo =
|
||||
fun replaceExplicitReceiver(explicitReceiver: FirExpression?): CallInfo =
|
||||
CallInfo(
|
||||
callKind, name, explicitReceiver, arguments,
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
|
||||
)
|
||||
|
||||
fun withReceiverAsArgument(receiverExpression: FirExpression): CallInfo =
|
||||
CallInfo(
|
||||
callKind, name, explicitReceiver, listOf(receiverExpression) + arguments,
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs
|
||||
isSafeCall, typeArguments, session, containingFile, implicitReceiverStack, expectedType, outerCSBuilder, lhs, stubReceiver
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+6
-66
@@ -5,39 +5,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
open class CandidateCollector(
|
||||
val components: BodyResolveComponents,
|
||||
val resolutionStageRunner: ResolutionStageRunner
|
||||
private val resolutionStageRunner: ResolutionStageRunner
|
||||
) {
|
||||
private val groupNumbers = mutableListOf<Int>()
|
||||
private val groupNumbers = mutableListOf<TowerGroup>()
|
||||
private val candidates = mutableListOf<Candidate>()
|
||||
|
||||
var currentApplicability = CandidateApplicability.HIDDEN
|
||||
private set
|
||||
|
||||
private var currentGroup = TowerGroup.Start
|
||||
|
||||
fun newDataSet() {
|
||||
groupNumbers.clear()
|
||||
candidates.clear()
|
||||
currentApplicability = CandidateApplicability.HIDDEN
|
||||
}
|
||||
|
||||
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
open fun consumeCandidate(group: TowerGroup, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = resolutionStageRunner.processCandidate(candidate)
|
||||
|
||||
if (applicability > currentApplicability) {
|
||||
groupNumbers.clear()
|
||||
candidates.clear()
|
||||
currentApplicability = applicability
|
||||
currentGroup = group
|
||||
}
|
||||
|
||||
if (applicability == currentApplicability) {
|
||||
@@ -71,58 +66,3 @@ open class CandidateCollector(
|
||||
}
|
||||
}
|
||||
|
||||
// Collects properties that potentially could be invoke receivers, like 'propertyName()',
|
||||
// and initiates further invoke resolution by adding property-bound invoke consumers
|
||||
class InvokeReceiverCandidateCollector(
|
||||
private val towerResolver: FirTowerResolver,
|
||||
private val invokeCallInfo: CallInfo,
|
||||
components: BodyResolveComponents,
|
||||
private val invokeConsumer: AccumulatingTowerDataConsumer,
|
||||
resolutionStageRunner: ResolutionStageRunner
|
||||
) : CandidateCollector(components, resolutionStageRunner) {
|
||||
private fun createBoundInvokeConsumer(boundInvokeCallInfo: CallInfo): TowerDataConsumer {
|
||||
return createSimpleFunctionConsumer(
|
||||
components.session, OperatorNameConventions.INVOKE,
|
||||
boundInvokeCallInfo, components, towerResolver.collector
|
||||
)
|
||||
}
|
||||
|
||||
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
|
||||
val symbol = candidate.symbol as FirCallableSymbol<*>
|
||||
return FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
null,
|
||||
symbol.callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||
}
|
||||
}
|
||||
|
||||
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
|
||||
val applicability = super.consumeCandidate(group, candidate)
|
||||
|
||||
if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) {
|
||||
val symbol = candidate.symbol as FirCallableSymbol<*>
|
||||
val extensionReceiverExpression = candidate.extensionReceiverExpression()
|
||||
val useExtensionReceiverAsArgument =
|
||||
symbol.fir.receiverTypeRef == null &&
|
||||
candidate.explicitReceiverKind == ExplicitReceiverKind.EXTENSION_RECEIVER &&
|
||||
symbol.fir.returnTypeRef.isExtensionFunctionType()
|
||||
val explicitReceiver = createExplicitReceiverForInvoke(candidate).apply {
|
||||
extensionReceiver = extensionReceiverExpression.takeIf { !useExtensionReceiverAsArgument } ?: FirNoReceiverExpression
|
||||
}.let {
|
||||
components.transformQualifiedAccessUsingSmartcastInfo(it)
|
||||
}
|
||||
val boundInvokeCallInfo = invokeCallInfo.replaceExplicitReceiver(explicitReceiver).let {
|
||||
if (useExtensionReceiverAsArgument) it.withReceiverAsArgument(extensionReceiverExpression)
|
||||
else it
|
||||
}
|
||||
|
||||
invokeConsumer.addConsumerAndProcessAccumulatedData(createBoundInvokeConsumer(boundInvokeCallInfo))
|
||||
}
|
||||
|
||||
return applicability
|
||||
}
|
||||
}
|
||||
|
||||
+20
-9
@@ -13,19 +13,30 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
|
||||
class CandidateFactory(
|
||||
class CandidateFactory private constructor(
|
||||
val bodyResolveComponents: BodyResolveComponents,
|
||||
private val callInfo: CallInfo
|
||||
val callInfo: CallInfo,
|
||||
private val baseSystem: ConstraintStorage
|
||||
) {
|
||||
|
||||
private val baseSystem: ConstraintStorage
|
||||
|
||||
init {
|
||||
val system = bodyResolveComponents.inferenceComponents.createConstraintSystem()
|
||||
callInfo.arguments.forEach {
|
||||
system.addSubsystemFromExpression(it)
|
||||
companion object {
|
||||
private fun buildBaseSystem(bodyResolveComponents: BodyResolveComponents, callInfo: CallInfo): ConstraintStorage {
|
||||
val system = bodyResolveComponents.inferenceComponents.createConstraintSystem()
|
||||
callInfo.arguments.forEach {
|
||||
system.addSubsystemFromExpression(it)
|
||||
}
|
||||
return system.asReadOnlyStorage()
|
||||
}
|
||||
baseSystem = system.asReadOnlyStorage()
|
||||
}
|
||||
|
||||
constructor(bodyResolveComponents: BodyResolveComponents, callInfo: CallInfo) :
|
||||
this(bodyResolveComponents, callInfo, buildBaseSystem(bodyResolveComponents, callInfo))
|
||||
|
||||
fun replaceCallInfo(callInfo: CallInfo): CandidateFactory {
|
||||
if (this.callInfo.arguments.size != callInfo.arguments.size) {
|
||||
throw AssertionError("Incorrect replacement of call info in CandidateFactory")
|
||||
}
|
||||
return CandidateFactory(bodyResolveComponents, callInfo, baseSystem)
|
||||
}
|
||||
|
||||
fun createCandidate(
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* 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.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
fun createVariableAndObjectConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
return PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Properties,
|
||||
callInfo,
|
||||
bodyResolveComponents,
|
||||
resultCollector
|
||||
),
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Objects,
|
||||
callInfo,
|
||||
bodyResolveComponents,
|
||||
resultCollector
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createSimpleFunctionConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
return createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Functions,
|
||||
callInfo,
|
||||
bodyResolveComponents,
|
||||
resultCollector
|
||||
)
|
||||
}
|
||||
|
||||
fun createFunctionConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
resultCollector: CandidateCollector,
|
||||
towerResolver: FirTowerResolver
|
||||
): TowerDataConsumer {
|
||||
val varCallInfo = callInfo.replaceWithVariableAccess()
|
||||
return PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Functions,
|
||||
callInfo,
|
||||
bodyResolveComponents,
|
||||
resultCollector
|
||||
),
|
||||
AccumulatingTowerDataConsumer(resultCollector).apply {
|
||||
initialConsumer = createSimpleConsumer(
|
||||
session,
|
||||
name,
|
||||
TowerScopeLevel.Token.Properties,
|
||||
varCallInfo,
|
||||
bodyResolveComponents,
|
||||
InvokeReceiverCandidateCollector(
|
||||
towerResolver,
|
||||
invokeCallInfo = callInfo,
|
||||
components = bodyResolveComponents,
|
||||
invokeConsumer = this,
|
||||
resolutionStageRunner = resultCollector.resolutionStageRunner
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun createSimpleConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
token: TowerScopeLevel.Token<*>,
|
||||
callInfo: CallInfo,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
val factory = CandidateFactory(bodyResolveComponents, callInfo)
|
||||
val explicitReceiver = callInfo.explicitReceiver
|
||||
return if (explicitReceiver != null) {
|
||||
ExplicitReceiverTowerDataConsumer(session, name, token, qualifierOrExpressionReceiver(explicitReceiver), factory, resultCollector)
|
||||
} else {
|
||||
NoExplicitReceiverTowerDataConsumer(session, name, token, factory, resultCollector)
|
||||
}
|
||||
}
|
||||
|
||||
fun createCallableReferencesConsumer(
|
||||
session: FirSession,
|
||||
name: Name,
|
||||
callInfo: CallInfo,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
resultCollector: CandidateCollector
|
||||
): TowerDataConsumer {
|
||||
// TODO: Use SamePriorityConsumer
|
||||
return PrioritizedTowerDataConsumer(
|
||||
resultCollector,
|
||||
createSimpleConsumer(session, name, TowerScopeLevel.Token.Functions, callInfo, bodyResolveComponents, resultCollector),
|
||||
createSimpleConsumer(session, name, TowerScopeLevel.Token.Properties, callInfo, bodyResolveComponents, resultCollector)
|
||||
)
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParametersOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
|
||||
@@ -17,10 +16,8 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirThisReceiverExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirImplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.scopes.scope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -57,9 +54,11 @@ class ClassDispatchReceiverValue(klassSymbol: FirClassSymbol<*>) : ReceiverValue
|
||||
}
|
||||
|
||||
// TODO: should inherit just Receiver, not ReceiverValue
|
||||
abstract class AbstractExplicitReceiver<E : FirExpression> : ReceiverValue {
|
||||
abstract class AbstractExplicitReceiver<E : FirExpression> : Receiver {
|
||||
abstract val explicitReceiver: FirExpression
|
||||
}
|
||||
|
||||
abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplicitReceiver<E>(), ReceiverValue {
|
||||
override val type: ConeKotlinType
|
||||
get() = explicitReceiver.typeRef.coneTypeSafe()
|
||||
?: ConeKotlinErrorType("No type calculated for: ${explicitReceiver.renderWithType()}") // TODO: assert here
|
||||
@@ -68,11 +67,6 @@ abstract class AbstractExplicitReceiver<E : FirExpression> : ReceiverValue {
|
||||
get() = explicitReceiver
|
||||
}
|
||||
|
||||
fun qualifierOrExpressionReceiver(explicitReceiver: FirExpression): AbstractExplicitReceiver<*> {
|
||||
if (explicitReceiver is FirResolvedQualifier) return QualifierReceiver(explicitReceiver)
|
||||
return ExpressionReceiverValue(explicitReceiver)
|
||||
}
|
||||
|
||||
class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : AbstractExplicitReceiver<FirResolvedQualifier>() {
|
||||
private fun getClassSymbolWithCallablesScope(
|
||||
classId: ClassId,
|
||||
@@ -95,7 +89,7 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
|
||||
return null to null
|
||||
}
|
||||
|
||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
||||
fun qualifierScope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
||||
val classId = explicitReceiver.classId ?: return null
|
||||
|
||||
val (classSymbol, callablesScope) = getClassSymbolWithCallablesScope(classId, useSiteSession, scopeSession)
|
||||
@@ -107,22 +101,21 @@ class QualifierReceiver(override val explicitReceiver: FirResolvedQualifier) : A
|
||||
useSiteSession.firSymbolProvider.getNestedClassifierScope(classId)
|
||||
}
|
||||
|
||||
val qualifierScope = FirQualifierScope(callablesScope, classifierScope)
|
||||
if ((klass as? FirRegularClass)?.companionObject == null) {
|
||||
return qualifierScope
|
||||
}
|
||||
val companionScope = super.scope(useSiteSession, scopeSession) ?: return qualifierScope
|
||||
return FirCompositeScope(qualifierScope, companionScope)
|
||||
return FirQualifierScope(callablesScope, classifierScope)
|
||||
}
|
||||
return super.scope(useSiteSession, scopeSession)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
||||
return qualifierScope(useSiteSession, scopeSession)
|
||||
}
|
||||
}
|
||||
|
||||
private class ExpressionReceiverValue(
|
||||
internal class ExpressionReceiverValue(
|
||||
override val explicitReceiver: FirExpression
|
||||
) : AbstractExplicitReceiver<FirExpression>(), ReceiverValue
|
||||
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
|
||||
|
||||
abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
|
||||
sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
|
||||
val boundSymbol: S,
|
||||
type: ConeKotlinType,
|
||||
private val useSiteSession: FirSession,
|
||||
@@ -148,20 +141,29 @@ abstract class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
|
||||
}
|
||||
}
|
||||
|
||||
class ImplicitDispatchReceiverValue(
|
||||
internal enum class ImplicitDispatchReceiverKind {
|
||||
REGULAR,
|
||||
COMPANION,
|
||||
COMPANION_FROM_SUPERTYPE
|
||||
}
|
||||
|
||||
class ImplicitDispatchReceiverValue internal constructor(
|
||||
boundSymbol: FirClassSymbol<*>,
|
||||
type: ConeKotlinType,
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
scopeSession: ScopeSession,
|
||||
private val kind: ImplicitDispatchReceiverKind = ImplicitDispatchReceiverKind.REGULAR
|
||||
) : ImplicitReceiverValue<FirClassSymbol<*>>(boundSymbol, type, useSiteSession, scopeSession) {
|
||||
val implicitCompanionScopes: List<FirScope> = run {
|
||||
val klass = boundSymbol.fir as? FirRegularClass ?: return@run emptyList()
|
||||
listOfNotNull(klass.companionObject?.scope(ConeSubstitutor.Empty, useSiteSession, scopeSession)) +
|
||||
lookupSuperTypes(klass, lookupInterfaces = false, deep = true, useSiteSession = useSiteSession).mapNotNull {
|
||||
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(useSiteSession)?.fir as? FirRegularClass
|
||||
superClass?.companionObject?.scope(ConeSubstitutor.Empty, useSiteSession, scopeSession)
|
||||
}
|
||||
}
|
||||
internal constructor(
|
||||
boundSymbol: FirClassSymbol<*>, useSiteSession: FirSession, scopeSession: ScopeSession, kind: ImplicitDispatchReceiverKind
|
||||
) : this(
|
||||
boundSymbol, boundSymbol.constructType(typeArguments = emptyArray(), isNullable = false),
|
||||
useSiteSession, scopeSession, kind
|
||||
)
|
||||
|
||||
val implicitCompanion: Boolean get() = kind != ImplicitDispatchReceiverKind.REGULAR
|
||||
|
||||
val companionFromSupertype: Boolean get() = kind == ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
|
||||
}
|
||||
|
||||
class ImplicitExtensionReceiverValue(
|
||||
|
||||
+404
-341
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
@@ -10,396 +10,459 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.isInner
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.TowerDataKind.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NONE
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStaticScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
enum class TowerDataKind {
|
||||
EMPTY, // Corresponds to stub tower level which is replaced by receiver-related level
|
||||
TOWER_LEVEL // Corresponds to real tower level which may process elements itself
|
||||
}
|
||||
|
||||
class FirTowerResolver(
|
||||
val typeCalculator: ReturnTypeCalculator,
|
||||
val components: BodyResolveComponents,
|
||||
resolutionStageRunner: ResolutionStageRunner,
|
||||
val topLevelScopes: List<FirScope>,
|
||||
val localScopes: List<FirLocalScope>
|
||||
private val topLevelScopes: List<FirScope>,
|
||||
private val localScopes: List<FirLocalScope>
|
||||
) {
|
||||
|
||||
val session: FirSession get() = components.session
|
||||
private val session: FirSession get() = components.session
|
||||
private val collector = CandidateCollector(components, resolutionStageRunner)
|
||||
private val manager = TowerResolveManager(this)
|
||||
private lateinit var implicitReceivers: List<ImplicitReceiver>
|
||||
|
||||
private fun processImplicitReceiver(
|
||||
towerDataConsumer: TowerDataConsumer,
|
||||
implicitReceiverValue: ImplicitReceiverValue<*>,
|
||||
nonEmptyLocalScopes: List<FirLocalScope>,
|
||||
oldGroup: Int
|
||||
): Int {
|
||||
var group = oldGroup
|
||||
// Member (no explicit receiver) / extension member (with explicit receiver) access via implicit receiver
|
||||
// class Foo(val x: Int) {
|
||||
// fun Bar.baz() {}
|
||||
// fun test() { x }
|
||||
// fun test(b: Bar) { b.baz() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession),
|
||||
group++
|
||||
)
|
||||
private data class ImplicitReceiver(val receiver: ImplicitReceiverValue<*>, val usableAsValue: Boolean, val depth: Int)
|
||||
|
||||
// class Foo {
|
||||
// fun foo(block: Foo.() -> Unit) {
|
||||
// block()
|
||||
// }
|
||||
// }
|
||||
// invokeExtension on local variable
|
||||
towerDataConsumer.consume(
|
||||
EMPTY,
|
||||
TowerScopeLevel.OnlyImplicitReceiver(implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
//TowerData.OnlyImplicitReceiver(implicitReceiver).process()?.let { return it }
|
||||
|
||||
// Same receiver is dispatch & extension
|
||||
// class Foo {
|
||||
// fun Foo.bar() {}
|
||||
// fun test() { bar() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(
|
||||
session, components,
|
||||
dispatchReceiver = implicitReceiverValue,
|
||||
implicitExtensionReceiver = implicitReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
),
|
||||
group++
|
||||
)
|
||||
|
||||
for (scope in nonEmptyLocalScopes) {
|
||||
// Local scope extensions via implicit receiver
|
||||
// class Foo {
|
||||
// fun test() {
|
||||
// fun Foo.bar() {}
|
||||
// bar()
|
||||
// }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, scope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
}
|
||||
|
||||
var blockDispatchReceivers = false
|
||||
|
||||
for (implicitDispatchReceiverValue in implicitReceiverValues) {
|
||||
val implicitScope = implicitDispatchReceiverValue.implicitScope
|
||||
if (implicitScope != null) {
|
||||
// Extensions in outer object
|
||||
// object Outer {
|
||||
// fun Nested.foo() {}
|
||||
// class Nested {
|
||||
// fun test() { foo() }
|
||||
// }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, implicitScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
}
|
||||
if (implicitDispatchReceiverValue is ImplicitDispatchReceiverValue) {
|
||||
val implicitCompanionScopes = implicitDispatchReceiverValue.implicitCompanionScopes
|
||||
for (implicitCompanionScope in implicitCompanionScopes) {
|
||||
// Extension in companion
|
||||
// class My {
|
||||
// companion object { fun My.foo() {} }
|
||||
// fun test() { foo() }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(session, components, implicitCompanionScope, implicitExtensionReceiver = implicitReceiverValue),
|
||||
group++
|
||||
)
|
||||
}
|
||||
if (blockDispatchReceivers) {
|
||||
continue
|
||||
}
|
||||
if ((implicitDispatchReceiverValue.boundSymbol.fir as? FirRegularClass)?.isInner == false) {
|
||||
blockDispatchReceivers = true
|
||||
private fun prepareImplicitReceivers(implicitReceiverValues: List<ImplicitReceiverValue<*>>): List<ImplicitReceiver> {
|
||||
var depth = 0
|
||||
var firstDispatchValue = true
|
||||
val explicitCompanions = mutableListOf<FirRegularClassSymbol>()
|
||||
implicitReceivers = implicitReceiverValues.mapNotNull {
|
||||
val usableAsValue = when (it) {
|
||||
is ImplicitExtensionReceiverValue -> true
|
||||
is ImplicitDispatchReceiverValue -> {
|
||||
val symbol = it.boundSymbol
|
||||
val klass = symbol.fir as? FirRegularClass
|
||||
if (!it.implicitCompanion && klass?.isCompanion == true) {
|
||||
explicitCompanions += klass.symbol
|
||||
}
|
||||
if (firstDispatchValue) {
|
||||
if (!it.implicitCompanion &&
|
||||
klass?.isInner == false &&
|
||||
!symbol.classId.isLocal
|
||||
) {
|
||||
firstDispatchValue = false
|
||||
}
|
||||
true
|
||||
} else {
|
||||
symbol.fir.classKind == ClassKind.OBJECT
|
||||
}
|
||||
}
|
||||
}
|
||||
if (implicitDispatchReceiverValue !== implicitReceiverValue) {
|
||||
// Two different implicit receivers (dispatch & extension)
|
||||
// class A
|
||||
// class B {
|
||||
// fun A.foo() {}
|
||||
// }
|
||||
// fun test(a: A, b: B) {
|
||||
// with(a) { with(b) { foo() } }
|
||||
// }
|
||||
towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
MemberScopeTowerLevel(
|
||||
session, components,
|
||||
scopeSession = components.scopeSession,
|
||||
dispatchReceiver = implicitDispatchReceiverValue,
|
||||
implicitExtensionReceiver = implicitReceiverValue
|
||||
),
|
||||
group++
|
||||
)
|
||||
}
|
||||
if (it is ImplicitDispatchReceiverValue && it.implicitCompanion && it.boundSymbol in explicitCompanions) null
|
||||
else ImplicitReceiver(it, usableAsValue, depth++)
|
||||
}
|
||||
|
||||
return group
|
||||
return implicitReceivers
|
||||
}
|
||||
|
||||
private fun processTopLevelScope(
|
||||
towerDataConsumer: TowerDataConsumer,
|
||||
topLevelScope: FirScope,
|
||||
oldGroup: Int,
|
||||
extensionsOnly: Boolean = false
|
||||
): Int {
|
||||
var group = oldGroup
|
||||
// Top-level extensions via implicit receiver
|
||||
// fun Foo.bar() {}
|
||||
// class Foo {
|
||||
// fun test() { bar() }
|
||||
// }
|
||||
for (implicitReceiverValue in implicitReceiverValues) {
|
||||
if (towerDataConsumer.consume(
|
||||
TOWER_LEVEL,
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope,
|
||||
implicitExtensionReceiver = implicitReceiverValue,
|
||||
extensionsOnly = extensionsOnly
|
||||
),
|
||||
group++
|
||||
) == NONE
|
||||
) {
|
||||
return group
|
||||
}
|
||||
}
|
||||
// Member of top-level scope & importing scope
|
||||
// val x = 0
|
||||
// fun test() { x }
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, topLevelScope), group++)
|
||||
return group
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
collector.newDataSet()
|
||||
}
|
||||
|
||||
val collector = CandidateCollector(components, resolutionStageRunner)
|
||||
private lateinit var towerDataConsumer: TowerDataConsumer
|
||||
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue<*>>
|
||||
|
||||
private fun towerDataConsumer(info: CallInfo, collector: CandidateCollector): TowerDataConsumer {
|
||||
return when (info.callKind) {
|
||||
CallKind.VariableAccess -> {
|
||||
createVariableAndObjectConsumer(session, info.name, info, components, collector)
|
||||
}
|
||||
CallKind.Function -> {
|
||||
createFunctionConsumer(session, info.name, info, components, collector, this)
|
||||
}
|
||||
CallKind.CallableReference -> {
|
||||
if (info.stubReceiver == null) {
|
||||
createCallableReferencesConsumer(session, info.name, info, components, collector)
|
||||
} else {
|
||||
PrioritizedTowerDataConsumer(
|
||||
collector,
|
||||
createCallableReferencesConsumer(
|
||||
session, info.name, info.replaceExplicitReceiver(info.stubReceiver), components, collector
|
||||
),
|
||||
createCallableReferencesConsumer(
|
||||
session, info.name, info, components, collector
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
|
||||
val symbol = candidate.symbol as FirCallableSymbol<*>
|
||||
return FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
null,
|
||||
symbol.callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||
typeRef = typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||
}
|
||||
}
|
||||
|
||||
// Only case when qualifiedReceiver is a package (no classId) is handled here
|
||||
private fun runResolverForFullyQualifiedReceiver(
|
||||
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
|
||||
private fun runResolverForQualifierReceiver(
|
||||
info: CallInfo,
|
||||
collector: CandidateCollector,
|
||||
qualifiedReceiver: FirResolvedQualifier
|
||||
resolvedQualifier: FirResolvedQualifier,
|
||||
manager: TowerResolveManager
|
||||
): CandidateCollector {
|
||||
val qualifierScope = FirExplicitSimpleImportingScope(
|
||||
listOf(
|
||||
FirResolvedImportImpl(
|
||||
FirImportImpl(null, FqName.topLevel(info.name), false, null),
|
||||
qualifiedReceiver.packageFqName,
|
||||
qualifiedReceiver.relativeClassFqName
|
||||
)
|
||||
), session, components.scopeSession
|
||||
)
|
||||
val candidateFactory = CandidateFactory(components, info)
|
||||
val qualifierScope = if (resolvedQualifier.classId == null) {
|
||||
FirExplicitSimpleImportingScope(
|
||||
listOf(
|
||||
FirResolvedImportImpl(
|
||||
FirImportImpl(source = null, importedFqName = FqName.topLevel(info.name), isAllUnder = false, aliasName = null),
|
||||
resolvedQualifier.packageFqName,
|
||||
relativeClassName = null
|
||||
)
|
||||
), session, components.scopeSession
|
||||
)
|
||||
} else {
|
||||
QualifierReceiver(resolvedQualifier).qualifierScope(session, components.scopeSession)
|
||||
}
|
||||
|
||||
when (info.callKind) {
|
||||
CallKind.VariableAccess -> {
|
||||
qualifierScope.processPropertiesByName(info.name) {
|
||||
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
|
||||
if (qualifierScope != null) {
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(session, components, qualifierScope), info.noStubReceiver(), TowerGroup.Qualifier
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
|
||||
if (resolvedQualifier.classId != null) {
|
||||
val typeRef = resolvedQualifier.typeRef
|
||||
// NB: yet built-in Unit is used for "no-value" type
|
||||
if (info.callKind == CallKind.CallableReference) {
|
||||
if (info.stubReceiver != null || typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, collector, resolvedQualifier, manager)
|
||||
}
|
||||
qualifierScope.processClassifiersByName(info.name) {
|
||||
if (it is FirClassSymbol<*> && it.fir.classKind == ClassKind.OBJECT) {
|
||||
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
|
||||
} else {
|
||||
if (typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
runResolverForExpressionReceiver(info, collector, resolvedQualifier, manager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
|
||||
return collector
|
||||
}
|
||||
|
||||
private fun runResolverForNoReceiver(
|
||||
info: CallInfo,
|
||||
collector: CandidateCollector,
|
||||
manager: TowerResolveManager
|
||||
): CandidateCollector {
|
||||
val shouldProcessExtensionsBeforeMembers =
|
||||
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
|
||||
if (shouldProcessExtensionsBeforeMembers) {
|
||||
// Special case (extension hides member)
|
||||
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
|
||||
if (!usableAsValue) continue
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = implicitReceiverValue, extensionsOnly = true
|
||||
), info, TowerGroup.TopPrioritized(index).Implicit(depth)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
}
|
||||
}
|
||||
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
|
||||
val emptyTopLevelScopes = mutableSetOf<FirScope>()
|
||||
for ((index, localScope) in localScopes.withIndex()) {
|
||||
val result = manager.processLevel(
|
||||
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
if (result != ProcessorAction.NONE) {
|
||||
nonEmptyLocalScopes += localScope
|
||||
}
|
||||
}
|
||||
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
|
||||
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
|
||||
// NB: companions are processed via implicitReceiverValues!
|
||||
val parentGroup = TowerGroup.Implicit(depth)
|
||||
|
||||
if (usableAsValue) {
|
||||
val implicitResult = manager.processLevel(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
|
||||
), info, parentGroup.Member
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
if (implicitResult == ProcessorAction.NONE) {
|
||||
implicitReceiverValuesWithEmptyScopes += implicitReceiverValue
|
||||
}
|
||||
for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) {
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, localScope, extensionReceiver = implicitReceiverValue
|
||||
), info, parentGroup.Local(localIndex)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
|
||||
if (!usable) continue
|
||||
if (implicitDispatchReceiverValue in implicitReceiverValuesWithEmptyScopes) continue
|
||||
manager.processLevel(
|
||||
MemberScopeTowerLevel(
|
||||
session,
|
||||
components,
|
||||
dispatchReceiver = implicitDispatchReceiverValue,
|
||||
extensionReceiver = implicitReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
), info, parentGroup.Implicit(dispatchDepth)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
if (topLevelScope in emptyTopLevelScopes) continue
|
||||
val result = manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = implicitReceiverValue
|
||||
), info, parentGroup.Top(topIndex)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
if (result == ProcessorAction.NONE) {
|
||||
emptyTopLevelScopes += topLevelScope
|
||||
}
|
||||
}
|
||||
}
|
||||
CallKind.Function -> {
|
||||
qualifierScope.processFunctionsAndConstructorsByName(info.name, session, components) {
|
||||
collector.consumeCandidate(0, candidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER))
|
||||
}
|
||||
|
||||
val invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
|
||||
val invokeReceiverCandidateFactory = CandidateFactory(
|
||||
components,
|
||||
info.replaceWithVariableAccess()
|
||||
)
|
||||
|
||||
qualifierScope.processPropertiesByName(info.name) {
|
||||
invokeReceiverCollector.consumeCandidate(
|
||||
0, invokeReceiverCandidateFactory.createCandidate(it, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER)
|
||||
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
||||
val scope = implicitReceiverValue.scope(session, components.scopeSession)
|
||||
if (scope != null) {
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session,
|
||||
components,
|
||||
FirStaticScope(scope)
|
||||
), info, parentGroup.Static(depth)
|
||||
)
|
||||
}
|
||||
if (invokeReceiverCollector.isSuccess()) {
|
||||
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
|
||||
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
|
||||
components.transformQualifiedAccessUsingSmartcastInfo(it)
|
||||
}
|
||||
runResolver(
|
||||
implicitReceiverValues,
|
||||
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE),
|
||||
collector
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
CallKind.CallableReference -> return collector
|
||||
else -> throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
|
||||
}
|
||||
|
||||
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
// NB: this check does not work for variables
|
||||
// because we do not search for objects if we have extension receiver
|
||||
if (info.callKind != CallKind.VariableAccess && topLevelScope in emptyTopLevelScopes) continue
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index)
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
|
||||
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
|
||||
return collector
|
||||
}
|
||||
|
||||
private fun runResolverForExpressionReceiver(
|
||||
info: CallInfo,
|
||||
collector: CandidateCollector,
|
||||
receiver: FirExpression,
|
||||
manager: TowerResolveManager
|
||||
): CandidateCollector {
|
||||
val explicitReceiverValue = ExpressionReceiverValue(receiver)
|
||||
|
||||
val shouldProcessExtensionsBeforeMembers =
|
||||
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
|
||||
if (shouldProcessExtensionsBeforeMembers) {
|
||||
// Special case (extension hides member)
|
||||
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = explicitReceiverValue, extensionsOnly = true
|
||||
), info, TowerGroup.TopPrioritized(index), ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
}
|
||||
|
||||
manager.processLevel(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = explicitReceiverValue, scopeSession = components.scopeSession
|
||||
), info, TowerGroup.Member, ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
|
||||
val shouldProcessExplicitReceiverScopeOnly =
|
||||
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
if (shouldProcessExplicitReceiverScopeOnly) {
|
||||
// Special case (integer literal type)
|
||||
return collector
|
||||
}
|
||||
|
||||
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
|
||||
for ((index, localScope) in localScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(session, components, localScope), info, TowerGroup.Local(index),
|
||||
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
val result = manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, localScope, extensionReceiver = explicitReceiverValue
|
||||
), info, TowerGroup.Local(index), ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
if (result != ProcessorAction.NONE) {
|
||||
nonEmptyLocalScopes += localScope
|
||||
}
|
||||
}
|
||||
for ((implicitReceiverValue, usableAsValue, depth) in implicitReceivers) {
|
||||
if (!usableAsValue) continue
|
||||
// NB: companions are processed via implicitReceiverValues!
|
||||
val parentGroup = TowerGroup.Implicit(depth)
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = implicitReceiverValue, scopeSession = components.scopeSession
|
||||
), info, parentGroup.Member, InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
manager.processLevel(
|
||||
MemberScopeTowerLevel(
|
||||
session, components,
|
||||
dispatchReceiver = implicitReceiverValue, extensionReceiver = explicitReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
), info, parentGroup.Member, ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
for ((localIndex, localScope) in nonEmptyLocalScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(
|
||||
session, components, localScope, extensionReceiver = implicitReceiverValue
|
||||
), info, parentGroup.Local(localIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
}
|
||||
for ((implicitDispatchReceiverValue, usable, dispatchDepth) in implicitReceivers) {
|
||||
if (!usable) continue
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session,
|
||||
components,
|
||||
dispatchReceiver = implicitDispatchReceiverValue,
|
||||
extensionReceiver = implicitReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
), info, parentGroup.Implicit(dispatchDepth),
|
||||
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
}
|
||||
for ((topIndex, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = implicitReceiverValue
|
||||
), info, parentGroup.Top(topIndex), InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
}
|
||||
}
|
||||
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(session, components, topLevelScope), info, TowerGroup.Top(index),
|
||||
InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
)
|
||||
manager.processLevel(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = explicitReceiverValue
|
||||
), info, TowerGroup.Top(index), ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
if (collector.isSuccess()) return collector
|
||||
}
|
||||
|
||||
manager.processQueuedLevelsForInvoke(groupLimit = TowerGroup.Last)
|
||||
return collector
|
||||
}
|
||||
|
||||
internal fun enqueueResolverForInvoke(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
manager: TowerResolveManager
|
||||
) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = invokeReceiverValue, scopeSession = components.scopeSession
|
||||
), info, TowerGroup.Member,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
for ((index, localScope) in localScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(
|
||||
session, components, localScope, extensionReceiver = invokeReceiverValue
|
||||
), info, TowerGroup.Local(index),
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
|
||||
if (!usable) continue
|
||||
// NB: companions are processed via implicitReceiverValues!
|
||||
val parentGroup = TowerGroup.Implicit(depth)
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session, components,
|
||||
dispatchReceiver = implicitReceiverValue, extensionReceiver = invokeReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
), info, parentGroup.Member,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
for ((index, topLevelScope) in topLevelScopes.withIndex()) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
ScopeTowerLevel(
|
||||
session, components, topLevelScope, extensionReceiver = invokeReceiverValue
|
||||
), info, TowerGroup.Top(index),
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Here we already know extension receiver for invoke, and it's stated in info as first argument
|
||||
internal fun enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
manager: TowerResolveManager
|
||||
) {
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = invokeReceiverValue,
|
||||
scopeSession = components.scopeSession
|
||||
), info, TowerGroup.Member,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
|
||||
// Here we don't know extension receiver for invoke, assuming it's one of implicit receivers
|
||||
internal fun enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
info: CallInfo,
|
||||
invokeReceiverValue: ExpressionReceiverValue,
|
||||
manager: TowerResolveManager
|
||||
) {
|
||||
for ((implicitReceiverValue, usable, depth) in implicitReceivers) {
|
||||
if (!usable) continue
|
||||
val parentGroup = TowerGroup.Implicit(depth)
|
||||
manager.enqueueLevelForInvoke(
|
||||
MemberScopeTowerLevel(
|
||||
session, components, dispatchReceiver = invokeReceiverValue,
|
||||
extensionReceiver = implicitReceiverValue,
|
||||
implicitExtensionInvokeMode = true,
|
||||
scopeSession = components.scopeSession
|
||||
), info, parentGroup.InvokeExtension,
|
||||
InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun runResolver(
|
||||
implicitReceiverValues: List<ImplicitReceiverValue<*>>,
|
||||
info: CallInfo,
|
||||
collector: CandidateCollector = this.collector
|
||||
collector: CandidateCollector = this.collector,
|
||||
manager: TowerResolveManager = this.manager
|
||||
): CandidateCollector {
|
||||
this.implicitReceiverValues = implicitReceiverValues
|
||||
|
||||
val receiver = info.explicitReceiver
|
||||
if (receiver is FirResolvedQualifier && receiver.classId == null) {
|
||||
return runResolverForFullyQualifiedReceiver(implicitReceiverValues, info, collector, receiver)
|
||||
// TODO: add flag receiver / non-receiver position
|
||||
prepareImplicitReceivers(implicitReceiverValues)
|
||||
val candidateFactory = CandidateFactory(components, info)
|
||||
manager.candidateFactory = candidateFactory
|
||||
if (info.callKind == CallKind.CallableReference && info.stubReceiver != null) {
|
||||
manager.stubReceiverCandidateFactory = candidateFactory.replaceCallInfo(info.replaceExplicitReceiver(info.stubReceiver))
|
||||
}
|
||||
|
||||
towerDataConsumer = towerDataConsumer(info, collector)
|
||||
val shouldProcessExtensionsBeforeMembers =
|
||||
info.callKind == CallKind.Function && info.name in HIDES_MEMBERS_NAME_LIST
|
||||
val shouldProcessExplicitReceiverScopeOnly =
|
||||
info.callKind == CallKind.Function && info.explicitReceiver?.typeRef?.coneTypeSafe<ConeIntegerLiteralType>() != null
|
||||
|
||||
var group = 0
|
||||
|
||||
// Specific case when extension should be processed before members (Kotlin forEach vs Java forEach)
|
||||
if (shouldProcessExtensionsBeforeMembers) {
|
||||
for (topLevelScope in topLevelScopes) {
|
||||
group = processTopLevelScope(towerDataConsumer, topLevelScope, group, extensionsOnly = true)
|
||||
}
|
||||
}
|
||||
|
||||
// Member of explicit receiver' type (this stage does nothing without explicit receiver)
|
||||
// class Foo(val x: Int)
|
||||
// fun test(f: Foo) { f.x }
|
||||
towerDataConsumer.consume(EMPTY, TowerScopeLevel.Empty, group++)
|
||||
|
||||
if (shouldProcessExplicitReceiverScopeOnly) {
|
||||
return collector
|
||||
}
|
||||
|
||||
// Member of local scope
|
||||
// fun test(x: Int) = x
|
||||
val nonEmptyLocalScopes = mutableListOf<FirLocalScope>()
|
||||
for (scope in localScopes) {
|
||||
if (towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, scope), group++) != NONE) {
|
||||
nonEmptyLocalScopes += scope
|
||||
}
|
||||
}
|
||||
|
||||
var blockDispatchReceivers = false
|
||||
|
||||
// Member of implicit receiver' type *and* relevant scope
|
||||
for (implicitReceiverValue in implicitReceiverValues) {
|
||||
if (!blockDispatchReceivers || implicitReceiverValue !is ImplicitDispatchReceiverValue) {
|
||||
// Direct use of implicit receiver (see inside)
|
||||
group = processImplicitReceiver(towerDataConsumer, implicitReceiverValue, nonEmptyLocalScopes, group)
|
||||
}
|
||||
val implicitScope = implicitReceiverValue.implicitScope
|
||||
if (implicitScope != null) {
|
||||
// Regular implicit receiver scope (outer objects, statics)
|
||||
// object Outer {
|
||||
// val x = 0
|
||||
// class Nested { val y = x }
|
||||
// }
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitScope), group++)
|
||||
}
|
||||
if (implicitReceiverValue is ImplicitDispatchReceiverValue) {
|
||||
val implicitCompanionScopes = implicitReceiverValue.implicitCompanionScopes
|
||||
for (implicitCompanionScope in implicitCompanionScopes) {
|
||||
// Companion scope bound to implicit receiver scope
|
||||
// class Outer {
|
||||
// companion object { val x = 0 }
|
||||
// class Nested { val y = x }
|
||||
// }
|
||||
towerDataConsumer.consume(TOWER_LEVEL, ScopeTowerLevel(session, components, implicitCompanionScope), group++)
|
||||
}
|
||||
if ((implicitReceiverValue.boundSymbol.fir as? FirRegularClass)?.isInner == false) {
|
||||
blockDispatchReceivers = true
|
||||
manager.resultCollector = collector
|
||||
if (info.callKind == CallKind.Function) {
|
||||
manager.invokeReceiverCollector = CandidateCollector(components, components.resolutionStageRunner)
|
||||
manager.invokeReceiverCandidateFactory = CandidateFactory(components, info.replaceWithVariableAccess())
|
||||
if (info.explicitReceiver != null) {
|
||||
with(manager.invokeReceiverCandidateFactory) {
|
||||
manager.invokeBuiltinExtensionReceiverCandidateFactory = replaceCallInfo(callInfo.replaceExplicitReceiver(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (topLevelScope in topLevelScopes) {
|
||||
group = processTopLevelScope(towerDataConsumer, topLevelScope, group)
|
||||
return when (val receiver = info.explicitReceiver) {
|
||||
is FirResolvedQualifier -> runResolverForQualifierReceiver(info, collector, receiver, manager)
|
||||
null -> runResolverForNoReceiver(info, collector, manager)
|
||||
else -> runResolverForExpressionReceiver(info, collector, receiver, manager)
|
||||
}
|
||||
|
||||
return collector
|
||||
}
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
collector.newDataSet()
|
||||
manager.reset()
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -74,7 +74,8 @@ class PostponedArgumentsAnalyzer(
|
||||
|
||||
val callableReferenceAccess = atom.reference
|
||||
atom.analyzed = true
|
||||
val (candidate, applicability) = atom.resultingCandidate ?: Pair(null, CandidateApplicability.INAPPLICABLE)
|
||||
val (candidate, applicability) = atom.resultingCandidate
|
||||
?: Pair(null, CandidateApplicability.INAPPLICABLE)
|
||||
|
||||
val namedReference = when {
|
||||
candidate == null || applicability < CandidateApplicability.SYNTHETIC_RESOLVED ->
|
||||
|
||||
@@ -40,14 +40,19 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
||||
// TODO: add invoke cases
|
||||
when (receiverKind) {
|
||||
NO_EXPLICIT_RECEIVER -> {
|
||||
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier)
|
||||
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier) {
|
||||
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
}
|
||||
}
|
||||
EXTENSION_RECEIVER, DISPATCH_RECEIVER -> {
|
||||
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
if (explicitReceiver == null) {
|
||||
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
}
|
||||
}
|
||||
BOTH_RECEIVERS -> {
|
||||
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
if (explicitReceiver == null) {
|
||||
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
|
||||
}
|
||||
// Here we should also check additional invoke receiver
|
||||
}
|
||||
}
|
||||
@@ -284,13 +289,11 @@ internal object CheckVisibility : CheckerStage() {
|
||||
private fun ImplicitReceiverStack.canSeePrivateMemberOf(ownerId: ClassId): Boolean {
|
||||
for (implicitReceiverValue in receiversAsReversed()) {
|
||||
if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue
|
||||
if (implicitReceiverValue.companionFromSupertype) continue
|
||||
val boundSymbol = implicitReceiverValue.boundSymbol
|
||||
if (boundSymbol.classId.isSame(ownerId)) {
|
||||
return true
|
||||
}
|
||||
if (boundSymbol is FirRegularClassSymbol && boundSymbol.fir.companionObject?.symbol?.classId?.isSame(ownerId) == true) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -316,6 +319,7 @@ internal object CheckVisibility : CheckerStage() {
|
||||
val visited = mutableSetOf<ClassId>()
|
||||
for (implicitReceiverValue in receiversAsReversed()) {
|
||||
if (implicitReceiverValue !is ImplicitDispatchReceiverValue) continue
|
||||
if (implicitReceiverValue.companionFromSupertype) continue
|
||||
val boundSymbol = implicitReceiverValue.boundSymbol
|
||||
val superTypes = boundSymbol.fir.superConeTypes
|
||||
for (superType in superTypes) {
|
||||
|
||||
-266
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* 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.resolve.constructClassType
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeStarProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
|
||||
abstract class TowerDataConsumer {
|
||||
abstract val resultCollector: CandidateCollector
|
||||
|
||||
abstract fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction
|
||||
|
||||
private var stopGroup = Int.MAX_VALUE
|
||||
|
||||
fun skipGroup(group: Int): Boolean {
|
||||
if (stopGroup == Int.MAX_VALUE && resultCollector.isSuccess()) {
|
||||
stopGroup = group
|
||||
}
|
||||
if (group >= stopGroup) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class PrioritizedTowerDataConsumer(
|
||||
override val resultCollector: CandidateCollector,
|
||||
private vararg val consumers: TowerDataConsumer
|
||||
) : TowerDataConsumer() {
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group)) return ProcessorAction.NEXT
|
||||
var empty = true
|
||||
for ((index, consumer) in consumers.withIndex()) {
|
||||
when (val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
}
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
// Yet is used exclusively for invokes:
|
||||
// - initialConsumer consumes property which is invoke receiver
|
||||
// - additionalConsumers consume invoke calls themselves
|
||||
class AccumulatingTowerDataConsumer(
|
||||
override val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
lateinit var initialConsumer: TowerDataConsumer
|
||||
|
||||
private val additionalConsumers = mutableListOf<TowerDataConsumer>()
|
||||
|
||||
private data class TowerData(val kind: TowerDataKind, val level: TowerScopeLevel, val group: Int)
|
||||
|
||||
private val accumulatedTowerData = mutableListOf<TowerData>()
|
||||
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group)) return ProcessorAction.NEXT
|
||||
accumulatedTowerData += TowerData(kind, towerScopeLevel, group)
|
||||
|
||||
var empty = true
|
||||
when (val action = initialConsumer.consume(kind, towerScopeLevel, group)) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
for (consumer in additionalConsumers) {
|
||||
when (val action = consumer.consume(kind, towerScopeLevel, group)) {
|
||||
ProcessorAction.STOP -> return action
|
||||
ProcessorAction.NEXT -> empty = false
|
||||
}
|
||||
}
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
fun addConsumerAndProcessAccumulatedData(consumer: TowerDataConsumer): ProcessorAction {
|
||||
additionalConsumers += consumer
|
||||
if (accumulatedTowerData.isEmpty()) return ProcessorAction.NEXT
|
||||
for ((kind, level, group) in accumulatedTowerData.asSequence().take(accumulatedTowerData.size - 1)) {
|
||||
if (consumer.consume(kind, level, group).stop()) {
|
||||
return ProcessorAction.STOP
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
class ExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
|
||||
val session: FirSession,
|
||||
val name: Name,
|
||||
val token: TowerScopeLevel.Token<T>,
|
||||
val explicitReceiver: AbstractExplicitReceiver<*>,
|
||||
val candidateFactory: CandidateFactory,
|
||||
override val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
|
||||
companion object {
|
||||
val defaultPackage = Name.identifier("kotlin")
|
||||
}
|
||||
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group)) return ProcessorAction.NEXT
|
||||
return when (kind) {
|
||||
TowerDataKind.EMPTY -> {
|
||||
MemberScopeTowerLevel(
|
||||
session, resultCollector.components, explicitReceiver,
|
||||
implicitExtensionReceiver = (towerScopeLevel as? TowerScopeLevel.OnlyImplicitReceiver)?.implicitReceiverValue,
|
||||
implicitExtensionInvokeMode = towerScopeLevel is TowerScopeLevel.OnlyImplicitReceiver,
|
||||
scopeSession = candidateFactory.bodyResolveComponents.scopeSession
|
||||
).processElementsByName(
|
||||
token,
|
||||
name,
|
||||
explicitReceiver = null,
|
||||
processor = EmptyKindTowerProcessor(group)
|
||||
)
|
||||
}
|
||||
TowerDataKind.TOWER_LEVEL -> {
|
||||
if (token == TowerScopeLevel.Token.Objects) return ProcessorAction.NEXT
|
||||
towerScopeLevel.processElementsByName(
|
||||
token,
|
||||
name,
|
||||
explicitReceiver = explicitReceiver,
|
||||
processor = TowerLevelKindTowerProcessor(group)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private inner class EmptyKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||
override fun consumeCandidate(
|
||||
symbol: T,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
||||
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
||||
) {
|
||||
resultCollector.consumeCandidate(
|
||||
group,
|
||||
candidateFactory.createCandidate(
|
||||
symbol,
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER,
|
||||
dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue,
|
||||
builtInExtensionFunctionReceiverValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class TowerLevelKindTowerProcessor(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||
override fun consumeCandidate(
|
||||
symbol: T,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
||||
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
||||
) {
|
||||
if (symbol is FirNamedFunctionSymbol && symbol.callableId.packageName.startsWith(defaultPackage)) {
|
||||
val explicitReceiverType = explicitReceiver.type
|
||||
if (dispatchReceiverValue == null && explicitReceiverType is ConeClassLikeType) {
|
||||
val declarationReceiverTypeRef =
|
||||
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
|
||||
val declarationReceiverType = declarationReceiverTypeRef?.type
|
||||
if (declarationReceiverType is ConeClassLikeType) {
|
||||
if (!AbstractTypeChecker.isSubtypeOf(
|
||||
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
|
||||
explicitReceiverType,
|
||||
declarationReceiverType.lookupTag.constructClassType(
|
||||
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
||||
isNullable = true
|
||||
)
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val candidate = candidateFactory.createCandidate(
|
||||
symbol,
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER,
|
||||
dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue,
|
||||
builtInExtensionFunctionReceiverValue
|
||||
)
|
||||
|
||||
resultCollector.consumeCandidate(
|
||||
group,
|
||||
candidate
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NoExplicitReceiverTowerDataConsumer<T : AbstractFirBasedSymbol<*>>(
|
||||
val session: FirSession,
|
||||
val name: Name,
|
||||
val token: TowerScopeLevel.Token<T>,
|
||||
val candidateFactory: CandidateFactory,
|
||||
override val resultCollector: CandidateCollector
|
||||
) : TowerDataConsumer() {
|
||||
override fun consume(
|
||||
kind: TowerDataKind,
|
||||
towerScopeLevel: TowerScopeLevel,
|
||||
group: Int
|
||||
): ProcessorAction {
|
||||
if (skipGroup(group)) return ProcessorAction.NEXT
|
||||
return when (kind) {
|
||||
|
||||
TowerDataKind.TOWER_LEVEL -> {
|
||||
towerScopeLevel.processElementsByName(
|
||||
token,
|
||||
name,
|
||||
explicitReceiver = null,
|
||||
processor = TowerLevelProcessorImpl(group)
|
||||
)
|
||||
}
|
||||
else -> ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
private inner class TowerLevelProcessorImpl(val group: Int) : TowerScopeLevel.TowerScopeLevelProcessor<T> {
|
||||
override fun consumeCandidate(
|
||||
symbol: T,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
||||
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
||||
) {
|
||||
resultCollector.consumeCandidate(
|
||||
group,
|
||||
candidateFactory.createCandidate(
|
||||
symbol,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue,
|
||||
builtInExtensionFunctionReceiverValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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
|
||||
|
||||
sealed class TowerGroupKind(private val index: Int) : Comparable<TowerGroupKind> {
|
||||
abstract class WithDepth(index: Int, val depth: Int) : TowerGroupKind(index)
|
||||
|
||||
object Start : TowerGroupKind(Integer.MIN_VALUE)
|
||||
|
||||
class Weakened(depth: Int) : WithDepth(-10, depth)
|
||||
|
||||
object Qualifier : TowerGroupKind(0)
|
||||
|
||||
class TopPrioritized(depth: Int) : WithDepth(1, depth)
|
||||
|
||||
object Member : TowerGroupKind(2)
|
||||
|
||||
class Local(depth: Int) : WithDepth(3, depth)
|
||||
|
||||
class Implicit(depth: Int) : WithDepth(4, depth)
|
||||
|
||||
object InvokeExtension : TowerGroupKind(5)
|
||||
|
||||
class Top(depth: Int) : WithDepth(6, depth)
|
||||
|
||||
class Static(depth: Int) : WithDepth(7, depth)
|
||||
|
||||
object Last : TowerGroupKind(Integer.MAX_VALUE)
|
||||
|
||||
override fun compareTo(other: TowerGroupKind): Int {
|
||||
val indexResult = index.compareTo(other.index)
|
||||
if (indexResult != 0) return indexResult
|
||||
if (this is WithDepth && other is WithDepth) {
|
||||
return depth.compareTo(other.depth)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("FunctionName", "unused", "PropertyName")
|
||||
class TowerGroup private constructor(private val list: List<TowerGroupKind>) : Comparable<TowerGroup> {
|
||||
companion object {
|
||||
private fun kindOf(kind: TowerGroupKind): TowerGroup = TowerGroup(listOf(kind))
|
||||
|
||||
val Start = kindOf(TowerGroupKind.Start)
|
||||
|
||||
val Qualifier = kindOf(TowerGroupKind.Qualifier)
|
||||
|
||||
val Member = kindOf(TowerGroupKind.Member)
|
||||
|
||||
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
||||
|
||||
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
||||
|
||||
fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth))
|
||||
|
||||
fun TopPrioritized(depth: Int) = kindOf(TowerGroupKind.TopPrioritized(depth))
|
||||
|
||||
fun Static(depth: Int) = kindOf(TowerGroupKind.Static(depth))
|
||||
|
||||
val Last = kindOf(TowerGroupKind.Last)
|
||||
}
|
||||
|
||||
private fun kindOf(kind: TowerGroupKind): TowerGroup = TowerGroup(list + kind)
|
||||
|
||||
fun Weakened(depth: Int) = kindOf(TowerGroupKind.Weakened(depth))
|
||||
|
||||
val Qualifier get() = kindOf(TowerGroupKind.Qualifier)
|
||||
|
||||
val Member get() = kindOf(TowerGroupKind.Member)
|
||||
|
||||
fun Local(depth: Int) = kindOf(TowerGroupKind.Local(depth))
|
||||
|
||||
fun Implicit(depth: Int) = kindOf(TowerGroupKind.Implicit(depth))
|
||||
|
||||
val InvokeExtension get() = kindOf(TowerGroupKind.InvokeExtension)
|
||||
|
||||
fun Top(depth: Int) = kindOf(TowerGroupKind.Top(depth))
|
||||
|
||||
fun Static(depth: Int) = kindOf(TowerGroupKind.Static(depth))
|
||||
|
||||
override fun compareTo(other: TowerGroup): Int {
|
||||
var index = 0
|
||||
while (index < list.size) {
|
||||
if (index >= other.list.size) return 1
|
||||
when {
|
||||
list[index] < other.list[index] -> return -1
|
||||
list[index] > other.list[index] -> return 1
|
||||
}
|
||||
index++
|
||||
}
|
||||
if (index < other.list.size) return -1
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
println(TowerGroup.Member < TowerGroup.Last)
|
||||
println(TowerGroup.Member < TowerGroup.Member.Weakened(1))
|
||||
println(TowerGroup.Member.Weakened(1) < TowerGroup.Member)
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.resolve.calls.tasks.ExplicitReceiverKind
|
||||
|
||||
internal class TowerInvokeResolveQuery(
|
||||
val towerLevel: SessionBasedTowerLevel,
|
||||
val callInfo: CallInfo,
|
||||
val explicitReceiverKind: ExplicitReceiverKind,
|
||||
val group: TowerGroup,
|
||||
val mode: InvokeResolveMode
|
||||
) : Comparable<TowerInvokeResolveQuery> {
|
||||
override fun compareTo(other: TowerInvokeResolveQuery): Int {
|
||||
return group.compareTo(other.group)
|
||||
}
|
||||
}
|
||||
|
||||
enum class InvokeResolveMode {
|
||||
IMPLICIT_CALL_ON_GIVEN_RECEIVER,
|
||||
RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
}
|
||||
@@ -6,10 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.isStatic
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
@@ -18,11 +15,11 @@ import org.jetbrains.kotlin.fir.resolve.withNullability
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirQualifierScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
import org.jetbrains.kotlin.fir.types.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
@@ -39,7 +36,6 @@ interface TowerScopeLevel {
|
||||
fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
|
||||
token: Token<T>,
|
||||
name: Name,
|
||||
explicitReceiver: AbstractExplicitReceiver<*>?,
|
||||
processor: TowerScopeLevelProcessor<T>
|
||||
): ProcessorAction
|
||||
|
||||
@@ -51,19 +47,6 @@ interface TowerScopeLevel {
|
||||
builtInExtensionFunctionReceiverValue: ReceiverValue? = null
|
||||
)
|
||||
}
|
||||
|
||||
abstract class StubTowerScopeLevel : TowerScopeLevel {
|
||||
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
|
||||
token: Token<T>,
|
||||
name: Name,
|
||||
explicitReceiver: AbstractExplicitReceiver<*>?,
|
||||
processor: TowerScopeLevelProcessor<T>
|
||||
): ProcessorAction = ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
object Empty : StubTowerScopeLevel()
|
||||
|
||||
class OnlyImplicitReceiver(val implicitReceiverValue: ImplicitReceiverValue<*>) : StubTowerScopeLevel()
|
||||
}
|
||||
|
||||
abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel {
|
||||
@@ -77,12 +60,11 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
|
||||
}
|
||||
}
|
||||
|
||||
protected fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(extensionReceiver: ReceiverValue?): Boolean {
|
||||
return when {
|
||||
extensionReceiver != null -> hasExtensionReceiver()
|
||||
else -> fir.receiverTypeRef == null
|
||||
}
|
||||
protected fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(extensionReceiver: Receiver?): Boolean {
|
||||
return (extensionReceiver != null) == hasExtensionReceiver()
|
||||
}
|
||||
|
||||
open fun replaceReceiverValue(receiverValue: ReceiverValue) = this
|
||||
}
|
||||
|
||||
// This is more like "dispatch receiver-based tower level"
|
||||
@@ -93,73 +75,82 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
|
||||
// or given implicit or explicit receiver, otherwise
|
||||
class MemberScopeTowerLevel(
|
||||
session: FirSession,
|
||||
val bodyResolveComponents: BodyResolveComponents,
|
||||
private val bodyResolveComponents: BodyResolveComponents,
|
||||
val dispatchReceiver: ReceiverValue,
|
||||
val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null,
|
||||
val extensionReceiver: ReceiverValue? = null,
|
||||
val implicitExtensionInvokeMode: Boolean = false,
|
||||
val scopeSession: ScopeSession
|
||||
) : SessionBasedTowerLevel(session) {
|
||||
private fun <T : AbstractFirBasedSymbol<*>> processMembers(
|
||||
output: TowerScopeLevel.TowerScopeLevelProcessor<T>,
|
||||
explicitExtensionReceiver: AbstractExplicitReceiver<*>?,
|
||||
processScopeMembers: FirScope.(processor: (T) -> Unit) -> Unit
|
||||
) {
|
||||
if (implicitExtensionReceiver != null && explicitExtensionReceiver != null) return
|
||||
val extensionReceiver = implicitExtensionReceiver ?: explicitExtensionReceiver
|
||||
val scope = dispatchReceiver.scope(session, scopeSession) ?: return
|
||||
): ProcessorAction {
|
||||
var empty = true
|
||||
val scope = dispatchReceiver.scope(session, scopeSession) ?: return ProcessorAction.NONE
|
||||
scope.processScopeMembers { candidate ->
|
||||
empty = false
|
||||
if (candidate is FirCallableSymbol<*> &&
|
||||
(implicitExtensionInvokeMode || candidate.hasConsistentExtensionReceiver(extensionReceiver))
|
||||
) {
|
||||
val fir = candidate.fir
|
||||
if ((fir as? FirCallableMemberDeclaration<*>)?.isStatic == true || (fir as? FirConstructor)?.isInner == false) {
|
||||
return@processScopeMembers
|
||||
}
|
||||
val dispatchReceiverValue = NotNullableReceiverValue(dispatchReceiver)
|
||||
if (implicitExtensionInvokeMode) {
|
||||
output.consumeCandidate(
|
||||
candidate, dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue = implicitExtensionReceiver
|
||||
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
|
||||
)
|
||||
output.consumeCandidate(
|
||||
candidate, dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue = null,
|
||||
builtInExtensionFunctionReceiverValue = implicitExtensionReceiver
|
||||
builtInExtensionFunctionReceiverValue = this.extensionReceiver
|
||||
)
|
||||
} else {
|
||||
output.consumeCandidate(candidate, dispatchReceiverValue, implicitExtensionReceiver, null)
|
||||
output.consumeCandidate(candidate, dispatchReceiverValue, extensionReceiver as? ImplicitReceiverValue<*>)
|
||||
}
|
||||
} else if (candidate is FirClassLikeSymbol<*>) {
|
||||
output.consumeCandidate(candidate, null, implicitExtensionReceiver, null)
|
||||
output.consumeCandidate(candidate, null, extensionReceiver as? ImplicitReceiverValue<*>)
|
||||
}
|
||||
}
|
||||
|
||||
val withSynthetic = FirSyntheticPropertiesScope(session, scope)
|
||||
withSynthetic.processScopeMembers { symbol ->
|
||||
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), implicitExtensionReceiver, null)
|
||||
output.consumeCandidate(symbol, NotNullableReceiverValue(dispatchReceiver), extensionReceiver as? ImplicitReceiverValue<*>)
|
||||
}
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
|
||||
token: TowerScopeLevel.Token<T>,
|
||||
name: Name,
|
||||
explicitReceiver: AbstractExplicitReceiver<*>?,
|
||||
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
|
||||
): ProcessorAction {
|
||||
val isInvoke = name == OperatorNameConventions.INVOKE && token == TowerScopeLevel.Token.Functions
|
||||
if (implicitExtensionInvokeMode && !isInvoke) {
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
val explicitExtensionReceiver = if (dispatchReceiver == explicitReceiver) null else explicitReceiver
|
||||
val noInnerConstructors = dispatchReceiver is QualifierReceiver
|
||||
when (token) {
|
||||
TowerScopeLevel.Token.Properties -> processMembers(processor, explicitExtensionReceiver) { symbol ->
|
||||
return when (token) {
|
||||
TowerScopeLevel.Token.Properties -> processMembers(processor) { symbol ->
|
||||
this.processPropertiesByName(name, symbol.cast())
|
||||
}
|
||||
TowerScopeLevel.Token.Functions -> processMembers(processor, explicitExtensionReceiver) { symbol ->
|
||||
this.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, noInnerConstructors, symbol.cast())
|
||||
TowerScopeLevel.Token.Functions -> processMembers(processor) { symbol ->
|
||||
this.processFunctionsAndConstructorsByName(
|
||||
name, session, bodyResolveComponents,
|
||||
noInnerConstructors = false, processor = symbol.cast()
|
||||
)
|
||||
}
|
||||
TowerScopeLevel.Token.Objects -> processMembers(processor, explicitExtensionReceiver) { symbol ->
|
||||
TowerScopeLevel.Token.Objects -> processMembers(processor) { symbol ->
|
||||
this.processClassifiersByName(name, symbol.cast())
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
override fun replaceReceiverValue(receiverValue: ReceiverValue): SessionBasedTowerLevel {
|
||||
return MemberScopeTowerLevel(
|
||||
session, bodyResolveComponents, receiverValue, extensionReceiver, implicitExtensionInvokeMode, scopeSession
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +165,10 @@ class ScopeTowerLevel(
|
||||
session: FirSession,
|
||||
private val bodyResolveComponents: BodyResolveComponents,
|
||||
val scope: FirScope,
|
||||
val implicitExtensionReceiver: ImplicitReceiverValue<*>? = null,
|
||||
val extensionReceiver: ReceiverValue? = null,
|
||||
private val extensionsOnly: Boolean = false
|
||||
) : SessionBasedTowerLevel(session) {
|
||||
private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: ReceiverValue?): Boolean =
|
||||
private fun FirCallableSymbol<*>.hasConsistentReceivers(extensionReceiver: Receiver?): Boolean =
|
||||
when {
|
||||
extensionsOnly && !hasExtensionReceiver() -> false
|
||||
!hasConsistentExtensionReceiver(extensionReceiver) -> false
|
||||
@@ -188,43 +179,43 @@ class ScopeTowerLevel(
|
||||
override fun <T : AbstractFirBasedSymbol<*>> processElementsByName(
|
||||
token: TowerScopeLevel.Token<T>,
|
||||
name: Name,
|
||||
explicitReceiver: AbstractExplicitReceiver<*>?,
|
||||
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
|
||||
): ProcessorAction {
|
||||
if (explicitReceiver != null && implicitExtensionReceiver != null) {
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
val extensionReceiver = explicitReceiver ?: implicitExtensionReceiver
|
||||
var empty = true
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (token) {
|
||||
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate ->
|
||||
empty = false
|
||||
if (candidate.hasConsistentReceivers(extensionReceiver)) {
|
||||
processor.consumeCandidate(
|
||||
candidate as T, dispatchReceiverValue = null,
|
||||
implicitExtensionReceiverValue = implicitExtensionReceiver
|
||||
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
|
||||
)
|
||||
}
|
||||
}
|
||||
TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName(
|
||||
name,
|
||||
session,
|
||||
bodyResolveComponents
|
||||
bodyResolveComponents,
|
||||
noInnerConstructors = scope is FirQualifierScope
|
||||
) { candidate ->
|
||||
empty = false
|
||||
if (candidate.hasConsistentReceivers(extensionReceiver)) {
|
||||
processor.consumeCandidate(
|
||||
candidate as T, dispatchReceiverValue = null,
|
||||
implicitExtensionReceiverValue = implicitExtensionReceiver
|
||||
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
|
||||
)
|
||||
}
|
||||
}
|
||||
TowerScopeLevel.Token.Objects -> scope.processClassifiersByName(name) {
|
||||
empty = false
|
||||
processor.consumeCandidate(
|
||||
it as T, dispatchReceiverValue = null,
|
||||
implicitExtensionReceiverValue = null
|
||||
)
|
||||
}
|
||||
}
|
||||
return ProcessorAction.NEXT
|
||||
return if (empty) ProcessorAction.NONE else ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +237,5 @@ fun FirCallableDeclaration<*>.dispatchReceiverValue(session: FirSession): ClassD
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean {
|
||||
if (fir.receiverTypeRef != null) return true
|
||||
return fir.returnTypeRef.isExtensionFunctionType()
|
||||
return fir.receiverTypeRef != null
|
||||
}
|
||||
|
||||
+306
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.constructClassType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
class TowerResolveManager internal constructor(private val towerResolver: FirTowerResolver) {
|
||||
private val queue = PriorityQueue<TowerInvokeResolveQuery>()
|
||||
|
||||
private var group = TowerGroup.Start
|
||||
|
||||
lateinit var candidateFactory: CandidateFactory
|
||||
|
||||
lateinit var invokeOnGivenReceiverCandidateFactory: CandidateFactory
|
||||
|
||||
lateinit var invokeReceiverCandidateFactory: CandidateFactory
|
||||
|
||||
lateinit var invokeBuiltinExtensionReceiverCandidateFactory: CandidateFactory
|
||||
|
||||
lateinit var stubReceiverCandidateFactory: CandidateFactory
|
||||
|
||||
lateinit var resultCollector: CandidateCollector
|
||||
|
||||
lateinit var invokeReceiverCollector: CandidateCollector
|
||||
|
||||
private class TowerScopeLevelProcessor(
|
||||
val explicitReceiver: FirExpression?,
|
||||
val explicitReceiverKind: ExplicitReceiverKind,
|
||||
val resultCollector: CandidateCollector,
|
||||
val candidateFactory: CandidateFactory,
|
||||
val group: TowerGroup
|
||||
) : TowerScopeLevel.TowerScopeLevelProcessor<AbstractFirBasedSymbol<*>> {
|
||||
override fun consumeCandidate(
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
dispatchReceiverValue: ReceiverValue?,
|
||||
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
|
||||
builtInExtensionFunctionReceiverValue: ReceiverValue?
|
||||
) {
|
||||
// Check explicit extension receiver for default package members
|
||||
if (symbol is FirNamedFunctionSymbol && dispatchReceiverValue == null &&
|
||||
(implicitExtensionReceiverValue == null) != (explicitReceiver == null) &&
|
||||
explicitReceiver !is FirResolvedQualifier &&
|
||||
symbol.callableId.packageName.startsWith(defaultPackage)
|
||||
) {
|
||||
val extensionReceiverType = explicitReceiver?.typeRef?.coneTypeSafe()
|
||||
?: implicitExtensionReceiverValue?.type as? ConeClassLikeType
|
||||
if (extensionReceiverType != null) {
|
||||
val declarationReceiverTypeRef =
|
||||
(symbol as? FirCallableSymbol<*>)?.fir?.receiverTypeRef as? FirResolvedTypeRef
|
||||
val declarationReceiverType = declarationReceiverTypeRef?.type
|
||||
if (declarationReceiverType is ConeClassLikeType) {
|
||||
if (!AbstractTypeChecker.isSubtypeOf(
|
||||
candidateFactory.bodyResolveComponents.inferenceComponents.ctx,
|
||||
extensionReceiverType,
|
||||
declarationReceiverType.lookupTag.constructClassType(
|
||||
declarationReceiverType.typeArguments.map { ConeStarProjection }.toTypedArray(),
|
||||
isNullable = true
|
||||
)
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---
|
||||
resultCollector.consumeCandidate(
|
||||
group, candidateFactory.createCandidate(
|
||||
symbol,
|
||||
explicitReceiverKind,
|
||||
dispatchReceiverValue,
|
||||
implicitExtensionReceiverValue,
|
||||
builtInExtensionFunctionReceiverValue
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val defaultPackage = Name.identifier("kotlin")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private inner class LevelHandler(
|
||||
val info: CallInfo,
|
||||
val explicitReceiverKind: ExplicitReceiverKind,
|
||||
val group: TowerGroup
|
||||
) {
|
||||
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionImpl {
|
||||
val symbol = candidate.symbol as FirCallableSymbol<*>
|
||||
return FirQualifiedAccessExpressionImpl(null).apply {
|
||||
calleeReference = FirNamedReferenceWithCandidate(
|
||||
null,
|
||||
symbol.callableId.callableName,
|
||||
candidate
|
||||
)
|
||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||
}
|
||||
}
|
||||
|
||||
fun SessionBasedTowerLevel.handleLevel(invokeResolveMode: InvokeResolveMode? = null): ProcessorAction {
|
||||
var result = ProcessorAction.NONE
|
||||
val processor =
|
||||
TowerScopeLevelProcessor(
|
||||
info.explicitReceiver,
|
||||
explicitReceiverKind,
|
||||
resultCollector,
|
||||
// TODO: performance?
|
||||
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER) {
|
||||
invokeOnGivenReceiverCandidateFactory
|
||||
} else candidateFactory,
|
||||
group
|
||||
)
|
||||
when (info.callKind) {
|
||||
CallKind.VariableAccess -> {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||
// TODO: more accurate condition, or process properties/object in some other way
|
||||
if (!resultCollector.isSuccess() &&
|
||||
(this !is ScopeTowerLevel || this.extensionReceiver == null)
|
||||
) {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, processor)
|
||||
}
|
||||
}
|
||||
CallKind.Function -> {
|
||||
val invokeBuiltinExtensionMode =
|
||||
invokeResolveMode == InvokeResolveMode.RECEIVER_FOR_INVOKE_BUILTIN_EXTENSION
|
||||
if (!invokeBuiltinExtensionMode) {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||
}
|
||||
if (invokeResolveMode == InvokeResolveMode.IMPLICIT_CALL_ON_GIVEN_RECEIVER ||
|
||||
resultCollector.isSuccess()
|
||||
) {
|
||||
return result
|
||||
}
|
||||
|
||||
val invokeReceiverProcessor = TowerScopeLevelProcessor(
|
||||
info.explicitReceiver,
|
||||
explicitReceiverKind,
|
||||
invokeReceiverCollector,
|
||||
if (invokeBuiltinExtensionMode) invokeBuiltinExtensionReceiverCandidateFactory
|
||||
else invokeReceiverCandidateFactory,
|
||||
group
|
||||
)
|
||||
invokeReceiverCollector.newDataSet()
|
||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
|
||||
|
||||
if (invokeReceiverCollector.isSuccess()) {
|
||||
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
|
||||
|
||||
val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*>
|
||||
val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType()
|
||||
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
||||
continue
|
||||
}
|
||||
val extensionReceiverExpression = invokeReceiverCandidate.extensionReceiverExpression()
|
||||
val useImplicitReceiverAsBuiltinInvokeArgument =
|
||||
!invokeBuiltinExtensionMode && isExtensionFunctionType &&
|
||||
invokeReceiverCandidate.explicitReceiverKind == ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
|
||||
val invokeReceiverExpression = createExplicitReceiverForInvoke(invokeReceiverCandidate).let {
|
||||
if (!invokeBuiltinExtensionMode) {
|
||||
it.extensionReceiver = extensionReceiverExpression
|
||||
// NB: this should fix problem in DFA (KT-36014)
|
||||
it.explicitReceiver = info.explicitReceiver
|
||||
it.safe = info.isSafeCall
|
||||
}
|
||||
towerResolver.components.transformQualifiedAccessUsingSmartcastInfo(it)
|
||||
}
|
||||
|
||||
val invokeFunctionInfo =
|
||||
info.copy(explicitReceiver = invokeReceiverExpression, name = OperatorNameConventions.INVOKE).let {
|
||||
when {
|
||||
invokeBuiltinExtensionMode -> it.withReceiverAsArgument(info.explicitReceiver!!)
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
|
||||
val explicitReceiver = ExpressionReceiverValue(invokeReceiverExpression)
|
||||
invokeOnGivenReceiverCandidateFactory = CandidateFactory(towerResolver.components, invokeFunctionInfo)
|
||||
when {
|
||||
invokeBuiltinExtensionMode -> {
|
||||
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithExplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
||||
)
|
||||
}
|
||||
useImplicitReceiverAsBuiltinInvokeArgument -> {
|
||||
towerResolver.enqueueResolverForBuiltinInvokeExtensionWithImplicitArgument(
|
||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
||||
)
|
||||
towerResolver.enqueueResolverForInvoke(
|
||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
towerResolver.enqueueResolverForInvoke(
|
||||
invokeFunctionInfo, explicitReceiver, this@TowerResolveManager
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
processQueuedLevelsForInvoke()
|
||||
}
|
||||
}
|
||||
CallKind.CallableReference -> {
|
||||
val stubReceiver = info.stubReceiver
|
||||
if (stubReceiver != null) {
|
||||
val stubReceiverValue = ExpressionReceiverValue(stubReceiver)
|
||||
val stubProcessor = TowerScopeLevelProcessor(
|
||||
info.explicitReceiver,
|
||||
if (this is MemberScopeTowerLevel && dispatchReceiver is AbstractExplicitReceiver<*>) {
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER
|
||||
} else {
|
||||
ExplicitReceiverKind.EXTENSION_RECEIVER
|
||||
},
|
||||
resultCollector,
|
||||
stubReceiverCandidateFactory, group
|
||||
)
|
||||
val towerLevelWithStubReceiver = replaceReceiverValue(stubReceiverValue)
|
||||
with(towerLevelWithStubReceiver) {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, stubProcessor)
|
||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, stubProcessor)
|
||||
}
|
||||
// NB: we don't perform this for implicit Unit
|
||||
if (!resultCollector.isSuccess() && info.explicitReceiver?.typeRef !is FirImplicitBuiltinTypeRef) {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||
}
|
||||
} else {
|
||||
result += processElementsByName(TowerScopeLevel.Token.Functions, info.name, processor)
|
||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, processor)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw AssertionError("Unsupported call kind in tower resolver: ${info.callKind}")
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
queue.clear()
|
||||
group = TowerGroup.Start
|
||||
}
|
||||
|
||||
fun processLevel(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
): ProcessorAction {
|
||||
assert(group > this.group) {
|
||||
"Incorrect TowerGroup processing order (c) Mikhail Glukhikh"
|
||||
}
|
||||
this.group = group
|
||||
val result = with(LevelHandler(callInfo, explicitReceiverKind, group)) {
|
||||
towerLevel.handleLevel()
|
||||
}
|
||||
processQueuedLevelsForInvoke()
|
||||
return result
|
||||
}
|
||||
|
||||
fun enqueueLevelForInvoke(
|
||||
towerLevel: SessionBasedTowerLevel,
|
||||
callInfo: CallInfo,
|
||||
group: TowerGroup,
|
||||
mode: InvokeResolveMode,
|
||||
explicitReceiverKind: ExplicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
) {
|
||||
if (callInfo.callKind == CallKind.Function) {
|
||||
queue.add(TowerInvokeResolveQuery(towerLevel, callInfo, explicitReceiverKind, group, mode))
|
||||
}
|
||||
}
|
||||
|
||||
fun processQueuedLevelsForInvoke(groupLimit: TowerGroup = this.group) {
|
||||
while (queue.isNotEmpty()) {
|
||||
if (queue.peek().group > groupLimit) {
|
||||
break
|
||||
}
|
||||
val query = queue.poll()
|
||||
with(LevelHandler(query.callInfo, query.explicitReceiverKind, query.group)) {
|
||||
query.towerLevel.handleLevel(invokeResolveMode = query.mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-2
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitExtensionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.extractLambdaInfoFromFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
@@ -493,8 +492,24 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
||||
type: ConeKotlinType,
|
||||
block: () -> T
|
||||
): T {
|
||||
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>()
|
||||
val implicitReceiverValue = when (owner) {
|
||||
is FirClass<*> -> {
|
||||
// Questionable: performance
|
||||
(owner as? FirRegularClass)?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION
|
||||
)
|
||||
}
|
||||
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
|
||||
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
|
||||
superClass?.companionObject?.let { companion ->
|
||||
implicitCompanionValues += ImplicitDispatchReceiverValue(
|
||||
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
|
||||
)
|
||||
}
|
||||
}
|
||||
// ---
|
||||
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
|
||||
}
|
||||
is FirFunction<*> -> {
|
||||
@@ -507,9 +522,15 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
|
||||
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
|
||||
}
|
||||
}
|
||||
for (implicitCompanionValue in implicitCompanionValues.asReversed()) {
|
||||
implicitReceiverStack.add(null, implicitCompanionValue)
|
||||
}
|
||||
implicitReceiverStack.add(labelName, implicitReceiverValue)
|
||||
val result = block()
|
||||
implicitReceiverStack.pop(labelName)
|
||||
for (implicitCompanionValue in implicitCompanionValues) {
|
||||
implicitReceiverStack.pop(null)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirVariableAssignmentImpl
|
||||
import org.jetbrains.kotlin.fir.references.FirDelegateFieldReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.references.FirThisReference
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirErrorNamedReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirExplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
|
||||
|
||||
@@ -81,8 +81,6 @@ class KotlinScopeProvider(
|
||||
): FirScope? {
|
||||
return when (klass.classKind) {
|
||||
ClassKind.ENUM_CLASS -> FirStaticScope(declaredMemberScope(klass))
|
||||
// TODO: should be wrapped with FirStaticScope, non-static callables should be processed separately
|
||||
ClassKind.OBJECT -> getUseSiteMemberScope(klass, ConeSubstitutor.Empty, useSiteSession, scopeSession)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,18 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.isStatic
|
||||
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.name.Name
|
||||
|
||||
class FirStaticScope(private val delegateScope: FirScope) : FirScope() {
|
||||
|
||||
override fun processClassifiersByName(name: Name, processor: (FirClassifierSymbol<*>) -> Unit) {
|
||||
delegateScope.processClassifiersByName(name) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(
|
||||
name: Name,
|
||||
processor: (FirFunctionSymbol<*>) -> Unit
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.kotlin.codegen.range.inExpression
|
||||
|
||||
class CallBasedInExpressionGenerator(
|
||||
val codegen: ExpressionCodegen,
|
||||
operatorReference: KtSimpleNameExpression
|
||||
) : InExpressionGenerator {
|
||||
private val resolvedCall = operatorReference.<!UNRESOLVED_REFERENCE!>getResolvedCallWithAssert<!>(codegen.<!UNRESOLVED_REFERENCE!>bindingContext<!>)
|
||||
private val isInverted = operatorReference.<!UNRESOLVED_REFERENCE!>getReferencedNameElementType<!>() == <!UNRESOLVED_REFERENCE!>KtTokens<!>.<!UNRESOLVED_REFERENCE!>NOT_IN<!>
|
||||
|
||||
override fun generate(argument: StackValue): BranchedValue =
|
||||
gen(argument).<!INAPPLICABLE_CANDIDATE!>let<!> { if (isInverted) <!UNRESOLVED_REFERENCE!>Invert<!>(<!UNRESOLVED_REFERENCE!>it<!>) else <!UNRESOLVED_REFERENCE!>it<!> }
|
||||
|
||||
private fun gen(argument: StackValue): BranchedValue =
|
||||
object : BranchedValue(argument, null, argument.<!UNRESOLVED_REFERENCE!>type<!>, <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFEQ<!>) {
|
||||
override fun putSelector(type: Type, kotlinType: KotlinType?, v: InstructionAdapter) {
|
||||
invokeFunction(v)
|
||||
<!UNRESOLVED_REFERENCE!>coerceTo<!>(type, kotlinType, v)
|
||||
}
|
||||
|
||||
override fun condJump(jumpLabel: Label, v: InstructionAdapter, jumpIfFalse: Boolean) {
|
||||
invokeFunction(v)
|
||||
v.<!UNRESOLVED_REFERENCE!>visitJumpInsn<!>(if (jumpIfFalse) <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFEQ<!> else <!UNRESOLVED_REFERENCE!>Opcodes<!>.<!UNRESOLVED_REFERENCE!>IFNE<!>, jumpLabel)
|
||||
}
|
||||
|
||||
private fun invokeFunction(v: InstructionAdapter) {
|
||||
val result = codegen.<!UNRESOLVED_REFERENCE!>invokeFunction<!>(resolvedCall.<!UNRESOLVED_REFERENCE!>call<!>, resolvedCall, <!UNRESOLVED_REFERENCE!>none<!>())
|
||||
result.<!UNRESOLVED_REFERENCE!>put<!>(result.<!UNRESOLVED_REFERENCE!>type<!>, result.<!UNRESOLVED_REFERENCE!>kotlinType<!>, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
FILE: CallBasedInExpressionGenerator.kt
|
||||
public final class CallBasedInExpressionGenerator : R|class error: Symbol not found, for `InExpressionGenerator`| {
|
||||
public constructor(codegen: R|class error: Symbol not found, for `ExpressionCodegen`|, operatorReference: R|class error: Symbol not found, for `KtSimpleNameExpression`|): R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val codegen: R|class error: Symbol not found, for `ExpressionCodegen`| = R|<local>/codegen|
|
||||
public get(): R|class error: Symbol not found, for `ExpressionCodegen`|
|
||||
|
||||
private final val resolvedCall: <ERROR TYPE REF: Unresolved name: getResolvedCallWithAssert> = R|<local>/operatorReference|.<Unresolved name: getResolvedCallWithAssert>#(R|<local>/codegen|.<Unresolved name: bindingContext>#)
|
||||
private get(): <ERROR TYPE REF: Unresolved name: getResolvedCallWithAssert>
|
||||
|
||||
private final val isInverted: R|kotlin/Boolean| = ==(R|<local>/operatorReference|.<Unresolved name: getReferencedNameElementType>#(), <Unresolved name: KtTokens>#.<Unresolved name: NOT_IN>#)
|
||||
private get(): R|kotlin/Boolean|
|
||||
|
||||
public final override fun generate(argument: R|class error: Symbol not found, for `StackValue`|): R|class error: Symbol not found, for `BranchedValue`| {
|
||||
^generate R?C|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.gen|(R|<local>/argument|).<Inapplicable(WRONG_RECEIVER): [kotlin/let]>#(<L> = let@fun <anonymous>(): R|class error: Can't resolve when expression| {
|
||||
when () {
|
||||
this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.isInverted| -> {
|
||||
<Unresolved name: Invert>#(<Unresolved name: it>#)
|
||||
}
|
||||
else -> {
|
||||
<Unresolved name: it>#
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private final fun gen(argument: R|class error: Symbol not found, for `StackValue`|): R|class error: Symbol not found, for `BranchedValue`| {
|
||||
^gen object : R|class error: Symbol not found, for `BranchedValue`| {
|
||||
private constructor(): R|class error: Symbol not found, for `BranchedValue`| {
|
||||
super<R|class error: Symbol not found, for `BranchedValue`|>(R|<local>/argument|, Null(null), R|<local>/argument|.<Unresolved name: type>#, <Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#)
|
||||
}
|
||||
|
||||
public final override fun putSelector(type: R|class error: Symbol not found, for `Type`|, kotlinType: R|class error: Symbol not found, for `KotlinType?`|, v: R|class error: Symbol not found, for `InstructionAdapter`|): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
|
||||
<Unresolved name: coerceTo>#(R|<local>/type|, R|<local>/kotlinType|, R|<local>/v|)
|
||||
}
|
||||
|
||||
public final override fun condJump(jumpLabel: R|class error: Symbol not found, for `Label`|, v: R|class error: Symbol not found, for `InstructionAdapter`|, jumpIfFalse: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
|
||||
R|<local>/v|.<Unresolved name: visitJumpInsn>#(when () {
|
||||
R|<local>/jumpIfFalse| -> {
|
||||
<Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#
|
||||
}
|
||||
else -> {
|
||||
<Unresolved name: Opcodes>#.<Unresolved name: IFNE>#
|
||||
}
|
||||
}
|
||||
, R|<local>/jumpLabel|)
|
||||
}
|
||||
|
||||
private final fun invokeFunction(v: R|class error: Symbol not found, for `InstructionAdapter`|): R|kotlin/Unit| {
|
||||
lval result: <ERROR TYPE REF: Unresolved name: invokeFunction> = this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.codegen|.<Unresolved name: invokeFunction>#(this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.resolvedCall|.<Unresolved name: call>#, this@R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator|.R|org/jetbrains/kotlin/codegen/range/inExpression/CallBasedInExpressionGenerator.resolvedCall|, <Unresolved name: none>#())
|
||||
R|<local>/result|.<Unresolved name: put>#(R|<local>/result|.<Unresolved name: type>#, R|<local>/result|.<Unresolved name: kotlinType>#, R|<local>/v|)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Factory {
|
||||
sealed class Function {
|
||||
object Default
|
||||
}
|
||||
|
||||
companion object {
|
||||
val f = Function
|
||||
val x = Function.Default
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
FILE: classifierAccessFromCompanion.kt
|
||||
public final class Factory : R|kotlin/Any| {
|
||||
public constructor(): R|Factory| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public sealed class Function : R|kotlin/Any| {
|
||||
public constructor(): R|Factory.Function| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final object Default : R|kotlin/Any| {
|
||||
private constructor(): R|Factory.Function.Default| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
private constructor(): R|Factory.Companion| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val f: R|kotlin/Unit| = Q|Factory.Function|
|
||||
public get(): R|kotlin/Unit|
|
||||
|
||||
public final val x: R|Factory.Function.Default| = Q|Factory.Function.Default|
|
||||
public get(): R|Factory.Function.Default|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ FILE: companion.kt
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
R|/A.Companion.foo|()
|
||||
this@R|/A.Companion|.R|/A.Companion.foo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ FILE: companionExtension.kt
|
||||
}
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
this@R|/My|.R|/My.Companion.foo|()
|
||||
(this@R|/My.Companion|, this@R|/My|).R|/My.Companion.foo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ class My {
|
||||
}
|
||||
|
||||
fun Your.foo() {
|
||||
val x = ::Nested // Still should be error
|
||||
val x = <!UNRESOLVED_REFERENCE!>::Nested<!> // Still should be error
|
||||
}
|
||||
@@ -23,5 +23,5 @@ FILE: errCallable.kt
|
||||
|
||||
}
|
||||
public final fun R|Your|.foo(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/reflect/KFunction0<Your.Nested>| = ::R|/Your.Nested.Nested|
|
||||
lval x: <ERROR TYPE REF: No result type for initializer> = ::<Unresolved name: Nested>#
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
open class Base {
|
||||
companion object {
|
||||
val some = 0
|
||||
}
|
||||
}
|
||||
|
||||
class Outer {
|
||||
val codegen = ""
|
||||
|
||||
inner class Inner : Base() {
|
||||
val c = codegen
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
FILE: innerWithSuperCompanion.kt
|
||||
public open class Base : R|kotlin/Any| {
|
||||
public constructor(): R|Base| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
private constructor(): R|Base.Companion| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val some: R|kotlin/Int| = Int(0)
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final class Outer : R|kotlin/Any| {
|
||||
public constructor(): R|Outer| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val codegen: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public final inner class Inner : R|Base| {
|
||||
public constructor(): R|Outer.Inner| {
|
||||
super<R|Base|>()
|
||||
}
|
||||
|
||||
public final val c: R|kotlin/String| = this@R|/Outer|.R|/Outer.codegen|
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
object X
|
||||
|
||||
class Y {
|
||||
fun f(op: X.() -> Unit) {
|
||||
X.op()
|
||||
|
||||
val x = X
|
||||
x.op()
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
FILE: extensionOnObject.kt
|
||||
public final object X : R|kotlin/Any| {
|
||||
private constructor(): R|X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class Y : R|kotlin/Any| {
|
||||
public constructor(): R|Y| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun f(op: R|X.() -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
R|<local>/op|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(Q|X|)
|
||||
lval x: R|X| = Q|X|
|
||||
R|<local>/op|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/x|)
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
fun String.invoke() = this
|
||||
operator fun String.invoke() = this
|
||||
|
||||
val some = ""
|
||||
fun sss() {
|
||||
val some = 10
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>some<!>() // Should be inapplicable
|
||||
// Should be resolved to top-level some,
|
||||
// because with local some invoke isn't applicable
|
||||
some()
|
||||
}
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
FILE: incorrectInvokeReceiver.kt
|
||||
public final fun R|kotlin/String|.invoke(): R|kotlin/String| {
|
||||
public final operator fun R|kotlin/String|.invoke(): R|kotlin/String| {
|
||||
^invoke this@R|/invoke|
|
||||
}
|
||||
public final val some: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
public final fun sss(): R|kotlin/Unit| {
|
||||
lval some: R|kotlin/Int| = Int(10)
|
||||
<Inapplicable(WRONG_RECEIVER): [/invoke]>#()
|
||||
R|/some|.R|/invoke|()
|
||||
}
|
||||
|
||||
+2
-1
@@ -12,10 +12,11 @@ class Foo {
|
||||
val Buz.foobar: Bar get() = Bar()
|
||||
|
||||
fun FooBar.chk(buz: Buz) {
|
||||
// NB: really this example is unresolvable (in old FE too)
|
||||
// local/buz is extension receiver of foobar
|
||||
// this@Foo is dispatch receiver of foobar
|
||||
// Foo/foobar is dispatch receiver of invoke
|
||||
// this@chk is extension receiver of invoke
|
||||
buz.foobar()
|
||||
buz.<!UNRESOLVED_REFERENCE!>foobar<!>()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ FILE: threeReceivers.kt
|
||||
}
|
||||
|
||||
public final fun R|FooBar|.chk(buz: R|Buz|): R|kotlin/Unit| {
|
||||
((this@R|/Foo|, R|<local>/buz|).R|/Foo.foobar|, this@R|/Foo.chk|).R|/Bar.invoke|()
|
||||
R|<local>/buz|.<Unresolved name: foobar>#()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
class C
|
||||
|
||||
class B
|
||||
|
||||
class A {
|
||||
val B.foo: C.() -> Unit get() = null
|
||||
}
|
||||
|
||||
fun <T, R> with(arg: T, f: T.() -> R): R = arg.f()
|
||||
|
||||
fun test(a: A, b: B, c: C) {
|
||||
with(a) {
|
||||
with(c) {
|
||||
b.foo(c)
|
||||
// [this@a,b].foo.invoke(c)
|
||||
}
|
||||
with(b) {
|
||||
c.foo()
|
||||
// [this@a,this@b].foo.invoke(c)
|
||||
with(c) {
|
||||
foo()
|
||||
// [this@a,this@b].foo.invoke(this@c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
FILE: threeReceiversCorrect.kt
|
||||
public final class C : R|kotlin/Any| {
|
||||
public constructor(): R|C| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class B : R|kotlin/Any| {
|
||||
public constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val R|B|.foo: R|C.() -> kotlin/Unit|
|
||||
public get(): R|C.() -> kotlin/Unit| {
|
||||
^ Null(null)
|
||||
}
|
||||
|
||||
}
|
||||
public final fun <T, R> with(arg: R|T|, f: R|T.() -> R|): R|R| {
|
||||
^with R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|R|>|(R|<local>/arg|)
|
||||
}
|
||||
public final fun test(a: R|A|, b: R|B|, c: R|C|): R|kotlin/Unit| {
|
||||
R|/with|<R|A|, R|kotlin/Unit|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Unit| {
|
||||
R|/with|<R|C|, R|kotlin/Unit|>(R|<local>/c|, <L> = with@fun R|C|.<anonymous>(): R|kotlin/Unit| {
|
||||
(this@R|special/anonymous|, R|<local>/b|).R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/c|)
|
||||
}
|
||||
)
|
||||
R|/with|<R|B|, R|kotlin/Unit|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Unit| {
|
||||
this@R|special/anonymous|.R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(R|<local>/c|)
|
||||
R|/with|<R|C|, R|kotlin/Unit|>(R|<local>/c|, <L> = with@fun R|C|.<anonymous>(): R|kotlin/Unit| {
|
||||
(this@R|special/anonymous|, this@R|special/anonymous|).R|/A.foo|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Unit|>|(this@R|special/anonymous|)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
FILE: test.kt
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lval staticReference: R|kotlin/reflect/KMutableProperty1<JavaClass, ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.staticField|
|
||||
lval staticReference: R|kotlin/reflect/KMutableProperty0<ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.staticField|
|
||||
lval nonStaticReference: R|kotlin/reflect/KMutableProperty1<JavaClass, ft<kotlin/String, kotlin/String?>!>| = Q|JavaClass|::R|/JavaClass.nonStaticField|
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Outer {
|
||||
fun foo() {
|
||||
class Local {
|
||||
fun bar() {
|
||||
val x = y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
FILE: localClassAccessesContainingClass.kt
|
||||
public final class Outer : R|kotlin/Any| {
|
||||
public constructor(): R|Outer| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
local final class Local : R|kotlin/Any| {
|
||||
public constructor(): R|Outer.Local| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/String| = this@R|/Outer|.R|/Outer.y|
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final val y: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
class Nested
|
||||
|
||||
fun main() {
|
||||
val x = ::Nested
|
||||
val y = A::Nested
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
FILE: nestedConstructorCallable.kt
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final class Nested : R|kotlin/Any| {
|
||||
public constructor(): R|A.Nested| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/reflect/KFunction0<A.Nested>| = ::R|/A.Nested.Nested|
|
||||
lval y: R|kotlin/reflect/KFunction0<A.Nested>| = Q|A|::R|/A.Nested.Nested|
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
object A {
|
||||
object B {
|
||||
object A
|
||||
}
|
||||
}
|
||||
|
||||
object B
|
||||
|
||||
val err = B.<!UNRESOLVED_REFERENCE!>A<!>.<!UNRESOLVED_REFERENCE!>B<!>
|
||||
val correct = A.B.A
|
||||
@@ -0,0 +1,31 @@
|
||||
FILE: nestedObjects.kt
|
||||
public final object A : R|kotlin/Any| {
|
||||
private constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final object B : R|kotlin/Any| {
|
||||
private constructor(): R|A.B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final object A : R|kotlin/Any| {
|
||||
private constructor(): R|A.B.A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final object B : R|kotlin/Any| {
|
||||
private constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final val err: <ERROR TYPE REF: Unresolved name: B> = Q|B|.<Unresolved name: A>#.<Unresolved name: B>#
|
||||
public get(): <ERROR TYPE REF: Unresolved name: B>
|
||||
public final val correct: R|A.B.A| = Q|A.B.A|
|
||||
public get(): R|A.B.A|
|
||||
@@ -0,0 +1,45 @@
|
||||
// FILE: Base.java
|
||||
|
||||
public class Base {
|
||||
protected String foo() { return ""; }
|
||||
}
|
||||
|
||||
// FILE: O.kt
|
||||
|
||||
open class Wrapper(val b: Boolean)
|
||||
|
||||
object O {
|
||||
private class Derived(private val bar: Int) : Base() {
|
||||
private inner class Some(val z: Boolean) {
|
||||
fun test() {
|
||||
val x = bar
|
||||
val o = object : Wrapper(z) {
|
||||
fun local() {
|
||||
val y = foo()
|
||||
}
|
||||
val oo = object {
|
||||
val zz = z
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun test() {
|
||||
val x = bar
|
||||
val o = object {
|
||||
fun local() {
|
||||
val y = foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Generator(val codegen: Any) {
|
||||
private fun gen(): Any =
|
||||
object : Wrapper(true) {
|
||||
private fun invokeFunction() {
|
||||
val c = codegen
|
||||
val cc = codegen.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
FILE: O.kt
|
||||
public open class Wrapper : R|kotlin/Any| {
|
||||
public constructor(b: R|kotlin/Boolean|): R|Wrapper| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val b: R|kotlin/Boolean| = R|<local>/b|
|
||||
public get(): R|kotlin/Boolean|
|
||||
|
||||
}
|
||||
public final object O : R|kotlin/Any| {
|
||||
private constructor(): R|O| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
private final class Derived : R|Base| {
|
||||
public constructor(bar: R|kotlin/Int|): R|O.Derived| {
|
||||
super<R|Base|>()
|
||||
}
|
||||
|
||||
private final val bar: R|kotlin/Int| = R|<local>/bar|
|
||||
private get(): R|kotlin/Int|
|
||||
|
||||
private final inner class Some : R|kotlin/Any| {
|
||||
public constructor(z: R|kotlin/Boolean|): R|O.Derived.Some| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val z: R|kotlin/Boolean| = R|<local>/z|
|
||||
public get(): R|kotlin/Boolean|
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
|
||||
lval o: R|anonymous| = object : R|Wrapper| {
|
||||
private constructor(): R|Wrapper| {
|
||||
super<R|Wrapper|>(this@R|/O.Derived.Some|.R|/O.Derived.Some.z|)
|
||||
}
|
||||
|
||||
public final fun local(): R|kotlin/Unit| {
|
||||
lval y: R|ft<kotlin/String, kotlin/String?>!| = this@R|/O.Derived|.R|/Base.foo|()
|
||||
}
|
||||
|
||||
public final val oo: R|anonymous| = object : R|kotlin/Any| {
|
||||
private constructor(): R|kotlin/Any| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val zz: R|kotlin/Boolean| = R|<local>/z|
|
||||
public get(): R|kotlin/Boolean|
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
|
||||
lval o: R|anonymous| = object : R|kotlin/Any| {
|
||||
private constructor(): R|kotlin/Any| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun local(): R|kotlin/Unit| {
|
||||
lval y: R|ft<kotlin/String, kotlin/String?>!| = this@R|/O.Derived|.R|/Base.foo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public final class Generator : R|kotlin/Any| {
|
||||
public constructor(codegen: R|kotlin/Any|): R|Generator| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val codegen: R|kotlin/Any| = R|<local>/codegen|
|
||||
public get(): R|kotlin/Any|
|
||||
|
||||
private final fun gen(): R|kotlin/Any| {
|
||||
^gen object : R|Wrapper| {
|
||||
private constructor(): R|Wrapper| {
|
||||
super<R|Wrapper|>(Boolean(true))
|
||||
}
|
||||
|
||||
private final fun invokeFunction(): R|kotlin/Unit| {
|
||||
lval c: R|kotlin/Any| = this@R|/Generator|.R|/Generator.codegen|
|
||||
lval cc: R|kotlin/Int| = this@R|/Generator|.R|/Generator.codegen|.R|kotlin/Any.hashCode|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,11 +15,11 @@ FILE: outerObject.kt
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val y: R|kotlin/Int| = R|/Outer.x|
|
||||
public final val y: R|kotlin/Int| = this@R|/Outer|.R|/Outer.x|
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
this@R|/Outer.Nested|.R|/Outer.foo|()
|
||||
(this@R|/Outer|, this@R|/Outer.Nested|).R|/Outer.foo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ FILE: first.kt
|
||||
|
||||
public final fun baz(): R|kotlin/Unit| {
|
||||
this@R|/Private|.R|/Private.bar|()
|
||||
this@R|/Private|.R|/Private.Nested.Nested|()
|
||||
R|/Private.Companion.fromCompanion|()
|
||||
R|/Private.Nested.Nested|()
|
||||
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
|
||||
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ FILE: first.kt
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
this@R|/Private|.R|/Private.bar|()
|
||||
R|/Private.Companion.fromCompanion|()
|
||||
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
|
||||
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ FILE: first.kt
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
R|/Private.Companion.fromCompanion|()
|
||||
this@R|/Private.Companion|.R|/Private.Companion.fromCompanion|()
|
||||
Q|Private.NotCompanion|.<Inapplicable(HIDDEN): [/Private.NotCompanion.foo]>#()
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ FILE: protectedVisibility.kt
|
||||
|
||||
public final fun baz(): R|kotlin/Unit| {
|
||||
this@R|/Protected|.R|/Protected.bar|()
|
||||
this@R|/Protected|.R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
|
||||
R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
|
||||
}
|
||||
|
||||
public final inner class Inner : R|kotlin/Any| {
|
||||
@@ -58,9 +58,9 @@ FILE: protectedVisibility.kt
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
this@R|/Derived|.R|/Protected.bar|()
|
||||
this@R|/Derived|.R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
|
||||
this@R|/Derived|.R|/Protected.Nested.Nested|().<Inapplicable(HIDDEN): [/Protected.Nested.bar]>#()
|
||||
R|/Protected.Companion.fromCompanion|()
|
||||
R|/Protected.Nested.Nested|().R|/Protected.Nested.foo|()
|
||||
R|/Protected.Nested.Nested|().<Inapplicable(HIDDEN): [/Protected.Nested.bar]>#()
|
||||
this@R|/Protected.Companion|.R|/Protected.Companion.fromCompanion|()
|
||||
<Inapplicable(HIDDEN): [/Protected.Companion.protectedFromCompanion]>#()
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class A {
|
||||
}
|
||||
|
||||
val ab = A.B // property
|
||||
val abc = A.B.<!UNRESOLVED_REFERENCE!>C<!> // object
|
||||
val abc = A.B.C // object
|
||||
|
||||
object D {
|
||||
class E {
|
||||
@@ -34,5 +34,5 @@ enum class G {
|
||||
}
|
||||
}
|
||||
|
||||
val gh = G.<!AMBIGUITY!>H<!> // companion property
|
||||
val gv = G.<!AMBIGUITY!>values<!>() // static function
|
||||
val gh = G.H // companion property
|
||||
val gv = G.values() // static function
|
||||
|
||||
@@ -29,10 +29,10 @@ FILE: qualifierPriority.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final val ab: R|kotlin/String| = Q|A|.R|/A.Companion.B|
|
||||
public get(): R|kotlin/String|
|
||||
public final val abc: <ERROR TYPE REF: Unresolved name: C> = Q|A|.R|/A.Companion.B|.<Unresolved name: C>#
|
||||
public get(): <ERROR TYPE REF: Unresolved name: C>
|
||||
public final val ab: R|A.B| = Q|A.B|
|
||||
public get(): R|A.B|
|
||||
public final val abc: R|A.B.C| = Q|A.B.C|
|
||||
public get(): R|A.B.C|
|
||||
public final object D : R|kotlin/Any| {
|
||||
private constructor(): R|D| {
|
||||
super<R|kotlin/Any|>()
|
||||
@@ -94,7 +94,7 @@ FILE: qualifierPriority.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final val gh: <ERROR TYPE REF: Ambiguity: H, [/G.H, /G.Companion.H]> = Q|G|.<Ambiguity: H, [/G.H, /G.Companion.H]>#
|
||||
public get(): <ERROR TYPE REF: Ambiguity: H, [/G.H, /G.Companion.H]>
|
||||
public final val gv: <ERROR TYPE REF: Ambiguity: values, [/G.values, /G.Companion.values]> = Q|G|.<Ambiguity: values, [/G.values, /G.Companion.values]>#()
|
||||
public get(): <ERROR TYPE REF: Ambiguity: values, [/G.values, /G.Companion.values]>
|
||||
public final val gh: R|G| = Q|G|.R|/G.H|
|
||||
public get(): R|G|
|
||||
public final val gv: R|kotlin/Array<G>| = Q|G|.R|/G.values|()
|
||||
public get(): R|kotlin/Array<G>|
|
||||
|
||||
@@ -6,7 +6,7 @@ class C {
|
||||
|
||||
class Nested {
|
||||
fun test() {
|
||||
err()
|
||||
<!UNRESOLVED_REFERENCE!>err<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ FILE: receiverConsistency.kt
|
||||
}
|
||||
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
R|/C.err|()
|
||||
<Unresolved name: err>#()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ FILE: enums.kt
|
||||
|
||||
}
|
||||
|
||||
public final val g: R|kotlin/Double| = R|/Planet.Companion.G|.R|kotlin/Double.times|(R|<local>/m|).R|kotlin/Double.div|(R|<local>/r|.R|kotlin/Double.times|(R|<local>/r|))
|
||||
public final val g: R|kotlin/Double| = this@R|/Planet.Companion|.R|/Planet.Companion.G|.R|kotlin/Double.times|(R|<local>/m|).R|kotlin/Double.div|(R|<local>/r|.R|kotlin/Double.times|(R|<local>/r|))
|
||||
public get(): R|kotlin/Double|
|
||||
|
||||
public abstract fun sayHello(): R|kotlin/Unit|
|
||||
|
||||
+2
-2
@@ -64,14 +64,14 @@ FILE: localObject.kt
|
||||
^ Int(1)
|
||||
}
|
||||
|
||||
public final val z: R|kotlin/Int| = R|/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
|
||||
public final val z: R|kotlin/Int| = this@R|/TestProperty|.R|kotlin/run|<R|TestProperty|, R|kotlin/Int|>(<L> = run@fun R|TestProperty|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
lval obj: R|anonymous| = object : R|Foo| {
|
||||
private constructor(): R|kotlin/Any| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final override fun foo(): R|kotlin/Int| {
|
||||
^foo this@R|/TestProperty|.R|/TestProperty.x|.R|kotlin/Int.plus|(Int(1))
|
||||
^foo this@R|special/anonymous|.R|/TestProperty.x|.R|kotlin/Int.plus|(Int(1))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class Owner {
|
||||
}
|
||||
|
||||
fun err() {
|
||||
foo()
|
||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
this.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ FILE: simple.kt
|
||||
}
|
||||
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
lval n: R|Owner.Nested| = this@R|/Owner|.R|/Owner.Nested.Nested|()
|
||||
lval n: R|Owner.Nested| = R|/Owner.Nested.Nested|()
|
||||
R|<local>/n|.R|/Owner.Nested.baz|()
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ FILE: simple.kt
|
||||
}
|
||||
|
||||
public final fun err(): R|kotlin/Unit| {
|
||||
R|/Owner.foo|()
|
||||
<Unresolved name: foo>#()
|
||||
this@R|/Owner.Nested|.<Unresolved name: foo>#()
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,12 @@ FILE: nestedClassNameClash.kt
|
||||
}
|
||||
|
||||
public final fun test_5(): R|kotlin/Unit| {
|
||||
lval result: R|Foo.Result| = this@R|/Foo|.R|/Foo.Result.Result|()
|
||||
lval result: R|Foo.Result| = R|/Foo.Result.Result|()
|
||||
this@R|/Foo|.R|/Foo.saveResult|(R|<local>/result|)
|
||||
}
|
||||
|
||||
private final fun getResult(): R|Foo.Result| {
|
||||
^getResult this@R|/Foo|.R|/Foo.Result.Result|()
|
||||
^getResult R|/Foo.Result.Result|()
|
||||
}
|
||||
|
||||
private final fun saveResults(results: R|kotlin/collections/List<Foo.Result>|): R|kotlin/Unit| {
|
||||
|
||||
@@ -12,7 +12,7 @@ FILE: nestedReturnType.kt
|
||||
}
|
||||
|
||||
public final fun foo(): R|Some.Nested| {
|
||||
^foo this@R|/Some|.R|/Some.Nested.Nested|()
|
||||
^foo R|/Some.Nested.Nested|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ FILE: nestedClassContructor.kt
|
||||
}
|
||||
|
||||
public final fun copy(): R|A.B| {
|
||||
^copy this@R|/A.B|.R|/A.B.B|()
|
||||
^copy R|/A.B.B|()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,7 @@ FILE: nestedClassContructor.kt
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval a: R|A| = R|/A.A|()
|
||||
lval c: R|A.C| = this@R|/E|.R|/A.C.C|()
|
||||
lval c: R|A.C| = R|/A.C.C|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ FILE: qualifierWithCompanion.kt
|
||||
local final fun R|my/A|.invoke(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
R|my/xx|.R|<local>/invoke|()
|
||||
Q|my|.R|my/xx|.R|<local>/invoke|()
|
||||
}
|
||||
|
||||
@@ -30,13 +30,16 @@ fun foo3(x: (String) -> Int) {}
|
||||
fun main() {
|
||||
foo1(KotlinClass::baz)
|
||||
foo2(KotlinClass::baz)
|
||||
// Ambiguity (companion/class)
|
||||
<!AMBIGUITY!>foo3<!>(KotlinClass::baz)
|
||||
|
||||
// Type mismatch
|
||||
<!INAPPLICABLE_CANDIDATE!>foo1<!>(KotlinClass::bar)
|
||||
foo2(KotlinClass::bar)
|
||||
foo3(KotlinClass::bar)
|
||||
|
||||
foo1(KotlinClass2::bar)
|
||||
// Type mismatch
|
||||
<!INAPPLICABLE_CANDIDATE!>foo2<!>(KotlinClass2::bar)
|
||||
foo3(KotlinClass2::bar)
|
||||
}
|
||||
|
||||
+1
-1
@@ -57,6 +57,6 @@ FILE: main.kt
|
||||
R|/foo2|(Q|KotlinClass|::R|/JavaClass.bar|)
|
||||
R|/foo3|(Q|KotlinClass|::R|/JavaClass.bar|)
|
||||
R|/foo1|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
|
||||
<Inapplicable(INAPPLICABLE): [/foo2]>#(Q|KotlinClass2|::R|/JavaClass.bar|)
|
||||
<Inapplicable(INAPPLICABLE): [/foo2]>#(Q|KotlinClass2|::R|/KotlinClass2.bar|)
|
||||
R|/foo3|(Q|KotlinClass2|::R|/KotlinClass2.Companion.bar|)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ FILE: hashTableWithForEach.kt
|
||||
R|/DEBUG| -> {
|
||||
^ Q|java/util/Collections|.R|java/util/Collections.unmodifiableSet|<R|kotlin/collections/MutableMap.MutableEntry<K, V>|>(R|kotlin/collections/mutableSetOf|<R|kotlin/collections/MutableMap.MutableEntry<K, V>|>().R|kotlin/apply|<R|kotlin/collections/MutableSet<kotlin/collections/MutableMap.MutableEntry<K, V>>|>(<L> = apply@fun R|kotlin/collections/MutableSet<kotlin/collections/MutableMap.MutableEntry<K, V>>|.<anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
this@R|/SomeHashTable|.R|FakeOverride</SomeHashTable.forEach: R|kotlin/Unit|>|(<L> = forEach@fun <anonymous>(key: R|K|, value: R|V|): R|kotlin/Unit| {
|
||||
this@R|special/anonymous|.R|FakeOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(this@R|/SomeHashTable|.R|/SomeHashTable.Entry.Entry|<R|K|, R|V|>(R|<local>/key|, R|<local>/value|))
|
||||
this@R|special/anonymous|.R|FakeOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(R|/SomeHashTable.Entry.Entry|<R|K|, R|V|>(R|<local>/key|, R|<local>/value|))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ FILE: implicitReceiverOrder.kt
|
||||
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/A.foo|()
|
||||
this@R|special/anonymous|.R|/B.bar|()
|
||||
(this@R|special/anonymous|, this@R|special/anonymous|).R|/B.bar|()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ FILE: implicitReceiverOrder.kt
|
||||
R|kotlin/with|<R|A|, R|kotlin/Int|>(R|<local>/a|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
R|kotlin/with|<R|B|, R|kotlin/Int|>(R|<local>/b|, <L> = with@fun R|B|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/B.foo|()
|
||||
this@R|special/anonymous|.R|/A.bar|()
|
||||
(this@R|special/anonymous|, this@R|special/anonymous|).R|/A.bar|()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ FILE: User.kt
|
||||
}
|
||||
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval sc: R|AbstractClass.StaticClass| = this@R|/User|.R|/AbstractClass.StaticClass.StaticClass|()
|
||||
lval sc: R|AbstractClass.StaticClass| = R|/AbstractClass.StaticClass.StaticClass|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ FILE: multipleImplicitReceivers.kt
|
||||
public final fun test(fooImpl: R|IFoo|, invokeImpl: R|IInvoke|): R|kotlin/Unit| {
|
||||
R|kotlin/with|<R|A|, R|kotlin/Int|>(Q|A|, <L> = with@fun R|A|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
R|kotlin/with|<R|IFoo|, R|kotlin/Int|>(R|<local>/fooImpl|, <L> = with@fun R|IFoo|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
this@R|special/anonymous|.R|/IFoo.foo|
|
||||
(this@R|special/anonymous|, this@R|special/anonymous|).R|/IFoo.foo|
|
||||
R|kotlin/with|<R|IInvoke|, R|kotlin/Int|>(R|<local>/invokeImpl|, <L> = with@fun R|IInvoke|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
(this@R|special/anonymous|, this@R|special/anonymous|.R|/IFoo.foo|).R|/IInvoke.invoke|()
|
||||
(this@R|special/anonymous|, (this@R|special/anonymous|, this@R|special/anonymous|).R|/IFoo.foo|).R|/IInvoke.invoke|()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+45
@@ -434,11 +434,21 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/baseQualifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("CallBasedInExpressionGenerator.kt")
|
||||
public void testCallBasedInExpressionGenerator() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/CallBasedInExpressionGenerator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkArguments.kt")
|
||||
public void testCheckArguments() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/checkArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classifierAccessFromCompanion.kt")
|
||||
public void testClassifierAccessFromCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/classifierAccessFromCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/companion.kt");
|
||||
@@ -514,6 +524,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerQualifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerWithSuperCompanion.kt")
|
||||
public void testInnerWithSuperCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerWithSuperCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaFieldCallable.kt")
|
||||
public void testJavaFieldCallable() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/javaFieldCallable.kt");
|
||||
@@ -529,6 +544,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassAccessesContainingClass.kt")
|
||||
public void testLocalClassAccessesContainingClass() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localClassAccessesContainingClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localConstructor.kt")
|
||||
public void testLocalConstructor() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localConstructor.kt");
|
||||
@@ -574,6 +594,16 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/memberExtension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedConstructorCallable.kt")
|
||||
public void testNestedConstructorCallable() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedConstructorCallable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedObjects.kt")
|
||||
public void testNestedObjects() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedObjects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedVisibility.kt")
|
||||
public void testNestedVisibility() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt");
|
||||
@@ -594,6 +624,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("outerMemberAccesses.kt")
|
||||
public void testOuterMemberAccesses() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerMemberAccesses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("outerObject.kt")
|
||||
public void testOuterObject() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerObject.kt");
|
||||
@@ -724,6 +759,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionOnObject.kt")
|
||||
public void testExtensionOnObject() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extensionOnObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("farInvokeExtension.kt")
|
||||
public void testFarInvokeExtension() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/farInvokeExtension.kt");
|
||||
@@ -763,6 +803,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
public void testThreeReceivers() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("threeReceiversCorrect.kt")
|
||||
public void testThreeReceiversCorrect() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceiversCorrect.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/resolve/expresssions/operators")
|
||||
|
||||
Generated
+45
@@ -434,11 +434,21 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/baseQualifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("CallBasedInExpressionGenerator.kt")
|
||||
public void testCallBasedInExpressionGenerator() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/CallBasedInExpressionGenerator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("checkArguments.kt")
|
||||
public void testCheckArguments() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/checkArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classifierAccessFromCompanion.kt")
|
||||
public void testClassifierAccessFromCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/classifierAccessFromCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/companion.kt");
|
||||
@@ -514,6 +524,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerQualifier.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerWithSuperCompanion.kt")
|
||||
public void testInnerWithSuperCompanion() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/innerWithSuperCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaFieldCallable.kt")
|
||||
public void testJavaFieldCallable() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/javaFieldCallable.kt");
|
||||
@@ -529,6 +544,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/lambdaWithReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassAccessesContainingClass.kt")
|
||||
public void testLocalClassAccessesContainingClass() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localClassAccessesContainingClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localConstructor.kt")
|
||||
public void testLocalConstructor() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/localConstructor.kt");
|
||||
@@ -574,6 +594,16 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/memberExtension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedConstructorCallable.kt")
|
||||
public void testNestedConstructorCallable() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedConstructorCallable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedObjects.kt")
|
||||
public void testNestedObjects() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedObjects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedVisibility.kt")
|
||||
public void testNestedVisibility() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/nestedVisibility.kt");
|
||||
@@ -594,6 +624,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("outerMemberAccesses.kt")
|
||||
public void testOuterMemberAccesses() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerMemberAccesses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("outerObject.kt")
|
||||
public void testOuterObject() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/outerObject.kt");
|
||||
@@ -724,6 +759,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extension.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionOnObject.kt")
|
||||
public void testExtensionOnObject() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/extensionOnObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("farInvokeExtension.kt")
|
||||
public void testFarInvokeExtension() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/farInvokeExtension.kt");
|
||||
@@ -763,6 +803,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
public void testThreeReceivers() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("threeReceiversCorrect.kt")
|
||||
public void testThreeReceiversCorrect() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceiversCorrect.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/resolve/expresssions/operators")
|
||||
|
||||
@@ -43,4 +43,9 @@ enum class ProcessorAction {
|
||||
|
||||
fun stop() = this == STOP
|
||||
fun next() = this != STOP
|
||||
|
||||
operator fun plus(other: ProcessorAction): ProcessorAction {
|
||||
if (this == NEXT || other == NEXT) return NEXT
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ fun bar(doIt: Int.() -> Int) {
|
||||
1.doIt()
|
||||
1?.doIt()
|
||||
val i: Int? = 1
|
||||
i.<!UNRESOLVED_REFERENCE!>doIt<!>()
|
||||
i.doIt()
|
||||
i?.doIt()
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ class X {}
|
||||
val s = java
|
||||
val ss = System
|
||||
val sss = X
|
||||
val x = "${System}"
|
||||
val x = "${<!UNRESOLVED_REFERENCE!>System<!>}"
|
||||
val xs = java.lang
|
||||
val xss = java.lang.System
|
||||
val xsss = foo.X
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ class Outer {
|
||||
|
||||
fun test() {
|
||||
Outer()::Inner
|
||||
Outer()::Nested
|
||||
<!UNRESOLVED_REFERENCE!>Outer()::Nested<!>
|
||||
}
|
||||
|
||||
compiler/testData/diagnostics/tests/callableReference/bound/referenceToStaticMethodOnInstance.fir.kt
Vendored
+2
-2
@@ -9,6 +9,6 @@ public class A {
|
||||
enum class E { EN }
|
||||
|
||||
fun test() {
|
||||
A()::test
|
||||
E.EN::valueOf
|
||||
<!UNRESOLVED_REFERENCE!>A()::test<!>
|
||||
<!UNRESOLVED_REFERENCE!>E.EN::valueOf<!>
|
||||
}
|
||||
|
||||
+2
-2
@@ -16,6 +16,6 @@ fun test() {
|
||||
|
||||
Outer.Companion::Wrapper
|
||||
(Outer.Companion)::Wrapper
|
||||
Outer::Wrapper
|
||||
(Outer)::Wrapper
|
||||
<!UNRESOLVED_REFERENCE!>Outer::Wrapper<!>
|
||||
<!UNRESOLVED_REFERENCE!>(Outer)::Wrapper<!>
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,5 +15,5 @@ fun take(f: () -> Unit) {}
|
||||
fun test() {
|
||||
B::foo checkType { <!UNRESOLVED_REFERENCE!>_<!><KFunction1<B, Unit>>() }
|
||||
|
||||
take(B::foo)
|
||||
<!INAPPLICABLE_CANDIDATE!>take<!>(B::foo)
|
||||
}
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ import test.A
|
||||
|
||||
fun foo(args: Array<String>) {
|
||||
val main2 = A::main
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction1<Array<String>, Unit>>(main2)
|
||||
<!INAPPLICABLE_CANDIDATE!>main2<!>(args)
|
||||
<!INAPPLICABLE_CANDIDATE!>(A::main)(args)<!>
|
||||
checkSubtype<KFunction1<Array<String>, Unit>>(main2)
|
||||
main2(args)
|
||||
(A::main)(args)
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -10,7 +10,7 @@ class A {
|
||||
val y = A::Nested
|
||||
|
||||
checkSubtype<KFunction0<Nested>>(x)
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<Nested>>(y)
|
||||
checkSubtype<KFunction0<Nested>>(y)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -18,7 +18,7 @@ class A {
|
||||
::Nested
|
||||
val y = A::Nested
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
|
||||
checkSubtype<KFunction0<A.Nested>>(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,6 @@ class B {
|
||||
<!UNRESOLVED_REFERENCE!>::Nested<!>
|
||||
val y = A::Nested
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
|
||||
checkSubtype<KFunction0<A.Nested>>(y)
|
||||
}
|
||||
}
|
||||
compiler/testData/diagnostics/tests/callableReference/function/nestedConstructorFromExtension.fir.kt
Vendored
+3
-3
@@ -7,15 +7,15 @@ class A {
|
||||
}
|
||||
|
||||
fun A.main() {
|
||||
::Nested
|
||||
<!UNRESOLVED_REFERENCE!>::Nested<!>
|
||||
val y = A::Nested
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
|
||||
checkSubtype<KFunction0<A.Nested>>(y)
|
||||
}
|
||||
|
||||
fun Int.main() {
|
||||
<!UNRESOLVED_REFERENCE!>::Nested<!>
|
||||
val y = A::Nested
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(y)
|
||||
checkSubtype<KFunction0<A.Nested>>(y)
|
||||
}
|
||||
Vendored
+1
-1
@@ -9,5 +9,5 @@ class A {
|
||||
fun main() {
|
||||
val x = A::Nested
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><KFunction0<A.Nested>>(x)
|
||||
checkSubtype<KFunction0<A.Nested>>(x)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package foo
|
||||
|
||||
fun test() {
|
||||
<!UNRESOLVED_REFERENCE!>foo::test<!>
|
||||
foo::test
|
||||
}
|
||||
|
||||
// FILE: qualifiedName.kt
|
||||
@@ -12,5 +12,5 @@ fun test() {
|
||||
package foo.bar
|
||||
|
||||
fun test() {
|
||||
<!UNRESOLVED_REFERENCE!>foo.bar::test<!>
|
||||
foo.bar::test
|
||||
}
|
||||
|
||||
+2
-2
@@ -14,14 +14,14 @@ class A {
|
||||
|
||||
fun A.foo(): String = "A"
|
||||
|
||||
val x0 = A::foo
|
||||
val x0 = <!UNRESOLVED_REFERENCE!>A::foo<!>
|
||||
|
||||
val x1 = ofType<(A) -> Unit>(A::foo)
|
||||
val x2 = ofType<KProperty1<A, Int>>(A::foo)
|
||||
val x3: KProperty1<A, Int> = A::foo
|
||||
val x4: (A) -> String = A::foo
|
||||
|
||||
val y0 = A::bar
|
||||
val y0 = <!UNRESOLVED_REFERENCE!>A::bar<!>
|
||||
val y1 = ofType<(A) -> Unit>(A::bar)
|
||||
val y2 = ofType<KProperty1<A, Int>>(A::bar)
|
||||
val y3: KProperty1<A, Int> = A::bar
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ class A() {
|
||||
val x = 1
|
||||
|
||||
companion object {
|
||||
val y = x
|
||||
val y = <!UNRESOLVED_REFERENCE!>x<!>
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -21,7 +21,7 @@ enum class C {
|
||||
C.A()
|
||||
A()
|
||||
//TODO: should be resolved with error
|
||||
this.A()
|
||||
this.<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ enum class C {
|
||||
|
||||
fun f() {
|
||||
C.E1.A
|
||||
C.E1.A()
|
||||
C.E1.<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
C.E2.B()
|
||||
|
||||
C.E2.O
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ enum class C {
|
||||
C.A()
|
||||
A()
|
||||
//TODO: should be resolved with error
|
||||
this.A()
|
||||
this.<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ enum class C {
|
||||
|
||||
fun f() {
|
||||
C.E1.A
|
||||
C.E1.A()
|
||||
C.E1.<!UNRESOLVED_REFERENCE!>A<!>()
|
||||
C.E2.B()
|
||||
|
||||
C.E2.O
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ class Test {
|
||||
fun test(): Int = 12
|
||||
|
||||
companion object {
|
||||
val a = test() // Check if resolver will be able to infer type of a variable
|
||||
val a = <!UNRESOLVED_REFERENCE!>test<!>() // Check if resolver will be able to infer type of a variable
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ class My {
|
||||
|
||||
companion object {
|
||||
|
||||
val y = foo()
|
||||
val y = <!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
|
||||
val u = bar()
|
||||
|
||||
|
||||
@@ -14,5 +14,5 @@ class TopLevel {
|
||||
fun useNested() {
|
||||
val d = TopLevel.Nested.use()
|
||||
TopLevel.Nested.Nested2()
|
||||
TopLevel.Nested.CompanionNested2()
|
||||
TopLevel.Nested.<!UNRESOLVED_REFERENCE!>CompanionNested2<!>()
|
||||
}
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ enum class A {
|
||||
A1,
|
||||
A2;
|
||||
|
||||
fun valueOf(s: String): A = <!AMBIGUITY!>valueOf<!>(s)
|
||||
fun valueOf(s: String): A = valueOf(s)
|
||||
|
||||
fun valueOf() = "OK"
|
||||
|
||||
|
||||
@@ -10,6 +10,6 @@ public enum A {
|
||||
|
||||
fun main() {
|
||||
val c: A = A.ENTRY
|
||||
val c2: String? = c.<!AMBIGUITY!>ENTRY<!>
|
||||
val c3: String? = A.ANOTHER.<!AMBIGUITY!>ENTRY<!>
|
||||
val c2: String? = c.ENTRY
|
||||
val c3: String? = A.ANOTHER.ENTRY
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ public class A {
|
||||
// FILE: B.kt
|
||||
fun Any?.bar() = 42
|
||||
|
||||
fun f1() = A.bar()
|
||||
fun f2() = A.Nested.bar()
|
||||
fun f1() = A.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
fun f2() = A.Nested.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
|
||||
+1
-1
@@ -12,5 +12,5 @@ fun <V, T : V?> G<T>.foo(vararg values: V2<V?>) = build()
|
||||
fun forReference(ref: Any?) {}
|
||||
|
||||
fun test() {
|
||||
forReference(<!UNRESOLVED_REFERENCE!>G<Int?>::foo<!>)
|
||||
<!INAPPLICABLE_CANDIDATE!>forReference<!>(<!UNRESOLVED_REFERENCE!>G<Int?>::foo<!>)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ class Outer {
|
||||
|
||||
fun Outer.foo() {
|
||||
Outer()
|
||||
Nested()
|
||||
<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||
Inner()
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ class Test {
|
||||
fun more(): InnerClass {
|
||||
val b = InnerClass()
|
||||
|
||||
val testVal = inClass
|
||||
foo()
|
||||
val testVal = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ class Test {
|
||||
fun more(): InnerClass {
|
||||
val b = InnerClass()
|
||||
|
||||
val testVal = inClass
|
||||
foo()
|
||||
val testVal = <!UNRESOLVED_REFERENCE!>inClass<!>
|
||||
<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ class Outer {
|
||||
class Nested {
|
||||
fun foo() {
|
||||
class Local {
|
||||
val state = outerState
|
||||
val state = <!UNRESOLVED_REFERENCE!>outerState<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -24,30 +24,30 @@ object Obj {
|
||||
}
|
||||
|
||||
fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
|
||||
with.Nested()
|
||||
with.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||
with.NestedWithClassObject
|
||||
with.NestedWithClassObject()
|
||||
with.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
|
||||
with.NestedWithClassObject.foo()
|
||||
with.NestedEnum.A
|
||||
with.NestedObj
|
||||
with.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
|
||||
with.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
||||
with.NestedObj.foo()
|
||||
|
||||
without.Nested()
|
||||
without.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||
without.NestedWithClassObject
|
||||
without.NestedWithClassObject()
|
||||
without.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
|
||||
without.NestedWithClassObject.foo()
|
||||
without.NestedEnum.A
|
||||
without.NestedObj
|
||||
without.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
|
||||
without.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
||||
without.NestedObj.foo()
|
||||
|
||||
obj.Nested()
|
||||
obj.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||
obj.NestedWithClassObject
|
||||
obj.NestedWithClassObject()
|
||||
obj.<!UNRESOLVED_REFERENCE!>NestedWithClassObject<!>()
|
||||
obj.NestedWithClassObject.foo()
|
||||
obj.NestedEnum.A
|
||||
obj.NestedObj
|
||||
obj.<!INAPPLICABLE_CANDIDATE!>NestedObj<!>()
|
||||
obj.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
||||
obj.NestedObj.foo()
|
||||
}
|
||||
+2
-2
@@ -5,8 +5,8 @@ class Outer {
|
||||
val property = ""
|
||||
|
||||
class Nested {
|
||||
fun f() = function()
|
||||
fun g() = property
|
||||
fun f() = <!UNRESOLVED_REFERENCE!>function<!>()
|
||||
fun g() = <!UNRESOLVED_REFERENCE!>property<!>
|
||||
fun h() = this@Outer.function()
|
||||
fun i() = this@Outer.property
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ open class Base {
|
||||
|
||||
class Derived : Base() {
|
||||
class Nested {
|
||||
fun bar() = foo()
|
||||
fun bar() = <!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
Vendored
+2
-2
@@ -119,8 +119,8 @@ class C : O.B() {
|
||||
val b = O.A::foo
|
||||
|
||||
// DEPRECATED: Classifiers from companions of direct superclasses
|
||||
val e = <!UNRESOLVED_REFERENCE!>O.A.<!AMBIGUITY!>Companion<!>.<!UNRESOLVED_REFERENCE!>FromCompanionA<!>::foo<!>
|
||||
val f = <!UNRESOLVED_REFERENCE!>O.B.<!AMBIGUITY!>Companion<!>.<!UNRESOLVED_REFERENCE!>FromCompanionB<!>::foo<!>
|
||||
val e = O.A.Companion.FromCompanionA::foo
|
||||
val f = O.B.Companion.FromCompanionB::foo
|
||||
|
||||
// INVISIBLE: "cousin" supertypes themselves
|
||||
val g = O.Alpha::foo
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user