KT-14352 Record short reference to companion object via type alias,
so that it would be checked properly.
This commit is contained in:
@@ -117,8 +117,8 @@ public interface BindingContext {
|
|||||||
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
|
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
|
||||||
new BasicWritableSlice<KtReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
|
new BasicWritableSlice<KtReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
|
||||||
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
||||||
WritableSlice<KtReferenceExpression, ClassDescriptor> SHORT_REFERENCE_TO_COMPANION_OBJECT =
|
WritableSlice<KtReferenceExpression, ClassifierDescriptorWithTypeParameters> SHORT_REFERENCE_TO_COMPANION_OBJECT =
|
||||||
new BasicWritableSlice<KtReferenceExpression, ClassDescriptor>(DO_NOTHING);
|
new BasicWritableSlice<KtReferenceExpression, ClassifierDescriptorWithTypeParameters>(DO_NOTHING);
|
||||||
|
|
||||||
WritableSlice<Call, ResolvedCall<?>> RESOLVED_CALL = new BasicWritableSlice<Call, ResolvedCall<?>>(DO_NOTHING);
|
WritableSlice<Call, ResolvedCall<?>> RESOLVED_CALL = new BasicWritableSlice<Call, ResolvedCall<?>>(DO_NOTHING);
|
||||||
WritableSlice<Call, TailRecursionKind> TAIL_RECURSION_CALL = Slices.createSimpleSlice();
|
WritableSlice<Call, TailRecursionKind> TAIL_RECURSION_CALL = Slices.createSimpleSlice();
|
||||||
|
|||||||
+1
-1
@@ -89,7 +89,7 @@ private fun resolveQualifierReferenceTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO make decisions about short reference to companion object somewhere else
|
// TODO make decisions about short reference to companion object somewhere else
|
||||||
if (qualifier is ClassQualifier) {
|
if (qualifier is ClassifierQualifier) {
|
||||||
val classifier = qualifier.descriptor
|
val classifier = qualifier.descriptor
|
||||||
val selectorIsCallable = selector is CallableDescriptor &&
|
val selectorIsCallable = selector is CallableDescriptor &&
|
||||||
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null)
|
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null)
|
||||||
|
|||||||
+8
-6
@@ -56,15 +56,17 @@ interface ClassifierUsageChecker {
|
|||||||
|
|
||||||
val target = getReferencedClassifier(expression) ?: return
|
val target = getReferencedClassifier(expression) ?: return
|
||||||
|
|
||||||
for (checker in checkers) {
|
runCheckersWithTarget(target, expression)
|
||||||
checker.check(target, trace, expression, languageVersionSettings)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isReferenceToCompanionViaOuterClass(expression, target)) {
|
if (isReferenceToCompanionViaOuterClass(expression, target)) {
|
||||||
val outerClass = target.containingDeclaration as ClassDescriptor
|
val outerClass = target.containingDeclaration as ClassDescriptor
|
||||||
for (checker in checkers) {
|
runCheckersWithTarget(outerClass, expression)
|
||||||
checker.check(outerClass, trace, expression, languageVersionSettings)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun runCheckersWithTarget(target: ClassifierDescriptor, expression: KtReferenceExpression) {
|
||||||
|
for (checker in checkers) {
|
||||||
|
checker.check(target, trace, expression, languageVersionSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ class TypeParameterQualifier(
|
|||||||
override fun toString() = "TypeParameter{$descriptor}"
|
override fun toString() = "TypeParameter{$descriptor}"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClassifierQualifier : Qualifier
|
interface ClassifierQualifier : Qualifier {
|
||||||
|
override val descriptor: ClassifierDescriptorWithTypeParameters
|
||||||
|
}
|
||||||
|
|
||||||
class ClassQualifier(
|
class ClassQualifier(
|
||||||
override val referenceExpression: KtSimpleNameExpression,
|
override val referenceExpression: KtSimpleNameExpression,
|
||||||
|
|||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// !API_VERSION: 1.0
|
||||||
|
|
||||||
|
class C {
|
||||||
|
@SinceKotlin("1.1")
|
||||||
|
companion object {
|
||||||
|
val x = 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias CA = C
|
||||||
|
|
||||||
|
val test1 = <!NO_COMPANION_OBJECT!>CA<!>
|
||||||
|
val test2 = CA.<!UNRESOLVED_REFERENCE!>Companion<!>
|
||||||
|
val test3 = <!API_NOT_AVAILABLE!>CA<!>.x
|
||||||
|
val test4 = CA.<!UNRESOLVED_REFERENCE!>Companion<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
|
||||||
compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsCompanionObjects.txt
Vendored
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: [ERROR : Type for CA]
|
||||||
|
public val test2: [ERROR : Type for CA.Companion]
|
||||||
|
public val test3: kotlin.Int = 42
|
||||||
|
public val test4: [ERROR : <ERROR PROPERTY TYPE>]
|
||||||
|
|
||||||
|
public final class C {
|
||||||
|
public constructor C()
|
||||||
|
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
|
||||||
|
|
||||||
|
@kotlin.SinceKotlin(version = "1.1") public companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
public final val x: kotlin.Int = 42
|
||||||
|
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 typealias CA = C
|
||||||
@@ -19574,6 +19574,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typealiasesAsCompanionObjects.kt")
|
||||||
|
public void testTypealiasesAsCompanionObjects() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsCompanionObjects.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("typealiasesAsConstructors.kt")
|
@TestMetadata("typealiasesAsConstructors.kt")
|
||||||
public void testTypealiasesAsConstructors() throws Exception {
|
public void testTypealiasesAsConstructors() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/typealiasesAsConstructors.kt");
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjection
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
@@ -65,6 +67,13 @@ fun ModuleDescriptor.resolveTopLevelClass(topLevelClassFqName: FqName, location:
|
|||||||
return getPackage(topLevelClassFqName.parent()).memberScope.getContributedClassifier(topLevelClassFqName.shortName(), location) as? ClassDescriptor
|
return getPackage(topLevelClassFqName.parent()).memberScope.getContributedClassifier(topLevelClassFqName.shortName(), location) as? ClassDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ClassifierDescriptorWithTypeParameters.denotedClassDescriptor: ClassDescriptor?
|
||||||
|
get() = when (this) {
|
||||||
|
is ClassDescriptor -> this
|
||||||
|
is TypeAliasDescriptor -> classDescriptor
|
||||||
|
else -> throw UnsupportedOperationException("Unexpected descriptor kind: $this")
|
||||||
|
}
|
||||||
|
|
||||||
val ClassDescriptor.classId: ClassId
|
val ClassDescriptor.classId: ClassId
|
||||||
get() {
|
get() {
|
||||||
val owner = containingDeclaration
|
val owner = containingDeclaration
|
||||||
@@ -77,23 +86,31 @@ val ClassDescriptor.classId: ClassId
|
|||||||
throw IllegalStateException("Illegal container: $owner")
|
throw IllegalStateException("Illegal container: $owner")
|
||||||
}
|
}
|
||||||
|
|
||||||
val ClassDescriptor.hasCompanionObject: Boolean get() = companionObjectDescriptor != null
|
val ClassifierDescriptorWithTypeParameters.hasCompanionObject: Boolean
|
||||||
|
get() = denotedClassDescriptor?.companionObjectDescriptor != null
|
||||||
|
|
||||||
val ClassDescriptor.hasClassValueDescriptor: Boolean get() = classValueDescriptor != null
|
val ClassDescriptor.hasClassValueDescriptor: Boolean get() = classValueDescriptor != null
|
||||||
|
|
||||||
val ClassDescriptor.classValueDescriptor: ClassDescriptor?
|
val ClassifierDescriptorWithTypeParameters.classValueDescriptor: ClassDescriptor?
|
||||||
get() = if (kind.isSingleton) this else companionObjectDescriptor
|
get() = denotedClassDescriptor?.let {
|
||||||
|
if (it.kind.isSingleton)
|
||||||
|
it
|
||||||
|
else
|
||||||
|
it.companionObjectDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
val ClassDescriptor.classValueTypeDescriptor: ClassDescriptor?
|
val ClassifierDescriptorWithTypeParameters.classValueTypeDescriptor: ClassDescriptor?
|
||||||
get() = when (kind) {
|
get() = denotedClassDescriptor?.let {
|
||||||
OBJECT -> this
|
when (it.kind) {
|
||||||
ENUM_ENTRY -> {
|
OBJECT -> it
|
||||||
// enum entry has the type of enum class
|
ENUM_ENTRY -> {
|
||||||
val container = this.containingDeclaration
|
// enum entry has the type of enum class
|
||||||
assert(container is ClassDescriptor && container.kind == ENUM_CLASS)
|
val container = this.containingDeclaration
|
||||||
container as ClassDescriptor
|
assert(container is ClassDescriptor && container.kind == ENUM_CLASS)
|
||||||
|
container as ClassDescriptor
|
||||||
|
}
|
||||||
|
else -> it.companionObjectDescriptor
|
||||||
}
|
}
|
||||||
else -> companionObjectDescriptor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If a literal of this class can be used as a value, returns the type of this value */
|
/** If a literal of this class can be used as a value, returns the type of this value */
|
||||||
|
|||||||
Reference in New Issue
Block a user