001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.resolve.calls;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.util.Condition;
021 import com.intellij.util.containers.ContainerUtil;
022 import kotlin.Unit;
023 import kotlin.jvm.functions.Function0;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
027 import org.jetbrains.kotlin.descriptors.*;
028 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
029 import org.jetbrains.kotlin.lexer.JetTokens;
030 import org.jetbrains.kotlin.name.Name;
031 import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
032 import org.jetbrains.kotlin.psi.*;
033 import org.jetbrains.kotlin.resolve.*;
034 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilPackage;
035 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
036 import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
037 import org.jetbrains.kotlin.resolve.calls.context.*;
038 import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
039 import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
040 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
041 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
042 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
043 import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler;
044 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
045 import org.jetbrains.kotlin.resolve.calls.tasks.*;
046 import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
047 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
048 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
049 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
050 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
051 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
052 import org.jetbrains.kotlin.resolve.scopes.utils.UtilsPackage;
053 import org.jetbrains.kotlin.types.JetType;
054 import org.jetbrains.kotlin.types.TypeSubstitutor;
055 import org.jetbrains.kotlin.types.TypeUtils;
056 import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
057 import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
058 import org.jetbrains.kotlin.types.expressions.ExpressionTypingVisitorDispatcher;
059 import org.jetbrains.kotlin.types.expressions.OperatorConventions;
060 import org.jetbrains.kotlin.util.PerformanceCounter;
061
062 import javax.inject.Inject;
063 import java.util.ArrayList;
064 import java.util.Collection;
065 import java.util.Collections;
066 import java.util.List;
067
068 import static org.jetbrains.kotlin.diagnostics.Errors.*;
069 import static org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage.recordScopeAndDataFlowInfo;
070 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
071 import static org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
072 import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.EXIT_ON_FIRST_ERROR;
073 import static org.jetbrains.kotlin.resolve.calls.context.CandidateResolveMode.FULLY;
074 import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
075 import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE;
076 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
077
078 @SuppressWarnings("RedundantTypeArguments")
079 public class CallResolver {
080 private ExpressionTypingServices expressionTypingServices;
081 private TypeResolver typeResolver;
082 private CandidateResolver candidateResolver;
083 private ArgumentTypeResolver argumentTypeResolver;
084 private GenericCandidateResolver genericCandidateResolver;
085 private CallCompleter callCompleter;
086 private final TaskPrioritizer taskPrioritizer;
087 private final ResolutionResultsHandler resolutionResultsHandler;
088 @NotNull private KotlinBuiltIns builtIns;
089
090 private static final PerformanceCounter callResolvePerfCounter = PerformanceCounter.Companion.create("Call resolve", ExpressionTypingVisitorDispatcher.typeInfoPerfCounter);
091 private static final PerformanceCounter candidatePerfCounter = PerformanceCounter.Companion.create("Call resolve candidate analysis", true);
092
093 public CallResolver(
094 @NotNull TaskPrioritizer taskPrioritizer,
095 @NotNull ResolutionResultsHandler resolutionResultsHandler,
096 @NotNull KotlinBuiltIns builtIns
097 ) {
098 this.taskPrioritizer = taskPrioritizer;
099 this.resolutionResultsHandler = resolutionResultsHandler;
100 this.builtIns = builtIns;
101 }
102
103 // component dependency cycle
104 @Inject
105 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
106 this.expressionTypingServices = expressionTypingServices;
107 }
108
109 // component dependency cycle
110 @Inject
111 public void setTypeResolver(@NotNull TypeResolver typeResolver) {
112 this.typeResolver = typeResolver;
113 }
114
115 // component dependency cycle
116 @Inject
117 public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
118 this.candidateResolver = candidateResolver;
119 }
120
121 // component dependency cycle
122 @Inject
123 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
124 this.argumentTypeResolver = argumentTypeResolver;
125 }
126
127 // component dependency cycle
128 @Inject
129 public void setGenericCandidateResolver(GenericCandidateResolver genericCandidateResolver) {
130 this.genericCandidateResolver = genericCandidateResolver;
131 }
132
133 // component dependency cycle
134 @Inject
135 public void setCallCompleter(@NotNull CallCompleter callCompleter) {
136 this.callCompleter = callCompleter;
137 }
138
139 @NotNull
140 public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
141 JetExpression calleeExpression = context.call.getCalleeExpression();
142 assert calleeExpression instanceof JetSimpleNameExpression;
143 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
144 Name referencedName = nameExpression.getReferencedNameAsName();
145 CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
146 if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
147 referencedName = Name.identifier(referencedName.asString().substring(1));
148 callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
149 }
150 else {
151 callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
152 }
153 return computeTasksAndResolveCall(
154 context, referencedName, nameExpression,
155 callableDescriptorCollectors, CallTransformer.VARIABLE_CALL_TRANSFORMER);
156 }
157
158 @NotNull
159 public OverloadResolutionResults<CallableDescriptor> resolveCallForMember(
160 @NotNull JetSimpleNameExpression nameExpression,
161 @NotNull BasicCallResolutionContext context
162 ) {
163 return computeTasksAndResolveCall(
164 context, nameExpression.getReferencedNameAsName(), nameExpression,
165 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.MEMBER_CALL_TRANSFORMER);
166 }
167
168 @NotNull
169 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
170 @NotNull ExpressionTypingContext context,
171 @NotNull Call call,
172 @NotNull JetReferenceExpression functionReference,
173 @NotNull Name name
174 ) {
175 BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
176 return computeTasksAndResolveCall(
177 callResolutionContext, name, functionReference,
178 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
179 }
180
181 @NotNull
182 public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
183 @NotNull BasicCallResolutionContext context,
184 @NotNull TracingStrategy tracing
185 ) {
186 return computeTasksAndResolveCall(
187 context, OperatorConventions.INVOKE, tracing,
188 CallableDescriptorCollectors.FUNCTIONS, CallTransformer.FUNCTION_CALL_TRANSFORMER);
189 }
190
191 @NotNull
192 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
193 @NotNull BasicCallResolutionContext context,
194 @NotNull Name name,
195 @NotNull JetReferenceExpression referenceExpression,
196 @NotNull CallableDescriptorCollectors<D> collectors,
197 @NotNull CallTransformer<D, F> callTransformer
198 ) {
199 TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
200 return computeTasksAndResolveCall(context, name, tracing, collectors, callTransformer);
201 }
202
203 @NotNull
204 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
205 @NotNull final BasicCallResolutionContext context,
206 @NotNull final Name name,
207 @NotNull final TracingStrategy tracing,
208 @NotNull final CallableDescriptorCollectors<D> collectors,
209 @NotNull final CallTransformer<D, F> callTransformer
210 ) {
211 return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
212 @Override
213 public OverloadResolutionResults<F> invoke() {
214 List<ResolutionTask<D, F>> tasks = taskPrioritizer.<D, F>computePrioritizedTasks(context, name, tracing, collectors);
215 return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
216 }
217 });
218 }
219
220 @NotNull
221 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
222 @NotNull BasicCallResolutionContext context,
223 @NotNull JetReferenceExpression referenceExpression,
224 @NotNull Collection<ResolutionCandidate<D>> candidates,
225 @NotNull CallTransformer<D, F> callTransformer
226 ) {
227 return computeTasksFromCandidatesAndResolvedCall(context, candidates, callTransformer,
228 TracingStrategyImpl.create(referenceExpression, context.call));
229 }
230
231 @NotNull
232 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
233 @NotNull final BasicCallResolutionContext context,
234 @NotNull final Collection<ResolutionCandidate<D>> candidates,
235 @NotNull final CallTransformer<D, F> callTransformer,
236 @NotNull final TracingStrategy tracing
237 ) {
238 return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<F>>() {
239 @Override
240 public OverloadResolutionResults<F> invoke() {
241 List<ResolutionTask<D, F>> prioritizedTasks =
242 taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
243 return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
244 }
245 });
246 }
247
248 @NotNull
249 public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
250 ExpressionTypingContext context,
251 ExpressionReceiver receiver,
252 JetBinaryExpression binaryExpression,
253 Name name
254 ) {
255 return resolveCallWithGivenName(
256 context,
257 CallMaker.makeCall(receiver, binaryExpression),
258 binaryExpression.getOperationReference(),
259 name
260 );
261 }
262
263 @NotNull
264 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
265 @NotNull BindingTrace trace,
266 @NotNull LexicalScope scope,
267 @NotNull Call call,
268 @NotNull JetType expectedType,
269 @NotNull DataFlowInfo dataFlowInfo,
270 boolean isAnnotationContext
271 ) {
272 return resolveFunctionCall(
273 BasicCallResolutionContext.create(
274 trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
275 CallChecker.DoNothing.INSTANCE$, isAnnotationContext
276 )
277 );
278 }
279
280 @NotNull
281 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
282 ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
283
284 JetExpression calleeExpression = context.call.getCalleeExpression();
285 if (calleeExpression instanceof JetSimpleNameExpression) {
286 JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
287 return computeTasksAndResolveCall(
288 context, expression.getReferencedNameAsName(), expression,
289 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
290 }
291 if (calleeExpression instanceof JetConstructorCalleeExpression) {
292 return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
293 }
294 else if (calleeExpression == null) {
295 return checkArgumentTypesAndFail(context);
296 }
297
298 // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
299 JetType expectedType = NO_EXPECTED_TYPE;
300 if (calleeExpression instanceof JetFunctionLiteralExpression) {
301 int parameterNumber = ((JetFunctionLiteralExpression) calleeExpression).getValueParameters().size();
302 List<JetType> parameterTypes = new ArrayList<JetType>(parameterNumber);
303 for (int i = 0; i < parameterNumber; i++) {
304 parameterTypes.add(NO_EXPECTED_TYPE);
305 }
306 expectedType = builtIns.getFunctionType(Annotations.EMPTY, null, parameterTypes, context.expectedType);
307 }
308 JetType calleeType = expressionTypingServices.safeGetType(
309 context.scope, calleeExpression, expectedType, context.dataFlowInfo, context.trace);
310 ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
311
312 Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
313 TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
314 return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
315 }
316
317 private OverloadResolutionResults<FunctionDescriptor> resolveCallForConstructor(
318 @NotNull BasicCallResolutionContext context,
319 @NotNull JetConstructorCalleeExpression expression
320 ) {
321 assert !context.call.getExplicitReceiver().exists() :
322 "Constructor can't be invoked with explicit receiver: " + context.call.getCallElement().getText();
323
324 JetReferenceExpression functionReference = expression.getConstructorReferenceExpression();
325 JetTypeReference typeReference = expression.getTypeReference();
326 if (functionReference == null || typeReference == null) {
327 return checkArgumentTypesAndFail(context); // No type there
328 }
329 JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
330 if (constructedType.isError()) {
331 return checkArgumentTypesAndFail(context);
332 }
333
334 DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
335 if (!(declarationDescriptor instanceof ClassDescriptor)) {
336 context.trace.report(NOT_A_CLASS.on(expression));
337 return checkArgumentTypesAndFail(context);
338 }
339 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
340 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
341 if (constructors.isEmpty()) {
342 context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
343 return checkArgumentTypesAndFail(context);
344 }
345 Collection<ResolutionCandidate<CallableDescriptor>> candidates =
346 taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(context.scope, constructors, context.call);
347
348 return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
349 }
350
351 @Nullable
352 public OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
353 @NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull DataFlowInfo dataFlowInfo,
354 @NotNull ConstructorDescriptor constructorDescriptor,
355 @NotNull JetConstructorDelegationCall call, @NotNull CallChecker callChecker
356 ) {
357 // Method returns `null` when there is nothing to resolve in trivial cases like `null` call expression or
358 // when super call should be conventional enum constructor and super call should be empty
359
360 BasicCallResolutionContext context = BasicCallResolutionContext.create(
361 trace, scope,
362 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
363 NO_EXPECTED_TYPE,
364 dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
365 callChecker, false);
366
367 if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
368
369 if (constructorDescriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.isImplicit()) {
370 return null;
371 }
372
373 return resolveConstructorDelegationCall(
374 context,
375 call,
376 call.getCalleeExpression(),
377 constructorDescriptor
378 );
379 }
380
381 @NotNull
382 private OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
383 @NotNull BasicCallResolutionContext context,
384 @NotNull JetConstructorDelegationCall call,
385 @NotNull JetConstructorDelegationReferenceExpression calleeExpression,
386 @NotNull ConstructorDescriptor calleeConstructor
387 ) {
388 ClassDescriptor currentClassDescriptor = calleeConstructor.getContainingDeclaration();
389
390 boolean isThisCall = calleeExpression.isThis();
391 if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
392 context.trace.report(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(calleeExpression));
393 return checkArgumentTypesAndFail(context);
394 }
395
396 ClassDescriptor delegateClassDescriptor = isThisCall ? currentClassDescriptor :
397 DescriptorUtilPackage.getSuperClassOrAny(currentClassDescriptor);
398 Collection<ConstructorDescriptor> constructors = delegateClassDescriptor.getConstructors();
399
400 if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
401 if (DescriptorUtils.canHaveDeclaredConstructors(currentClassDescriptor)) {
402 // Diagnostic is meaningless when reporting on interfaces and object
403 context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
404 (JetConstructorDelegationCall) calleeExpression.getParent()
405 ));
406 }
407 if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound();
408 }
409
410 if (constructors.isEmpty()) {
411 context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
412 return checkArgumentTypesAndFail(context);
413 }
414
415 List<ResolutionCandidate<CallableDescriptor>> candidates = Lists.newArrayList();
416 ReceiverValue constructorDispatchReceiver = !delegateClassDescriptor.isInner() ? ReceiverValue.NO_RECEIVER :
417 ((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()).
418 getThisAsReceiverParameter().getValue();
419
420 JetType expectedType = isThisCall ?
421 calleeConstructor.getContainingDeclaration().getDefaultType() :
422 DescriptorUtils.getSuperClassType(currentClassDescriptor);
423
424 TypeSubstitutor knownTypeParametersSubstitutor = TypeSubstitutor.create(expectedType);
425 for (CallableDescriptor descriptor : constructors) {
426 candidates.add(ResolutionCandidate.create(
427 context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER,
428 ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
429 knownTypeParametersSubstitutor));
430 }
431
432 TracingStrategy tracing = call.isImplicit() ?
433 new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) :
434 TracingStrategyImpl.create(calleeExpression, context.call);
435
436 return computeTasksFromCandidatesAndResolvedCall(context, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
437 }
438
439 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
440 @NotNull final Call call,
441 @NotNull final TracingStrategy tracing,
442 @NotNull final ResolutionContext<?> context,
443 @NotNull final ResolutionCandidate<CallableDescriptor> candidate,
444 @Nullable final MutableDataFlowInfoForArguments dataFlowInfoForArguments
445 ) {
446 return callResolvePerfCounter.time(new Function0<OverloadResolutionResults<FunctionDescriptor>>() {
447 @Override
448 public OverloadResolutionResults<FunctionDescriptor> invoke() {
449 BasicCallResolutionContext basicCallResolutionContext =
450 BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, dataFlowInfoForArguments);
451
452 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
453 taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
454 basicCallResolutionContext, Collections.singleton(candidate), tracing);
455 return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
456 }
457 });
458 }
459
460 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
461 @NotNull BasicCallResolutionContext context,
462 @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
463 @NotNull CallTransformer<D, F> callTransformer,
464 @NotNull TracingStrategy tracing
465 ) {
466 Call call = context.call;
467 tracing.bindCall(context.trace, call);
468
469 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
470 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
471
472 recordScopeAndDataFlowInfo(newContext, newContext.call.getCalleeExpression());
473 OverloadResolutionResultsImpl<F> results = doResolveCall(newContext, prioritizedTasks, callTransformer, tracing);
474 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
475 if (deltasTraceForTypeInference != null) {
476 deltasTraceForTypeInference.addOwnDataTo(traceToResolveCall);
477 }
478 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
479 if (context.contextDependency == ContextDependency.DEPENDENT) {
480 cacheResults(context, results, traceToResolveCall, tracing);
481 }
482 traceToResolveCall.commit();
483
484 if (context.contextDependency == ContextDependency.INDEPENDENT) {
485 results = callCompleter.completeCall(context, results, tracing);
486 }
487
488 return results;
489 }
490
491 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
492 @NotNull BasicCallResolutionContext context,
493 @NotNull OverloadResolutionResultsImpl<D> results,
494 @NotNull TracingStrategy tracing
495 ) {
496 if (CallResolverUtilPackage.isInvokeCallOnVariable(context.call)) return;
497 if (!results.isSingleResult()) {
498 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
499 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
500 }
501 return;
502 }
503
504 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
505 results.getResultingCall(), context, tracing);
506 genericCandidateResolver.completeTypeInferenceDependentOnFunctionArgumentsForCall(candidateContext);
507 }
508
509 private static <F extends CallableDescriptor> void cacheResults(
510 @NotNull BasicCallResolutionContext context,
511 @NotNull OverloadResolutionResultsImpl<F> results,
512 @NotNull DelegatingBindingTrace traceToResolveCall,
513 @NotNull TracingStrategy tracing
514 ) {
515 Call call = context.call;
516 if (CallResolverUtilPackage.isInvokeCallOnVariable(call)) return;
517
518 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
519 BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
520 traceToResolveCall.addOwnDataTo(deltasTraceToCacheResolve);
521
522 context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
523 }
524
525 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
526 argumentTypeResolver.checkTypesWithNoCallee(context);
527 return OverloadResolutionResultsImpl.nameNotFound();
528 }
529
530 @NotNull
531 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
532 @NotNull BasicCallResolutionContext context,
533 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
534 @NotNull CallTransformer<D, F> callTransformer,
535 @NotNull TracingStrategy tracing
536 ) {
537 if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
538 argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
539 }
540 Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
541 OverloadResolutionResultsImpl<F> successfulResults = null;
542 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
543 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
544 for (ResolutionTask<D, F> task : prioritizedTasks) {
545 if (task.getCandidates().isEmpty()) continue;
546
547 TemporaryBindingTrace taskTrace =
548 TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
549 OverloadResolutionResultsImpl<F> results = performResolution(task.replaceBindingTrace(taskTrace), callTransformer);
550
551
552 allCandidates.addAll(task.getResolvedCalls());
553
554 if (successfulResults != null) continue;
555
556 if (results.isSuccess() || results.isAmbiguity()) {
557 taskTrace.commit();
558 successfulResults = results;
559 }
560 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
561 results.setTrace(taskTrace);
562 successfulResults = results;
563 }
564 boolean updateResults = traceForFirstNonemptyCandidateSet == null
565 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
566 && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
567 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
568 traceForFirstNonemptyCandidateSet = taskTrace;
569 resultsForFirstNonemptyCandidateSet = results;
570 }
571
572 if (successfulResults != null && !context.collectAllCandidates) break;
573 }
574 OverloadResolutionResultsImpl<F> results;
575 if (successfulResults != null) {
576 results = successfulResults;
577 }
578 else if (traceForFirstNonemptyCandidateSet == null) {
579 tracing.unresolvedReference(context.trace);
580 argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
581 results = OverloadResolutionResultsImpl.<F>nameNotFound();
582 }
583 else {
584 traceForFirstNonemptyCandidateSet.commit();
585 results = resultsForFirstNonemptyCandidateSet;
586 }
587 results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
588 return results;
589 }
590
591 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
592
593 @NotNull
594 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
595 @NotNull ResolutionTask<D, F> task,
596 @NotNull CallTransformer<D, F> callTransformer
597 ) {
598 List<CallCandidateResolutionContext<D>> contexts = collectCallCandidateContext(task, callTransformer, EXIT_ON_FIRST_ERROR);
599 boolean isSuccess = ContainerUtil.exists(contexts, new Condition<CallCandidateResolutionContext<D>>() {
600 @Override
601 public boolean value(CallCandidateResolutionContext<D> context) {
602 return context.candidateCall.getStatus().possibleTransformToSuccess();
603 }
604 });
605 if (!isSuccess) {
606 contexts = collectCallCandidateContext(task, callTransformer, FULLY);
607 }
608
609 for (CallCandidateResolutionContext<D> context : contexts) {
610 addResolvedCall(task, callTransformer, context);
611 }
612
613 OverloadResolutionResultsImpl<F> results = resolutionResultsHandler.computeResultAndReportErrors(
614 task, task.getResolvedCalls());
615 if (!results.isSingleResult() && !results.isIncomplete()) {
616 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
617 }
618 return results;
619 }
620
621 @NotNull
622 private <D extends CallableDescriptor, F extends D> List<CallCandidateResolutionContext<D>> collectCallCandidateContext(
623 @NotNull final ResolutionTask<D, F> task,
624 @NotNull final CallTransformer<D, F> callTransformer,
625 @NotNull final CandidateResolveMode candidateResolveMode
626 ) {
627 final List<CallCandidateResolutionContext<D>> candidateResolutionContexts = ContainerUtil.newArrayList();
628 for (final ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
629 if (DescriptorUtilPackage.isAnnotatedAsHidden(resolutionCandidate.getDescriptor())) continue;
630
631 candidatePerfCounter.time(new Function0<Unit>() {
632 @Override
633 public Unit invoke() {
634 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
635 task.trace, "trace to resolve candidate");
636 Collection<CallCandidateResolutionContext<D>> contexts =
637 callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace, candidateResolveMode);
638 for (CallCandidateResolutionContext<D> context : contexts) {
639 candidateResolver.performResolutionForCandidateCall(context, task);
640 candidateResolutionContexts.add(context);
641 }
642 return Unit.INSTANCE$;
643 }
644 });
645 }
646 return candidateResolutionContexts;
647 }
648
649 private <D extends CallableDescriptor, F extends D> void addResolvedCall(
650 @NotNull ResolutionTask<D, F> task,
651 @NotNull CallTransformer<D, F> callTransformer,
652 @NotNull CallCandidateResolutionContext<D> context) {
653 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
654 to have a binding to variable while 'invoke' call resolve */
655 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
656
657 Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, this, task);
658
659 for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
660 BindingTrace trace = resolvedCall.getTrace();
661 task.tracing.bindReference(trace, resolvedCall);
662 task.tracing.bindResolvedCall(trace, resolvedCall);
663 task.addResolvedCall(resolvedCall);
664 }
665 }
666 }