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.diagnostics.Errors
import org.jetbrains.kotlin.resolve.descriptorUtil.classObjectType
import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.companionObjectType
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassifierQualifier
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
if (qualifier is ClassQualifier) {
val classifier = qualifier.classifier
if (selector is CallableDescriptor &&
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null) &&
classifier is ClassDescriptor &&
classifier.hasClassObjectType
) {
val companionObjectDescriptor = classifier.companionObjectDescriptor
if (companionObjectDescriptor != null) {
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, companionObjectDescriptor)
val selectorIsCallable = selector is CallableDescriptor &&
(selector.dispatchReceiverParameter != null || selector.extensionReceiverParameter != null)
val referenceTarget = classifier.classValueDescriptor
if (selectorIsCallable && referenceTarget != null) {
val classObjectType = classifier.companionObjectType!!
val classObjectDescriptor = DescriptorUtils.getClassDescriptorForType(classObjectType)
context.trace.record(BindingContext.REFERENCE_TARGET, qualifier.referenceExpression, referenceTarget)
context.trace.recordType(qualifier.expression, classObjectType)
if (classifier.companionObjectDescriptor != null) {
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
symbolUsageValidator.validateTypeUsage(referenceTarget, context.trace, qualifier.referenceExpression)
}
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();
result[0] = !resolutionResult.isNothing();
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> {
val result = SmartList<VariableDescriptor>()
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))
return result
}
@@ -186,7 +187,7 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
private fun getContributedFakeDescriptorForObject(scope: LexicalScope, name: Name, location: LookupLocation): VariableDescriptor? {
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)
}
@@ -99,15 +99,15 @@ public class TaskPrioritizer(
taskPrioritizerContext: TaskPrioritizerContext<D, F>
) {
if (qualifier is ClassQualifier) {
val companionObject = qualifierReceiver.companionObjectReceiver ?: return
val classifierDescriptor = qualifierReceiver.classifier
val companionObject = qualifier.companionObjectReceiver ?: return
val classifierDescriptor = qualifier.classifier
doComputeTasks(companionObject, taskPrioritizerContext.filterCollectors {
when {
classifierDescriptor is ClassDescriptor && classifierDescriptor.getCompanionObjectDescriptor() != null -> {
// nested classes and objects should not be accessible via short reference to companion object
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
it !is FakeCallableDescriptorForObject
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.scopes.receivers
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression
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.JetScopeUtils
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 java.util.*
@@ -78,9 +73,6 @@ class PackageQualifier(
override fun getNestedClassesAndPackageMembersScope(): MemberScope = packageView.memberScope
override fun toString() = "Package{$packageView}"
override val companionObjectReceiver: ReceiverValue?
get() = null
}
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())
}
fun getClassObjectReceiver(): ReceiverValue =
classifier.classObjectType?.let { ExpressionReceiver(referenceExpression, it) } ?: ReceiverValue.NO_RECEIVER
override fun toString() = "Class{$classifier}"
}
@@ -157,5 +146,8 @@ fun createClassifierQualifier(
val companionObjectReceiver = (classifier as? ClassDescriptor)?.companionObjectType?.let {
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.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 */
public val ClassDescriptor.companionObjectType: KotlinType?
get() {
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()
}
get() = classValueTypeDescriptor?.getDefaultType()
public val DeclarationDescriptorWithVisibility.isEffectivelyPublicApi: Boolean
get() {
@@ -28,9 +28,11 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
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.scopes.DescriptorKindExclude
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.types.KotlinType
import org.jetbrains.kotlin.util.supertypesWithAny
@@ -247,8 +249,13 @@ public fun CallTypeAndReceiver<*, *>.receiverTypes(
}
val receiverValues = if (receiverExpression != null) {
val expressionType = bindingContext.getType(receiverExpression)
expressionType?.let { listOf(ExpressionReceiver.create(receiverExpression, expressionType, bindingContext)) } ?: return emptyList()
val receiverType =
bindingContext.getType(receiverExpression) ?:
(bindingContext.get(BindingContext.QUALIFIER, receiverExpression) as? ClassQualifier)?.let {
it.classifier.companionObjectType
} ?:
return emptyList()
listOf(ExpressionReceiver.create(receiverExpression, receiverType, bindingContext))
}
else {
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.getResolvedCall
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.Qualifier
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
@@ -111,11 +112,15 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
receiver is Qualifier -> {
val qualifierType = context.getType(receiver.expression)
if (qualifierType != null) return TypeInfo(qualifierType, Variance.IN_VARIANCE)
if (receiver !is ClassQualifier) return null
val classifier = receiver.classifier as? JavaClassDescriptor ?: return null
val javaClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classifier) as? PsiClass
val classifierType = receiver.classifier.companionObjectType
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
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)
else -> throw AssertionError("Unexpected receiver: $receiver")