Refine double colon LHS resolution if expression is an object
This commit is contained in:
+16
-4
@@ -51,7 +51,7 @@ import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||
import javax.inject.Inject
|
||||
|
||||
sealed class DoubleColonLHS(val type: KotlinType) {
|
||||
class Expression(typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!) {
|
||||
class Expression(typeInfo: KotlinTypeInfo, val isObject: Boolean) : DoubleColonLHS(typeInfo.type!!) {
|
||||
val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo
|
||||
}
|
||||
|
||||
@@ -160,8 +160,10 @@ class DoubleColonExpressionResolver(
|
||||
private fun resolveDoubleColonLHS(doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext): DoubleColonLHS? {
|
||||
val resultForExpr = tryResolveLHS(doubleColonExpression, c, this::shouldTryResolveLHSAsExpression, this::resolveExpressionOnLHS)
|
||||
if (resultForExpr != null) {
|
||||
val lhs = resultForExpr.lhs
|
||||
if (lhs != null) {
|
||||
val lhs = resultForExpr.lhs as DoubleColonLHS.Expression?
|
||||
// If expression result is an object, we remember this and skip it here, because there are valid situations where
|
||||
// another type (representing another classifier) should win
|
||||
if (lhs != null && !lhs.isObject) {
|
||||
return resultForExpr.commit()
|
||||
}
|
||||
}
|
||||
@@ -171,6 +173,12 @@ class DoubleColonExpressionResolver(
|
||||
}
|
||||
if (resultForType != null) {
|
||||
val lhs = resultForType.lhs
|
||||
if (resultForExpr != null && lhs != null && lhs.type == resultForExpr.lhs?.type) {
|
||||
// If we skipped an object expression result before and the type result is the same, this means that
|
||||
// there were no other classifier except that object that could win. We prefer to treat the LHS as an expression here,
|
||||
// to have a bound callable reference / class literal
|
||||
return resultForExpr.commit()
|
||||
}
|
||||
if (lhs != null) {
|
||||
return resultForType.commit()
|
||||
}
|
||||
@@ -235,13 +243,17 @@ class DoubleColonExpressionResolver(
|
||||
if (resultingDescriptor is FakeCallableDescriptorForObject) {
|
||||
val classDescriptor = resultingDescriptor.classDescriptor
|
||||
if (classDescriptor.companionObjectDescriptor != null) return null
|
||||
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
return DoubleColonLHS.Expression(typeInfo, isObject = true)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is resolved to a function (with the error "arguments expected"), such as in "Runnable::class"
|
||||
if (expression.canBeConsideredProperType() && resultingDescriptor !is VariableDescriptor) return null
|
||||
}
|
||||
|
||||
return DoubleColonLHS.Expression(typeInfo)
|
||||
return DoubleColonLHS.Expression(typeInfo, isObject = false)
|
||||
}
|
||||
|
||||
private fun resolveTypeOnLHS(
|
||||
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// FILE: 1.kt
|
||||
|
||||
package a
|
||||
|
||||
import b.B.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class Companion
|
||||
|
||||
val f: KClass<a.Companion> = Companion::class
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
package b
|
||||
|
||||
class B {
|
||||
companion object Companion
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
package a {
|
||||
public val f: kotlin.reflect.KClass<a.Companion>
|
||||
|
||||
public final class Companion {
|
||||
public constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
package b {
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// FILE: 1.kt
|
||||
|
||||
package a
|
||||
|
||||
import b.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class A
|
||||
object B
|
||||
|
||||
val f: KClass<a.A> = A::class
|
||||
val g: KClass<a.B> = B::class
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
package b
|
||||
|
||||
object A
|
||||
object B
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package
|
||||
|
||||
package a {
|
||||
public val f: kotlin.reflect.KClass<a.A>
|
||||
public val g: kotlin.reflect.KClass<a.B>
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object B {
|
||||
private constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
package b {
|
||||
|
||||
public object A {
|
||||
private constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object B {
|
||||
private constructor B()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -1721,6 +1721,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("classVsStarImportedCompanion.kt")
|
||||
public void testClassVsStarImportedCompanion() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/classVsStarImportedCompanion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classVsStarImportedObject.kt")
|
||||
public void testClassVsStarImportedObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/classVsStarImportedObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("companionObject.kt")
|
||||
public void testCompanionObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/companionObject.kt");
|
||||
|
||||
Reference in New Issue
Block a user