From 1690dcd8df70a50bae522c751c63e9711cac2b27 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 30 Jun 2016 15:11:40 +0300 Subject: [PATCH] Refactor FakeCallResolver and usages Remove useless overload, inline another to the single usage in tests, make some parameters non-null --- .../types/expressions/FakeCallResolver.kt | 78 ++++++------------- .../ForLoopConventionsChecker.java | 50 ++++++------ .../resolve/ExpectedResolveDataUtil.java | 22 ++++-- 3 files changed, 65 insertions(+), 85 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt index 4ccecfed326..14bd21445ec 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt @@ -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 { - val traceWithFakeArgumentInfo = TemporaryBindingTrace.create(context.trace, "trace to store fake argument for", name) - val fakeArguments = ArrayList() - 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 = emptyList() + reportErrorsOn: KtExpression, + callKind: FakeCallKind, + valueArguments: List ): OverloadResolutionResults { - return makeAndResolveFakeCall(receiver, context, valueArguments, name, callElement, callKind, reportErrorsOn).second - } - - fun makeAndResolveFakeCall( - receiver: ReceiverValue?, - context: ResolutionContext<*>, - valueArguments: List, - name: Name, - callElement: KtExpression?, - callKind: FakeCallKind = FakeCallKind.OTHER, - reportErrorsOn: KtExpression? = callElement - ): Pair> { 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, name: Name, - callElement: KtExpression?, + callElement: KtExpression, onComplete: (KtSimpleNameExpression, Boolean) -> Unit = { x, y -> } ): Pair> { - 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) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java index abd43d0c9af..13ea1b7dcf9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ForLoopConventionsChecker.java @@ -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> calls = fakeCallResolver.makeAndResolveFakeCall( - loopRange, context, Collections.emptyList(), OperatorNameConventions.ITERATOR, loopRangeExpression, - FakeCallKind.ITERATOR, loopRangeExpression + OverloadResolutionResults iteratorResolutionResults = fakeCallResolver.resolveFakeCall( + context, loopRange, OperatorNameConventions.ITERATOR, loopRangeExpression, + loopRangeExpression, FakeCallKind.ITERATOR, Collections.emptyList() ); - OverloadResolutionResults iteratorResolutionResults = calls.getSecond(); + if (!iteratorResolutionResults.isSuccess()) return null; - if (iteratorResolutionResults.isSuccess()) { - ResolvedCall iteratorResolvedCall = iteratorResolutionResults.getResultingCall(); - context.trace.record(LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall); - FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor(); + ResolvedCall 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> resolvedCallKey ) { OverloadResolutionResults nextResolutionResults = fakeCallResolver.resolveFakeCall( - context, new TransientReceiver(iteratorType), name, loopRangeExpression + context, new TransientReceiver(iteratorType), name, loopRangeExpression, loopRangeExpression, FakeCallKind.OTHER, + Collections.emptyList() ); if (nextResolutionResults.isAmbiguity()) { context.trace.report(ambiguity.on(loopRangeExpression, iteratorType)); diff --git a/compiler/tests-common/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java b/compiler/tests-common/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java index 66e1ebae1f0..b1d9c15d321 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java +++ b/compiler/tests-common/org/jetbrains/kotlin/resolve/ExpectedResolveDataUtil.java @@ -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 fakeArguments = new ArrayList(parameterTypes.length); + for (KotlinType type : parameterTypes) { + fakeArguments.add(ExpressionTypingUtils.createFakeExpressionOfType( + project, traceWithFakeArgumentInfo, "fakeArgument" + fakeArguments.size(), type + )); + } + OverloadResolutionResults 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 resolvedCall : functions.getResultingCalls()) { List unsubstitutedValueParameters = resolvedCall.getResultingDescriptor().getValueParameters();