Refactor FakeCallResolver and usages
Remove useless overload, inline another to the single usage in tests, make some parameters non-null
This commit is contained in:
@@ -32,8 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
enum class FakeCallKind {
|
||||
ITERATOR,
|
||||
@@ -45,47 +43,15 @@ class FakeCallResolver(
|
||||
private val project: Project,
|
||||
private val callResolver: CallResolver
|
||||
) {
|
||||
fun resolveFakeCall(
|
||||
context: ExpressionTypingContext,
|
||||
receiver: ReceiverValue?,
|
||||
name: Name,
|
||||
callElement: KtExpression?,
|
||||
reportErrorsOn: KtExpression? = callElement,
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
vararg argumentTypes: KotlinType
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
val traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name)
|
||||
val fakeArguments = ArrayList<KtExpression>()
|
||||
for (type in argumentTypes) {
|
||||
fakeArguments.add(ExpressionTypingUtils.createFakeExpressionOfType(project, traceWithFakeArgumentInfo,
|
||||
"fakeArgument" + fakeArguments.size, type))
|
||||
}
|
||||
return makeAndResolveFakeCall(receiver, context.replaceBindingTrace(traceWithFakeArgumentInfo),
|
||||
fakeArguments, name, callElement, callKind, reportErrorsOn).second
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun resolveFakeCall(
|
||||
context: ResolutionContext<*>,
|
||||
receiver: ReceiverValue,
|
||||
receiver: ReceiverValue?,
|
||||
name: Name,
|
||||
callElement: KtExpression,
|
||||
reportErrorsOn: KtExpression = callElement,
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
valueArguments: List<KtExpression> = emptyList()
|
||||
reportErrorsOn: KtExpression,
|
||||
callKind: FakeCallKind,
|
||||
valueArguments: List<KtExpression>
|
||||
): OverloadResolutionResults<FunctionDescriptor> {
|
||||
return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement, callKind, reportErrorsOn).second
|
||||
}
|
||||
|
||||
fun makeAndResolveFakeCall(
|
||||
receiver: ReceiverValue?,
|
||||
context: ResolutionContext<*>,
|
||||
valueArguments: List<KtExpression>,
|
||||
name: Name,
|
||||
callElement: KtExpression?,
|
||||
callKind: FakeCallKind = FakeCallKind.OTHER,
|
||||
reportErrorsOn: KtExpression? = callElement
|
||||
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
|
||||
val fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name)
|
||||
val fakeBindingTrace = context.replaceBindingTrace(fakeTrace)
|
||||
|
||||
@@ -93,17 +59,19 @@ class FakeCallResolver(
|
||||
val result = makeAndResolveFakeCallInContext(receiver, fakeBindingTrace, valueArguments, name, callElement) { fake, isSuccess ->
|
||||
unreportedDiagnostic = fakeTrace.bindingContext.diagnostics.noSuppression().forElement(fake).firstOrNull { it.severity == Severity.ERROR }
|
||||
|
||||
if (!isSuccess) return@makeAndResolveFakeCallInContext
|
||||
|
||||
fakeTrace.commit({ slice, key ->
|
||||
// excluding all entries related to fake expression
|
||||
// convert all errors on this expression to ITERATOR_MISSING on callElement
|
||||
key != fake
|
||||
}, true)
|
||||
if (isSuccess) {
|
||||
fakeTrace.commit(
|
||||
{ slice, key ->
|
||||
// excluding all entries related to fake expression
|
||||
// convert all errors on this expression to ITERATOR_MISSING on callElement
|
||||
key != fake
|
||||
}, true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val resolutionResults = result.second
|
||||
if ((!resolutionResults.isSuccess || unreportedDiagnostic != null) && reportErrorsOn != null) {
|
||||
if (!resolutionResults.isSuccess || unreportedDiagnostic != null) {
|
||||
val isUnsafeCall = unreportedDiagnostic?.factory == Errors.UNSAFE_CALL
|
||||
val diagnostic = when (callKind) {
|
||||
FakeCallKind.ITERATOR ->
|
||||
@@ -127,22 +95,26 @@ class FakeCallResolver(
|
||||
context.trace.report(diagnostic)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
return resolutionResults
|
||||
}
|
||||
|
||||
@JvmOverloads fun makeAndResolveFakeCallInContext(
|
||||
@JvmOverloads
|
||||
fun makeAndResolveFakeCallInContext(
|
||||
receiver: ReceiverValue?,
|
||||
context: ResolutionContext<*>,
|
||||
valueArguments: List<KtExpression>,
|
||||
name: Name,
|
||||
callElement: KtExpression?,
|
||||
callElement: KtExpression,
|
||||
onComplete: (KtSimpleNameExpression, Boolean) -> Unit = { x, y -> }
|
||||
): Pair<Call, OverloadResolutionResults<FunctionDescriptor>> {
|
||||
val fake = KtPsiFactory(project).createSimpleName(name.asString())
|
||||
val call = CallMaker.makeCallWithExpressions(callElement ?: fake, receiver, null, fake, valueArguments)
|
||||
val results = callResolver.resolveCallWithGivenName(context, call, fake, name)
|
||||
val fakeCalleeExpression = KtPsiFactory(project).createSimpleName(name.asString())
|
||||
val call = CallMaker.makeCallWithExpressions(
|
||||
callElement, receiver, /* callOperationNode = */ null, fakeCalleeExpression, valueArguments
|
||||
)
|
||||
val results = callResolver.resolveCallWithGivenName(context, call, fakeCalleeExpression, name)
|
||||
|
||||
onComplete(fake, results.isSuccess)
|
||||
onComplete(fakeCalleeExpression, results.isSuccess)
|
||||
|
||||
return Pair(call, results)
|
||||
}
|
||||
|
||||
+23
-27
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
@@ -25,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.Call;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -56,38 +54,35 @@ public class ForLoopConventionsChecker {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public KotlinType checkIterableConvention(@NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) {
|
||||
public KotlinType checkIterableConvention(@NotNull ExpressionReceiver loopRange, @NotNull ExpressionTypingContext context) {
|
||||
KtExpression loopRangeExpression = loopRange.getExpression();
|
||||
|
||||
// Make a fake call loopRange.iterator(), and try to resolve it
|
||||
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls = fakeCallResolver.makeAndResolveFakeCall(
|
||||
loopRange, context, Collections.<KtExpression>emptyList(), OperatorNameConventions.ITERATOR, loopRangeExpression,
|
||||
FakeCallKind.ITERATOR, loopRangeExpression
|
||||
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = fakeCallResolver.resolveFakeCall(
|
||||
context, loopRange, OperatorNameConventions.ITERATOR, loopRangeExpression,
|
||||
loopRangeExpression, FakeCallKind.ITERATOR, Collections.<KtExpression>emptyList()
|
||||
);
|
||||
OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();
|
||||
if (!iteratorResolutionResults.isSuccess()) return null;
|
||||
|
||||
if (iteratorResolutionResults.isSuccess()) {
|
||||
ResolvedCall<FunctionDescriptor> iteratorResolvedCall = iteratorResolutionResults.getResultingCall();
|
||||
context.trace.record(LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall);
|
||||
FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
|
||||
ResolvedCall<FunctionDescriptor> iteratorResolvedCall = iteratorResolutionResults.getResultingCall();
|
||||
context.trace.record(LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall);
|
||||
FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();
|
||||
|
||||
checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace);
|
||||
checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace);
|
||||
|
||||
KotlinType iteratorType = iteratorFunction.getReturnType();
|
||||
//noinspection ConstantConditions
|
||||
KotlinType hasNextType = checkConventionForIterator(
|
||||
context, loopRangeExpression, iteratorType, OperatorNameConventions.HAS_NEXT,
|
||||
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
|
||||
);
|
||||
if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) {
|
||||
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
|
||||
}
|
||||
return checkConventionForIterator(
|
||||
context, loopRangeExpression, iteratorType, OperatorNameConventions.NEXT,
|
||||
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL
|
||||
);
|
||||
KotlinType iteratorType = iteratorFunction.getReturnType();
|
||||
//noinspection ConstantConditions
|
||||
KotlinType hasNextType = checkConventionForIterator(
|
||||
context, loopRangeExpression, iteratorType, OperatorNameConventions.HAS_NEXT,
|
||||
HAS_NEXT_FUNCTION_AMBIGUITY, HAS_NEXT_MISSING, HAS_NEXT_FUNCTION_NONE_APPLICABLE, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
|
||||
);
|
||||
if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) {
|
||||
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
|
||||
}
|
||||
return null;
|
||||
return checkConventionForIterator(
|
||||
context, loopRangeExpression, iteratorType, OperatorNameConventions.NEXT,
|
||||
NEXT_AMBIGUITY, NEXT_MISSING, NEXT_NONE_APPLICABLE, LOOP_RANGE_NEXT_RESOLVED_CALL
|
||||
);
|
||||
}
|
||||
|
||||
private static void checkIfOperatorModifierPresent(KtExpression expression, FunctionDescriptor descriptor, DiagnosticSink sink) {
|
||||
@@ -112,7 +107,8 @@ public class ForLoopConventionsChecker {
|
||||
@NotNull WritableSlice<KtExpression, ResolvedCall<FunctionDescriptor>> resolvedCallKey
|
||||
) {
|
||||
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = fakeCallResolver.resolveFakeCall(
|
||||
context, new TransientReceiver(iteratorType), name, loopRangeExpression
|
||||
context, new TransientReceiver(iteratorType), name, loopRangeExpression, loopRangeExpression, FakeCallKind.OTHER,
|
||||
Collections.<KtExpression>emptyList()
|
||||
);
|
||||
if (nextResolutionResults.isAmbiguity()) {
|
||||
context.trace.report(ambiguity.on(loopRangeExpression, iteratorType));
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
|
||||
@@ -41,13 +42,12 @@ import org.jetbrains.kotlin.tests.di.InjectionKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
|
||||
import org.jetbrains.kotlin.types.expressions.FakeCallKind;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.psi.KtPsiFactoryKt.KtPsiFactory;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class ExpectedResolveDataUtil {
|
||||
@@ -150,8 +150,20 @@ public class ExpectedResolveDataUtil {
|
||||
new BindingTraceContext(), lexicalScope,
|
||||
DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE);
|
||||
|
||||
KtExpression callElement = KtPsiFactory(project).createExpression(name);
|
||||
|
||||
TemporaryBindingTrace traceWithFakeArgumentInfo =
|
||||
TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name);
|
||||
List<KtExpression> fakeArguments = new ArrayList<KtExpression>(parameterTypes.length);
|
||||
for (KotlinType type : parameterTypes) {
|
||||
fakeArguments.add(ExpressionTypingUtils.createFakeExpressionOfType(
|
||||
project, traceWithFakeArgumentInfo, "fakeArgument" + fakeArguments.size(), type
|
||||
));
|
||||
}
|
||||
|
||||
OverloadResolutionResults<FunctionDescriptor> functions = container.getFakeCallResolver().resolveFakeCall(
|
||||
context, null, Name.identifier(name), null, null, FakeCallKind.OTHER, parameterTypes);
|
||||
context, null, Name.identifier(name), callElement, callElement, FakeCallKind.OTHER, fakeArguments
|
||||
);
|
||||
|
||||
for (ResolvedCall<? extends FunctionDescriptor> resolvedCall : functions.getResultingCalls()) {
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
|
||||
|
||||
Reference in New Issue
Block a user