Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.resolve.calls.CallResolver Maven / Gradle / Ivy
/*
* Copyright 2010-2015 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.kotlin.resolve.calls;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Condition;
import com.intellij.util.containers.ContainerUtil;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
import org.jetbrains.kotlin.resolve.calls.context.*;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.tasks.*;
import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
import org.jetbrains.kotlin.resolve.calls.tower.NewResolveOldInference;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeSubstitutor;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingVisitorDispatcher;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import org.jetbrains.kotlin.util.PerformanceCounter;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.EXIT_ON_FIRST_ERROR;
import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.FULLY;
import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
@SuppressWarnings("RedundantTypeArguments")
public class CallResolver {
private ExpressionTypingServices expressionTypingServices;
private TypeResolver typeResolver;
private CandidateResolver candidateResolver;
private ArgumentTypeResolver argumentTypeResolver;
private GenericCandidateResolver genericCandidateResolver;
private CallCompleter callCompleter;
private NewResolveOldInference newCallResolver;
private final TaskPrioritizer taskPrioritizer;
private final ResolutionResultsHandler resolutionResultsHandler;
@NotNull private KotlinBuiltIns builtIns;
private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
public static boolean useNewResolve = System.getProperty("kotlin.internal.new_resolve") != null;
public CallResolver(
@NotNull TaskPrioritizer taskPrioritizer,
@NotNull ResolutionResultsHandler resolutionResultsHandler,
@NotNull KotlinBuiltIns builtIns
) {
this.taskPrioritizer = taskPrioritizer;
this.resolutionResultsHandler = resolutionResultsHandler;
this.builtIns = builtIns;
}
// component dependency cycle
@Inject
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
this.expressionTypingServices = expressionTypingServices;
}
// component dependency cycle
@Inject
public void setTypeResolver(@NotNull TypeResolver typeResolver) {
this.typeResolver = typeResolver;
}
// component dependency cycle
@Inject
public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
this.candidateResolver = candidateResolver;
}
// component dependency cycle
@Inject
public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
this.argumentTypeResolver = argumentTypeResolver;
}
// component dependency cycle
@Inject
public void setGenericCandidateResolver(GenericCandidateResolver genericCandidateResolver) {
this.genericCandidateResolver = genericCandidateResolver;
}
// component dependency cycle
@Inject
public void setCallCompleter(@NotNull CallCompleter callCompleter) {
this.callCompleter = callCompleter;
}
// component dependency cycle
@Inject
public void setCallCompleter(@NotNull NewResolveOldInference newCallResolver) {
this.newCallResolver = newCallResolver;
}
@NotNull
public OverloadResolutionResults resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
KtExpression calleeExpression = context.call.getCalleeExpression();
assert calleeExpression instanceof KtSimpleNameExpression;
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) calleeExpression;
Name referencedName = nameExpression.getReferencedNameAsName();
CallableDescriptorCollectors callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
return computeTasksAndResolveCall(
context, referencedName, nameExpression,
callableDescriptorCollectors, CallTransformer.VARIABLE_CALL_TRANSFORMER, ResolveKind.VARIABLE);
}
@NotNull
public OverloadResolutionResults resolveCallForMember(
@NotNull KtSimpleNameExpression nameExpression,
@NotNull BasicCallResolutionContext context
) {
return computeTasksAndResolveCall(
context, nameExpression.getReferencedNameAsName(), nameExpression,
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.MEMBER_CALL_TRANSFORMER, ResolveKind.CALLABLE_REFERENCE);
}
@NotNull
public OverloadResolutionResults resolveCallWithGivenName(
@NotNull ExpressionTypingContext context,
@NotNull Call call,
@NotNull KtReferenceExpression functionReference,
@NotNull Name name
) {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
return computeTasksAndResolveCall(
callResolutionContext, name, functionReference,
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER, ResolveKind.FUNCTION);
}
@NotNull
public OverloadResolutionResults resolveCallForInvoke(
@NotNull BasicCallResolutionContext context,
@NotNull TracingStrategy tracing
) {
return computeTasksAndResolveCall(
context, OperatorNameConventions.INVOKE, tracing,
CallableDescriptorCollectors.FUNCTIONS, CallTransformer.FUNCTION_CALL_TRANSFORMER,
ResolveKind.INVOKE);
}
@NotNull
private OverloadResolutionResults computeTasksAndResolveCall(
@NotNull BasicCallResolutionContext context,
@NotNull Name name,
@NotNull KtReferenceExpression referenceExpression,
@NotNull CallableDescriptorCollectors collectors,
@NotNull CallTransformer callTransformer,
@NotNull ResolveKind kind
) {
TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
return computeTasksAndResolveCall(context, name, tracing, collectors, callTransformer, kind);
}
@NotNull
private OverloadResolutionResults computeTasksAndResolveCall(
@NotNull final BasicCallResolutionContext context,
@NotNull final Name name,
@NotNull final TracingStrategy tracing,
@NotNull final CallableDescriptorCollectors collectors,
@NotNull final CallTransformer callTransformer,
@NotNull final ResolveKind kind
) {
return callResolvePerfCounter.time(new Function0>() {
@Override
public OverloadResolutionResults invoke() {
TaskContextForMigration contextForMigration = new TaskContextForMigration(
kind, callTransformer, name, null,
new Function0>>() {
@Override
public List> invoke() {
return taskPrioritizer.computePrioritizedTasks(context, name, tracing, collectors);
}
});
return doResolveCallOrGetCachedResults(context, contextForMigration, tracing);
}
});
}
@NotNull
private OverloadResolutionResults computeTasksFromCandidatesAndResolvedCall(
@NotNull BasicCallResolutionContext context,
@NotNull KtReferenceExpression referenceExpression,
@NotNull Collection> candidates,
@NotNull CallTransformer callTransformer
) {
return computeTasksFromCandidatesAndResolvedCall(context, candidates, callTransformer,
TracingStrategyImpl.create(referenceExpression, context.call));
}
@NotNull
private OverloadResolutionResults computeTasksFromCandidatesAndResolvedCall(
@NotNull final BasicCallResolutionContext context,
@NotNull final Collection> candidates,
@NotNull final CallTransformer callTransformer,
@NotNull final TracingStrategy tracing
) {
return callResolvePerfCounter.time(new Function0>() {
@Override
public OverloadResolutionResults invoke() {
TaskContextForMigration contextForMigration = new TaskContextForMigration(
ResolveKind.GIVEN_CANDIDATES, callTransformer, null, candidates,
new Function0>>() {
@Override
public List> invoke() {
return taskPrioritizer.computePrioritizedTasksFromCandidates(
context, candidates, tracing);
}
});
return doResolveCallOrGetCachedResults(context, contextForMigration, tracing);
}
});
}
@NotNull
public OverloadResolutionResults resolveBinaryCall(
ExpressionTypingContext context,
ExpressionReceiver receiver,
KtBinaryExpression binaryExpression,
Name name
) {
return resolveCallWithGivenName(
context,
CallMaker.makeCall(receiver, binaryExpression),
binaryExpression.getOperationReference(),
name
);
}
@NotNull
public OverloadResolutionResults resolveFunctionCall(
@NotNull BindingTrace trace,
@NotNull LexicalScope scope,
@NotNull Call call,
@NotNull KotlinType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
boolean isAnnotationContext
) {
return resolveFunctionCall(
BasicCallResolutionContext.create(
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
CallChecker.DoNothing.INSTANCE$, isAnnotationContext
)
);
}
@NotNull
public OverloadResolutionResults resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
Call.CallType callType = context.call.getCallType();
if (callType == Call.CallType.ARRAY_GET_METHOD || callType == Call.CallType.ARRAY_SET_METHOD) {
Name name = Name.identifier(callType == Call.CallType.ARRAY_GET_METHOD ? "get" : "set");
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) context.call.getCallElement();
return computeTasksAndResolveCall(
context, name, arrayAccessExpression,
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES,
CallTransformer.FUNCTION_CALL_TRANSFORMER,
ResolveKind.FUNCTION);
}
KtExpression calleeExpression = context.call.getCalleeExpression();
if (calleeExpression instanceof KtSimpleNameExpression) {
KtSimpleNameExpression expression = (KtSimpleNameExpression) calleeExpression;
return computeTasksAndResolveCall(
context, expression.getReferencedNameAsName(), expression,
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER, ResolveKind.FUNCTION);
}
else if (calleeExpression instanceof KtConstructorCalleeExpression) {
return resolveCallForConstructor(context, (KtConstructorCalleeExpression) calleeExpression);
}
else if (calleeExpression instanceof KtConstructorDelegationReferenceExpression) {
KtConstructorDelegationCall delegationCall = (KtConstructorDelegationCall) context.call.getCallElement();
DeclarationDescriptor container = context.scope.getOwnerDescriptor();
assert container instanceof ConstructorDescriptor : "Trying to resolve JetConstructorDelegationCall not in constructor. scope.ownerDescriptor = " + container;
return resolveConstructorDelegationCall(context, delegationCall, (KtConstructorDelegationReferenceExpression) calleeExpression,
(ConstructorDescriptor) container);
}
else if (calleeExpression == null) {
return checkArgumentTypesAndFail(context);
}
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
KotlinType expectedType = NO_EXPECTED_TYPE;
if (calleeExpression instanceof KtFunctionLiteralExpression) {
int parameterNumber = ((KtFunctionLiteralExpression) calleeExpression).getValueParameters().size();
List parameterTypes = new ArrayList(parameterNumber);
for (int i = 0; i < parameterNumber; i++) {
parameterTypes.add(NO_EXPECTED_TYPE);
}
expectedType = builtIns.getFunctionType(Annotations.Companion.getEMPTY(), null, parameterTypes, context.expectedType);
}
KotlinType calleeType = expressionTypingServices.safeGetType(
context.scope, calleeExpression, expectedType, context.dataFlowInfo, context.trace);
ExpressionReceiver expressionReceiver = ExpressionReceiver.Companion.create(calleeExpression, calleeType, context.trace.getBindingContext());
Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
}
private OverloadResolutionResults resolveCallForConstructor(
@NotNull BasicCallResolutionContext context,
@NotNull KtConstructorCalleeExpression expression
) {
assert !context.call.getExplicitReceiver().exists() :
"Constructor can't be invoked with explicit receiver: " + context.call.getCallElement().getText();
context.trace.record(BindingContext.LEXICAL_SCOPE, context.call.getCallElement(), context.scope);
KtReferenceExpression functionReference = expression.getConstructorReferenceExpression();
KtTypeReference typeReference = expression.getTypeReference();
if (functionReference == null || typeReference == null) {
return checkArgumentTypesAndFail(context); // No type there
}
KotlinType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
if (constructedType.isError()) {
return checkArgumentTypesAndFail(context);
}
DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
if (!(declarationDescriptor instanceof ClassDescriptor)) {
context.trace.report(NOT_A_CLASS.on(expression));
return checkArgumentTypesAndFail(context);
}
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
Collection constructors = classDescriptor.getConstructors();
if (constructors.isEmpty()) {
context.trace.report(NO_CONSTRUCTOR.on(CallUtilKt.getValueArgumentListOrElement(context.call)));
return checkArgumentTypesAndFail(context);
}
Collection> candidates =
taskPrioritizer.convertWithImpliedThisAndNoReceiver(context.scope, constructors, context.call);
return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
}
@Nullable
public OverloadResolutionResults resolveConstructorDelegationCall(
@NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull DataFlowInfo dataFlowInfo,
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull KtConstructorDelegationCall call, @NotNull CallChecker callChecker
) {
// Method returns `null` when there is nothing to resolve in trivial cases like `null` call expression or
// when super call should be conventional enum constructor and super call should be empty
BasicCallResolutionContext context = BasicCallResolutionContext.create(
trace, scope,
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
NO_EXPECTED_TYPE,
dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
callChecker, false);
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
if (constructorDescriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.isImplicit()) {
return null;
}
return resolveConstructorDelegationCall(
context,
call,
call.getCalleeExpression(),
constructorDescriptor
);
}
@NotNull
private OverloadResolutionResults resolveConstructorDelegationCall(
@NotNull BasicCallResolutionContext context,
@NotNull KtConstructorDelegationCall call,
@NotNull KtConstructorDelegationReferenceExpression calleeExpression,
@NotNull ConstructorDescriptor calleeConstructor
) {
context.trace.record(BindingContext.LEXICAL_SCOPE, call, context.scope);
ClassDescriptor currentClassDescriptor = calleeConstructor.getContainingDeclaration();
boolean isThisCall = calleeExpression.isThis();
if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
context.trace.report(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(calleeExpression));
return checkArgumentTypesAndFail(context);
}
ClassDescriptor delegateClassDescriptor = isThisCall ? currentClassDescriptor :
DescriptorUtilsKt.getSuperClassOrAny(currentClassDescriptor);
Collection constructors = delegateClassDescriptor.getConstructors();
if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
if (DescriptorUtils.canHaveDeclaredConstructors(currentClassDescriptor)) {
// Diagnostic is meaningless when reporting on interfaces and object
context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
(KtConstructorDelegationCall) calleeExpression.getParent()
));
}
if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound();
}
if (constructors.isEmpty()) {
context.trace.report(NO_CONSTRUCTOR.on(CallUtilKt.getValueArgumentListOrElement(context.call)));
return checkArgumentTypesAndFail(context);
}
List> candidates = Lists.newArrayList();
ReceiverValue constructorDispatchReceiver = !delegateClassDescriptor.isInner() ? ReceiverValue.NO_RECEIVER :
((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()).
getThisAsReceiverParameter().getValue();
KotlinType expectedType = isThisCall ?
calleeConstructor.getContainingDeclaration().getDefaultType() :
DescriptorUtils.getSuperClassType(currentClassDescriptor);
TypeSubstitutor knownTypeParametersSubstitutor = TypeSubstitutor.create(expectedType);
for (CallableDescriptor descriptor : constructors) {
candidates.add(ResolutionCandidate.create(
context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
knownTypeParametersSubstitutor));
}
TracingStrategy tracing = call.isImplicit() ?
new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) :
TracingStrategyImpl.create(calleeExpression, context.call);
return computeTasksFromCandidatesAndResolvedCall(context, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
}
public OverloadResolutionResults resolveCallWithKnownCandidate(
@NotNull final Call call,
@NotNull final TracingStrategy tracing,
@NotNull final ResolutionContext> context,
@NotNull final ResolutionCandidate candidate,
@Nullable final MutableDataFlowInfoForArguments dataFlowInfoForArguments
) {
return callResolvePerfCounter.time(new Function0>() {
@Override
public OverloadResolutionResults invoke() {
final BasicCallResolutionContext basicCallResolutionContext =
BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, dataFlowInfoForArguments);
final Set> candidates = Collections.singleton(candidate);
TaskContextForMigration contextForMigration =
new TaskContextForMigration(
ResolveKind.GIVEN_CANDIDATES, CallTransformer.FUNCTION_CALL_TRANSFORMER, null, candidates,
new Function0>>() {
@Override
public List> invoke() {
return taskPrioritizer.computePrioritizedTasksFromCandidates(
basicCallResolutionContext, candidates, tracing);
}
}
);
return doResolveCallOrGetCachedResults(basicCallResolutionContext, contextForMigration, tracing);
}
});
}
private OverloadResolutionResultsImpl doResolveCallOrGetCachedResults(
@NotNull BasicCallResolutionContext context,
@NotNull TaskContextForMigration contextForMigration,
@NotNull TracingStrategy tracing
) {
Call call = context.call;
tracing.bindCall(context.trace, call);
TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
BindingContextUtilsKt.recordScope(newContext.trace, newContext.scope, newContext.call.getCalleeExpression());
BindingContextUtilsKt.recordDataFlowInfo(newContext, newContext.call.getCalleeExpression());
OverloadResolutionResultsImpl results = doResolveCall(newContext, contextForMigration, tracing);
DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
if (deltasTraceForTypeInference != null) {
deltasTraceForTypeInference.addOwnDataTo(traceToResolveCall);
}
completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
if (context.contextDependency == ContextDependency.DEPENDENT) {
cacheResults(context, results, traceToResolveCall, tracing);
}
traceToResolveCall.commit();
if (context.contextDependency == ContextDependency.INDEPENDENT) {
results = callCompleter.completeCall(context, results, tracing);
}
return results;
}
private void completeTypeInferenceDependentOnFunctionLiterals(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResultsImpl results,
@NotNull TracingStrategy tracing
) {
if (CallResolverUtilKt.isInvokeCallOnVariable(context.call)) return;
if (!results.isSingleResult()) {
if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
}
return;
}
CallCandidateResolutionContext candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
results.getResultingCall(), context, tracing);
genericCandidateResolver.completeTypeInferenceDependentOnFunctionArgumentsForCall(candidateContext);
}
private static void cacheResults(
@NotNull BasicCallResolutionContext context,
@NotNull OverloadResolutionResultsImpl results,
@NotNull DelegatingBindingTrace traceToResolveCall,
@NotNull TracingStrategy tracing
) {
Call call = context.call;
if (CallResolverUtilKt.isInvokeCallOnVariable(call)) return;
DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
traceToResolveCall.addOwnDataTo(deltasTraceToCacheResolve);
context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
}
private OverloadResolutionResultsImpl checkArgumentTypesAndFail(BasicCallResolutionContext context) {
argumentTypeResolver.checkTypesWithNoCallee(context);
return OverloadResolutionResultsImpl.nameNotFound();
}
@NotNull
private OverloadResolutionResultsImpl doResolveCall(
@NotNull BasicCallResolutionContext context,
@NotNull TaskContextForMigration contextForMigration,
@NotNull TracingStrategy tracing
) {
if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
}
List typeArguments = context.call.getTypeArguments();
for (KtTypeProjection projection : typeArguments) {
if (projection.getProjectionKind() != KtProjectionKind.NONE) {
context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
ModifierCheckerCore.INSTANCE.check(projection, context.trace, null);
}
KotlinType type = argumentTypeResolver.resolveTypeRefWithDefault(
projection.getTypeReference(), context.scope, context.trace,
null);
if (type != null) {
ForceResolveUtil.forceResolveAllContents(type);
}
}
if (contextForMigration.resolveKind != ResolveKind.GIVEN_CANDIDATES && useNewResolve) {
assert contextForMigration.name != null;
return (OverloadResolutionResultsImpl)
newCallResolver.runResolve(context, contextForMigration.name, contextForMigration.resolveKind, tracing);
}
return doResolveCall(context, contextForMigration.lazyTasks.invoke(), contextForMigration.callTransformer, tracing);
}
@NotNull
private OverloadResolutionResultsImpl doResolveCall(
@NotNull BasicCallResolutionContext context,
@NotNull List> prioritizedTasks, // high to low priority
@NotNull CallTransformer callTransformer,
@NotNull TracingStrategy tracing
) {
Collection> allCandidates = Lists.newArrayList();
OverloadResolutionResultsImpl successfulResults = null;
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask task : prioritizedTasks) {
if (task.getCandidates().isEmpty()) continue;
TemporaryBindingTrace taskTrace =
TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
OverloadResolutionResultsImpl results = performResolution(task.replaceBindingTrace(taskTrace), callTransformer);
allCandidates.addAll(task.getResolvedCalls());
if (successfulResults != null) continue;
if (results.isSuccess() || results.isAmbiguity()) {
taskTrace.commit();
successfulResults = results;
}
if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
results.setTrace(taskTrace);
successfulResults = results;
}
boolean updateResults = traceForFirstNonemptyCandidateSet == null
|| (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
&& results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
traceForFirstNonemptyCandidateSet = taskTrace;
resultsForFirstNonemptyCandidateSet = results;
}
if (successfulResults != null && !context.collectAllCandidates) break;
}
OverloadResolutionResultsImpl results;
if (successfulResults != null) {
results = successfulResults;
}
else if (traceForFirstNonemptyCandidateSet == null) {
tracing.unresolvedReference(context.trace);
argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
results = OverloadResolutionResultsImpl.nameNotFound();
}
else {
traceForFirstNonemptyCandidateSet.commit();
results = resultsForFirstNonemptyCandidateSet;
}
results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
return results;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private OverloadResolutionResultsImpl performResolution(
@NotNull ResolutionTask task,
@NotNull CallTransformer callTransformer
) {
CandidateResolveMode mode = task.collectAllCandidates ? FULLY : EXIT_ON_FIRST_ERROR;
List> contexts = collectCallCandidateContext(task, callTransformer, mode);
boolean isSuccess = ContainerUtil.exists(contexts, new Condition>() {
@Override
public boolean value(CallCandidateResolutionContext context) {
return context.candidateCall.getStatus().possibleTransformToSuccess();
}
});
if (!isSuccess && mode == EXIT_ON_FIRST_ERROR) {
contexts = collectCallCandidateContext(task, callTransformer, FULLY);
}
for (CallCandidateResolutionContext context : contexts) {
addResolvedCall(task, callTransformer, context);
}
OverloadResolutionResultsImpl results = resolutionResultsHandler.computeResultAndReportErrors(
task, task.tracing, task.getResolvedCalls());
if (!results.isSingleResult() && !results.isIncomplete()) {
argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
}
return results;
}
@NotNull
private List> collectCallCandidateContext(
@NotNull final ResolutionTask task,
@NotNull final CallTransformer callTransformer,
@NotNull final CandidateResolveMode candidateResolveMode
) {
final List> candidateResolutionContexts = ContainerUtil.newArrayList();
for (final ResolutionCandidate resolutionCandidate : task.getCandidates()) {
if (DeprecationUtilKt.isAnnotatedAsHidden(resolutionCandidate.getDescriptor())) continue;
candidatePerfCounter.time(new Function0() {
@Override
public Unit invoke() {
TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
task.trace, "trace to resolve candidate");
Collection> contexts =
callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace, candidateResolveMode);
for (CallCandidateResolutionContext context : contexts) {
candidateResolver.performResolutionForCandidateCall(context, task.checkArguments);
candidateResolutionContexts.add(context);
}
return Unit.INSTANCE$;
}
});
}
return candidateResolutionContexts;
}
private void addResolvedCall(
@NotNull ResolutionTask task,
@NotNull CallTransformer callTransformer,
@NotNull CallCandidateResolutionContext context) {
/* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
to have a binding to variable while 'invoke' call resolve */
task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
Collection> resolvedCalls = callTransformer.transformCall(context, this, task);
for (MutableResolvedCall resolvedCall : resolvedCalls) {
BindingTrace trace = resolvedCall.getTrace();
task.tracing.bindReference(trace, resolvedCall);
task.tracing.bindResolvedCall(trace, resolvedCall);
task.addResolvedCall(resolvedCall);
}
}
private static class TaskContextForMigration {
@NotNull
final Function0>> lazyTasks;
@NotNull
final CallTransformer callTransformer;
@Nullable
final Name name;
@Nullable
final Collection> givenCandidates;
@NotNull
final ResolveKind resolveKind;
private TaskContextForMigration(
@NotNull ResolveKind kind,
@NotNull CallTransformer transformer,
@Nullable Name name,
@Nullable Collection> candidates, @NotNull Function0>> tasks
) {
lazyTasks = tasks;
callTransformer = transformer;
this.name = name;
givenCandidates = candidates;
resolveKind = kind;
}
}
public enum ResolveKind {
FUNCTION,
INVOKE,
VARIABLE,
CALLABLE_REFERENCE,
GIVEN_CANDIDATES,
}
}