Slightly reduce number of candidates in task prioritizer
return only extensions (functions) when we expecting extensions (not all functions); for properties it's not that easy: they may have extension function types, and we want to avoid early computing of deferred types rename: getNonMembersByName -> getExtensionsByName Report NO_RECEIVER_ALLOWED for '42.(f)()' where f: () -> Unit in TracingStrategyForInvoke (we don't store candidates for such 'invoke' functions any more)
This commit is contained in:
@@ -287,7 +287,7 @@ public class CallResolver {
|
||||
else if (calleeExpression != null) {
|
||||
|
||||
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
||||
JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); // We are actually expecting a function, but there seems to be no easy way of expressing this
|
||||
JetType calleeType = expressionTypingServices.safeGetType(context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
|
||||
ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
|
||||
|
||||
Call call = new CallTransformer.CallForImplicitInvoke(
|
||||
|
||||
@@ -104,10 +104,7 @@ public class CandidateResolver {
|
||||
ValueArgumentsToParametersMapper.Status argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
||||
context.call, context.tracing, candidateCall, unmappedArguments);
|
||||
if (!argumentMappingStatus.isSuccess()) {
|
||||
//For the expressions like '42.(f)()' where f: () -> Unit we'd like to generate an error 'no receiver admitted',
|
||||
//not to throw away the candidate.
|
||||
if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR
|
||||
&& !CallResolverUtil.isInvokeCallOnExpressionWithBothReceivers(context.call)) {
|
||||
if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.STRONG_ERROR) {
|
||||
candidateCall.addStatus(RECEIVER_PRESENCE_ERROR);
|
||||
checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS);
|
||||
return;
|
||||
|
||||
+9
-8
@@ -32,7 +32,7 @@ public trait CallableDescriptorCollector<D : CallableDescriptor> {
|
||||
|
||||
public fun getMembersByName(receiver: JetType, name: Name, bindingTrace: BindingTrace): Collection<D>
|
||||
|
||||
public fun getNonMembersByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<D>
|
||||
public fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<D>
|
||||
}
|
||||
|
||||
private val FUNCTIONS_COLLECTOR = FilteredCollector(FunctionCollector)
|
||||
@@ -66,8 +66,8 @@ private object FunctionCollector : CallableDescriptorCollector<FunctionDescripto
|
||||
return receiverScope.getFunctions(name) + getConstructors(receiverScope, name)
|
||||
}
|
||||
|
||||
override fun getNonMembersByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<FunctionDescriptor> {
|
||||
return scope.getFunctions(name)
|
||||
override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<FunctionDescriptor> {
|
||||
return scope.getFunctions(name).filter { it.getExtensionReceiverParameter() != null }
|
||||
}
|
||||
|
||||
private fun getConstructors(scope: JetScope, name: Name): Collection<FunctionDescriptor> {
|
||||
@@ -106,7 +106,8 @@ private object VariableCollector : CallableDescriptorCollector<VariableDescripto
|
||||
return (memberScope.getProperties(name) + getFakeDescriptorForObject(memberScope, name)).filterNotNull()
|
||||
}
|
||||
|
||||
override fun getNonMembersByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<VariableDescriptor> {
|
||||
override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<VariableDescriptor> {
|
||||
// property may have an extension function type, we check the applicability later to avoid an early computing of deferred types
|
||||
return (listOf(scope.getLocalVariable(name)) + scope.getProperties(name)).filterNotNull()
|
||||
}
|
||||
|
||||
@@ -125,8 +126,8 @@ private object PropertyCollector : CallableDescriptorCollector<VariableDescripto
|
||||
return filterProperties(VARIABLES_COLLECTOR.getMembersByName(receiver, name, bindingTrace))
|
||||
}
|
||||
|
||||
override fun getNonMembersByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<VariableDescriptor> {
|
||||
return filterProperties(VARIABLES_COLLECTOR.getNonMembersByName(scope, name, bindingTrace))
|
||||
override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<VariableDescriptor> {
|
||||
return filterProperties(VARIABLES_COLLECTOR.getExtensionsByName(scope, name, bindingTrace))
|
||||
}
|
||||
|
||||
override fun toString() = "PROPERTIES"
|
||||
@@ -142,8 +143,8 @@ private class FilteredCollector<D : CallableDescriptor>(private val delegate: Ca
|
||||
return filterOutMembersFromLibrarySource(delegate.getMembersByName(receiver, name, bindingTrace))
|
||||
}
|
||||
|
||||
override fun getNonMembersByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<D> {
|
||||
return filterOutMembersFromLibrarySource(delegate.getNonMembersByName(scope, name, bindingTrace))
|
||||
override fun getExtensionsByName(scope: JetScope, name: Name, bindingTrace: BindingTrace): Collection<D> {
|
||||
return filterOutMembersFromLibrarySource(delegate.getExtensionsByName(scope, name, bindingTrace))
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
+2
-2
@@ -153,7 +153,7 @@ public class TaskPrioritizer {
|
||||
}
|
||||
//extensions
|
||||
Collection<ResolutionCandidate<D>> extensions = convertWithImpliedThis(
|
||||
c.scope, explicitReceiver, callableDescriptorCollector.getNonMembersByName(c.scope, c.name, c.context.trace),
|
||||
c.scope, explicitReceiver, callableDescriptorCollector.getExtensionsByName(c.scope, c.name, c.context.trace),
|
||||
createKind(EXTENSION_RECEIVER, isExplicit), c.context.call);
|
||||
c.result.addCandidates(extensions);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public class TaskPrioritizer {
|
||||
@NotNull CallableDescriptorCollector<D> callableDescriptorCollector, TaskPrioritizerContext<D, F> c,
|
||||
@NotNull ExplicitReceiverKind receiverKind
|
||||
) {
|
||||
Collection<D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
||||
Collection<D> memberExtensions = callableDescriptorCollector.getExtensionsByName(
|
||||
dispatchReceiver.getType().getMemberScope(), c.name, c.context.trace);
|
||||
c.result.addCandidates(convertWithReceivers(
|
||||
memberExtensions, dispatchReceiver, receiverParameter, receiverKind, c.context.call));
|
||||
|
||||
+20
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.calls.tasks;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
@@ -27,14 +28,18 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.FUNCTION_EXPECTED;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.NO_RECEIVER_ALLOWED;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
|
||||
|
||||
public class TracingStrategyForInvoke extends AbstractTracingStrategy {
|
||||
private static final Logger LOG = Logger.getInstance(TracingStrategyForInvoke.class);
|
||||
|
||||
private final JetType calleeType;
|
||||
|
||||
public TracingStrategyForInvoke(
|
||||
@@ -74,13 +79,26 @@ public class TracingStrategyForInvoke extends AbstractTracingStrategy {
|
||||
|
||||
@Override
|
||||
public void unresolvedReference(@NotNull BindingTrace trace) {
|
||||
trace.report(FUNCTION_EXPECTED.on(reference, reference, calleeType));
|
||||
functionExpectedOrNoReceiverAllowed(trace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends CallableDescriptor> void unresolvedReferenceWrongReceiver(
|
||||
@NotNull BindingTrace trace, @NotNull Collection<? extends ResolvedCall<D>> candidates
|
||||
) {
|
||||
trace.report(FUNCTION_EXPECTED.on(reference, reference, calleeType));
|
||||
functionExpectedOrNoReceiverAllowed(trace);
|
||||
}
|
||||
|
||||
private void functionExpectedOrNoReceiverAllowed(BindingTrace trace) {
|
||||
if (KotlinBuiltIns.getInstance().isFunctionType(calleeType)) {
|
||||
//LOG.assert
|
||||
if (!call.getExplicitReceiver().exists()) {
|
||||
LOG.error("'Invoke' is not found on expression of function type (" + calleeType + "): " + call.getCallElement().getText());
|
||||
}
|
||||
trace.report(NO_RECEIVER_ALLOWED.on(reference));
|
||||
}
|
||||
else {
|
||||
trace.report(FUNCTION_EXPECTED.on(reference, reference, calleeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user