Smart completion: support for overloaded method calls
This commit is contained in:
@@ -21,21 +21,21 @@ import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingComponents;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.context.GlobalContext;
|
||||
import org.jetbrains.jet.storage.StorageManager;
|
||||
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.TypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.DelegatedPropertyResolver;
|
||||
import org.jetbrains.jet.lang.resolve.TypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolverExtensionProvider;
|
||||
import org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
||||
import org.jetbrains.jet.lang.types.expressions.ForLoopConventionsChecker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CandidateResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
@@ -48,21 +48,21 @@ public class InjectorForMacros {
|
||||
private final PlatformToKotlinClassMap platformToKotlinClassMap;
|
||||
private final ExpressionTypingServices expressionTypingServices;
|
||||
private final ExpressionTypingComponents expressionTypingComponents;
|
||||
private final CallResolver callResolver;
|
||||
private final GlobalContext globalContext;
|
||||
private final StorageManager storageManager;
|
||||
private final AnnotationResolver annotationResolver;
|
||||
private final CallResolver callResolver;
|
||||
private final ArgumentTypeResolver argumentTypeResolver;
|
||||
private final TypeResolver typeResolver;
|
||||
private final QualifiedExpressionResolver qualifiedExpressionResolver;
|
||||
private final CandidateResolver candidateResolver;
|
||||
private final CallExpressionResolver callExpressionResolver;
|
||||
private final DescriptorResolver descriptorResolver;
|
||||
private final DelegatedPropertyResolver delegatedPropertyResolver;
|
||||
private final TypeResolver typeResolver;
|
||||
private final QualifiedExpressionResolver qualifiedExpressionResolver;
|
||||
private final CallResolverExtensionProvider callResolverExtensionProvider;
|
||||
private final ControlStructureTypingUtils controlStructureTypingUtils;
|
||||
private final ExpressionTypingUtils expressionTypingUtils;
|
||||
private final ForLoopConventionsChecker forLoopConventionsChecker;
|
||||
private final ArgumentTypeResolver argumentTypeResolver;
|
||||
private final CandidateResolver candidateResolver;
|
||||
|
||||
public InjectorForMacros(
|
||||
@NotNull Project project,
|
||||
@@ -73,21 +73,21 @@ public class InjectorForMacros {
|
||||
this.platformToKotlinClassMap = moduleDescriptor.getPlatformToKotlinClassMap();
|
||||
this.expressionTypingComponents = new ExpressionTypingComponents();
|
||||
this.expressionTypingServices = new ExpressionTypingServices(getExpressionTypingComponents());
|
||||
this.callResolver = new CallResolver();
|
||||
this.globalContext = org.jetbrains.jet.context.ContextPackage.GlobalContext();
|
||||
this.storageManager = globalContext.getStorageManager();
|
||||
this.annotationResolver = new AnnotationResolver();
|
||||
this.callResolver = new CallResolver();
|
||||
this.argumentTypeResolver = new ArgumentTypeResolver();
|
||||
this.typeResolver = new TypeResolver();
|
||||
this.qualifiedExpressionResolver = new QualifiedExpressionResolver();
|
||||
this.candidateResolver = new CandidateResolver();
|
||||
this.callExpressionResolver = new CallExpressionResolver();
|
||||
this.descriptorResolver = new DescriptorResolver();
|
||||
this.delegatedPropertyResolver = new DelegatedPropertyResolver();
|
||||
this.typeResolver = new TypeResolver();
|
||||
this.qualifiedExpressionResolver = new QualifiedExpressionResolver();
|
||||
this.callResolverExtensionProvider = new CallResolverExtensionProvider();
|
||||
this.controlStructureTypingUtils = new ControlStructureTypingUtils(getExpressionTypingServices());
|
||||
this.expressionTypingUtils = new ExpressionTypingUtils(getExpressionTypingServices(), callResolver);
|
||||
this.expressionTypingUtils = new ExpressionTypingUtils(getExpressionTypingServices(), getCallResolver());
|
||||
this.forLoopConventionsChecker = new ForLoopConventionsChecker();
|
||||
this.argumentTypeResolver = new ArgumentTypeResolver();
|
||||
this.candidateResolver = new CandidateResolver();
|
||||
|
||||
this.expressionTypingServices.setAnnotationResolver(annotationResolver);
|
||||
this.expressionTypingServices.setCallExpressionResolver(callExpressionResolver);
|
||||
@@ -105,24 +105,15 @@ public class InjectorForMacros {
|
||||
this.expressionTypingComponents.setGlobalContext(globalContext);
|
||||
this.expressionTypingComponents.setPlatformToKotlinClassMap(platformToKotlinClassMap);
|
||||
|
||||
this.callResolver.setArgumentTypeResolver(argumentTypeResolver);
|
||||
this.callResolver.setCandidateResolver(candidateResolver);
|
||||
this.callResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
this.callResolver.setTypeResolver(typeResolver);
|
||||
|
||||
annotationResolver.setCallResolver(callResolver);
|
||||
annotationResolver.setStorageManager(storageManager);
|
||||
annotationResolver.setTypeResolver(typeResolver);
|
||||
|
||||
callResolver.setArgumentTypeResolver(argumentTypeResolver);
|
||||
callResolver.setCandidateResolver(candidateResolver);
|
||||
callResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
callResolver.setTypeResolver(typeResolver);
|
||||
|
||||
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
argumentTypeResolver.setTypeResolver(typeResolver);
|
||||
|
||||
typeResolver.setAnnotationResolver(annotationResolver);
|
||||
typeResolver.setModuleDescriptor(moduleDescriptor);
|
||||
typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
|
||||
|
||||
candidateResolver.setArgumentTypeResolver(argumentTypeResolver);
|
||||
|
||||
callExpressionResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
|
||||
descriptorResolver.setAnnotationResolver(annotationResolver);
|
||||
@@ -134,10 +125,19 @@ public class InjectorForMacros {
|
||||
delegatedPropertyResolver.setCallResolver(callResolver);
|
||||
delegatedPropertyResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
|
||||
typeResolver.setAnnotationResolver(annotationResolver);
|
||||
typeResolver.setModuleDescriptor(moduleDescriptor);
|
||||
typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver);
|
||||
|
||||
forLoopConventionsChecker.setExpressionTypingServices(expressionTypingServices);
|
||||
forLoopConventionsChecker.setExpressionTypingUtils(expressionTypingUtils);
|
||||
forLoopConventionsChecker.setProject(project);
|
||||
|
||||
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
|
||||
argumentTypeResolver.setTypeResolver(typeResolver);
|
||||
|
||||
candidateResolver.setArgumentTypeResolver(argumentTypeResolver);
|
||||
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@@ -152,4 +152,8 @@ public class InjectorForMacros {
|
||||
return this.expressionTypingComponents;
|
||||
}
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
return this.callResolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.psi.Call.CallType;
|
||||
|
||||
@@ -159,12 +161,14 @@ public class CallMaker {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
|
||||
@Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
|
||||
@NotNull List<JetExpression> argumentExpressions) {
|
||||
return makeCallWithExpressions(callElement, explicitReceiver, callOperationNode, calleeExpression, argumentExpressions, CallType.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver,
|
||||
@Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression,
|
||||
@NotNull List<JetExpression> argumentExpressions, @NotNull CallType callType) {
|
||||
@@ -175,23 +179,28 @@ public class CallMaker {
|
||||
return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, JetExpression calleeExpression, List<? extends ValueArgument> arguments) {
|
||||
return makeCall(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, CallType.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(JetElement callElement, ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode,
|
||||
JetExpression calleeExpression, List<? extends ValueArgument> arguments, CallType callType) {
|
||||
return new CallImpl(callElement, explicitReceiver, callOperationNode, calleeExpression, arguments, callType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(@NotNull ReceiverValue leftAsReceiver, JetBinaryExpression expression) {
|
||||
return makeCallWithExpressions(expression, leftAsReceiver, null, expression.getOperationReference(), Collections.singletonList(expression.getRight()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(@NotNull ReceiverValue baseAsReceiver, JetUnaryExpression expression) {
|
||||
return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.<ValueArgument>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeArraySetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
|
||||
@NotNull JetExpression rightHandSide, @NotNull CallType callType) {
|
||||
List<JetExpression> arguments = Lists.newArrayList(arrayAccessExpression.getIndexExpressions());
|
||||
@@ -199,23 +208,28 @@ public class CallMaker {
|
||||
return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arguments, callType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeArrayGetCall(@NotNull ReceiverValue arrayAsReceiver, @NotNull JetArrayAccessExpression arrayAccessExpression,
|
||||
@NotNull CallType callType) {
|
||||
return makeCallWithExpressions(arrayAccessExpression, arrayAsReceiver, null, arrayAccessExpression, arrayAccessExpression.getIndexExpressions(), callType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ValueArgument makeValueArgument(@NotNull JetExpression expression) {
|
||||
return makeValueArgument(expression, expression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ValueArgument makeValueArgument(@Nullable JetExpression expression, @NotNull PsiElement reportErrorsOn) {
|
||||
return new ExpressionValueArgument(expression, reportErrorsOn);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makePropertyCall(@NotNull ReceiverValue explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
|
||||
return makeCallWithExpressions(nameExpression, explicitReceiver, callOperationNode, nameExpression, Collections.<JetExpression>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(@NotNull final ReceiverValue explicitReceiver, @Nullable final ASTNode callOperationNode, @NotNull final JetCallElement callElement) {
|
||||
return new Call() {
|
||||
@Override
|
||||
@@ -290,6 +304,7 @@ public class CallMaker {
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Call makeCall(@NotNull JetElement callElement, @NotNull ReceiverValue explicitReceiver) {
|
||||
return new CallImpl(callElement, explicitReceiver, null, null, Collections.<ValueArgument>emptyList());
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
public interface KotlinCodeAnalyzer {
|
||||
@NotNull
|
||||
ModuleDescriptor getModuleDescriptor();
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.jetbrains.jet.di.*
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingComponents
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.jet.descriptors.serialization.descriptors.MemberFilter
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver
|
||||
|
||||
// NOTE: After making changes, you need to re-generate the injectors.
|
||||
// To do that, you can run main in this file.
|
||||
@@ -174,6 +175,7 @@ private fun generatorForMacro() =
|
||||
|
||||
publicField(javaClass<ExpressionTypingServices>())
|
||||
publicField(javaClass<ExpressionTypingComponents>())
|
||||
publicField(javaClass<CallResolver>())
|
||||
|
||||
field(javaClass<GlobalContext>(), useAsContext = true,
|
||||
init = GivenExpression("org.jetbrains.jet.context.ContextPackage.GlobalContext()"))
|
||||
|
||||
@@ -33,6 +33,18 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences
|
||||
import org.jetbrains.jet.utils.*
|
||||
import org.jetbrains.jet.di.InjectorForMacros
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode
|
||||
import org.jetbrains.jet.lang.resolve.calls.CompositeExtension
|
||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
|
||||
import com.intellij.lang.ASTNode
|
||||
|
||||
trait SmartCompletionData{
|
||||
fun accepts(descriptor: DeclarationDescriptor): Boolean
|
||||
@@ -53,17 +65,25 @@ fun buildSmartCompletionData(expression: JetSimpleNameExpression, resolveSession
|
||||
}
|
||||
|
||||
val bindingContext = resolveSession.resolveToElement(expressionWithType)
|
||||
val expectedType: JetType? = bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType)
|
||||
if (expectedType == null || expectedType.isError()) return null
|
||||
|
||||
val allExpectedTypes = calcExpectedTypes(expressionWithType, bindingContext, resolveSession.getModuleDescriptor()) ?: return null
|
||||
val expectedTypes = allExpectedTypes.filter { !it.isError() }
|
||||
if (expectedTypes.isEmpty()) return null
|
||||
|
||||
val itemsToSkip = calcItemsToSkip(expressionWithType, resolveSession)
|
||||
|
||||
val additionalElements = ArrayList<LookupElement>()
|
||||
|
||||
if (receiver == null) {
|
||||
typeInstantiationItems(expectedType, resolveSession, bindingContext).toCollection(additionalElements)
|
||||
thisItems(expressionWithType, expectedType, bindingContext).toCollection(additionalElements)
|
||||
staticMembers(expressionWithType, expectedType, resolveSession, bindingContext).toCollection(additionalElements)
|
||||
for (expectedType in expectedTypes) {
|
||||
//TODO: there can be duplicates here for multiple expected types
|
||||
typeInstantiationItems(expectedType, resolveSession, bindingContext).toCollection(additionalElements)
|
||||
|
||||
//TODO: there can be duplicates here for multiple expected types
|
||||
staticMembers(expressionWithType, expectedType, resolveSession, bindingContext).toCollection(additionalElements)
|
||||
}
|
||||
|
||||
thisItems(expressionWithType, expectedTypes, bindingContext).toCollection(additionalElements)
|
||||
}
|
||||
|
||||
val dataFlowInfo = bindingContext.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, expressionWithType)
|
||||
@@ -97,12 +117,74 @@ fun buildSmartCompletionData(expression: JetSimpleNameExpression, resolveSession
|
||||
|
||||
return object: SmartCompletionData {
|
||||
override fun accepts(descriptor: DeclarationDescriptor)
|
||||
= !itemsToSkip.contains(descriptor) && typesOf(descriptor).any { isSubtypeOf(it, expectedType) }
|
||||
= !itemsToSkip.contains(descriptor)
|
||||
&& typesOf(descriptor).any {
|
||||
descriptorType -> expectedTypes.any { expectedType -> isSubtypeOf(descriptorType, expectedType) }
|
||||
}
|
||||
|
||||
override val additionalElements = additionalElements
|
||||
}
|
||||
}
|
||||
|
||||
private fun calcExpectedTypes(expressionWithType: JetExpression, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor): Collection<JetType>? {
|
||||
val expectedTypes = calcArgumentExpectedTypes(expressionWithType, bindingContext, moduleDescriptor)
|
||||
if (expectedTypes != null) {
|
||||
return expectedTypes
|
||||
}
|
||||
else{
|
||||
val expectedType = bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType) ?: return null
|
||||
return listOf(expectedType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun calcArgumentExpectedTypes(expressionWithType: JetExpression, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor): Collection<JetType>? {
|
||||
val argument = expressionWithType.getParent() as? JetValueArgument ?: return null
|
||||
if (argument.isNamed()) return null //TODO - support named arguments (also do not forget to check for presence of named arguments before)
|
||||
val argumentList = argument.getParent() as JetValueArgumentList
|
||||
val argumentIndex = argumentList.getArguments().indexOf(argument)
|
||||
val callExpression = argumentList.getParent() as? JetCallExpression ?: return null
|
||||
val calleeExpression = callExpression.getCalleeExpression()
|
||||
|
||||
val parent = callExpression.getParent()
|
||||
val receiver: ReceiverValue
|
||||
val callOperationNode: ASTNode?
|
||||
if (parent is JetQualifiedExpression && callExpression == parent.getSelectorExpression()) {
|
||||
val receiverExpression = parent.getReceiverExpression()
|
||||
val expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, receiverExpression) ?: return null
|
||||
receiver = ExpressionReceiver(receiverExpression, expressionType)
|
||||
callOperationNode = parent.getOperationTokenNode()
|
||||
}
|
||||
else {
|
||||
receiver = ReceiverValue.NO_RECEIVER
|
||||
callOperationNode = null
|
||||
}
|
||||
val call = CallMaker.makeCall(receiver, callOperationNode, callExpression)
|
||||
|
||||
val resolutionScope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, calleeExpression) ?: return null //TODO: discuss it
|
||||
|
||||
val callResolutionContext = BasicCallResolutionContext.create(
|
||||
DelegatingBindingTrace(bindingContext, "Temporary trace for smart completion"),
|
||||
resolutionScope,
|
||||
call,
|
||||
bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, callExpression) ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||
bindingContext.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, callExpression) ?: DataFlowInfo.EMPTY,
|
||||
ContextDependency.INDEPENDENT,
|
||||
CheckValueArgumentsMode.ENABLED,
|
||||
CompositeExtension(listOf()),
|
||||
false).replaceCollectAllCandidates(true)
|
||||
val callResolver = InjectorForMacros(expressionWithType.getProject(), moduleDescriptor).getCallResolver()!!
|
||||
val results: OverloadResolutionResults<FunctionDescriptor> = callResolver.resolveFunctionCall(callResolutionContext)
|
||||
|
||||
val expectedTypes = HashSet<JetType>()
|
||||
for (candidate: ResolvedCall<FunctionDescriptor> in results.getAllCandidates()!!) {
|
||||
val parameters = candidate.getResultingDescriptor().getValueParameters()
|
||||
if (parameters.size <= argumentIndex) continue
|
||||
val parameterDescriptor = parameters[argumentIndex]
|
||||
expectedTypes.add(parameterDescriptor.getType())
|
||||
}
|
||||
return expectedTypes
|
||||
}
|
||||
|
||||
private fun calcItemsToSkip(expression: JetExpression, resolveSession: ResolveSessionForBodies): Collection<DeclarationDescriptor> {
|
||||
val parent = expression.getParent()
|
||||
when(parent) {
|
||||
@@ -215,7 +297,7 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Resolv
|
||||
}
|
||||
}
|
||||
|
||||
private fun thisItems(context: JetExpression, expectedType: JetType, bindingContext: BindingContext): Iterable<LookupElement> {
|
||||
private fun thisItems(context: JetExpression, expectedTypes: Collection<JetType>, bindingContext: BindingContext): Iterable<LookupElement> {
|
||||
val scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, context)
|
||||
if (scope == null) return listOf()
|
||||
|
||||
@@ -224,7 +306,7 @@ private fun thisItems(context: JetExpression, expectedType: JetType, bindingCont
|
||||
for (i in 0..receivers.size - 1) {
|
||||
val receiver = receivers[i]
|
||||
val thisType = receiver.getType()
|
||||
if (isSubtypeOf(thisType, expectedType)) {
|
||||
if (expectedTypes.any { isSubtypeOf(thisType, it) }) {
|
||||
//TODO: use this code when KT-4258 fixed
|
||||
//val expressionText = if (i == 0) "this" else "this@" + (thisQualifierName(receiver, bindingContext) ?: continue)
|
||||
val qualifier = if (i == 0) null else thisQualifierName(receiver, bindingContext) ?: continue
|
||||
|
||||
@@ -54,6 +54,7 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
|
||||
return resolveElementCache.resolveToElement(element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ModuleDescriptor getModuleDescriptor() {
|
||||
return resolveSession.getModuleDescriptor();
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.io.File
|
||||
|
||||
fun f(p1: Any, p2: String, p3: File) {
|
||||
File(<caret>)
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// EXIST: p3
|
||||
@@ -0,0 +1,18 @@
|
||||
val s = ""
|
||||
val i = 123
|
||||
|
||||
fun f(p1: Any, p2: String, p3: Int) {
|
||||
foo(<caret>123) // this call is resolved to Foo(Int) but types from all signatures should participate
|
||||
}
|
||||
|
||||
fun foo(p1: String, p2: Any) {
|
||||
}
|
||||
|
||||
fun foo(p1: Int) {
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// EXIST: p3
|
||||
// EXIST: s
|
||||
// EXIST: i
|
||||
@@ -0,0 +1,23 @@
|
||||
val s = ""
|
||||
val i = 123
|
||||
|
||||
fun f(p1: Any, p2: String, p3: Int, p4: Char) {
|
||||
foo(<caret>abc)
|
||||
}
|
||||
|
||||
fun foo(p1: String, p2: Any) {
|
||||
}
|
||||
|
||||
fun foo(p1: Int) {
|
||||
}
|
||||
|
||||
// add this signature so that call above is not resolved
|
||||
fun foo(p1: Char) {
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// EXIST: p3
|
||||
// EXIST: p4
|
||||
// EXIST: s
|
||||
// EXIST: i
|
||||
@@ -0,0 +1,13 @@
|
||||
fun f(p1: Any, p2: String, p3: Int) {
|
||||
foo("abc", <caret>)
|
||||
}
|
||||
|
||||
fun foo(p1: String, p2: String) {
|
||||
}
|
||||
|
||||
fun foo(p1: Int, p2: Int) {
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// ABSENT: p3
|
||||
@@ -0,0 +1,24 @@
|
||||
val s = ""
|
||||
val i = 123
|
||||
|
||||
fun f(p1: Any, p2: String, p3: Int, p4: Char) {
|
||||
C().foo(<caret>abc)
|
||||
}
|
||||
|
||||
class C {
|
||||
fun foo(p1: String, p2: Any) {
|
||||
}
|
||||
|
||||
fun foo(p1: Int) {
|
||||
}
|
||||
|
||||
fun foo(p1: Char) {
|
||||
}
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// EXIST: p3
|
||||
// EXIST: p4
|
||||
// EXIST: s
|
||||
// EXIST: i
|
||||
@@ -0,0 +1,24 @@
|
||||
val s = ""
|
||||
val i = 123
|
||||
|
||||
fun f(c: C?, p1: Any, p2: String, p3: Int, p4: Char) {
|
||||
c?.foo(<caret>abc)
|
||||
}
|
||||
|
||||
class C {
|
||||
fun foo(p1: String, p2: Any) {
|
||||
}
|
||||
|
||||
fun foo(p1: Int) {
|
||||
}
|
||||
|
||||
fun foo(p1: Char) {
|
||||
}
|
||||
}
|
||||
|
||||
// ABSENT: p1
|
||||
// EXIST: p2
|
||||
// EXIST: p3
|
||||
// EXIST: p4
|
||||
// EXIST: s
|
||||
// EXIST: i
|
||||
@@ -186,6 +186,31 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest("idea/testData/completion/smart/NotSillyAssignment.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("OverloadedConstructorArgument.kt")
|
||||
public void testOverloadedConstructorArgument() throws Exception {
|
||||
doTest("idea/testData/completion/smart/OverloadedConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("OverloadedMethodCallArgument1.kt")
|
||||
public void testOverloadedMethodCallArgument1() throws Exception {
|
||||
doTest("idea/testData/completion/smart/OverloadedMethodCallArgument1.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("OverloadedMethodCallArgument2.kt")
|
||||
public void testOverloadedMethodCallArgument2() throws Exception {
|
||||
doTest("idea/testData/completion/smart/OverloadedMethodCallArgument2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedOverloadedMethodCallArgument1.kt")
|
||||
public void testQualifiedOverloadedMethodCallArgument1() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedOverloadedMethodCallArgument1.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedOverloadedMethodCallArgument2.kt")
|
||||
public void testQualifiedOverloadedMethodCallArgument2() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedOverloadedMethodCallArgument2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("QualifiedThis.kt")
|
||||
public void testQualifiedThis() throws Exception {
|
||||
doTest("idea/testData/completion/smart/QualifiedThis.kt");
|
||||
|
||||
Reference in New Issue
Block a user