[FIR] Add object support as implicit invoke receiver
This commit is contained in:
+22
-5
@@ -9,13 +9,16 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
|
import org.jetbrains.kotlin.fir.expressions.builder.FirQualifiedAccessExpressionBuilder
|
||||||
import org.jetbrains.kotlin.fir.resolve.constructClassType
|
import org.jetbrains.kotlin.fir.resolve.constructClassType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
import org.jetbrains.kotlin.fir.resolve.transformQualifiedAccessUsingSmartcastInfo
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
@@ -106,15 +109,25 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
|||||||
val group: TowerGroup
|
val group: TowerGroup
|
||||||
) {
|
) {
|
||||||
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder {
|
private fun createExplicitReceiverForInvoke(candidate: Candidate): FirQualifiedAccessExpressionBuilder {
|
||||||
val symbol = candidate.symbol as FirCallableSymbol<*>
|
val (name, typeRef) = when (val symbol = candidate.symbol) {
|
||||||
|
is FirCallableSymbol<*> -> {
|
||||||
|
symbol.callableId.callableName to towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
||||||
|
}
|
||||||
|
is FirRegularClassSymbol -> {
|
||||||
|
symbol.classId.shortClassName to buildResolvedTypeRef {
|
||||||
|
type = symbol.constructType(emptyArray(), isNullable = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> throw AssertionError()
|
||||||
|
}
|
||||||
return FirQualifiedAccessExpressionBuilder().apply {
|
return FirQualifiedAccessExpressionBuilder().apply {
|
||||||
calleeReference = FirNamedReferenceWithCandidate(
|
calleeReference = FirNamedReferenceWithCandidate(
|
||||||
null,
|
null,
|
||||||
symbol.callableId.callableName,
|
name,
|
||||||
candidate
|
candidate
|
||||||
)
|
)
|
||||||
dispatchReceiver = candidate.dispatchReceiverExpression()
|
dispatchReceiver = candidate.dispatchReceiverExpression()
|
||||||
typeRef = towerResolver.typeCalculator.tryCalculateReturnType(symbol.firUnsafe())
|
this.typeRef = typeRef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,12 +176,16 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow
|
|||||||
)
|
)
|
||||||
invokeReceiverCollector.newDataSet()
|
invokeReceiverCollector.newDataSet()
|
||||||
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
|
result += processElementsByName(TowerScopeLevel.Token.Properties, info.name, invokeReceiverProcessor)
|
||||||
|
if (this !is ScopeTowerLevel || this.extensionReceiver == null) {
|
||||||
|
result += processElementsByName(TowerScopeLevel.Token.Objects, info.name, invokeReceiverProcessor)
|
||||||
|
}
|
||||||
|
|
||||||
if (invokeReceiverCollector.isSuccess()) {
|
if (invokeReceiverCollector.isSuccess()) {
|
||||||
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
|
for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) {
|
||||||
|
|
||||||
val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*>
|
val symbol = invokeReceiverCandidate.symbol
|
||||||
val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType(towerResolver.components.session)
|
if (symbol !is FirCallableSymbol<*> && symbol !is FirRegularClassSymbol) continue
|
||||||
|
val isExtensionFunctionType = (symbol as? FirCallableSymbol<*>)?.fir?.returnTypeRef?.isExtensionFunctionType(towerResolver.components.session) == true
|
||||||
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
if (invokeBuiltinExtensionMode && !isExtensionFunctionType) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -74,6 +74,6 @@ FILE: invokePriority.kt
|
|||||||
|
|
||||||
}
|
}
|
||||||
public final fun main(): R|kotlin/Unit| {
|
public final fun main(): R|kotlin/Unit| {
|
||||||
Q|E|.R|/E.Companion.f|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
|
Q|E|.R|/E.Companion.f|.R|/E.f.invoke|()
|
||||||
Q|E.f|.R|/E.f.invoke|()
|
Q|E.f|.R|/E.f.invoke|()
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
-4
@@ -7,9 +7,9 @@ object TestClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(s: String): String {
|
fun test(s: String): String {
|
||||||
val a = <!INAPPLICABLE_CANDIDATE!>TestClass<!> { <!INAPPLICABLE_CANDIDATE!>TestClass<!> { TestClass } }
|
val a = TestClass { TestClass { TestClass } }
|
||||||
a <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><TestClass>() }
|
a checkType { <!UNRESOLVED_REFERENCE!>_<!><TestClass>() }
|
||||||
|
|
||||||
val b = <!INAPPLICABLE_CANDIDATE!>TestClass<!> { return s }
|
val b = TestClass { return s }
|
||||||
b <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Nothing>() }
|
b checkType { <!UNRESOLVED_REFERENCE!>_<!><Nothing>() }
|
||||||
}
|
}
|
||||||
+3
-3
@@ -30,7 +30,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
|
|||||||
with.NestedWithClassObject.foo()
|
with.NestedWithClassObject.foo()
|
||||||
with.NestedEnum.A
|
with.NestedEnum.A
|
||||||
with.NestedObj
|
with.NestedObj
|
||||||
with.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
with.NestedObj()
|
||||||
with.NestedObj.foo()
|
with.NestedObj.foo()
|
||||||
|
|
||||||
without.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
without.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||||
@@ -39,7 +39,7 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
|
|||||||
without.NestedWithClassObject.foo()
|
without.NestedWithClassObject.foo()
|
||||||
without.NestedEnum.A
|
without.NestedEnum.A
|
||||||
without.NestedObj
|
without.NestedObj
|
||||||
without.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
without.NestedObj()
|
||||||
without.NestedObj.foo()
|
without.NestedObj.foo()
|
||||||
|
|
||||||
obj.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
obj.<!UNRESOLVED_REFERENCE!>Nested<!>()
|
||||||
@@ -48,6 +48,6 @@ fun test(with: WithClassObject, without: WithoutClassObject, obj: Obj) {
|
|||||||
obj.NestedWithClassObject.foo()
|
obj.NestedWithClassObject.foo()
|
||||||
obj.NestedEnum.A
|
obj.NestedEnum.A
|
||||||
obj.NestedObj
|
obj.NestedObj
|
||||||
obj.<!UNRESOLVED_REFERENCE!>NestedObj<!>()
|
obj.NestedObj()
|
||||||
obj.NestedObj.foo()
|
obj.NestedObj.foo()
|
||||||
}
|
}
|
||||||
@@ -3,5 +3,5 @@ object Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
<!INAPPLICABLE_CANDIDATE!>Foo<!><Int>()
|
Foo<Int>()
|
||||||
}
|
}
|
||||||
@@ -85,15 +85,16 @@ FILE fqName:<root> fileName:/objectAsCallable.kt
|
|||||||
RETURN type=kotlin.Nothing from='public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>'
|
||||||
GET_VAR 'i: kotlin.Int declared in <root>.invoke' type=kotlin.Int origin=null
|
GET_VAR 'i: kotlin.Int declared in <root>.invoke' type=kotlin.Int origin=null
|
||||||
PROPERTY name:test1 visibility:public modality:FINAL [val]
|
PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||||
FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:private [final,static]
|
FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:private [final,static]
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
ERROR_CALL 'Unresolved reference: <Inapplicable(HIDDEN): [/A.A]>#' type=IrErrorType
|
CALL 'public final fun invoke (i: kotlin.Int): kotlin.Int [operator] declared in <root>' type=kotlin.Int origin=null
|
||||||
CONST Int type=kotlin.Int value=42
|
$receiver: ERROR_CALL 'Unresolved reference: R|/A|' type=IrErrorType
|
||||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:IrErrorType
|
i: CONST Int type=kotlin.Int value=42
|
||||||
|
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test1> visibility:public modality:FINAL <> () returnType:kotlin.Int
|
||||||
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
|
correspondingProperty: PROPERTY name:test1 visibility:public modality:FINAL [val]
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): IrErrorType declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun <get-test1> (): kotlin.Int declared in <root>'
|
||||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:IrErrorType visibility:private [final,static]' type=IrErrorType origin=null
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test1 type:kotlin.Int visibility:private [final,static]' type=kotlin.Int origin=null
|
||||||
PROPERTY name:test2 visibility:public modality:FINAL [val]
|
PROPERTY name:test2 visibility:public modality:FINAL [val]
|
||||||
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static]
|
FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Int visibility:private [final,static]
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
|
|||||||
Reference in New Issue
Block a user