Refactoring: extracted interface Qualifier (that is not a ReceiverValue)

This commit is contained in:
Svetlana Isakova
2014-08-23 11:18:22 +04:00
parent bc3f6e200a
commit 4e8f10b8ab
6 changed files with 68 additions and 52 deletions
@@ -34,7 +34,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.Qualifier;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.CaptureKind;
@@ -85,7 +85,10 @@ public interface BindingContext {
WritableSlice<JetExpression, DataFlowInfo> EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice<JetExpression, DataFlowInfo>(DO_NOTHING);
WritableSlice<JetExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
WritableSlice<JetExpression, QualifierReceiver> QUALIFIER_RECEIVER = new BasicWritableSlice<JetExpression, QualifierReceiver>(DO_NOTHING);
/**
* A qualifier corresponds to a receiver expression (if any). For 'A.B' qualifier is recorded for 'A'.
*/
WritableSlice<JetExpression, Qualifier> QUALIFIER = new BasicWritableSlice<JetExpression, Qualifier>(DO_NOTHING);
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
@@ -39,10 +39,7 @@ import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiversPackage;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
@@ -115,11 +112,11 @@ public class CallExpressionResolver {
}
}
QualifierReceiver qualifierReceiver = createQualifierReceiver(nameExpression, receiver, context);
if (qualifierReceiver != null) {
QualifierReceiver qualifier = createQualifier(nameExpression, receiver, context);
if (qualifier != null) {
result[0] = true;
if (!isLHSOfDot) {
resolveAsStandaloneExpression(qualifierReceiver, context);
resolveAsStandaloneExpression(qualifier, context);
}
return null;
}
@@ -286,7 +283,7 @@ public class CallExpressionResolver {
ResolutionContext contextForReceiver = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(receiverExpression, contextForReceiver);
JetType receiverType = receiverTypeInfo.getType();
QualifierReceiver qualifierReceiver = context.trace.get(BindingContext.QUALIFIER_RECEIVER, receiverExpression);
QualifierReceiver qualifierReceiver = (QualifierReceiver) context.trace.get(BindingContext.QUALIFIER, receiverExpression);
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
@@ -350,8 +347,8 @@ public class CallExpressionResolver {
// A.B - if B is a nested class accessed by outer class, 'A' and 'A.B' were marked as qualifiers
// a.B - if B is a nested class accessed by instance reference, 'a.B' was marked as a qualifier, but 'a' was not (it's an expression)
QualifierReceiver expressionQualifier = context.trace.get(BindingContext.QUALIFIER_RECEIVER, expression);
QualifierReceiver receiverQualifier = context.trace.get(BindingContext.QUALIFIER_RECEIVER, expression.getReceiverExpression());
Qualifier expressionQualifier = context.trace.get(BindingContext.QUALIFIER, expression);
Qualifier receiverQualifier = context.trace.get(BindingContext.QUALIFIER, expression.getReceiverExpression());
if (receiverQualifier == null && expressionQualifier != null) {
assert expressionQualifier.getClassifier() instanceof ClassDescriptor :
@@ -38,27 +38,47 @@ import org.jetbrains.jet.lang.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext
import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector
import org.jetbrains.jet.lang.resolve.descriptorUtil.getClassObjectReferenceTarget
import org.jetbrains.jet.lang.psi.JetExpression
import kotlin.properties.Delegates
public class QualifierReceiver(
val expression: JetSimpleNameExpression,
val packageView: PackageViewDescriptor?,
val classifier: ClassifierDescriptor?
) : ReceiverValue {
public trait Qualifier {
val expression: JetExpression
val packageView: PackageViewDescriptor?
val classifier: ClassifierDescriptor?
val name: Name
get() = classifier?.getName() ?: packageView!!.getName()
fun getClassObjectReceiver(): ReceiverValue =
classifier?.getClassObjectType()?.let { ExpressionReceiver(expression, it) } ?: ReceiverValue.NO_RECEIVER
// package, classifier or class object descriptor
val resultingDescriptor: DeclarationDescriptor
val scope: JetScope
}
class QualifierReceiver (
val referenceExpression: JetSimpleNameExpression,
override val packageView: PackageViewDescriptor?,
override val classifier: ClassifierDescriptor?
) : Qualifier, ReceiverValue {
override val expression: JetExpression = referenceExpression.getTopmostParentQualifiedExpressionForSelector() ?: referenceExpression
val descriptor: DeclarationDescriptor
get() = classifier ?: packageView ?: throw AssertionError("PackageView and classifier both are null")
fun getScope(): JetScope {
override var resultingDescriptor: DeclarationDescriptor by Delegates.notNull()
override val scope: JetScope get() {
val scopes = listOf(classifier?.getClassObjectType()?.getMemberScope(), getNestedClassesAndPackageMembersScope()).filterNotNull().copyToArray()
return ChainedScope(descriptor, "Member scope for " + name + " as package or class or object", *scopes as Array<JetScope?>)
}
fun getClassObjectReceiver(): ReceiverValue =
classifier?.getClassObjectType()?.let { ExpressionReceiver(referenceExpression, it) } ?: ReceiverValue.NO_RECEIVER
fun getNestedClassesAndPackageMembersScope(): JetScope {
val scopes = ArrayList<JetScope>(3)
@@ -84,14 +104,14 @@ public class QualifierReceiver(
override fun toString() = "Package{$packageView} OR Class{$classifier}"
}
fun createQualifierReceiver(
fun createQualifier(
expression: JetSimpleNameExpression,
receiver: ReceiverValue,
context: ExpressionTypingContext
): QualifierReceiver? {
val receiverScope = when {
!receiver.exists() -> context.scope
receiver is QualifierReceiver -> receiver.getScope()
receiver is QualifierReceiver -> receiver.scope
else -> receiver.getType().getMemberScope()
}
@@ -106,36 +126,41 @@ fun createQualifierReceiver(
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, expression, context.dataFlowInfo)
}
val qualifierReceiver = QualifierReceiver(expression, packageViewDescriptor, classifierDescriptor)
context.trace.record(QUALIFIER_RECEIVER, expression.getTopmostParentQualifiedExpressionForSelector() ?: expression, qualifierReceiver)
return qualifierReceiver
val qualifier = QualifierReceiver(expression, packageViewDescriptor, classifierDescriptor)
context.trace.record(QUALIFIER, qualifier.expression, qualifier)
return qualifier
}
private fun QualifierReceiver.resolveAsStandaloneExpression(context: ExpressionTypingContext): JetType? {
context.trace.record(REFERENCE_TARGET, expression, resolveReferenceTarget(selector = null))
resolveAndRecordReferenceTarget(context, selector = null)
if (classifier is TypeParameterDescriptor) {
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, classifier))
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(referenceExpression, classifier))
}
else if (classifier is ClassDescriptor && classifier.getClassObjectType() == null) {
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier))
context.trace.report(NO_CLASS_OBJECT.on(referenceExpression, classifier))
}
else if (packageView != null) {
context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(expression))
context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(referenceExpression))
}
return null
}
private fun QualifierReceiver.resolveAsReceiverInQualifiedExpression(context: ExpressionTypingContext, selector: DeclarationDescriptor?) {
context.trace.record(REFERENCE_TARGET, expression, resolveReferenceTarget(selector))
resolveAndRecordReferenceTarget(context, selector)
if (classifier is TypeParameterDescriptor) {
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, classifier as TypeParameterDescriptor))
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(referenceExpression, classifier as TypeParameterDescriptor))
}
else if (classifier is ClassDescriptor && classifier.getClassObjectDescriptor() != null) {
checkClassObjectVisibility(context)
context.trace.record(EXPRESSION_TYPE, expression, classifier.getClassObjectType())
context.trace.record(EXPRESSION_TYPE, referenceExpression, classifier.getClassObjectType())
}
}
private fun QualifierReceiver.resolveAndRecordReferenceTarget(context: ExpressionTypingContext, selector: DeclarationDescriptor?) {
resultingDescriptor = resolveReferenceTarget(selector)
context.trace.record(REFERENCE_TARGET, referenceExpression, resultingDescriptor)
}
private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescriptor?): DeclarationDescriptor {
if (classifier is TypeParameterDescriptor) {
return classifier
@@ -168,7 +193,7 @@ private fun QualifierReceiver.checkClassObjectVisibility(context: ExpressionTypi
val classObject = classifier.getClassObjectDescriptor()
assert(classObject != null) { "This check should be done only for classes with class objects: " + classifier }
if (!Visibilities.isVisible(classObject!!, scopeContainer)) {
context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), scopeContainer))
context.trace.report(INVISIBLE_MEMBER.on(referenceExpression, classObject, classObject.getVisibility(), scopeContainer))
}
}
@@ -23,10 +23,7 @@ import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -35,7 +32,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.Qualifier;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
@@ -56,19 +53,18 @@ public final class TipsManager {
PsiElement parent = expression.getParent();
boolean inPositionForCompletionWithReceiver = parent instanceof JetCallExpression || parent instanceof JetQualifiedExpression;
if (receiverExpression != null && inPositionForCompletionWithReceiver) {
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
// Process as call expression
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
QualifierReceiver qualifierReceiver = context.get(BindingContext.QUALIFIER_RECEIVER, receiverExpression);
if (qualifierReceiver != null && resolutionScope != null) {
return includeExternalCallableExtensions(
excludePrivateDescriptors(qualifierReceiver.getScope().getAllDescriptors()),
resolutionScope, qualifierReceiver);
Qualifier qualifier = context.get(BindingContext.QUALIFIER, receiverExpression);
if (qualifier != null && resolutionScope != null) {
// It's impossible to add extension function for package or class (if it's class object, expression type is not null)
descriptors.addAll(new HashSet<DeclarationDescriptor>(excludePrivateDescriptors(qualifier.getScope().getAllDescriptors())));
}
JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
if (expressionType != null && resolutionScope != null && !expressionType.isError()) {
ExpressionReceiver receiverValue = new ExpressionReceiver(receiverExpression, expressionType);
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
DataFlowInfo info = context.get(BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW, expression);
if (info == null) {
@@ -83,9 +79,8 @@ public final class TipsManager {
resolutionScope, receiverValue));
}
return descriptors;
}
return Collections.emptyList();
return descriptors;
}
else {
return getVariantsNoReceiver(expression, context);
@@ -196,10 +191,6 @@ public final class TipsManager {
@NotNull JetScope externalScope,
@NotNull final ReceiverValue receiverValue
) {
// It's impossible to add extension function for package
if (receiverValue instanceof QualifierReceiver) {
return new HashSet<DeclarationDescriptor>(descriptors);
}
Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.addAll(
@@ -91,7 +91,7 @@ public open class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntent
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(parent)
val receiverType = bindingContext[BindingContext.EXPRESSION_TYPE, receiver]
if (receiverType == null) {
if (bindingContext[BindingContext.QUALIFIER_RECEIVER, receiver] != null) {
if (bindingContext[BindingContext.QUALIFIER, receiver] != null) {
intentionFailed(editor, "package.call")
return
}
@@ -139,7 +139,7 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase {
}
}
if (expressionType == null && bindingContext.get(BindingContext.QUALIFIER_RECEIVER, expression) != null) {
if (expressionType == null && bindingContext.get(BindingContext.QUALIFIER, expression) != null) {
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.package.expression"));
return;
}