Logic of completing call rewritten in CallCompleter
Changed interface ResolutionResultsCache
This commit is contained in:
+3
-11
@@ -48,6 +48,7 @@ import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgum
|
|||||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
|
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.*;
|
import static org.jetbrains.jet.lang.types.TypeUtils.*;
|
||||||
|
|
||||||
public class ArgumentTypeResolver {
|
public class ArgumentTypeResolver {
|
||||||
@@ -125,15 +126,6 @@ public class ArgumentTypeResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkUnmappedArgumentTypes(CallResolutionContext<?> context, Set<ValueArgument> unmappedArguments) {
|
|
||||||
for (ValueArgument valueArgument : unmappedArguments) {
|
|
||||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
|
||||||
if (argumentExpression != null) {
|
|
||||||
checkArgumentTypeWithNoCallee(context, argumentExpression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkArgumentTypeWithNoCallee(CallResolutionContext<?> context, JetExpression argumentExpression) {
|
private void checkArgumentTypeWithNoCallee(CallResolutionContext<?> context, JetExpression argumentExpression) {
|
||||||
expressionTypingServices.getTypeInfo(argumentExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
expressionTypingServices.getTypeInfo(argumentExpression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||||
updateResultArgumentTypeIfNotDenotable(context, argumentExpression);
|
updateResultArgumentTypeIfNotDenotable(context, argumentExpression);
|
||||||
@@ -201,7 +193,7 @@ public class ArgumentTypeResolver {
|
|||||||
JetType type = getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, true);
|
JetType type = getShapeTypeOfFunctionLiteral(functionLiteralExpression, context.scope, context.trace, true);
|
||||||
return JetTypeInfo.create(type, context.dataFlowInfo);
|
return JetTypeInfo.create(type, context.dataFlowInfo);
|
||||||
}
|
}
|
||||||
return expressionTypingServices.getTypeInfo(expression, context);
|
return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -260,7 +252,7 @@ public class ArgumentTypeResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <D extends CallableDescriptor> JetType updateResultArgumentTypeIfNotDenotable(
|
public static JetType updateResultArgumentTypeIfNotDenotable(
|
||||||
@NotNull ResolutionContext context,
|
@NotNull ResolutionContext context,
|
||||||
@NotNull JetExpression expression
|
@NotNull JetExpression expression
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -18,9 +18,284 @@ package org.jetbrains.jet.lang.resolve.calls
|
|||||||
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall
|
||||||
|
import org.jetbrains.jet.lang.types.JetType
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingTrace
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition.EXPECTED_TYPE_POSITION
|
||||||
|
import org.jetbrains.jet.lang.types.TypeUtils
|
||||||
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.CallCandidateResolutionContext
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData
|
||||||
|
import org.jetbrains.jet.lang.psi.ValueArgument
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMapping
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentUnmapped
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.model.ArgumentMatch
|
||||||
|
import org.jetbrains.jet.lang.psi.JetWhenExpression
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.DataFlowUtils
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.Call
|
||||||
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils
|
||||||
|
import org.jetbrains.jet.lang.psi.JetBlockExpression
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPsiUtil
|
||||||
|
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getCorrespondingCall
|
||||||
|
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
|
||||||
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace
|
||||||
|
|
||||||
public class CallCompleter(
|
public class CallCompleter(
|
||||||
val argumentTypeResolver: ArgumentTypeResolver,
|
val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
val candidateResolver: CandidateResolver
|
val candidateResolver: CandidateResolver
|
||||||
) {
|
) {
|
||||||
|
fun <D : CallableDescriptor> completeCall(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
results: OverloadResolutionResultsImpl<D>,
|
||||||
|
tracing: TracingStrategy
|
||||||
|
): OverloadResolutionResultsImpl<D> {
|
||||||
|
// for the case 'foo(a)' where 'foo' is a variable, the call 'foo.invoke(a)' shouldn't be completed separately,
|
||||||
|
// it's completed when the outer (variable as function call) is completed
|
||||||
|
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results
|
||||||
|
|
||||||
|
if (results.isSingleResult()) {
|
||||||
|
completeResolvedCall(results.getResultingCall(), context, tracing)
|
||||||
|
}
|
||||||
|
if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
|
||||||
|
completeArguments(context, results)
|
||||||
|
}
|
||||||
|
|
||||||
|
completeAllCandidates(context, results)
|
||||||
|
if (results.isSingleResult() && results.getResultingCall().getStatus().isSuccess()) {
|
||||||
|
return results.changeStatusToSuccess()
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> completeAllCandidates(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
results: OverloadResolutionResultsImpl<D>
|
||||||
|
) {
|
||||||
|
[suppress("UNCHECKED_CAST")]
|
||||||
|
val candidates = (if (context.collectAllCandidates) {
|
||||||
|
results.getAllCandidates()!!
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
results.getResultingCalls()
|
||||||
|
}) as Collection<MutableResolvedCall<D>>
|
||||||
|
|
||||||
|
candidates.filter { resolvedCall -> !resolvedCall.isCompleted() }.forEach {
|
||||||
|
resolvedCall ->
|
||||||
|
|
||||||
|
val temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "Trace to complete a candidate that is not a resulting call")
|
||||||
|
completeResolvedCall(resolvedCall, context.replaceBindingTrace(temporaryBindingTrace), TracingStrategy.EMPTY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> completeResolvedCall(
|
||||||
|
resolvedCall: MutableResolvedCall<D>,
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
tracing: TracingStrategy
|
||||||
|
) {
|
||||||
|
if (resolvedCall.isCompleted() || resolvedCall.getConstraintSystem() == null) {
|
||||||
|
resolvedCall.markCallAsCompleted()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedCall.completeConstraintSystem(context.expectedType, context.trace)
|
||||||
|
resolvedCall.updateResolutionStatusFromConstraintSystem(context, tracing)
|
||||||
|
resolvedCall.markCallAsCompleted()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> MutableResolvedCall<D>.completeConstraintSystem(
|
||||||
|
expectedType: JetType,
|
||||||
|
trace: BindingTrace
|
||||||
|
) {
|
||||||
|
fun updateSystemIfSuccessful(update: (ConstraintSystem) -> Boolean) {
|
||||||
|
val copy = getConstraintSystem()!!.copy()
|
||||||
|
if (update(copy)) {
|
||||||
|
setConstraintSystem(copy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnType = getCandidateDescriptor().getReturnType()
|
||||||
|
if (returnType != null) {
|
||||||
|
getConstraintSystem()!!.addSupertypeConstraint(expectedType, returnType, EXPECTED_TYPE_POSITION)
|
||||||
|
|
||||||
|
if (expectedType === TypeUtils.UNIT_EXPECTED_TYPE) {
|
||||||
|
updateSystemIfSuccessful {
|
||||||
|
system ->
|
||||||
|
system.addSupertypeConstraint(KotlinBuiltIns.getInstance().getUnitType(), returnType, EXPECTED_TYPE_POSITION)
|
||||||
|
system.getStatus().isSuccessful()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val constraintSystemCompleter = trace[CONSTRAINT_SYSTEM_COMPLETER, getCall().getCalleeExpression()]
|
||||||
|
if (constraintSystemCompleter != null) {
|
||||||
|
//todo improve error reporting with errors in constraints from completer
|
||||||
|
updateSystemIfSuccessful {
|
||||||
|
system ->
|
||||||
|
constraintSystemCompleter.completeConstraintSystem(system, this)
|
||||||
|
!system.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.FROM_COMPLETER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(getConstraintSystem() as ConstraintSystemImpl).processDeclaredBoundConstraints()
|
||||||
|
|
||||||
|
setResultingSubstitutor(getConstraintSystem()!!.getResultingSubstitutor())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
tracing: TracingStrategy
|
||||||
|
) {
|
||||||
|
val contextWithResolvedCall = CallCandidateResolutionContext.createForCallBeingAnalyzed(this, context, tracing)
|
||||||
|
val valueArgumentsCheckingResult = candidateResolver.checkAllValueArguments(
|
||||||
|
contextWithResolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS)
|
||||||
|
|
||||||
|
val status = getStatus()
|
||||||
|
if (getConstraintSystem()!!.getStatus().isSuccessful()) {
|
||||||
|
if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
||||||
|
setStatusToSuccess()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val receiverType = if (getReceiverArgument().exists()) getReceiverArgument().getType() else null
|
||||||
|
val errorData = InferenceErrorData.create(
|
||||||
|
getCandidateDescriptor(), getConstraintSystem()!!, valueArgumentsCheckingResult.argumentTypes,
|
||||||
|
receiverType, context.expectedType)
|
||||||
|
tracing.typeInferenceFailed(context.trace, errorData)
|
||||||
|
|
||||||
|
addStatus(ResolutionStatus.OTHER_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D : CallableDescriptor> completeArguments(
|
||||||
|
context: BasicCallResolutionContext,
|
||||||
|
results: OverloadResolutionResultsImpl<D>
|
||||||
|
) {
|
||||||
|
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return
|
||||||
|
|
||||||
|
val getArgumentMapping: (ValueArgument) -> ArgumentMapping
|
||||||
|
val getDataFlowInfoForArgument: (ValueArgument) -> DataFlowInfo
|
||||||
|
if (results.isSingleResult()) {
|
||||||
|
val resolvedCall = results.getResultingCall()
|
||||||
|
getArgumentMapping = { argument -> resolvedCall.getArgumentMapping(argument) }
|
||||||
|
getDataFlowInfoForArgument = {argument -> resolvedCall.getDataFlowInfoForArguments().getInfo(argument) }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getArgumentMapping = { ArgumentUnmapped }
|
||||||
|
getDataFlowInfoForArgument = { context.dataFlowInfo }
|
||||||
|
}
|
||||||
|
|
||||||
|
val arguments = ArrayList(context.call.getValueArguments())
|
||||||
|
arguments.addAll(context.call.getFunctionLiteralArguments().map { functionLiteral -> CallMaker.makeValueArgument(functionLiteral) })
|
||||||
|
|
||||||
|
for (valueArgument in arguments) {
|
||||||
|
val argumentMapping = getArgumentMapping(valueArgument!!)
|
||||||
|
val expectedType = when (argumentMapping) {
|
||||||
|
is ArgumentMatch -> CandidateResolver.getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument)
|
||||||
|
else -> TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
}
|
||||||
|
val newContext = context.replaceDataFlowInfo(getDataFlowInfoForArgument(valueArgument)).replaceExpectedType(expectedType)
|
||||||
|
completeOneArgument(valueArgument, newContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun completeOneArgument(
|
||||||
|
valueArgument: ValueArgument,
|
||||||
|
context: BasicCallResolutionContext
|
||||||
|
) {
|
||||||
|
val expression = valueArgument.getArgumentExpression()
|
||||||
|
if (expression == null) return
|
||||||
|
|
||||||
|
// for the 'in' call 'when (b) { in 1..10 -> true }' 'b' is an argument, but an error shouldn't be generated on it
|
||||||
|
// todo add special call type for such a case, and check this call type instead
|
||||||
|
val parent = expression.getParent()
|
||||||
|
if (parent is JetWhenExpression && expression == parent.getSubjectExpression()) return
|
||||||
|
|
||||||
|
val recordedType = context.trace[BindingContext.EXPRESSION_TYPE, expression]
|
||||||
|
var updatedType: JetType? = recordedType
|
||||||
|
|
||||||
|
val results = completeCallForArgument(expression, context)
|
||||||
|
if (results != null && results.isSingleResult()) {
|
||||||
|
val resolvedCall = results.getResultingCall()
|
||||||
|
updatedType = if (resolvedCall.hasInferredReturnType()) resolvedCall.getResultingDescriptor()?.getReturnType() else null
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||||
|
// so while the expected type is not known, it's IntegerValueType(1), and should be updated when the expected type is known.
|
||||||
|
if (recordedType != null && !recordedType.getConstructor().isDenotable()) {
|
||||||
|
updatedType = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context as ResolutionContext<*>, expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingContextUtils.updateRecordedType(updatedType, expression, context.trace, hasNecessarySafeCall(expression, context.trace))
|
||||||
|
|
||||||
|
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
|
||||||
|
// but they should be analyzed when the expected type is known (during the call completion).
|
||||||
|
if (ArgumentTypeResolver.isFunctionLiteralArgument(expression)) {
|
||||||
|
argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||||
|
expression, ArgumentTypeResolver.getFunctionLiteralArgument(expression),
|
||||||
|
context as CallResolutionContext<*>, RESOLVE_FUNCTION_ARGUMENTS)
|
||||||
|
}
|
||||||
|
|
||||||
|
DataFlowUtils.checkType(updatedType, expression, context as ResolutionContext<*>)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun completeCallForArgument(
|
||||||
|
expression: JetExpression,
|
||||||
|
context: BasicCallResolutionContext
|
||||||
|
): OverloadResolutionResultsImpl<*>? {
|
||||||
|
val argumentCall = getCallForArgument(expression, context.trace.getBindingContext())
|
||||||
|
if (argumentCall == null) return null
|
||||||
|
|
||||||
|
val cachedDataForCall = context.resolutionResultsCache[argumentCall]
|
||||||
|
if (cachedDataForCall == null) return null
|
||||||
|
|
||||||
|
val (cachedResolutionResults, cachedContext, tracing) = cachedDataForCall
|
||||||
|
[suppress("UNCHECKED_CAST")]
|
||||||
|
val cachedResults = cachedResolutionResults as OverloadResolutionResultsImpl<CallableDescriptor>
|
||||||
|
val contextForArgument = cachedContext.replaceBindingTrace(context.trace)
|
||||||
|
.replaceExpectedType(context.expectedType).replaceCollectAllCandidates(false)
|
||||||
|
|
||||||
|
return completeCall(contextForArgument, cachedResults, tracing)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCallForArgument(argument: JetExpression?, bindingContext: BindingContext): Call? {
|
||||||
|
if (!ExpressionTypingUtils.dependsOnExpectedType(argument)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (argument is JetBlockExpression) {
|
||||||
|
val lastStatement = JetPsiUtil.getLastStatementInABlock(argument)
|
||||||
|
return getCallForArgument(lastStatement as? JetExpression, bindingContext)
|
||||||
|
}
|
||||||
|
return argument?.getCorrespondingCall(bindingContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasNecessarySafeCall(expression: JetExpression, trace: BindingTrace): Boolean {
|
||||||
|
// We are interested in type of the last call:
|
||||||
|
// 'a.b?.foo()' is safe call, but 'a?.b.foo()' is not.
|
||||||
|
// Since receiver is 'a.b' and selector is 'foo()',
|
||||||
|
// we can only check if an expression is safe call.
|
||||||
|
if (expression !is JetSafeQualifiedExpression) return false
|
||||||
|
|
||||||
|
//If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
|
||||||
|
val expressionType = trace[BindingContext.EXPRESSION_TYPE, expression.getReceiverExpression()]
|
||||||
|
return expressionType != null && expressionType.isNullable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -339,12 +339,12 @@ public class CallResolver {
|
|||||||
OverloadResolutionResultsImpl<F> results = null;
|
OverloadResolutionResultsImpl<F> results = null;
|
||||||
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
|
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
|
||||||
if (!CallResolverUtil.isInvokeCallOnVariable(call)) {
|
if (!CallResolverUtil.isInvokeCallOnVariable(call)) {
|
||||||
OverloadResolutionResultsImpl<F> cachedResults = context.resolutionResultsCache.getResolutionResults(call);
|
ResolutionResultsCache.CachedData data = context.resolutionResultsCache.get(call);
|
||||||
if (cachedResults != null) {
|
if (data != null) {
|
||||||
DelegatingBindingTrace deltasTraceForResolve = context.resolutionResultsCache.getResolutionTrace(call);
|
DelegatingBindingTrace deltasTraceForResolve = data.getResolutionTrace();
|
||||||
assert deltasTraceForResolve != null;
|
|
||||||
deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
|
deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
|
||||||
results = cachedResults;
|
//noinspection unchecked
|
||||||
|
results = (OverloadResolutionResultsImpl<F>) data.getResolutionResults();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
@@ -360,7 +360,7 @@ public class CallResolver {
|
|||||||
traceToResolveCall.commit();
|
traceToResolveCall.commit();
|
||||||
|
|
||||||
if (context.contextDependency == ContextDependency.INDEPENDENT) {
|
if (context.contextDependency == ContextDependency.INDEPENDENT) {
|
||||||
results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
|
results = callCompleter.completeCall(context, results, tracing);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.isSingleResult()) {
|
if (results.isSingleResult()) {
|
||||||
@@ -388,38 +388,6 @@ public class CallResolver {
|
|||||||
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
|
candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> completeTypeInferenceDependentOnExpectedType(
|
|
||||||
@NotNull BasicCallResolutionContext context,
|
|
||||||
@NotNull OverloadResolutionResultsImpl<D> results,
|
|
||||||
@NotNull TracingStrategy tracing
|
|
||||||
) {
|
|
||||||
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return results;
|
|
||||||
|
|
||||||
if (!results.isSingleResult()) {
|
|
||||||
argumentTypeResolver.checkTypesForFunctionArgumentsWithNoCallee(context);
|
|
||||||
candidateResolver.completeNestedCallsForNotResolvedInvocation(context);
|
|
||||||
candidateResolver.completeTypeInferenceForAllCandidates(context, results);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
MutableResolvedCall<D> resolvedCall = results.getResultingCall();
|
|
||||||
|
|
||||||
Set<ValueArgument> unmappedArguments = resolvedCall.getUnmappedArguments();
|
|
||||||
argumentTypeResolver.checkUnmappedArgumentTypes(context, unmappedArguments);
|
|
||||||
candidateResolver.completeUnmappedArguments(context, unmappedArguments);
|
|
||||||
|
|
||||||
CallCandidateResolutionContext<D> callCandidateResolutionContext =
|
|
||||||
CallCandidateResolutionContext.createForCallBeingAnalyzed(resolvedCall, context, tracing);
|
|
||||||
candidateResolver.completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
|
|
||||||
|
|
||||||
candidateResolver.completeTypeInferenceForAllCandidates(context, results);
|
|
||||||
|
|
||||||
if (resolvedCall.getStatus().isSuccess()) {
|
|
||||||
return results.changeStatusToSuccess();
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <F extends CallableDescriptor> void cacheResults(
|
private static <F extends CallableDescriptor> void cacheResults(
|
||||||
@NotNull BasicCallResolutionContext context,
|
@NotNull BasicCallResolutionContext context,
|
||||||
@NotNull OverloadResolutionResultsImpl<F> results,
|
@NotNull OverloadResolutionResultsImpl<F> results,
|
||||||
@@ -433,14 +401,7 @@ public class CallResolver {
|
|||||||
BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
|
BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
|
||||||
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
|
traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
|
||||||
|
|
||||||
context.resolutionResultsCache.recordResolutionResults(call, results);
|
context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
|
||||||
context.resolutionResultsCache.recordResolutionTrace(call, deltasTraceToCacheResolve);
|
|
||||||
|
|
||||||
if (results.isSingleResult()) {
|
|
||||||
CallCandidateResolutionContext<F> contextForCallToCompleteTypeArgumentInference =
|
|
||||||
CallCandidateResolutionContext.createForCallBeingAnalyzed(results.getResultingCall(), context, tracing);
|
|
||||||
context.resolutionResultsCache.recordDeferredComputationForCall(call, contextForCallToCompleteTypeArgumentInference);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
|
||||||
|
|||||||
@@ -214,303 +214,6 @@ public class CandidateResolver {
|
|||||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public <D extends CallableDescriptor> JetType completeTypeInferenceDependentOnExpectedTypeForCall(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
|
||||||
boolean isInnerCall
|
|
||||||
) {
|
|
||||||
MutableResolvedCall<D> resolvedCall = context.candidateCall;
|
|
||||||
if (resolvedCall.isCompleted()) {
|
|
||||||
return resolvedCall.getResultingDescriptor().getReturnType();
|
|
||||||
}
|
|
||||||
if (!resolvedCall.hasIncompleteTypeParameters()) {
|
|
||||||
completeNestedCallsInference(context);
|
|
||||||
checkValueArgumentTypes(context);
|
|
||||||
resolvedCall.markCallAsCompleted();
|
|
||||||
return resolvedCall.getResultingDescriptor().getReturnType();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert resolvedCall.getConstraintSystem() != null;
|
|
||||||
|
|
||||||
JetType unsubstitutedReturnType = resolvedCall.getCandidateDescriptor().getReturnType();
|
|
||||||
if (unsubstitutedReturnType != null) {
|
|
||||||
resolvedCall.getConstraintSystem().addSupertypeConstraint(
|
|
||||||
context.expectedType, unsubstitutedReturnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSystemWithConstraintSystemCompleter(context, resolvedCall);
|
|
||||||
|
|
||||||
updateSystemIfExpectedTypeIsUnit(context, resolvedCall);
|
|
||||||
|
|
||||||
((ConstraintSystemImpl)resolvedCall.getConstraintSystem()).processDeclaredBoundConstraints();
|
|
||||||
|
|
||||||
JetType returnType;
|
|
||||||
if (!resolvedCall.getConstraintSystem().getStatus().isSuccessful()) {
|
|
||||||
returnType = reportInferenceError(context);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolvedCall.setResultingSubstitutor(resolvedCall.getConstraintSystem().getResultingSubstitutor());
|
|
||||||
|
|
||||||
completeNestedCallsInference(context);
|
|
||||||
// Here we type check the arguments with inferred types expected
|
|
||||||
checkAllValueArguments(context, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
|
|
||||||
|
|
||||||
resolvedCall.setHasIncompleteTypeParameters(false);
|
|
||||||
ResolutionStatus status = resolvedCall.getStatus();
|
|
||||||
if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) {
|
|
||||||
resolvedCall.setStatusToSuccess();
|
|
||||||
}
|
|
||||||
returnType = resolvedCall.getResultingDescriptor().getReturnType();
|
|
||||||
if (isInnerCall) {
|
|
||||||
PsiElement callElement = context.call.getCallElement();
|
|
||||||
if (callElement instanceof JetCallExpression) {
|
|
||||||
DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolvedCall.markCallAsCompleted();
|
|
||||||
return returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D extends CallableDescriptor> void completeTypeInferenceForAllCandidatesForArgument(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
|
||||||
@Nullable Call call
|
|
||||||
) {
|
|
||||||
// All candidates for inner calls are not needed, so there is no need to complete them
|
|
||||||
if (context.collectAllCandidates) return;
|
|
||||||
|
|
||||||
if (call == null) return;
|
|
||||||
|
|
||||||
OverloadResolutionResultsImpl<CallableDescriptor> resolutionResults = context.resolutionResultsCache.getResolutionResults(call);
|
|
||||||
if (resolutionResults == null) return;
|
|
||||||
|
|
||||||
completeTypeInferenceForAllCandidates(context.toBasic(), resolutionResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <D extends CallableDescriptor> void completeTypeInferenceForAllCandidates(
|
|
||||||
@NotNull BasicCallResolutionContext context,
|
|
||||||
@NotNull OverloadResolutionResultsImpl<D> results
|
|
||||||
) {
|
|
||||||
Collection<? extends ResolvedCall<D>> candidates;
|
|
||||||
if (context.collectAllCandidates) {
|
|
||||||
candidates = results.getAllCandidates();
|
|
||||||
assert candidates != null : "Should be guaranteed by collectAllCandidates == true";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
candidates = results.getResultingCalls();
|
|
||||||
}
|
|
||||||
for (ResolvedCall<D> resolvedCall : candidates) {
|
|
||||||
MutableResolvedCall<D> mutableResolvedCall = (MutableResolvedCall<D>) resolvedCall;
|
|
||||||
if (mutableResolvedCall.isCompleted()) continue;
|
|
||||||
|
|
||||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(
|
|
||||||
context.trace, "Trace to complete a candidate that is not a resulting call");
|
|
||||||
|
|
||||||
CallCandidateResolutionContext<D> callCandidateResolutionContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
|
|
||||||
mutableResolvedCall, context.replaceBindingTrace(temporaryBindingTrace), TracingStrategy.EMPTY);
|
|
||||||
|
|
||||||
completeTypeInferenceDependentOnExpectedTypeForCall(callCandidateResolutionContext, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void updateSystemWithConstraintSystemCompleter(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
|
||||||
@NotNull MutableResolvedCall<D> resolvedCall
|
|
||||||
) {
|
|
||||||
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
|
|
||||||
assert constraintSystem != null;
|
|
||||||
ConstraintSystemCompleter constraintSystemCompleter = context.trace.get(
|
|
||||||
BindingContext.CONSTRAINT_SYSTEM_COMPLETER, context.call.getCalleeExpression());
|
|
||||||
if (constraintSystemCompleter == null) return;
|
|
||||||
|
|
||||||
ConstraintSystem copy = constraintSystem.copy();
|
|
||||||
|
|
||||||
constraintSystemCompleter.completeConstraintSystem(copy, resolvedCall);
|
|
||||||
|
|
||||||
//todo improve error reporting with errors in constraints from completer
|
|
||||||
if (!copy.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.FROM_COMPLETER)) {
|
|
||||||
resolvedCall.setConstraintSystem(copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void updateSystemIfExpectedTypeIsUnit(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
|
||||||
@NotNull MutableResolvedCall<D> resolvedCall
|
|
||||||
) {
|
|
||||||
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
|
|
||||||
assert constraintSystem != null;
|
|
||||||
JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
|
|
||||||
if (returnType == null) return;
|
|
||||||
|
|
||||||
if (!constraintSystem.getStatus().isSuccessful() && context.expectedType == TypeUtils.UNIT_EXPECTED_TYPE) {
|
|
||||||
ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
|
|
||||||
|
|
||||||
copy.addSupertypeConstraint(KotlinBuiltIns.getInstance().getUnitType(), returnType, ConstraintPosition.EXPECTED_TYPE_POSITION);
|
|
||||||
if (copy.getStatus().isSuccessful()) {
|
|
||||||
resolvedCall.setConstraintSystem(copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D extends CallableDescriptor> JetType reportInferenceError(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context
|
|
||||||
) {
|
|
||||||
MutableResolvedCall<D> resolvedCall = context.candidateCall;
|
|
||||||
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
|
|
||||||
assert constraintSystem != null;
|
|
||||||
|
|
||||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
|
|
||||||
completeNestedCallsInference(context);
|
|
||||||
List<JetType> argumentTypes = checkValueArgumentTypes(
|
|
||||||
context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes;
|
|
||||||
JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
|
|
||||||
InferenceErrorData errorData = InferenceErrorData
|
|
||||||
.create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType);
|
|
||||||
|
|
||||||
context.tracing.typeInferenceFailed(context.trace, errorData);
|
|
||||||
resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR);
|
|
||||||
if (!resolvedCall.hasInferredReturnType()) return null;
|
|
||||||
return resolvedCall.getResultingDescriptor().getReturnType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public <D extends CallableDescriptor> void completeNestedCallsInference(
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context
|
|
||||||
) {
|
|
||||||
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
|
|
||||||
MutableResolvedCall<D> resolvedCall = context.candidateCall;
|
|
||||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
|
|
||||||
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
|
||||||
ResolvedValueArgument resolvedArgument = entry.getValue();
|
|
||||||
|
|
||||||
for (ValueArgument argument : resolvedArgument.getArguments()) {
|
|
||||||
completeInferenceForArgument(argument, parameterDescriptor, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completeUnmappedArguments(context, context.candidateCall.getUnmappedArguments());
|
|
||||||
recordReferenceForInvokeFunction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static Call getCallForArgument(@Nullable JetExpression argument, @NotNull BindingContext bindingContext) {
|
|
||||||
if (!ExpressionTypingUtils.dependsOnExpectedType(argument)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (argument instanceof JetBlockExpression) {
|
|
||||||
JetElement lastStatement = JetPsiUtil.getLastStatementInABlock((JetBlockExpression) argument);
|
|
||||||
if (lastStatement instanceof JetExpression) {
|
|
||||||
return getCallForArgument((JetExpression) lastStatement, bindingContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return BindingContextUtilPackage.getCorrespondingCall(argument, bindingContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D extends CallableDescriptor> void completeInferenceForArgument(
|
|
||||||
@NotNull ValueArgument argument,
|
|
||||||
@NotNull ValueParameterDescriptor parameterDescriptor,
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context
|
|
||||||
) {
|
|
||||||
JetExpression expression = argument.getArgumentExpression();
|
|
||||||
if (expression == null) return;
|
|
||||||
|
|
||||||
JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
|
|
||||||
context = context.replaceExpectedType(expectedType);
|
|
||||||
|
|
||||||
Call call = getCallForArgument(expression, context.trace.getBindingContext());
|
|
||||||
CallCandidateResolutionContext<?> storedContextForArgument = context.resolutionResultsCache.getDeferredComputation(call);
|
|
||||||
|
|
||||||
PsiElement parent = expression.getParent();
|
|
||||||
if (parent instanceof JetWhenExpression && expression == ((JetWhenExpression) parent).getSubjectExpression()
|
|
||||||
|| (expression instanceof JetFunctionLiteralExpression)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (storedContextForArgument == null) {
|
|
||||||
JetType type = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression);
|
|
||||||
checkResultArgumentType(type, argument, context);
|
|
||||||
completeTypeInferenceForAllCandidatesForArgument(context, call);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallCandidateResolutionContext<?> contextForArgument = storedContextForArgument
|
|
||||||
.replaceContextDependency(INDEPENDENT).replaceBindingTrace(context.trace).replaceExpectedType(expectedType);
|
|
||||||
JetType type = completeTypeInferenceDependentOnExpectedTypeForCall(contextForArgument, true);
|
|
||||||
JetType recordedType = context.trace.get(BindingContext.EXPRESSION_TYPE, expression);
|
|
||||||
if (recordedType != null && !recordedType.getConstructor().isDenotable()) {
|
|
||||||
type = ArgumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
JetType result = BindingContextUtils.updateRecordedType(
|
|
||||||
type, expression, context.trace, isFairSafeCallExpression(expression, context.trace));
|
|
||||||
|
|
||||||
completeTypeInferenceForAllCandidatesForArgument(context, call);
|
|
||||||
|
|
||||||
DataFlowUtils.checkType(result, expression, contextForArgument);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completeNestedCallsForNotResolvedInvocation(@NotNull CallResolutionContext<?> context) {
|
|
||||||
completeNestedCallsForNotResolvedInvocation(context, context.call.getValueArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void completeUnmappedArguments(@NotNull CallResolutionContext<?> context, @NotNull Collection<? extends ValueArgument> unmappedArguments) {
|
|
||||||
completeNestedCallsForNotResolvedInvocation(context, unmappedArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void completeNestedCallsForNotResolvedInvocation(@NotNull CallResolutionContext<?> context, @NotNull Collection<? extends ValueArgument> arguments) {
|
|
||||||
if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
|
|
||||||
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
|
|
||||||
|
|
||||||
for (ValueArgument argument : arguments) {
|
|
||||||
JetExpression expression = argument.getArgumentExpression();
|
|
||||||
|
|
||||||
Call call = getCallForArgument(expression, context.trace.getBindingContext());
|
|
||||||
CallCandidateResolutionContext<?> storedContextForArgument = context.resolutionResultsCache.getDeferredComputation(call);
|
|
||||||
if (storedContextForArgument == null) continue;
|
|
||||||
if (storedContextForArgument.candidateCall.isCompleted()) continue;
|
|
||||||
|
|
||||||
CallCandidateResolutionContext<?> newContext =
|
|
||||||
storedContextForArgument.replaceBindingTrace(context.trace).replaceContextDependency(INDEPENDENT);
|
|
||||||
completeTypeInferenceDependentOnExpectedTypeForCall(newContext, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isFairSafeCallExpression(@NotNull JetExpression expression, @NotNull BindingTrace trace) {
|
|
||||||
// We are interested in type of the last call:
|
|
||||||
// 'a.b?.foo()' is safe call, but 'a?.b.foo()' is not.
|
|
||||||
// Since receiver is 'a.b' and selector is 'foo()',
|
|
||||||
// we can only check if an expression is safe call.
|
|
||||||
if (!(expression instanceof JetSafeQualifiedExpression)) return false;
|
|
||||||
|
|
||||||
JetSafeQualifiedExpression safeQualifiedExpression = (JetSafeQualifiedExpression) expression;
|
|
||||||
//If a receiver type is not null, then this safe expression is useless, and we don't need to make the result type nullable.
|
|
||||||
JetType type = trace.get(BindingContext.EXPRESSION_TYPE, safeQualifiedExpression.getReceiverExpression());
|
|
||||||
return type != null && type.isNullable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void checkResultArgumentType(
|
|
||||||
@Nullable JetType type,
|
|
||||||
@NotNull ValueArgument argument,
|
|
||||||
@NotNull CallCandidateResolutionContext<D> context
|
|
||||||
) {
|
|
||||||
JetExpression expression = argument.getArgumentExpression();
|
|
||||||
if (expression == null) return;
|
|
||||||
|
|
||||||
DataFlowInfo dataFlowInfoForValueArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(argument);
|
|
||||||
ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(
|
|
||||||
dataFlowInfoForValueArgument);
|
|
||||||
DataFlowUtils.checkType(type, expression, newContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
|
|
||||||
PsiElement callElement = context.call.getCallElement();
|
|
||||||
if (!(callElement instanceof JetCallExpression)) return;
|
|
||||||
|
|
||||||
JetCallExpression callExpression = (JetCallExpression) callElement;
|
|
||||||
if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
|
|
||||||
CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
|
|
||||||
context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
|
|
||||||
context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, context.candidateCall.getCandidateDescriptor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
|
private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
|
||||||
@NotNull ValueArgument valueArgument,
|
@NotNull ValueArgument valueArgument,
|
||||||
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
@NotNull ValueParameterDescriptor valueParameterDescriptor,
|
||||||
@@ -647,9 +350,7 @@ public class CandidateResolver {
|
|||||||
if (!hasContradiction) {
|
if (!hasContradiction) {
|
||||||
return INCOMPLETE_TYPE_INFERENCE;
|
return INCOMPLETE_TYPE_INFERENCE;
|
||||||
}
|
}
|
||||||
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SHAPE_FUNCTION_ARGUMENTS);
|
return OTHER_ERROR;
|
||||||
ResolutionStatus argumentsStatus = checkingResult.status;
|
|
||||||
return OTHER_ERROR.combine(argumentsStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConstraintForValueArgument(
|
private void addConstraintForValueArgument(
|
||||||
@@ -699,13 +400,15 @@ public class CandidateResolver {
|
|||||||
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
|
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
@NotNull CallCandidateResolutionContext<D> context,
|
||||||
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
||||||
return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
|
return checkAllValueArguments(context, context.candidateCall.getTrace(), resolveFunctionArgumentBodies);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
@NotNull
|
||||||
|
public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
|
||||||
@NotNull CallCandidateResolutionContext<D> context,
|
@NotNull CallCandidateResolutionContext<D> context,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
|
@NotNull CallResolverUtil.ResolveArgumentsMode resolveFunctionArgumentBodies
|
||||||
@@ -746,12 +449,7 @@ public class CandidateResolver {
|
|||||||
return resultStatus;
|
return resultStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <D extends CallableDescriptor> ValueArgumentsCheckingResult checkValueArgumentTypes(
|
@NotNull
|
||||||
@NotNull CallCandidateResolutionContext<D> context
|
|
||||||
) {
|
|
||||||
return checkValueArgumentTypes(context, context.candidateCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
|
private <D extends CallableDescriptor, C extends CallResolutionContext<C>> ValueArgumentsCheckingResult checkValueArgumentTypes(
|
||||||
@NotNull CallResolutionContext<C> context,
|
@NotNull CallResolutionContext<C> context,
|
||||||
@NotNull MutableResolvedCall<D> candidateCall,
|
@NotNull MutableResolvedCall<D> candidateCall,
|
||||||
@@ -903,9 +601,10 @@ public class CandidateResolver {
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ValueArgumentsCheckingResult {
|
public static class ValueArgumentsCheckingResult {
|
||||||
|
@NotNull
|
||||||
public final List<JetType> argumentTypes;
|
public final List<JetType> argumentTypes;
|
||||||
|
@NotNull
|
||||||
public final ResolutionStatus status;
|
public final ResolutionStatus status;
|
||||||
|
|
||||||
private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
|
private ValueArgumentsCheckingResult(@NotNull ResolutionStatus status, @NotNull List<JetType> argumentTypes) {
|
||||||
@@ -915,7 +614,7 @@ public class CandidateResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
|
public static JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
|
||||||
if (argument.getSpreadElement() != null) {
|
if (argument.getSpreadElement() != null) {
|
||||||
if (parameterDescriptor.getVarargElementType() == null) {
|
if (parameterDescriptor.getVarargElementType() == null) {
|
||||||
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
|
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
|
||||||
|
|||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.context;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
|
||||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
|
||||||
|
|
||||||
public interface ResolutionResultsCache {
|
|
||||||
|
|
||||||
<D extends CallableDescriptor> void recordResolutionResults(@NotNull Call call, @NotNull OverloadResolutionResultsImpl<D> results);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
<D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(@NotNull Call call);
|
|
||||||
|
|
||||||
void recordResolutionTrace(@NotNull Call call, @NotNull DelegatingBindingTrace delegatingTrace);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
DelegatingBindingTrace getResolutionTrace(@NotNull Call call);
|
|
||||||
|
|
||||||
<D extends CallableDescriptor> void recordDeferredComputationForCall(
|
|
||||||
@NotNull Call call,
|
|
||||||
@NotNull CallCandidateResolutionContext<D> deferredComputation
|
|
||||||
);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
CallCandidateResolutionContext<?> getDeferredComputation(@Nullable Call call);
|
|
||||||
}
|
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.lang.resolve.calls.context
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl
|
||||||
|
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression
|
||||||
|
import java.util.HashMap
|
||||||
|
import org.jetbrains.jet.lang.psi.Call
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCache.CachedData
|
||||||
|
|
||||||
|
public trait ResolutionResultsCache {
|
||||||
|
public data class CachedData(
|
||||||
|
val resolutionResults: OverloadResolutionResultsImpl<*>,
|
||||||
|
val deferredComputation: BasicCallResolutionContext,
|
||||||
|
val tracing: TracingStrategy,
|
||||||
|
val resolutionTrace: DelegatingBindingTrace
|
||||||
|
)
|
||||||
|
|
||||||
|
fun record(
|
||||||
|
call: Call,
|
||||||
|
results: OverloadResolutionResultsImpl<*>,
|
||||||
|
deferredComputation: BasicCallResolutionContext,
|
||||||
|
tracing: TracingStrategy,
|
||||||
|
resolutionTrace: DelegatingBindingTrace
|
||||||
|
)
|
||||||
|
|
||||||
|
fun get(call: Call): CachedData?
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResolutionResultsCacheImpl : ResolutionResultsCache {
|
||||||
|
private val data = HashMap<Call, CachedData>()
|
||||||
|
|
||||||
|
override fun record(
|
||||||
|
call: Call,
|
||||||
|
results: OverloadResolutionResultsImpl<out CallableDescriptor?>,
|
||||||
|
deferredComputation: BasicCallResolutionContext,
|
||||||
|
tracing: TracingStrategy,
|
||||||
|
resolutionTrace: DelegatingBindingTrace
|
||||||
|
) {
|
||||||
|
data[call] = CachedData(results, deferredComputation, tracing, resolutionTrace)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(call: Call): CachedData? = data[call]
|
||||||
|
|
||||||
|
fun addData(cache: ResolutionResultsCacheImpl) {
|
||||||
|
data.putAll(cache.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TemporaryResolutionResultsCache(private val parentCache: ResolutionResultsCache) : ResolutionResultsCache {
|
||||||
|
private val innerCache = ResolutionResultsCacheImpl()
|
||||||
|
|
||||||
|
override fun record(
|
||||||
|
call: Call,
|
||||||
|
results: OverloadResolutionResultsImpl<out CallableDescriptor?>,
|
||||||
|
deferredComputation: BasicCallResolutionContext,
|
||||||
|
tracing: TracingStrategy,
|
||||||
|
resolutionTrace: DelegatingBindingTrace
|
||||||
|
) {
|
||||||
|
innerCache.record(call, results, deferredComputation, tracing, resolutionTrace)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(call: Call): CachedData? = innerCache[call] ?: parentCache[call]
|
||||||
|
|
||||||
|
public fun commit() {
|
||||||
|
when (parentCache) {
|
||||||
|
is ResolutionResultsCacheImpl -> parentCache.addData(innerCache)
|
||||||
|
is TemporaryResolutionResultsCache -> parentCache.innerCache.addData(innerCache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-66
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.context
|
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl
|
|
||||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression
|
|
||||||
import java.util.HashMap
|
|
||||||
import org.jetbrains.jet.lang.psi.Call
|
|
||||||
|
|
||||||
class ResolutionResultsCacheImpl : ResolutionResultsCache {
|
|
||||||
private class CachedData(
|
|
||||||
var results: OverloadResolutionResultsImpl<*>? = null,
|
|
||||||
var resolutionTrace: DelegatingBindingTrace? = null,
|
|
||||||
var deferredComputation: CallCandidateResolutionContext<*>? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
private val data = HashMap<Call, CachedData>()
|
|
||||||
|
|
||||||
private fun getOrCreateCachedInfo(call: Call) = data.getOrPut(call, { CachedData() })
|
|
||||||
|
|
||||||
override fun <D : CallableDescriptor?> recordResolutionResults(call: Call, results: OverloadResolutionResultsImpl<D>) {
|
|
||||||
getOrCreateCachedInfo(call).results = results
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <D : CallableDescriptor?> getResolutionResults(call: Call): OverloadResolutionResultsImpl<D>? {
|
|
||||||
return data[call]?.results as OverloadResolutionResultsImpl<D>?
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun recordResolutionTrace(call: Call, delegatingTrace: DelegatingBindingTrace) {
|
|
||||||
getOrCreateCachedInfo(call).resolutionTrace = delegatingTrace
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getResolutionTrace(call: Call): DelegatingBindingTrace? {
|
|
||||||
return data[call]?.resolutionTrace
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <D : CallableDescriptor?> recordDeferredComputationForCall(call: Call, deferredComputation: CallCandidateResolutionContext<D>) {
|
|
||||||
getOrCreateCachedInfo(call).deferredComputation = deferredComputation
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDeferredComputation(call: Call?): CallCandidateResolutionContext<out CallableDescriptor?>? {
|
|
||||||
if (call == null) return null
|
|
||||||
|
|
||||||
return data[call]?.deferredComputation
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addData(cache: ResolutionResultsCacheImpl) {
|
|
||||||
data.putAll(cache.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-100
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.context;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
|
||||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
|
||||||
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
|
|
||||||
|
|
||||||
public class TemporaryResolutionResultsCache implements ResolutionResultsCache {
|
|
||||||
private final ResolutionResultsCache parentCache;
|
|
||||||
private final ResolutionResultsCacheImpl innerCache;
|
|
||||||
|
|
||||||
public TemporaryResolutionResultsCache(@NotNull ResolutionResultsCache parentCache) {
|
|
||||||
assert parentCache instanceof ResolutionResultsCacheImpl || parentCache instanceof TemporaryResolutionResultsCache :
|
|
||||||
"Unsupported parent cache: " + parentCache;
|
|
||||||
this.parentCache = parentCache;
|
|
||||||
this.innerCache = new ResolutionResultsCacheImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void recordResolutionResults(
|
|
||||||
@NotNull Call call,
|
|
||||||
@NotNull OverloadResolutionResultsImpl<D> results
|
|
||||||
) {
|
|
||||||
innerCache.recordResolutionResults(call, results);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> getResolutionResults(
|
|
||||||
@NotNull Call call
|
|
||||||
) {
|
|
||||||
OverloadResolutionResultsImpl<D> results = innerCache.getResolutionResults(call);
|
|
||||||
if (results != null) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
return parentCache.getResolutionResults(call);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordResolutionTrace(
|
|
||||||
@NotNull Call call, @NotNull DelegatingBindingTrace delegatingTrace
|
|
||||||
) {
|
|
||||||
innerCache.recordResolutionTrace(call, delegatingTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public DelegatingBindingTrace getResolutionTrace(@NotNull Call call) {
|
|
||||||
DelegatingBindingTrace trace = innerCache.getResolutionTrace(call);
|
|
||||||
if (trace != null) {
|
|
||||||
return trace;
|
|
||||||
}
|
|
||||||
return parentCache.getResolutionTrace(call);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <D extends CallableDescriptor> void recordDeferredComputationForCall(
|
|
||||||
@NotNull Call call,
|
|
||||||
@NotNull CallCandidateResolutionContext<D> deferredComputation
|
|
||||||
) {
|
|
||||||
innerCache.recordDeferredComputationForCall(call, deferredComputation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public CallCandidateResolutionContext<?> getDeferredComputation(@Nullable Call call) {
|
|
||||||
CallCandidateResolutionContext<?> computation = innerCache.getDeferredComputation(call);
|
|
||||||
if (computation != null) {
|
|
||||||
return computation;
|
|
||||||
}
|
|
||||||
return parentCache.getDeferredComputation(call);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void commit() {
|
|
||||||
if (parentCache instanceof ResolutionResultsCacheImpl) {
|
|
||||||
((ResolutionResultsCacheImpl) parentCache).addData(innerCache);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert parentCache instanceof TemporaryResolutionResultsCache;
|
|
||||||
((TemporaryResolutionResultsCache) parentCache).innerCache.addData(innerCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -192,6 +192,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
|||||||
assert substitutedVersion != null : entry.getKey();
|
assert substitutedVersion != null : entry.getKey();
|
||||||
valueArguments.put(substitutedVersion, entry.getValue());
|
valueArguments.put(substitutedVersion, entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<ValueArgument, ArgumentMatch> originalArgumentToParameterMap = Maps.newLinkedHashMap(argumentToParameterMap);
|
||||||
|
argumentToParameterMap.clear();
|
||||||
|
for (Map.Entry<ValueArgument, ArgumentMatch> entry : originalArgumentToParameterMap.entrySet()) {
|
||||||
|
ArgumentMatch argumentMatch = entry.getValue();
|
||||||
|
ValueParameterDescriptor substitutedVersion = parameterMap.get(argumentMatch.getValueParameter().getOriginal());
|
||||||
|
assert substitutedVersion != null : argumentMatch.getValueParameter();
|
||||||
|
argumentToParameterMap.put(entry.getKey(), new ArgumentMatch(substitutedVersion, argumentMatch.getHasTypeMismatch()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+7
@@ -16,11 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls.tasks;
|
package org.jetbrains.jet.lang.resolve.calls.tasks;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
import org.jetbrains.jet.lang.psi.Call;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -55,6 +58,10 @@ public class TracingStrategyForInvoke extends AbstractTracingStrategy {
|
|||||||
public <D extends CallableDescriptor> void bindReference(
|
public <D extends CallableDescriptor> void bindReference(
|
||||||
@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall
|
@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall
|
||||||
) {
|
) {
|
||||||
|
PsiElement callElement = call.getCallElement();
|
||||||
|
if (callElement instanceof JetReferenceExpression) {
|
||||||
|
trace.record(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) callElement, resolvedCall.getCandidateDescriptor());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ package org.jetbrains.jet.lang.resolve.calls.util;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
|
||||||
import org.jetbrains.jet.lang.psi.Call.CallType;
|
import org.jetbrains.jet.lang.psi.Call.CallType;
|
||||||
import org.jetbrains.jet.lang.psi.debugText.DebugTextPackage;
|
import org.jetbrains.jet.lang.psi.debugText.DebugTextPackage;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
@@ -69,6 +67,23 @@ public class CallMaker {
|
|||||||
public LeafPsiElement getSpreadElement() {
|
public LeafPsiElement getSpreadElement() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
ExpressionValueArgument argument = (ExpressionValueArgument) o;
|
||||||
|
|
||||||
|
if (expression != null ? !expression.equals(argument.expression) : argument.expression != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return expression != null ? expression.hashCode() : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CallImpl implements Call {
|
private static class CallImpl implements Call {
|
||||||
|
|||||||
+1
-1
@@ -163,7 +163,7 @@ public class ControlStructureTypingUtils {
|
|||||||
) {
|
) {
|
||||||
final List<ValueArgument> valueArguments = Lists.newArrayList();
|
final List<ValueArgument> valueArguments = Lists.newArrayList();
|
||||||
for (JetExpression argument : arguments) {
|
for (JetExpression argument : arguments) {
|
||||||
valueArguments.add(CallMaker.makeValueArgument(argument, argument));
|
valueArguments.add(CallMaker.makeValueArgument(argument));
|
||||||
}
|
}
|
||||||
return new Call() {
|
return new Call() {
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.DEPENDENT;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
|
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.*;
|
import static org.jetbrains.jet.lang.types.TypeUtils.*;
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ class Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
<!TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH!>with<!>("", {
|
<!TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH!>with<!>("", <!TYPE_MISMATCH!>{
|
||||||
Foo.<!MISSING_RECEIVER, TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findByName<!>("")
|
Foo.<!MISSING_RECEIVER, TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findByName<!>("")
|
||||||
})
|
}<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> with(t: T, f: T.() -> Unit) {}
|
fun <T> with(t: T, f: T.() -> Unit) {}
|
||||||
Reference in New Issue
Block a user