[NI] Store stub resolved call to trace because some clients read this before all calls are completed.
This is bad idea, but this is how it works in old inference. Now we just save old behaviour. Future plan: fix checks where we get unfinished resolved calls.
This commit is contained in:
+2
-1
@@ -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.MutableResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.StubOnlyResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.tower.StubOnlyResolvedCall;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.StubOnlyVariableAsFunctionCall;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -60,7 +61,7 @@ public class OverloadResolutionResultsUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (resultingCall instanceof StubOnlyResolvedCall) {
|
if (resultingCall instanceof StubOnlyResolvedCall || resultingCall instanceof StubOnlyVariableAsFunctionCall) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-7
@@ -62,16 +62,47 @@ class KotlinToResolvedCallTransformer(
|
|||||||
trace: BindingTrace? // if trace is not null then all information will be reported to this trace
|
trace: BindingTrace? // if trace is not null then all information will be reported to this trace
|
||||||
): ResolvedCall<D> {
|
): ResolvedCall<D> {
|
||||||
if (baseResolvedCall is ResolvedKotlinCall.CompletedResolvedKotlinCall) {
|
if (baseResolvedCall is ResolvedKotlinCall.CompletedResolvedKotlinCall) {
|
||||||
baseResolvedCall.allInnerCalls.forEach { transformAndReportCompletedCall<D>(it, context, trace) }
|
val allResolvedCalls = baseResolvedCall.allInnerCalls.mapTo(ArrayList<ResolvedCall<*>>()) { transformAndReportCompletedCall<CallableDescriptor>(it, context, trace) }
|
||||||
return transformAndReportCompletedCall(baseResolvedCall.completedCall, context, trace)
|
val result = transformAndReportCompletedCall<D>(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)
|
val onlyResolvedCall = (baseResolvedCall as ResolvedKotlinCall.OnlyResolvedKotlinCall)
|
||||||
trace?.record(BindingContext.ONLY_RESOLVED_CALL, onlyResolvedCall.candidate.kotlinCall.psiKotlinCall.psiCall, onlyResolvedCall)
|
trace?.record(BindingContext.ONLY_RESOLVED_CALL, onlyResolvedCall.candidate.kotlinCall.psiKotlinCall.psiCall, onlyResolvedCall)
|
||||||
|
|
||||||
return StubOnlyResolvedCall(onlyResolvedCall.candidate.lastCall)
|
return createStubResolvedCallAndWriteItToTrace(onlyResolvedCall.candidate, trace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <D : CallableDescriptor> createStubResolvedCallAndWriteItToTrace(candidate: KotlinResolutionCandidate, trace: BindingTrace?): ResolvedCall<D> {
|
||||||
|
val result = when (candidate) {
|
||||||
|
is VariableAsFunctionKotlinResolutionCandidate -> {
|
||||||
|
val variableStub = StubOnlyResolvedCall<VariableDescriptor>(candidate.resolvedVariable)
|
||||||
|
val invokeStub = StubOnlyResolvedCall<FunctionDescriptor>(candidate.invokeCandidate)
|
||||||
|
StubOnlyVariableAsFunctionCall(variableStub, invokeStub) as ResolvedCall<D>
|
||||||
|
}
|
||||||
|
is SimpleKotlinResolutionCandidate -> {
|
||||||
|
StubOnlyResolvedCall<D>(candidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (trace != null) {
|
||||||
|
val tracing = candidate.kotlinCall.psiKotlinCall.tracingStrategy
|
||||||
|
|
||||||
|
tracing.bindReference(trace, result)
|
||||||
|
tracing.bindResolvedCall(trace, result)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun <D : CallableDescriptor> transformAndReportCompletedCall(
|
private fun <D : CallableDescriptor> transformAndReportCompletedCall(
|
||||||
completedCall: CompletedKotlinCall,
|
completedCall: CompletedKotlinCall,
|
||||||
context: BasicCallResolutionContext,
|
context: BasicCallResolutionContext,
|
||||||
@@ -97,12 +128,11 @@ class KotlinToResolvedCallTransformer(
|
|||||||
(resolvedCall as ResolvedCall<D>)
|
(resolvedCall as ResolvedCall<D>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runCallCheckers(resolvedCall, context)
|
|
||||||
|
|
||||||
return resolvedCall
|
return resolvedCall
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runCallCheckers(resolvedCall: ResolvedCall<*>, context: BasicCallResolutionContext) {
|
private fun runCallCheckers(resolvedCall: ResolvedCall<*>, callCheckerContext: CallCheckerContext) {
|
||||||
val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall)
|
val calleeExpression = if (resolvedCall is VariableAsFunctionResolvedCall)
|
||||||
resolvedCall.variableCall.call.calleeExpression
|
resolvedCall.variableCall.call.calleeExpression
|
||||||
else
|
else
|
||||||
@@ -111,9 +141,12 @@ class KotlinToResolvedCallTransformer(
|
|||||||
if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression
|
if (calleeExpression != null && !calleeExpression.isFakeElement) calleeExpression
|
||||||
else resolvedCall.call.callElement
|
else resolvedCall.call.callElement
|
||||||
|
|
||||||
val callCheckerContext = CallCheckerContext(context, languageFeatureSettings)
|
|
||||||
for (callChecker in callCheckers) {
|
for (callChecker in callCheckers) {
|
||||||
callChecker.check(resolvedCall, reportOn, callCheckerContext)
|
callChecker.check(resolvedCall, reportOn, callCheckerContext)
|
||||||
|
|
||||||
|
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||||
|
callChecker.check(resolvedCall.variableCall, reportOn, callCheckerContext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,4 +381,9 @@ class StubOnlyResolvedCall<D : CallableDescriptor>(val candidate: SimpleKotlinRe
|
|||||||
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
override val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||||
get() = candidate.argumentMappingByOriginal
|
get() = candidate.argumentMappingByOriginal
|
||||||
override val kotlinCall: KotlinCall get() = candidate.kotlinCall
|
override val kotlinCall: KotlinCall get() = candidate.kotlinCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StubOnlyVariableAsFunctionCall(
|
||||||
|
override val variableCall: StubOnlyResolvedCall<VariableDescriptor>,
|
||||||
|
override val functionCall: StubOnlyResolvedCall<FunctionDescriptor>
|
||||||
|
) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall
|
||||||
|
|||||||
+8
-1
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
|||||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
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.context.ContextDependency
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
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.model.LambdaKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
@@ -41,7 +43,8 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
|
|||||||
class LambdaAnalyzerImpl(
|
class LambdaAnalyzerImpl(
|
||||||
val expressionTypingServices: ExpressionTypingServices,
|
val expressionTypingServices: ExpressionTypingServices,
|
||||||
val trace: BindingTrace,
|
val trace: BindingTrace,
|
||||||
val typeApproximator: TypeApproximator
|
val typeApproximator: TypeApproximator,
|
||||||
|
val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer
|
||||||
): LambdaAnalyzer {
|
): LambdaAnalyzer {
|
||||||
|
|
||||||
override fun analyzeAndGetRelatedCalls(
|
override fun analyzeAndGetRelatedCalls(
|
||||||
@@ -87,4 +90,8 @@ class LambdaAnalyzerImpl(
|
|||||||
|
|
||||||
return listOfNotNull(simpleArgument)
|
return listOfNotNull(simpleArgument)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate) {
|
||||||
|
kotlinToResolvedCallTransformer.createStubResolvedCallAndWriteItToTrace<CallableDescriptor>(candidate, trace)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ class PSICallResolver(
|
|||||||
) : OverloadResolutionResults<D> {
|
) : OverloadResolutionResults<D> {
|
||||||
val kotlinCall = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, name, tracingStrategy)
|
val kotlinCall = toKotlinCall(context, resolutionKind.kotlinCallKind, context.call, name, tracingStrategy)
|
||||||
val scopeTower = ASTScopeTower(context)
|
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 callContext = createCallContext(scopeTower, lambdaAnalyzer)
|
||||||
val factoryProviderForInvoke = FactoryProviderForInvoke(context, callContext, kotlinCall)
|
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 kotlinCall = toKotlinCall(context, KotlinCallKind.FUNCTION, context.call, GIVEN_CANDIDATES_NAME, tracingStrategy, dispatchReceiver)
|
||||||
val scopeTower = ASTScopeTower(context)
|
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 callContext = createCallContext(scopeTower, lambdaAnalyzer)
|
||||||
|
|
||||||
val givenCandidates = resolutionCandidates.map {
|
val givenCandidates = resolutionCandidates.map {
|
||||||
|
|||||||
+5
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.components
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
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.model.LambdaKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
|
||||||
@@ -34,4 +35,8 @@ interface LambdaAnalyzer {
|
|||||||
parameters: List<UnwrappedType>,
|
parameters: List<UnwrappedType>,
|
||||||
expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables
|
expectedReturnType: UnwrappedType? // null means, that return type is not proper i.e. it depends on some type variables
|
||||||
): List<KotlinCallArgument>
|
): List<KotlinCallArgument>
|
||||||
|
|
||||||
|
// todo this is hack for some client which try to read ResolvedCall from trace before all calls completed
|
||||||
|
fun bindStubResolvedCallForCandidate(candidate: KotlinResolutionCandidate)
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
@@ -69,6 +69,7 @@ class KotlinCallCompleter(
|
|||||||
expectedType: UnwrappedType?,
|
expectedType: UnwrappedType?,
|
||||||
lambdaAnalyzer: LambdaAnalyzer
|
lambdaAnalyzer: LambdaAnalyzer
|
||||||
): ResolvedKotlinCall {
|
): ResolvedKotlinCall {
|
||||||
|
lambdaAnalyzer.bindStubResolvedCallForCandidate(candidate)
|
||||||
val topLevelCall =
|
val topLevelCall =
|
||||||
if (candidate is VariableAsFunctionKotlinResolutionCandidate) {
|
if (candidate is VariableAsFunctionKotlinResolutionCandidate) {
|
||||||
candidate.invokeCandidate
|
candidate.invokeCandidate
|
||||||
|
|||||||
Reference in New Issue
Block a user