Fixes for IDE tests after qualifier modifications:

- CallType should look into QUALIFIER,
 so that completion works for (companion) object qualifiers.
- Record type and reference target for object qualifiers (not only for companions).
- "Create (function/...)" should understand ClassQualifier as possible receiver.
- Cleanup after rebase on master.
This commit is contained in:
Dmitry Petrov
2015-11-16 19:29:24 +03:00
parent 9856af48ca
commit ba8372cc11
8 changed files with 55 additions and 54 deletions
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.resolve.descriptorUtil.classObjectType import org.jetbrains.kotlin.resolve.descriptorUtil.classValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType import org.jetbrains.kotlin.resolve.descriptorUtil.companionObjectType
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.PackageQualifier
@@ -94,19 +94,19 @@ 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 ClassQualifier) {
val classifier = qualifier.classifier val classifier = qualifier.classifier
if (selector is CallableDescriptor && val selectorIsCallable = selector is CallableDescriptor &&
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null) && (selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null)
classifier is ClassDescriptor && val referenceTarget = classifier.classValueDescriptor
classifier.hasClassObjectType if (selectorIsCallable && referenceTarget != null) {
) { val classObjectType = classifier.companionObjectType!!
val companionObjectDescriptor = classifier.companionObjectDescriptor val classObjectDescriptor = DescriptorUtils.getClassDescriptorForType(classObjectType)
if (companionObjectDescriptor != null) { context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, referenceTarget)
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, companionObjectDescriptor) context.trace.recordType(qualifier.expression, classObjectType)
if (classifier.companionObjectDescriptor != null) {
context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, classifier) context.trace.record(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, qualifier.referenceExpression, classifier)
context.trace.recordType(qualifier.expression, classifier.classObjectType) symbolUsageValidator.validateTypeUsage(referenceTarget, context.trace, qualifier.referenceExpression)
symbolUsageValidator.validateTypeUsage(companionObjectDescriptor, context.trace, qualifier.referenceExpression)
return companionObjectDescriptor
} }
return classObjectDescriptor
} }
} }
@@ -137,13 +137,6 @@ public class CallExpressionResolver {
} }
} }
//// 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(); temporaryForVariable.commit();
result[0] = !resolutionResult.isNothing(); result[0] = !resolutionResult.isNothing();
return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null; return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
@@ -169,6 +169,7 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> { override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection<VariableDescriptor> {
val result = SmartList<VariableDescriptor>() val result = SmartList<VariableDescriptor>()
result.addIfNotNull(lexicalScope.findLocalVariable(name)) result.addIfNotNull(lexicalScope.findLocalVariable(name))
// Although local objects are prohibited, we'll include objects declared in current scope so that their usages are still resolved.
result.addIfNotNull(getContributedFakeDescriptorForObject(lexicalScope, name, location)) result.addIfNotNull(getContributedFakeDescriptorForObject(lexicalScope, name, location))
return result return result
} }
@@ -186,7 +187,7 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
private fun getContributedFakeDescriptorForObject(scope: LexicalScope, name: Name, location: LookupLocation): VariableDescriptor? { private fun getContributedFakeDescriptorForObject(scope: LexicalScope, name: Name, location: LookupLocation): VariableDescriptor? {
val classifier = scope.getContributedClassifier(name, location) val classifier = scope.getContributedClassifier(name, location)
if (classifier !is ClassDescriptor || !classifier.hasClassObjectType) return null if (classifier !is ClassDescriptor || !classifier.hasCompanionObject) return null
return FakeCallableDescriptorForObject(classifier) return FakeCallableDescriptorForObject(classifier)
} }
@@ -99,15 +99,15 @@ public class TaskPrioritizer(
taskPrioritizerContext: TaskPrioritizerContext<D, F> taskPrioritizerContext: TaskPrioritizerContext<D, F>
) { ) {
if (qualifier is ClassQualifier) { if (qualifier is ClassQualifier) {
val companionObject = qualifierReceiver.companionObjectReceiver ?: return val companionObject = qualifier.companionObjectReceiver ?: return
val classifierDescriptor = qualifierReceiver.classifier val classifierDescriptor = qualifier.classifier
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors { doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
when { when {
classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> { classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> {
// nested classes and objects should not be accessible via short reference to companion object // nested classes and objects should not be accessible via short reference to companion object
it !is ConstructorDescriptor && it !is FakeCallableDescriptorForObject it !is ConstructorDescriptor && it !is FakeCallableDescriptorForObject
} }
classifierDescriptor != null && DescriptorUtils.isEnumEntry(classifierDescriptor) -> { DescriptorUtils.isEnumEntry(classifierDescriptor) -> {
// objects nested in enum should not be accessible via enum entries reference // objects nested in enum should not be accessible via enum entries reference
it !is FakeCallableDescriptorForObject it !is FakeCallableDescriptorForObject
} }
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.scopes.receivers package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression
@@ -32,10 +31,6 @@ import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.FilteringScope import org.jetbrains.kotlin.resolve.scopes.FilteringScope
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
import org.jetbrains.kotlin.resolve.scopes.utils.findPackage
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.* import java.util.*
@@ -78,9 +73,6 @@ class PackageQualifier(
override fun getNestedClassesAndPackageMembersScope(): MemberScope = packageView.memberScope override fun getNestedClassesAndPackageMembersScope(): MemberScope = packageView.memberScope
override fun toString() = "Package{$packageView}" override fun toString() = "Package{$packageView}"
override val companionObjectReceiver: ReceiverValue?
get() = null
} }
abstract class ClassifierQualifier(referenceExpression: KtSimpleNameExpression) : QualifierReceiver(referenceExpression) { abstract class ClassifierQualifier(referenceExpression: KtSimpleNameExpression) : QualifierReceiver(referenceExpression) {
@@ -143,9 +135,6 @@ class ClassQualifier(
return ChainedScope("Static scope for $name as class or object", *scopes.toTypedArray()) return ChainedScope("Static scope for $name as class or object", *scopes.toTypedArray())
} }
fun getClassObjectReceiver(): ReceiverValue =
classifier.classObjectType?.let { ExpressionReceiver(referenceExpression, it) } ?: ReceiverValue.NO_RECEIVER
override fun toString() = "Class{$classifier}" override fun toString() = "Class{$classifier}"
} }
@@ -157,5 +146,8 @@ fun createClassifierQualifier(
val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let { val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let {
ExpressionReceiver.create(referenceExpression, it, bindingContext) ExpressionReceiver.create(referenceExpression, it, bindingContext)
} }
return ClassQualifier(referenceExpression, classifier, companionObjectReceiver) return if (classifier is ClassDescriptor)
ClassQualifier(referenceExpression, classifier, companionObjectReceiver)
else
ClassifierQualifierWithEmptyScope(referenceExpression, classifier)
} }
@@ -73,21 +73,24 @@ public val ClassDescriptor.classId: ClassId
public val ClassDescriptor.hasCompanionObject: Boolean get() = companionObjectType != null public val ClassDescriptor.hasCompanionObject: Boolean get() = companionObjectType != null
public val ClassDescriptor.classValueDescriptor: ClassDescriptor?
get() = if (kind.isSingleton) this else companionObjectDescriptor
public val ClassDescriptor.classValueTypeDescriptor: ClassDescriptor?
get() = when (kind) {
OBJECT -> this
ENUM_ENTRY -> {
// enum entry has the type of enum class
val container = this.containingDeclaration
assert(container is ClassDescriptor && container.getKind() == ENUM_CLASS)
container as ClassDescriptor
}
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 */
public val ClassDescriptor.companionObjectType: KotlinType? public val ClassDescriptor.companionObjectType: KotlinType?
get() { get() = classValueTypeDescriptor?.getDefaultType()
val correspondingDescriptor = when (this.getKind()) {
OBJECT -> this
// enum entry has the type of enum class
ENUM_ENTRY -> {
val container = this.getContainingDeclaration()
assert(container is ClassDescriptor && container.getKind() == ENUM_CLASS)
container as ClassDescriptor
}
else -> getCompanionObjectDescriptor()
}
return correspondingDescriptor?.getDefaultType()
}
public val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean public val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean
get() { get() {
@@ -28,9 +28,11 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
import org.jetbrains.kotlin.resolve.descriptorUtil.companionObjectType
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.supertypesWithAny import org.jetbrains.kotlin.util.supertypesWithAny
@@ -247,8 +249,13 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
} }
val receiverValues = if (receiverExpression != null) { val receiverValues = if (receiverExpression != null) {
val expressionType = bindingContext.getType(receiverExpression) val receiverType =
expressionType?.let { listOf(ExpressionReceiver.create(receiverExpression, expressionType, bindingContext)) } ?: return emptyList() bindingContext.getType(receiverExpression) ?:
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? ClassQualifier)?.let {
it.classifier.companionObjectType
} ?:
return emptyList()
listOf(ExpressionReceiver.create(receiverExpression, receiverType, bindingContext))
} }
else { else {
val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade) val resolutionScope = contextElement.getResolutionScope(bindingContext, resolutionFacade)
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.companionObjectType
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier import org.jetbrains.kotlin.resolve.scopes.receivers.Qualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
@@ -111,11 +112,15 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
receiver is Qualifier -> { receiver is Qualifier -> {
val qualifierType = context.getType(receiver.expression) val qualifierType = context.getType(receiver.expression)
if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE) if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE)
if (receiver !is ClassQualifier) return null if (receiver !is ClassQualifier) return null
val classifier = receiver.classifier as? JavaClassDescriptor ?: return null val classifierType = receiver.classifier.companionObjectType
val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classifier) as? PsiClass if (classifierType != null) return TypeInfo(classifierType, Variance.IN_VARIANCE)
val javaClassifier = receiver.classifier as? JavaClassDescriptor ?: return null
val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, javaClassifier) as? PsiClass
if (javaClass == null || !javaClass.canRefactor()) return null if (javaClass == null || !javaClass.canRefactor()) return null
TypeInfo.StaticContextRequired(TypeInfo(classifier.defaultType, Variance.IN_VARIANCE)) TypeInfo.StaticContextRequired(TypeInfo(javaClassifier.defaultType, Variance.IN_VARIANCE))
} }
receiver is ReceiverValue -> TypeInfo(receiver.type, Variance.IN_VARIANCE) receiver is ReceiverValue -> TypeInfo(receiver.type, Variance.IN_VARIANCE)
else -> throw AssertionError("Unexpected receiver: $receiver") else -> throw AssertionError("Unexpected receiver: $receiver")