Moved method checkIsExtensionCallable from ExpressionTypingUtils to TipsManager (converting it to Kottlin)
This commit is contained in:
+7
-79
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -34,14 +33,8 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
@@ -50,13 +43,18 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory;
|
||||
@@ -188,76 +186,6 @@ public class ExpressionTypingUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if receiver declaration could be resolved to call expected receiver.
|
||||
*/
|
||||
public static boolean checkIsExtensionCallable (
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull CallableDescriptor callableDescriptor,
|
||||
boolean isInfixCall,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull DataFlowInfo dataFlowInfo
|
||||
) {
|
||||
if (isInfixCall
|
||||
&& (!(callableDescriptor instanceof SimpleFunctionDescriptor) || callableDescriptor.getValueParameters().size() != 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<JetType> types = SmartCastUtils.getSmartCastVariants(receiverArgument, bindingContext, dataFlowInfo);
|
||||
|
||||
for (JetType type : types) {
|
||||
if (checkReceiverResolution(receiverArgument, type, callableDescriptor)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkReceiverResolution (
|
||||
@NotNull ReceiverValue receiverArgument,
|
||||
@NotNull JetType receiverType,
|
||||
@NotNull CallableDescriptor callableDescriptor
|
||||
) {
|
||||
ReceiverParameterDescriptor receiverParameter = callableDescriptor.getExtensionReceiverParameter();
|
||||
|
||||
if (!receiverArgument.exists() && receiverParameter == null) {
|
||||
// Both receivers do not exist
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(receiverArgument.exists() && receiverParameter != null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<Name> typeNamesInReceiver = collectUsedTypeNames(receiverParameter.getType());
|
||||
|
||||
ConstraintSystem constraintSystem = new ConstraintSystemImpl();
|
||||
Map<TypeParameterDescriptor, Variance> typeVariables = Maps.newLinkedHashMap();
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : callableDescriptor.getTypeParameters()) {
|
||||
if (typeNamesInReceiver.contains(typeParameterDescriptor.getName())) {
|
||||
typeVariables.put(typeParameterDescriptor, Variance.INVARIANT);
|
||||
}
|
||||
}
|
||||
constraintSystem.registerTypeVariables(typeVariables);
|
||||
|
||||
constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
|
||||
return constraintSystem.getStatus().isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, true);
|
||||
}
|
||||
|
||||
private static Set<Name> collectUsedTypeNames(@NotNull JetType jetType) {
|
||||
Set<Name> typeNames = new HashSet<Name>();
|
||||
|
||||
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor != null) {
|
||||
typeNames.add(descriptor.getName());
|
||||
}
|
||||
|
||||
for (TypeProjection argument : jetType.getArguments()) {
|
||||
typeNames.addAll(collectUsedTypeNames(argument.getType()));
|
||||
}
|
||||
|
||||
return typeNames;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveFakeCall(
|
||||
@NotNull ExpressionTypingContext context,
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.resolve.*
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.util.HashSet
|
||||
@@ -36,7 +35,7 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver.LookupMode
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
import org.jetbrains.jet.plugin.codeInsight.TipsManager
|
||||
|
||||
public class KotlinIndicesHelper(private val project: Project,
|
||||
private val resolveSession: ResolveSessionForBodies,
|
||||
@@ -213,7 +212,7 @@ public class KotlinIndicesHelper(private val project: Project,
|
||||
}
|
||||
|
||||
return descriptors.filter { visibilityFilter(it) &&
|
||||
ExpressionTypingUtils.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) }
|
||||
TipsManager.checkIsExtensionCallable(receiverValue, it, isInfixCall, bindingContext, dataFlowInfo) }
|
||||
}
|
||||
|
||||
public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils
|
||||
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
|
||||
|
||||
import java.util.*
|
||||
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
|
||||
@@ -33,6 +32,12 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.jet.lang.resolve.scopes.getDescriptorsFiltered
|
||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindExclude
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl
|
||||
import com.google.dart.compiler.util.Maps
|
||||
import org.jetbrains.jet.lang.types.Variance
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil
|
||||
|
||||
public object TipsManager{
|
||||
|
||||
@@ -148,7 +153,7 @@ public object TipsManager{
|
||||
resolutionScope.getDescriptorsFiltered(kindFilter, nameFilter)
|
||||
.stream()
|
||||
.filterIsInstance(javaClass<CallableDescriptor>())
|
||||
.filterTo(this) { ExpressionTypingUtils.checkIsExtensionCallable(receiver, it, isInfixCall, context, dataFlowInfo) }
|
||||
.filterTo(this) { checkIsExtensionCallable(receiver, it, isInfixCall, context, dataFlowInfo) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +161,7 @@ public object TipsManager{
|
||||
context: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
isInfixCall: Boolean): Boolean
|
||||
= receivers.any { ExpressionTypingUtils.checkIsExtensionCallable(it, this, isInfixCall, context, dataFlowInfo) }
|
||||
= receivers.any { checkIsExtensionCallable(it, this, isInfixCall, context, dataFlowInfo) }
|
||||
|
||||
public fun CallableDescriptor.isExtensionCallableWithImplicitReceiver(scope: JetScope, context: BindingContext, dataFlowInfo: DataFlowInfo): Boolean
|
||||
= isExtensionCallable(scope.getImplicitReceiversHierarchy().map { it.getValue() }, context, dataFlowInfo, false)
|
||||
@@ -167,4 +172,69 @@ public object TipsManager{
|
||||
val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf()
|
||||
return resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.PACKAGES, nameFilter)
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if receiver declaration could be resolved to call expected receiver.
|
||||
*/
|
||||
public fun checkIsExtensionCallable(
|
||||
receiverArgument: ReceiverValue,
|
||||
callableDescriptor: CallableDescriptor,
|
||||
isInfixCall: Boolean,
|
||||
bindingContext: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
): Boolean {
|
||||
if (isInfixCall && (callableDescriptor !is SimpleFunctionDescriptor || callableDescriptor.getValueParameters().size() != 1)) {
|
||||
return false
|
||||
}
|
||||
|
||||
val types = SmartCastUtils.getSmartCastVariants(receiverArgument, bindingContext, dataFlowInfo)
|
||||
|
||||
for (type in types) {
|
||||
if (checkReceiverResolution(receiverArgument, type, callableDescriptor)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun checkReceiverResolution(receiverArgument: ReceiverValue, receiverType: JetType, callableDescriptor: CallableDescriptor): Boolean {
|
||||
val receiverParameter = callableDescriptor.getExtensionReceiverParameter()
|
||||
|
||||
if (!receiverArgument.exists() && receiverParameter == null) {
|
||||
// Both receivers do not exist
|
||||
return true
|
||||
}
|
||||
|
||||
if (!(receiverArgument.exists() && receiverParameter != null)) {
|
||||
return false
|
||||
}
|
||||
|
||||
val typeNamesInReceiver = collectUsedTypeNames(receiverParameter.getType())
|
||||
|
||||
val constraintSystem = ConstraintSystemImpl()
|
||||
val typeVariables = LinkedHashMap<TypeParameterDescriptor, Variance>()
|
||||
for (typeParameterDescriptor in callableDescriptor.getTypeParameters()) {
|
||||
if (typeNamesInReceiver.contains(typeParameterDescriptor.getName())) {
|
||||
typeVariables.put(typeParameterDescriptor, Variance.INVARIANT)
|
||||
}
|
||||
}
|
||||
constraintSystem.registerTypeVariables(typeVariables)
|
||||
|
||||
constraintSystem.addSubtypeConstraint(receiverType, receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION)
|
||||
return constraintSystem.getStatus().isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, true)
|
||||
}
|
||||
|
||||
private fun collectUsedTypeNames(jetType: JetType): Set<Name> {
|
||||
val typeNames = HashSet<Name>()
|
||||
|
||||
val descriptor = jetType.getConstructor().getDeclarationDescriptor()
|
||||
if (descriptor != null) {
|
||||
typeNames.add(descriptor.getName())
|
||||
}
|
||||
|
||||
for (argument in jetType.getArguments()) {
|
||||
typeNames.addAll(collectUsedTypeNames(argument.getType()))
|
||||
}
|
||||
|
||||
return typeNames
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user