Qualifier no longer defers "(nested) class vs package" resolution.
Consider FQN 'a.b.c'.
If 'a' is a classifier in the current scope,
resolve rest in the corresponding class scope.
Otherwise (if 'a' is a package),
find the maximum possible prefix 'a.b' resolving to a package,
resolve rest in the corresponding package scope.
This commit is contained in:
@@ -26,7 +26,8 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
@@ -426,10 +427,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun storageQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor) {
|
private fun storageQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor) {
|
||||||
if (descriptor is PackageViewDescriptor || descriptor is ClassifierDescriptor) {
|
val qualifier =
|
||||||
val qualifier = QualifierReceiver(referenceExpression, descriptor as? PackageViewDescriptor, descriptor as? ClassifierDescriptor)
|
when (descriptor) {
|
||||||
trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
|
is PackageViewDescriptor -> PackageQualifier(referenceExpression, descriptor)
|
||||||
}
|
is ClassifierDescriptor -> ClassifierQualifier(referenceExpression, descriptor)
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isVisible(
|
private fun isVisible(
|
||||||
|
|||||||
@@ -61,10 +61,8 @@ public interface Qualifier: ReceiverValue {
|
|||||||
public val scope: KtScope
|
public val scope: KtScope
|
||||||
}
|
}
|
||||||
|
|
||||||
class QualifierReceiver (
|
abstract class QualifierReceiver(
|
||||||
val referenceExpression: KtSimpleNameExpression,
|
val referenceExpression: KtSimpleNameExpression
|
||||||
override val packageView: PackageViewDescriptor?,
|
|
||||||
override val classifier: ClassifierDescriptor?
|
|
||||||
) : Qualifier {
|
) : Qualifier {
|
||||||
|
|
||||||
override val expression: KtExpression = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression
|
override val expression: KtExpression = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression
|
||||||
@@ -74,54 +72,79 @@ class QualifierReceiver (
|
|||||||
|
|
||||||
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
|
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
|
||||||
|
|
||||||
override val scope: KtScope get() {
|
|
||||||
val scopes = ArrayList<KtScope>(4)
|
|
||||||
|
|
||||||
val classObjectTypeScope = (classifier as? ClassDescriptor)?.classObjectType?.memberScope?.let {
|
|
||||||
FilteringScope(it) { it !is ClassDescriptor }
|
|
||||||
}
|
|
||||||
scopes.addIfNotNull(classObjectTypeScope)
|
|
||||||
|
|
||||||
scopes.addIfNotNull(packageView?.memberScope)
|
|
||||||
|
|
||||||
if (classifier is ClassDescriptor) {
|
|
||||||
scopes.add(classifier.staticScope)
|
|
||||||
|
|
||||||
if (classifier.kind != ClassKind.ENUM_ENTRY) {
|
|
||||||
scopes.add(classifier.unsubstitutedInnerClassesScope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChainedScope(descriptor, "Member scope for $name as package or class or object", *scopes.toTypedArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getClassObjectReceiver(): ReceiverValue =
|
fun getClassObjectReceiver(): ReceiverValue =
|
||||||
(classifier as? ClassDescriptor)?.classObjectType?.let { ExpressionReceiver(referenceExpression, it) }
|
(classifier as? ClassDescriptor)?.classObjectType?.let { ExpressionReceiver(referenceExpression, it) }
|
||||||
?: ReceiverValue.NO_RECEIVER
|
?: ReceiverValue.NO_RECEIVER
|
||||||
|
|
||||||
fun getNestedClassesAndPackageMembersScope(): KtScope {
|
abstract fun getNestedClassesAndPackageMembersScope(): KtScope
|
||||||
val scopes = ArrayList<KtScope>(4)
|
|
||||||
|
|
||||||
scopes.addIfNotNull(packageView?.memberScope)
|
|
||||||
|
|
||||||
if (classifier is ClassDescriptor) {
|
|
||||||
scopes.add(classifier.getStaticScope())
|
|
||||||
|
|
||||||
if (classifier.getKind() != ClassKind.ENUM_ENTRY) {
|
|
||||||
scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChainedScope(descriptor, "Static scope for " + name + " as package or class or object", *scopes.toTypedArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getType(): KotlinType = throw IllegalStateException("No type corresponds to QualifierReceiver '$this'")
|
override fun getType(): KotlinType = throw IllegalStateException("No type corresponds to QualifierReceiver '$this'")
|
||||||
|
|
||||||
override fun exists() = true
|
override fun exists() = true
|
||||||
|
|
||||||
override fun toString() = "Package{$packageView} OR Class{$classifier}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PackageQualifier(
|
||||||
|
referenceExpression: KtSimpleNameExpression,
|
||||||
|
override val packageView: PackageViewDescriptor
|
||||||
|
) : QualifierReceiver(referenceExpression) {
|
||||||
|
|
||||||
|
override val classifier: ClassifierDescriptor? get() = null
|
||||||
|
|
||||||
|
override val scope: KtScope get() = packageView.memberScope
|
||||||
|
|
||||||
|
override fun getNestedClassesAndPackageMembersScope(): KtScope = packageView.memberScope
|
||||||
|
|
||||||
|
override fun toString() = "Package{$packageView}"
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassifierQualifier(
|
||||||
|
referenceExpression: KtSimpleNameExpression,
|
||||||
|
override val classifier: ClassifierDescriptor
|
||||||
|
) : QualifierReceiver(referenceExpression) {
|
||||||
|
|
||||||
|
override val packageView: PackageViewDescriptor? get() = null
|
||||||
|
|
||||||
|
override val scope: KtScope get() {
|
||||||
|
if (classifier !is ClassDescriptor) {
|
||||||
|
return KtScope.Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
val scopes = ArrayList<KtScope>(3)
|
||||||
|
|
||||||
|
val classObjectTypeScope = classifier.classObjectType?.memberScope?.let {
|
||||||
|
FilteringScope(it) { it !is ClassDescriptor }
|
||||||
|
}
|
||||||
|
scopes.addIfNotNull(classObjectTypeScope)
|
||||||
|
|
||||||
|
scopes.add(classifier.staticScope)
|
||||||
|
|
||||||
|
if (classifier.kind != ClassKind.ENUM_ENTRY) {
|
||||||
|
scopes.add(classifier.unsubstitutedInnerClassesScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChainedScope(descriptor, "Member scope for $name as class or object", *scopes.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getNestedClassesAndPackageMembersScope(): KtScope {
|
||||||
|
if (classifier !is ClassDescriptor) {
|
||||||
|
return KtScope.Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
val scopes = ArrayList<KtScope>(2)
|
||||||
|
|
||||||
|
scopes.add(classifier.staticScope)
|
||||||
|
|
||||||
|
if (classifier.kind != ClassKind.ENUM_ENTRY) {
|
||||||
|
scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChainedScope(descriptor, "Static scope for $name as class or object", *scopes.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString() = "Classifier{$classifier}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createQualifier(
|
fun createQualifier(
|
||||||
expression: KtSimpleNameExpression,
|
expression: KtSimpleNameExpression,
|
||||||
receiver: ReceiverValue,
|
receiver: ReceiverValue,
|
||||||
@@ -141,7 +164,18 @@ fun createQualifier(
|
|||||||
|
|
||||||
context.trace.recordScope(context.scope, expression)
|
context.trace.recordScope(context.scope, expression)
|
||||||
|
|
||||||
val qualifier = QualifierReceiver(expression, packageViewDescriptor, classifierDescriptor)
|
val qualifier =
|
||||||
|
if (receiver is PackageQualifier)
|
||||||
|
if (packageViewDescriptor != null)
|
||||||
|
PackageQualifier(expression, packageViewDescriptor)
|
||||||
|
else
|
||||||
|
ClassifierQualifier(expression, classifierDescriptor!!)
|
||||||
|
else
|
||||||
|
if (classifierDescriptor != null)
|
||||||
|
ClassifierQualifier(expression, classifierDescriptor)
|
||||||
|
else
|
||||||
|
PackageQualifier(expression, packageViewDescriptor!!)
|
||||||
|
|
||||||
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
|
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
|
||||||
return qualifier
|
return qualifier
|
||||||
}
|
}
|
||||||
@@ -150,6 +184,8 @@ fun QualifierReceiver.resolveAsStandaloneExpression(
|
|||||||
context: ExpressionTypingContext,
|
context: ExpressionTypingContext,
|
||||||
symbolUsageValidator: SymbolUsageValidator
|
symbolUsageValidator: SymbolUsageValidator
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
|
val classifier = this.classifier
|
||||||
|
|
||||||
resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector = null)
|
resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector = null)
|
||||||
if (classifier is TypeParameterDescriptor) {
|
if (classifier is TypeParameterDescriptor) {
|
||||||
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(referenceExpression, classifier))
|
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(referenceExpression, classifier))
|
||||||
@@ -168,6 +204,8 @@ fun QualifierReceiver.resolveAsReceiverInQualifiedExpression(
|
|||||||
symbolUsageValidator: SymbolUsageValidator,
|
symbolUsageValidator: SymbolUsageValidator,
|
||||||
selector: DeclarationDescriptor?
|
selector: DeclarationDescriptor?
|
||||||
) {
|
) {
|
||||||
|
val classifier = this.classifier
|
||||||
|
|
||||||
resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector)
|
resolveAndRecordReferenceTarget(context, symbolUsageValidator, selector)
|
||||||
if (classifier is TypeParameterDescriptor) {
|
if (classifier is TypeParameterDescriptor) {
|
||||||
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(referenceExpression, classifier))
|
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(referenceExpression, classifier))
|
||||||
@@ -191,6 +229,9 @@ private fun QualifierReceiver.resolveReferenceTarget(
|
|||||||
symbolUsageValidator: SymbolUsageValidator,
|
symbolUsageValidator: SymbolUsageValidator,
|
||||||
selector: DeclarationDescriptor?
|
selector: DeclarationDescriptor?
|
||||||
): DeclarationDescriptor {
|
): DeclarationDescriptor {
|
||||||
|
val classifier = this.classifier
|
||||||
|
val packageView = this.packageView
|
||||||
|
|
||||||
if (classifier is TypeParameterDescriptor) {
|
if (classifier is TypeParameterDescriptor) {
|
||||||
return classifier
|
return classifier
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ fun test2(_a: a) {
|
|||||||
_ab._ab()
|
_ab._ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>_ab<!>() // todo
|
_ab2._ab()
|
||||||
|
|
||||||
_fun()
|
_fun()
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ fun test3(_a: a) {
|
|||||||
_ab._ab()
|
_ab._ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>_ab<!>() // todo
|
_ab2._ab()
|
||||||
|
|
||||||
_fun()
|
_fun()
|
||||||
}
|
}
|
||||||
+5
-4
@@ -30,9 +30,10 @@ fun test(ab_c: c) {
|
|||||||
ab_c3.ab_c()
|
ab_c3.ab_c()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(a_bc: a.b.c) {
|
// NB according to the maximum package prefix rule, 'a.b.c' denotes 'c' in package 'a.b' (thus ab_c, not a_bc)
|
||||||
a_bc.<!UNRESOLVED_REFERENCE!>a_bc<!>() // todo
|
fun test2(ab_c: a.b.c) {
|
||||||
a_bc.ab_c() // todo
|
ab_c.<!UNRESOLVED_REFERENCE!>a_bc<!>()
|
||||||
|
ab_c.ab_c()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ fun test(a_b: b) {
|
|||||||
_ab._ab()
|
_ab._ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>_ab<!>() // todo
|
_ab2._ab()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(_ab: a.b) {
|
fun test2(_ab: a.b) {
|
||||||
|
|||||||
+3
-1
@@ -42,7 +42,7 @@ package a {
|
|||||||
package
|
package
|
||||||
|
|
||||||
public fun test(/*0*/ ab_c: a.b.c): kotlin.Unit
|
public fun test(/*0*/ ab_c: a.b.c): kotlin.Unit
|
||||||
public fun test2(/*0*/ a_bc: a.b.c): kotlin.Unit
|
public fun test2(/*0*/ ab_c: a.b.c): kotlin.Unit
|
||||||
|
|
||||||
package a {
|
package a {
|
||||||
|
|
||||||
@@ -110,3 +110,5 @@ package a {
|
|||||||
// -- Module: <top_m1> --
|
// -- Module: <top_m1> --
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// MODULE: m1
|
||||||
|
// FILE: a.kt
|
||||||
|
package a
|
||||||
|
|
||||||
|
class b {
|
||||||
|
fun a_b() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m2(m1)
|
||||||
|
// FILE: b.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
class a
|
||||||
|
|
||||||
|
val x = a.<!UNRESOLVED_REFERENCE!>b<!>()
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// -- Module: <m1> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package a {
|
||||||
|
|
||||||
|
public final class b {
|
||||||
|
public constructor b()
|
||||||
|
public final fun a_b(): kotlin.Unit
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m2> --
|
||||||
|
package
|
||||||
|
|
||||||
|
package a {
|
||||||
|
|
||||||
|
public final class b {
|
||||||
|
// -- Module: <m1> --
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package test {
|
||||||
|
public val x: [ERROR : Type for 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+1
-1
@@ -40,5 +40,5 @@ fun test(_ab: a.b) {
|
|||||||
_ab._ab()
|
_ab._ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>_ab<!>() // todo
|
_ab2._ab() // todo
|
||||||
}
|
}
|
||||||
+6
-6
@@ -25,10 +25,10 @@ class a {}
|
|||||||
fun test(a_: a.<!UNRESOLVED_REFERENCE!>b<!>) {
|
fun test(a_: a.<!UNRESOLVED_REFERENCE!>b<!>) {
|
||||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_b<!>()
|
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_b<!>()
|
||||||
|
|
||||||
val a_2 = a.b()
|
val a_2 = a.<!UNRESOLVED_REFERENCE!>b<!>()
|
||||||
a_2.a_b() // todo: must be unresolved
|
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_2<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_b<!>()
|
||||||
a_2.<!UNRESOLVED_REFERENCE!>some_ab<!>()
|
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_2<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>some_ab<!>()
|
||||||
a_2.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_()<!>
|
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_2<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a_<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: c2.kt
|
// FILE: c2.kt
|
||||||
@@ -44,7 +44,7 @@ fun test(_ab: a.b) {
|
|||||||
_ab.other2_ab()
|
_ab.other2_ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>other2_ab<!>() // todo
|
_ab2.other2_ab()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: c3.kt
|
// FILE: c3.kt
|
||||||
@@ -54,5 +54,5 @@ fun test(_ab: a.b) {
|
|||||||
_ab.some_ab()
|
_ab.some_ab()
|
||||||
|
|
||||||
val _ab2 = a.b()
|
val _ab2 = a.b()
|
||||||
_ab2.<!UNRESOLVED_REFERENCE!>some_ab<!>() // todo
|
_ab2.some_ab()
|
||||||
}
|
}
|
||||||
@@ -11862,6 +11862,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PackageVsClass2.kt")
|
||||||
|
public void testPackageVsClass2() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/qualifiedExpression/PackageVsClass2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("PackageVsRootClass.kt")
|
@TestMetadata("PackageVsRootClass.kt")
|
||||||
public void testPackageVsRootClass() throws Exception {
|
public void testPackageVsRootClass() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/qualifiedExpression/PackageVsRootClass.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/qualifiedExpression/PackageVsRootClass.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user