[FIR] Carefully process constructors of inner and nested classes in the tower
If there is an expression receiver, we should process constructors only of inner classes. Constructors of nested classes can be called only on classifier ^KT-65333 Fixed
This commit is contained in:
committed by
Space Team
parent
67557ce731
commit
5b01396a11
+31
-14
@@ -22,17 +22,23 @@ import org.jetbrains.kotlin.fir.whileAnalysing
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
|
||||
|
||||
private operator fun <T> Pair<T, *>?.component1() = this?.first
|
||||
private operator fun <T> Pair<*, T>?.component2() = this?.second
|
||||
private operator fun <T> Pair<T, *>?.component1(): T? = this?.first
|
||||
private operator fun <T> Pair<*, T>?.component2(): T? = this?.second
|
||||
|
||||
internal fun FirScope.processConstructorsByName(
|
||||
internal enum class ConstructorFilter(val acceptInner: Boolean, val acceptNested: Boolean) {
|
||||
OnlyInner(acceptInner = true, acceptNested = false),
|
||||
OnlyNested(acceptInner = false, acceptNested = true),
|
||||
Both(acceptInner = true, acceptNested = true),
|
||||
}
|
||||
|
||||
private fun FirScope.processConstructorsByName(
|
||||
callInfo: CallInfo,
|
||||
session: FirSession,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
includeInnerConstructors: Boolean,
|
||||
constructorFilter: ConstructorFilter,
|
||||
processor: (FirCallableSymbol<*>) -> Unit
|
||||
) {
|
||||
val (matchedClassifierSymbol, substitutor) = getFirstClassifierOrNull(callInfo, session, bodyResolveComponents) ?: return
|
||||
val (matchedClassifierSymbol, substitutor) = getFirstClassifierOrNull(callInfo, constructorFilter, session, bodyResolveComponents) ?: return
|
||||
val matchedClassSymbol = matchedClassifierSymbol as? FirClassLikeSymbol<*> ?: return
|
||||
|
||||
processConstructors(
|
||||
@@ -41,7 +47,7 @@ internal fun FirScope.processConstructorsByName(
|
||||
processor,
|
||||
session,
|
||||
bodyResolveComponents,
|
||||
includeInnerConstructors
|
||||
constructorFilter
|
||||
)
|
||||
|
||||
processSyntheticConstructors(
|
||||
@@ -55,12 +61,12 @@ internal fun FirScope.processFunctionsAndConstructorsByName(
|
||||
callInfo: CallInfo,
|
||||
session: FirSession,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
includeInnerConstructors: Boolean,
|
||||
constructorFilter: ConstructorFilter,
|
||||
processor: (FirCallableSymbol<*>) -> Unit
|
||||
) {
|
||||
processConstructorsByName(
|
||||
callInfo, session, bodyResolveComponents,
|
||||
includeInnerConstructors = includeInnerConstructors,
|
||||
constructorFilter,
|
||||
processor
|
||||
)
|
||||
|
||||
@@ -116,6 +122,7 @@ private fun FirDeclaration.isInvisibleOrHidden(session: FirSession, bodyResolveC
|
||||
|
||||
private fun FirScope.getFirstClassifierOrNull(
|
||||
callInfo: CallInfo,
|
||||
constructorFilter: ConstructorFilter,
|
||||
session: FirSession,
|
||||
bodyResolveComponents: BodyResolveComponents
|
||||
): SymbolWithSubstitutor? {
|
||||
@@ -124,7 +131,14 @@ private fun FirScope.getFirstClassifierOrNull(
|
||||
var result: SymbolWithSubstitutor? = null
|
||||
processClassifiersByNameWithSubstitution(callInfo.name) { symbol, substitutor ->
|
||||
val classifierDeclaration = symbol.fir
|
||||
val isSuccessCandidate = !classifierDeclaration.isInvisibleOrHidden(session, bodyResolveComponents)
|
||||
var isSuccessCandidate = !classifierDeclaration.isInvisibleOrHidden(session, bodyResolveComponents)
|
||||
if (classifierDeclaration is FirClassLikeDeclaration) {
|
||||
val acceptedByFilter = when (classifierDeclaration.isInner) {
|
||||
true -> constructorFilter.acceptInner
|
||||
false -> constructorFilter.acceptNested
|
||||
}
|
||||
isSuccessCandidate = isSuccessCandidate && acceptedByFilter
|
||||
}
|
||||
|
||||
when {
|
||||
isSuccessCandidate && !isSuccessResult -> {
|
||||
@@ -212,7 +226,7 @@ private fun processConstructors(
|
||||
processor: (FirFunctionSymbol<*>) -> Unit,
|
||||
session: FirSession,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
includeInnerConstructors: Boolean
|
||||
constructorFilter: ConstructorFilter
|
||||
) {
|
||||
whileAnalysing(session, matchedSymbol.fir) {
|
||||
val scope = when (matchedSymbol) {
|
||||
@@ -254,10 +268,13 @@ private fun processConstructors(
|
||||
}
|
||||
}
|
||||
|
||||
scope?.processDeclaredConstructors {
|
||||
if (includeInnerConstructors || !it.fir.isInner) {
|
||||
processor(it)
|
||||
|
||||
scope?.processDeclaredConstructors {
|
||||
val shouldProcess = when (it.fir.isInner) {
|
||||
true -> constructorFilter.acceptInner
|
||||
false -> constructorFilter.acceptNested
|
||||
}
|
||||
if (shouldProcess) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -86,24 +86,31 @@ internal abstract class FirBaseTowerResolveTask(
|
||||
protected fun FirScope.toScopeTowerLevel(
|
||||
extensionReceiver: ReceiverValue? = null,
|
||||
withHideMembersOnly: Boolean = false,
|
||||
includeInnerConstructors: Boolean = extensionReceiver != null,
|
||||
constructorFilter: ConstructorFilter = extensionReceiver.toConstructorFilter(),
|
||||
contextReceiverGroup: ContextReceiverGroup? = null,
|
||||
dispatchReceiverForStatics: ExpressionReceiverValue? = null
|
||||
): ScopeTowerLevel {
|
||||
return ScopeTowerLevel(
|
||||
components, this,
|
||||
givenExtensionReceiverOptions = createExtensionReceiverOptions(contextReceiverGroup, extensionReceiver),
|
||||
withHideMembersOnly, includeInnerConstructors, dispatchReceiverForStatics
|
||||
withHideMembersOnly, constructorFilter, dispatchReceiverForStatics
|
||||
)
|
||||
}
|
||||
|
||||
private fun ReceiverValue?.toConstructorFilter(): ConstructorFilter {
|
||||
return when (this) {
|
||||
null -> ConstructorFilter.OnlyNested
|
||||
else -> ConstructorFilter.Both
|
||||
}
|
||||
}
|
||||
|
||||
protected fun FirScope.toScopeTowerLevelForStaticWithImplicitDispatchReceiver(
|
||||
staticOwnerOwnerSymbol: FirRegularClassSymbol? = null,
|
||||
source: KtSourceElement? = null
|
||||
): ScopeTowerLevel = toScopeTowerLevel(
|
||||
extensionReceiver = null,
|
||||
withHideMembersOnly = false,
|
||||
includeInnerConstructors = false,
|
||||
constructorFilter = ConstructorFilter.OnlyNested,
|
||||
contextReceiverGroup = null,
|
||||
staticOwnerOwnerSymbol?.let {
|
||||
val resolvedQualifier = buildResolvedQualifier {
|
||||
@@ -256,7 +263,7 @@ internal open class FirTowerResolveTask(
|
||||
val callableScope = qualifierReceiver.callableScope() ?: return
|
||||
processLevel(
|
||||
callableScope.toScopeTowerLevel(
|
||||
includeInnerConstructors = false,
|
||||
constructorFilter = ConstructorFilter.OnlyNested,
|
||||
dispatchReceiverForStatics = when (qualifierReceiver) {
|
||||
is ClassQualifierReceiver -> ExpressionReceiverValue(qualifierReceiver.explicitReceiver)
|
||||
else -> null
|
||||
@@ -276,7 +283,7 @@ internal open class FirTowerResolveTask(
|
||||
) return
|
||||
val scope = qualifierReceiver.classifierScope() ?: return
|
||||
processLevel(
|
||||
scope.toScopeTowerLevel(includeInnerConstructors = false), info,
|
||||
scope.toScopeTowerLevel(constructorFilter = ConstructorFilter.OnlyNested), info,
|
||||
TowerGroup.Classifier
|
||||
)
|
||||
}
|
||||
|
||||
+4
-4
@@ -280,7 +280,7 @@ class MemberScopeTowerLevel(
|
||||
withMemberCallLookup(lookupTracker, info) { lookupCtx ->
|
||||
this.processFunctionsAndConstructorsByName(
|
||||
info, session, bodyResolveComponents,
|
||||
includeInnerConstructors = true,
|
||||
ConstructorFilter.OnlyInner,
|
||||
processor = {
|
||||
lookupCtx.recordCallableMemberLookup(it)
|
||||
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
|
||||
@@ -370,12 +370,12 @@ class ContextReceiverGroupMemberScopeTowerLevel(
|
||||
// So: dispatch receiver = strictly none (EXCEPTIONS: importing scopes with import from objects, synthetic field variable)
|
||||
// So: extension receiver = either none or explicit
|
||||
// (if explicit receiver exists, it always *should* be an extension receiver)
|
||||
class ScopeTowerLevel(
|
||||
internal class ScopeTowerLevel(
|
||||
private val bodyResolveComponents: BodyResolveComponents,
|
||||
val scope: FirScope,
|
||||
private val givenExtensionReceiverOptions: List<FirExpression>,
|
||||
private val withHideMembersOnly: Boolean,
|
||||
private val includeInnerConstructors: Boolean,
|
||||
private val constructorFilter: ConstructorFilter,
|
||||
private val dispatchReceiverForStatics: ExpressionReceiverValue?
|
||||
) : TowerScopeLevel() {
|
||||
private val session: FirSession get() = bodyResolveComponents.session
|
||||
@@ -486,7 +486,7 @@ class ScopeTowerLevel(
|
||||
info,
|
||||
session,
|
||||
bodyResolveComponents,
|
||||
includeInnerConstructors = includeInnerConstructors
|
||||
constructorFilter
|
||||
) { candidate ->
|
||||
empty = false
|
||||
consumeCallableCandidate(candidate, info, processor)
|
||||
|
||||
Reference in New Issue
Block a user