FIR tower resolve: add level with implicit extension receiver
This commit is contained in:
@@ -245,7 +245,8 @@ private fun ConeCallableSymbol.hasExtensionReceiver(): Boolean = (this as? FirCa
|
|||||||
// (if explicit receiver exists, it always *should* be an extension receiver)
|
// (if explicit receiver exists, it always *should* be an extension receiver)
|
||||||
class ScopeTowerLevel(
|
class ScopeTowerLevel(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
val scope: FirScope
|
val scope: FirScope,
|
||||||
|
val implicitExtensionReceiver: ReceiverValue? = null
|
||||||
) : SessionBasedTowerLevel(session) {
|
) : SessionBasedTowerLevel(session) {
|
||||||
override fun <T : ConeSymbol> processElementsByName(
|
override fun <T : ConeSymbol> processElementsByName(
|
||||||
token: TowerScopeLevel.Token<T>,
|
token: TowerScopeLevel.Token<T>,
|
||||||
@@ -253,18 +254,21 @@ class ScopeTowerLevel(
|
|||||||
explicitReceiver: ExpressionReceiverValue?,
|
explicitReceiver: ExpressionReceiverValue?,
|
||||||
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
|
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
|
||||||
): ProcessorAction {
|
): ProcessorAction {
|
||||||
|
if (explicitReceiver != null && implicitExtensionReceiver != null) {
|
||||||
|
return ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
val extensionReceiver = explicitReceiver ?: implicitExtensionReceiver
|
||||||
return when (token) {
|
return when (token) {
|
||||||
|
|
||||||
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate ->
|
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate ->
|
||||||
if (candidate.hasConsistentExtensionReceiver(explicitReceiver) && candidate.dispatchReceiverValue() == null) {
|
if (candidate.hasConsistentExtensionReceiver(extensionReceiver) && candidate.dispatchReceiverValue() == null) {
|
||||||
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
|
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
|
||||||
} else {
|
} else {
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { candidate ->
|
TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { candidate ->
|
||||||
// TODO: fix implicit receiver
|
if (candidate.hasConsistentExtensionReceiver(extensionReceiver) && candidate.dispatchReceiverValue() == null) {
|
||||||
if (candidate.hasConsistentExtensionReceiver(explicitReceiver) && candidate.dispatchReceiverValue() == null) {
|
|
||||||
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
|
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
|
||||||
} else {
|
} else {
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
@@ -606,6 +610,14 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
|
|||||||
collector, group++
|
collector, group++
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for (scope in scopes!!) {
|
||||||
|
towerDataConsumer.consume(
|
||||||
|
TowerDataKind.TOWER_LEVEL,
|
||||||
|
ScopeTowerLevel(session, scope, implicitReceiverValue),
|
||||||
|
collector, group++
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,5 +2,5 @@ FILE: extension.kt
|
|||||||
public final fun R|kotlin/String|.foo(): R|kotlin/Unit| {
|
public final fun R|kotlin/String|.foo(): R|kotlin/Unit| {
|
||||||
}
|
}
|
||||||
public final fun R|kotlin/String|.bar(): R|kotlin/Unit| {
|
public final fun R|kotlin/String|.bar(): R|kotlin/Unit| {
|
||||||
<Unresolved name: foo>#()
|
R|/foo|()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ FILE: arrayFirstOrNull.kt
|
|||||||
}
|
}
|
||||||
public final fun <T> R|kotlin/Array<out T>|.firstOrNullX(): R|T|? {
|
public final fun <T> R|kotlin/Array<out T>|.firstOrNullX(): R|T|? {
|
||||||
^firstOrNullX when () {
|
^firstOrNullX when () {
|
||||||
<Unresolved name: isEmpty>#() -> {
|
<Ambiguity: isEmpty, [kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/collections/isEmpty, kotlin/text/isEmpty]>#() -> {
|
||||||
Null(null)
|
Null(null)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ FILE: topLevelResolve.kt
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
lval viaWith: R|kotlin/Nothing| = R|kotlin/with|<R|kotlin/collections/List<kotlin/Int>|, R|kotlin/Nothing|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(42)), <L> = with@fun R|kotlin/collections/List<kotlin/Int>|.<anonymous>(it: R|kotlin/collections/List<kotlin/Int>|): R|kotlin/Function2<kotlin/collections/List<kotlin/Int>, kotlin/collections/List<kotlin/Int>, kotlin/Nothing>| {
|
lval viaWith: R|kotlin/Nothing| = R|kotlin/with|<R|kotlin/collections/List<kotlin/Int>|, R|kotlin/Nothing|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(42)), <L> = with@fun R|kotlin/collections/List<kotlin/Int>|.<anonymous>(it: R|kotlin/collections/List<kotlin/Int>|): R|kotlin/Function2<kotlin/collections/List<kotlin/Int>, kotlin/collections/List<kotlin/Int>, kotlin/Nothing>| {
|
||||||
<Unresolved name: map>#(<L> = map@fun <implicit>.<anonymous>(): <implicit> {
|
<Ambiguity: map, [kotlin/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/collections/map, kotlin/sequences/map, kotlin/text/map]>#(<L> = map@fun <implicit>.<anonymous>(): <implicit> {
|
||||||
it#.times#(it#)
|
it#.times#(it#)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -49,7 +49,7 @@ FILE: topLevelResolve.kt
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
lval indices: R|kotlin/Nothing| = R|kotlin/with|<R|kotlin/String|, R|kotlin/Nothing|>(String(), <L> = with@fun R|kotlin/String|.<anonymous>(it: R|kotlin/String|): R|kotlin/Function2<kotlin/String, kotlin/String, kotlin/Nothing>| {
|
lval indices: R|kotlin/Nothing| = R|kotlin/with|<R|kotlin/String|, R|kotlin/Nothing|>(String(), <L> = with@fun R|kotlin/String|.<anonymous>(it: R|kotlin/String|): R|kotlin/Function2<kotlin/String, kotlin/String, kotlin/Nothing>| {
|
||||||
<Unresolved name: indices>#
|
<Ambiguity: indices, [kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/collections/indices, kotlin/text/indices]>#
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
lval indicesNoWith: R|kotlin/ranges/IntRange| = String().R|kotlin/text/indices|
|
lval indicesNoWith: R|kotlin/ranges/IntRange| = String().R|kotlin/text/indices|
|
||||||
|
|||||||
Reference in New Issue
Block a user