Drop createQualifier.
NB: some regression in diagnostics for special cases, such as class or package used in expression position or in safe access; see next commit.
This commit is contained in:
+40
-47
@@ -23,65 +23,54 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier
|
||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
|
||||
|
||||
public fun resolveAsReceiverInQualifiedExpression(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
public fun resolveQualifierAsReceiverInExpression(
|
||||
qualifier: Qualifier,
|
||||
selector: DeclarationDescriptor?,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
resolveAndRecordReferenceTarget(qualifier, context, selector, symbolUsageValidator)
|
||||
|
||||
if (qualifier is ClassifierQualifier) {
|
||||
val classifier = qualifier.classifier
|
||||
if (classifier is TypeParameterDescriptor) {
|
||||
context.trace.report(Errors.TYPE_PARAMETER_ON_LHS_OF_DOT.on(qualifier.referenceExpression, classifier))
|
||||
}
|
||||
else if (classifier is ClassDescriptor && classifier.hasClassObjectType) {
|
||||
context.trace.recordType(qualifier.expression, classifier.classObjectType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun resolveAsStandaloneExpression(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
resolveAndRecordReferenceTarget(qualifier, context, selector = null, symbolUsageValidator = symbolUsageValidator)
|
||||
): DeclarationDescriptor {
|
||||
val referenceTarget = resolveQualifierReferenceTarget(qualifier, selector, context, symbolUsageValidator)
|
||||
|
||||
if (qualifier is ClassifierQualifier) {
|
||||
val classifier = qualifier.classifier
|
||||
if (classifier is TypeParameterDescriptor) {
|
||||
context.trace.report(Errors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(qualifier.referenceExpression, classifier))
|
||||
}
|
||||
else if (classifier is ClassDescriptor && !classifier.hasClassObjectType) {
|
||||
context.trace.report(Errors.NO_COMPANION_OBJECT.on(qualifier.referenceExpression, classifier))
|
||||
}
|
||||
}
|
||||
else if (qualifier is PackageQualifier) {
|
||||
context.trace.report(Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND.on(qualifier.referenceExpression))
|
||||
if (referenceTarget is TypeParameterDescriptor) {
|
||||
context.trace.report(Errors.TYPE_PARAMETER_ON_LHS_OF_DOT.on(qualifier.referenceExpression, referenceTarget))
|
||||
}
|
||||
|
||||
return referenceTarget
|
||||
}
|
||||
|
||||
private fun resolveAndRecordReferenceTarget(
|
||||
qualifier: QualifierReceiver,
|
||||
public fun resolveQualifierAsStandaloneExpression(
|
||||
qualifier: Qualifier,
|
||||
context: ExpressionTypingContext,
|
||||
selector: DeclarationDescriptor?,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
) {
|
||||
val resultingDescriptor = resolveReferenceTarget(qualifier, context, selector, symbolUsageValidator)
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, resultingDescriptor)
|
||||
): DeclarationDescriptor {
|
||||
val referenceTarget = resolveQualifierReferenceTarget(qualifier, null, context, symbolUsageValidator)
|
||||
|
||||
when (referenceTarget) {
|
||||
is TypeParameterDescriptor -> {
|
||||
context.trace.report(Errors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(qualifier.referenceExpression, referenceTarget))
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
if (!referenceTarget.kind.isSingleton) {
|
||||
context.trace.report(Errors.NO_COMPANION_OBJECT.on(qualifier.referenceExpression, referenceTarget))
|
||||
}
|
||||
}
|
||||
is PackageViewDescriptor -> {
|
||||
context.trace.report(Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND.on(qualifier.referenceExpression))
|
||||
}
|
||||
}
|
||||
|
||||
return referenceTarget
|
||||
}
|
||||
|
||||
private fun resolveReferenceTarget(
|
||||
qualifier: QualifierReceiver,
|
||||
context: ExpressionTypingContext,
|
||||
private fun resolveQualifierReferenceTarget(
|
||||
qualifier: Qualifier,
|
||||
selector: DeclarationDescriptor?,
|
||||
context: ExpressionTypingContext,
|
||||
symbolUsageValidator: SymbolUsageValidator
|
||||
): DeclarationDescriptor {
|
||||
if (qualifier is ClassifierQualifier && qualifier.classifier is TypeParameterDescriptor) {
|
||||
@@ -102,15 +91,19 @@ private fun resolveReferenceTarget(
|
||||
return qualifier.packageView
|
||||
}
|
||||
|
||||
// TODO make decisions about short reference to companion object somewhere else
|
||||
if (qualifier is ClassQualifier) {
|
||||
val classifier = qualifier.classifier
|
||||
if (selector is CallableDescriptor &&
|
||||
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null) &&
|
||||
qualifier.classifier is ClassDescriptor &&
|
||||
qualifier.classifier.hasClassObjectType
|
||||
classifier is ClassDescriptor &&
|
||||
classifier.hasClassObjectType
|
||||
) {
|
||||
val companionObjectDescriptor = qualifier.classifier.companionObjectDescriptor
|
||||
val companionObjectDescriptor = classifier.companionObjectDescriptor
|
||||
if (companionObjectDescriptor != null) {
|
||||
context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, qualifier.classifier)
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, companionObjectDescriptor)
|
||||
context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, classifier)
|
||||
context.trace.recordType(qualifier.expression, classifier.classObjectType)
|
||||
symbolUsageValidator.validateTypeUsage(companionObjectDescriptor, context.trace, qualifier.referenceExpression)
|
||||
return companionObjectDescriptor
|
||||
}
|
||||
|
||||
@@ -28,14 +28,11 @@ import org.jetbrains.kotlin.resolve.calls.unrollToLeftMostQualifiedExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.createClassifierQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.*
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
@@ -392,6 +389,33 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
||||
return Pair(currentDescriptor, path.size)
|
||||
}
|
||||
|
||||
public fun resolveNameExpressionAsQualifierForDiagnostics(
|
||||
expression: KtSimpleNameExpression,
|
||||
receiver: Receiver,
|
||||
context: ExpressionTypingContext
|
||||
): Qualifier? {
|
||||
val name = expression.getReferencedNameAsName()
|
||||
|
||||
val qualifierDescriptor = when {
|
||||
receiver is PackageQualifier -> {
|
||||
val childPackageFQN = receiver.packageView.fqName.child(name)
|
||||
val childPackageDescriptor = receiver.packageView.module.getPackage(childPackageFQN).check { !it.isEmpty() }
|
||||
childPackageDescriptor ?: receiver.packageView.memberScope.getContributedClassifier(name, KotlinLookupLocation(expression))
|
||||
}
|
||||
receiver is ClassQualifier ->
|
||||
receiver.scope.getContributedClassifier(name, KotlinLookupLocation(expression))
|
||||
!receiver.exists() ->
|
||||
context.scope.findClassifier(name, KotlinLookupLocation(expression)) ?:
|
||||
context.scope.ownerDescriptor.module.getPackage(FqName.ROOT.child(name)).check { !it.isEmpty() }
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (qualifierDescriptor != null) {
|
||||
return storeResult(context.trace, expression, qualifierDescriptor, context.scope.ownerDescriptor, QualifierPosition.EXPRESSION)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
public fun resolveQualifierInExpressionAndUnroll(
|
||||
expression: KtQualifiedExpression,
|
||||
@@ -411,11 +435,11 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
||||
isValue = isValue
|
||||
).second
|
||||
|
||||
val firstExpressionAfterQualifierIndex =
|
||||
val nextExpressionIndexAfterQualifier =
|
||||
if (nextIndexAfterPrefix == 0) 0 else nextIndexAfterPrefix - 1
|
||||
|
||||
return qualifiedExpressions
|
||||
.subList(firstExpressionAfterQualifierIndex, qualifiedExpressions.size)
|
||||
.subList(nextExpressionIndexAfterQualifier, qualifiedExpressions.size)
|
||||
.map { CallExpressionElement(it) }
|
||||
}
|
||||
|
||||
@@ -520,10 +544,10 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
||||
shouldBeVisibleFrom: DeclarationDescriptor?,
|
||||
position: QualifierPosition,
|
||||
isQualifier: Boolean = true
|
||||
) {
|
||||
): Qualifier? {
|
||||
if (descriptor == null) {
|
||||
trace.report(Errors.UNRESOLVED_REFERENCE.on(referenceExpression, referenceExpression))
|
||||
return
|
||||
return null
|
||||
}
|
||||
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptor)
|
||||
@@ -545,20 +569,20 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa
|
||||
}
|
||||
}
|
||||
|
||||
if (isQualifier) {
|
||||
storeQualifier(trace, referenceExpression, descriptor)
|
||||
}
|
||||
return if (isQualifier) storeQualifier(trace, referenceExpression, descriptor) else null
|
||||
}
|
||||
|
||||
private fun storeQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor) {
|
||||
private fun storeQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor): Qualifier? {
|
||||
val qualifier =
|
||||
when (descriptor) {
|
||||
is PackageViewDescriptor -> PackageQualifier(referenceExpression, descriptor)
|
||||
is ClassifierDescriptor -> createClassifierQualifier(referenceExpression, descriptor, trace.bindingContext)
|
||||
else -> return
|
||||
else -> return null
|
||||
}
|
||||
|
||||
trace.record(BindingContext.QUALIFIER, qualifier.expression, qualifier)
|
||||
|
||||
return qualifier
|
||||
}
|
||||
|
||||
private fun isVisible(
|
||||
|
||||
+23
-12
@@ -127,8 +127,9 @@ public class CallExpressionResolver {
|
||||
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
|
||||
boolean isLHSOfDot = KtPsiUtil.isLHSOfDot(nameExpression);
|
||||
if (!resolutionResult.isNothing() && resolutionResult.getResultCode() != OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER) {
|
||||
boolean isQualifier = isLHSOfDot && resolutionResult.isSingleResult()
|
||||
&& resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject;
|
||||
boolean isQualifier = isLHSOfDot &&
|
||||
resolutionResult.isSingleResult() &&
|
||||
resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject;
|
||||
if (!isQualifier) {
|
||||
result[0] = true;
|
||||
temporaryForVariable.commit();
|
||||
@@ -136,14 +137,13 @@ public class CallExpressionResolver {
|
||||
}
|
||||
}
|
||||
|
||||
QualifierReceiver qualifier = QualifierKt.createQualifier(nameExpression, receiver, context);
|
||||
if (qualifier != null) {
|
||||
result[0] = true;
|
||||
if (!isLHSOfDot) {
|
||||
QualifiedExpressionResolveUtilKt.resolveAsStandaloneExpression(qualifier, context, symbolUsageValidator);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
//// Generate some diagnostics for qualifier in unexpected position
|
||||
//DeclarationDescriptor qualifierDescriptor =
|
||||
// QualifiedExpressionResolveUtilKt.getQualifierDescriptorOrNull(nameExpression, receiver, context);
|
||||
//if (qualifierDescriptor != null) {
|
||||
// QualifiedExpressionResolveUtilKt.checkQualifierAsStandaloneExpression(qualifierDescriptor, nameExpression, context);
|
||||
//}
|
||||
|
||||
temporaryForVariable.commit();
|
||||
result[0] = !resolutionResult.isNothing();
|
||||
return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
|
||||
@@ -191,6 +191,15 @@ public class CallExpressionResolver {
|
||||
return TypeInfoFactoryKt.createTypeInfo(type, context);
|
||||
}
|
||||
|
||||
TemporaryTraceAndCache temporaryForQualifier = TemporaryTraceAndCache.create(context, "trace to resolve as qualifier", nameExpression);
|
||||
ExpressionTypingContext contextForQualifier = context.replaceTraceAndCache(temporaryForQualifier);
|
||||
Qualifier qualifier = qualifiedExpressionResolver.resolveNameExpressionAsQualifierForDiagnostics(nameExpression, receiver, contextForQualifier);
|
||||
if (qualifier != null) {
|
||||
QualifiedExpressionResolveUtilKt.resolveQualifierAsStandaloneExpression(qualifier, contextForQualifier, symbolUsageValidator);
|
||||
temporaryForQualifier.commit();
|
||||
return TypeInfoFactoryKt.createTypeInfo(null, context);
|
||||
}
|
||||
|
||||
temporaryForVariable.commit();
|
||||
return TypeInfoFactoryKt.noTypeInfo(context);
|
||||
}
|
||||
@@ -350,7 +359,9 @@ public class CallExpressionResolver {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !resolutionResult.isNothing();
|
||||
OverloadResolutionResults.Code resultCode = resolutionResult.getResultCode();
|
||||
return resultCode != OverloadResolutionResults.Code.NAME_NOT_FOUND &&
|
||||
resultCode != OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
|
||||
}
|
||||
};
|
||||
List<CallExpressionElement> elementChain =
|
||||
@@ -462,7 +473,7 @@ public class CallExpressionResolver {
|
||||
calleeExpression instanceof KtReferenceExpression
|
||||
? context.trace.get(BindingContext.REFERENCE_TARGET, (KtReferenceExpression) calleeExpression) : null;
|
||||
|
||||
QualifiedExpressionResolveUtilKt.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor, symbolUsageValidator);
|
||||
QualifiedExpressionResolveUtilKt.resolveQualifierAsReceiverInExpression(qualifierReceiver, selectorDescriptor, context, symbolUsageValidator);
|
||||
}
|
||||
|
||||
private static void checkNestedClassAccess(
|
||||
|
||||
+15
-4
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tasks.collectors
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -33,6 +34,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.*
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
public interface CallableDescriptorCollector<D : CallableDescriptor> {
|
||||
|
||||
@@ -165,7 +167,10 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
|
||||
|
||||
private object VariableCollector : CallableDescriptorCollector<VariableDescriptor> {
|
||||
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
return listOfNotNull(lexicalScope.findLocalVariable(name))
|
||||
val result = SmartList<VariableDescriptor>()
|
||||
result.addIfNotNull(lexicalScope.findLocalVariable(name))
|
||||
result.addIfNotNull(getContributedFakeDescriptorForObject(lexicalScope, name, location))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getStaticInheritanceByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
@@ -179,7 +184,13 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFakeDescriptorForObject(scope: HierarchicalScope, name: Name, location: LookupLocation): VariableDescriptor? {
|
||||
private fun getContributedFakeDescriptorForObject(scope: LexicalScope, name: Name, location: LookupLocation): VariableDescriptor? {
|
||||
val classifier = scope.getContributedClassifier(name, location)
|
||||
if (classifier !is ClassDescriptor || !classifier.hasClassObjectType) return null
|
||||
return FakeCallableDescriptorForObject(classifier)
|
||||
}
|
||||
|
||||
private fun findFakeDescriptorForObject(scope: HierarchicalScope, name: Name, location: LookupLocation): VariableDescriptor? {
|
||||
val classifier = scope.findClassifier(name, location)
|
||||
if (classifier !is ClassDescriptor || !classifier.hasCompanionObject) return null
|
||||
|
||||
@@ -188,14 +199,14 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
|
||||
|
||||
override fun getNonExtensionsByName(scope: HierarchicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
val properties = scope.collectVariables(name, location).filter { it.extensionReceiverParameter == null }
|
||||
val fakeDescriptor = getFakeDescriptorForObject(scope, name, location)
|
||||
val fakeDescriptor = findFakeDescriptorForObject(scope, name, location)
|
||||
return if (fakeDescriptor != null) properties + fakeDescriptor else properties
|
||||
}
|
||||
|
||||
override fun getMembersByName(receiver: KotlinType, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
val memberScope = receiver.memberScope
|
||||
val properties = memberScope.getContributedVariables(name, location)
|
||||
val fakeDescriptor = getFakeDescriptorForObject(memberScope.memberScopeAsImportingScope(), name, location)
|
||||
val fakeDescriptor = findFakeDescriptorForObject(memberScope.memberScopeAsImportingScope(), name, location)
|
||||
return if (fakeDescriptor != null) properties + fakeDescriptor else properties
|
||||
}
|
||||
|
||||
|
||||
@@ -149,39 +149,6 @@ class ClassQualifier(
|
||||
override fun toString() = "Class{$classifier}"
|
||||
}
|
||||
|
||||
fun createQualifier(expression: KtSimpleNameExpression, receiver: Receiver, context: ExpressionTypingContext): QualifierReceiver? {
|
||||
val receiverScope = when {
|
||||
!receiver.exists() -> context.scope
|
||||
receiver is QualifierReceiver -> receiver.scope.memberScopeAsImportingScope()
|
||||
receiver is ReceiverValue -> receiver.type.memberScope.memberScopeAsImportingScope()
|
||||
else -> throw IllegalArgumentException("Unexpected receiver kind: $receiver")
|
||||
}
|
||||
|
||||
val name = expression.getReferencedNameAsName()
|
||||
val packageViewDescriptor = receiverScope.findPackage(name)
|
||||
val classifierDescriptor = receiverScope.findClassifier(name, KotlinLookupLocation(expression))
|
||||
|
||||
if (packageViewDescriptor == null && classifierDescriptor == null) return null
|
||||
|
||||
context.trace.recordScope(context.scope, expression)
|
||||
|
||||
val qualifier =
|
||||
if (receiver is PackageQualifier) {
|
||||
if (packageViewDescriptor != null)
|
||||
PackageQualifier(expression, packageViewDescriptor)
|
||||
else
|
||||
createClassifierQualifier(expression, classifierDescriptor!!, context.trace.bindingContext)
|
||||
else
|
||||
if (classifierDescriptor != null)
|
||||
createClassifierQualifier(expression, classifierDescriptor, context.trace.bindingContext)
|
||||
else
|
||||
PackageQualifier(expression, packageViewDescriptor!!)
|
||||
}
|
||||
|
||||
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
|
||||
return qualifier
|
||||
}
|
||||
|
||||
fun createClassifierQualifier(
|
||||
referenceExpression: KtSimpleNameExpression,
|
||||
classifier: ClassifierDescriptor,
|
||||
|
||||
Reference in New Issue
Block a user