Refactoring: extracted interface Qualifier (that is not a ReceiverValue)
This commit is contained in:
@@ -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);
|
||||
|
||||
+7
-10
@@ -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 :
|
||||
|
||||
+46
-21
@@ -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(
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user