diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadResolutionResultsUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadResolutionResultsUtil.java index e64bf0d49a8..61643f98ea1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadResolutionResultsUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/OverloadResolutionResultsUtil.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ContextDependency; import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.tower.StubOnlyResolvedCall; +import org.jetbrains.kotlin.resolve.calls.tower.StubOnlyVariableAsFunctionCall; import org.jetbrains.kotlin.types.KotlinType; import java.util.Collection; @@ -60,7 +61,7 @@ public class OverloadResolutionResultsUtil { } } else { - if (resultingCall instanceof StubOnlyResolvedCall) { + if (resultingCall instanceof StubOnlyResolvedCall || resultingCall instanceof StubOnlyVariableAsFunctionCall) { return null; } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 45884d144cb..903ce49bffe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -62,16 +62,47 @@ class KotlinToResolvedCallTransformer( trace: BindingTrace? // if trace is not null then all information will be reported to this trace ): ResolvedCall { if (baseResolvedCall is ResolvedKotlinCall.CompletedResolvedKotlinCall) { - baseResolvedCall.allInnerCalls.forEach { transformAndReportCompletedCall(it, context, trace) } - return transformAndReportCompletedCall(baseResolvedCall.completedCall, context, trace) + val allResolvedCalls = baseResolvedCall.allInnerCalls.mapTo(ArrayList>()) { transformAndReportCompletedCall(it, context, trace) } + val result = transformAndReportCompletedCall(baseResolvedCall.completedCall, context, trace) + allResolvedCalls.add(result) + + if (trace != null) { + val callCheckerContext = CallCheckerContext(context.replaceBindingTrace(trace), languageFeatureSettings) + for (resolvedCall in allResolvedCalls) { + runCallCheckers(resolvedCall, callCheckerContext) + } + } + + return result } val onlyResolvedCall = (baseResolvedCall as ResolvedKotlinCall.OnlyResolvedKotlinCall) trace?.record(BindingContext.ONLY_RESOLVED_CALL, onlyResolvedCall.candidate.kotlinCall.psiKotlinCall.psiCall, onlyResolvedCall) - return StubOnlyResolvedCall(onlyResolvedCall.candidate.lastCall) + return createStubResolvedCallAndWriteItToTrace(onlyResolvedCall.candidate, trace) } + fun createStubResolvedCallAndWriteItToTrace(candidate: KotlinResolutionCandidate, trace: BindingTrace?): ResolvedCall { + val result = when (candidate) { + is VariableAsFunctionKotlinResolutionCandidate -> { + val variableStub = StubOnlyResolvedCall(candidate.resolvedVariable) + val invokeStub = StubOnlyResolvedCall(candidate.invokeCandidate) + StubOnlyVariableAsFunctionCall(variableStub, invokeStub) as ResolvedCall + } + is SimpleKotlinResolutionCandidate -> { + StubOnlyResolvedCall(candidate) + } + } + if (trace != null) { + val tracing = candidate.kotlinCall.psiKotlinCall.tracingStrategy + + tracing.bindReference(trace, result) + tracing.bindResolvedCall(trace, result) + } + return result + } + + private fun transformAndReportCompletedCall( completedCall: CompletedKotlinCall, context: BasicCallResolutionContext, @@ -97,12 +128,11 @@ class KotlinToResolvedCallTransformer( (resolvedCall as ResolvedCall) } } - runCallCheckers(resolvedCall, context) return resolvedCall } - private fun runCallCheckers(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) { + private fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) { val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall) resolvedCall.variableCall.call.calleeExpression else @@ -111,9 +141,12 @@ class KotlinToResolvedCallTransformer( if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression else resolvedCall.call.callElement - val callCheckerContext = CallCheckerContext(context, languageFeatureSettings) for (callChecker in callCheckers) { callChecker.check(resolvedCall, reportOn, callCheckerContext) + + if (resolvedCall is VariableAsFunctionResolvedCall) { + callChecker.check(resolvedCall.variableCall, reportOn, callCheckerContext) + } } } @@ -348,4 +381,9 @@ class StubOnlyResolvedCall(val candidate: SimpleKotlinRe override val argumentMappingByOriginal: Map get() = candidate.argumentMappingByOriginal override val kotlinCall: KotlinCall get() = candidate.kotlinCall -} \ No newline at end of file +} + +class StubOnlyVariableAsFunctionCall( + override val variableCall: StubOnlyResolvedCall, + override val functionCall: StubOnlyResolvedCall +) : VariableAsFunctionResolvedCall, ResolvedCall by functionCall diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt index 707ceee3316..cfe30df8100 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/LambdaAnalyzerImpl.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.builtins.createFunctionType import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType import org.jetbrains.kotlin.builtins.isFunctionType +import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtPsiUtil @@ -30,6 +31,7 @@ import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.model.KotlinCall import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.util.CallMaker import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -41,7 +43,8 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo class LambdaAnalyzerImpl( val expressionTypingServices: ExpressionTypingServices, val trace: BindingTrace, - val typeApproximator: TypeApproximator + val typeApproximator: TypeApproximator, + val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer ): LambdaAnalyzer { override fun analyzeAndGetRelatedCalls( @@ -87,4 +90,8 @@ class LambdaAnalyzerImpl( return listOfNotNull(simpleArgument) } + + override fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) { + kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace(candidate, trace) + } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 00ad78b27e0..f17a7983e99 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -89,7 +89,7 @@ class PSICallResolver( ) : OverloadResolutionResults { val kotlinCall = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, name, tracingStrategy) val scopeTower = ASTScopeTower(context) - val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator) + val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator, kotlinToResolvedCallTransformer) val callContext = createCallContext(scopeTower, lambdaAnalyzer) val factoryProviderForInvoke = FactoryProviderForInvoke(context, callContext, kotlinCall) @@ -112,7 +112,7 @@ class PSICallResolver( val kotlinCall = toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, GIVEN_CANDIDATES_NAME, tracingStrategy, dispatchReceiver) val scopeTower = ASTScopeTower(context) - val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator) + val lambdaAnalyzer = LambdaAnalyzerImpl(expressionTypingServices, context.trace, typeApproximator, kotlinToResolvedCallTransformer) val callContext = createCallContext(scopeTower, lambdaAnalyzer) val givenCandidates = resolutionCandidates.map { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index f3d80a275f8..a69802354f0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.resolve.calls.model.KotlinCall import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument +import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument import org.jetbrains.kotlin.types.UnwrappedType @@ -34,4 +35,8 @@ interface LambdaAnalyzer { parameters: List, expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables ): List + + // todo this is hack for some client which try to read ResolvedCall from trace before all calls completed + fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) + } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index a4453f82ab6..0ba8df0d969 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -69,6 +69,7 @@ class KotlinCallCompleter( expectedType: UnwrappedType?, lambdaAnalyzer: LambdaAnalyzer ): ResolvedKotlinCall { + lambdaAnalyzer.bindStubResolvedCallForCandidate(candidate) val topLevelCall = if (candidate is VariableAsFunctionKotlinResolutionCandidate) { candidate.invokeCandidate