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.progress.ProgressIndicatorProvider;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.descriptors.*;
024 import org.jetbrains.kotlin.lexer.JetTokens;
025 import org.jetbrains.kotlin.name.Name;
026 import org.jetbrains.kotlin.psi.*;
027 import org.jetbrains.kotlin.resolve.*;
028 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
029 import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
030 import org.jetbrains.kotlin.resolve.calls.context.*;
031 import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
032 import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
033 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
034 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
035 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
036 import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler;
037 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
038 import org.jetbrains.kotlin.resolve.calls.tasks.*;
039 import org.jetbrains.kotlin.resolve.calls.tasks.collectors.CallableDescriptorCollectors;
040 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
041 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
042 import org.jetbrains.kotlin.resolve.scopes.JetScope;
043 import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
044 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
045 import org.jetbrains.kotlin.types.JetType;
046 import org.jetbrains.kotlin.types.TypeSubstitutor;
047 import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
048 import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
049 import org.jetbrains.kotlin.types.expressions.OperatorConventions;
050
051 import javax.inject.Inject;
052 import java.util.Collection;
053 import java.util.Collections;
054 import java.util.List;
055
056 import static org.jetbrains.kotlin.diagnostics.Errors.*;
057 import static org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilPackage.recordScopeAndDataFlowInfo;
058 import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS;
059 import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
060 import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.CANDIDATES_WITH_WRONG_RECEIVER;
061 import static org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults.Code.INCOMPLETE_TYPE_INFERENCE;
062 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
063
064 @SuppressWarnings("RedundantTypeArguments")
065 public class CallResolver {
066 private ExpressionTypingServices expressionTypingServices;
067 private TypeResolver typeResolver;
068 private CandidateResolver candidateResolver;
069 private ArgumentTypeResolver argumentTypeResolver;
070 private CallCompleter callCompleter;
071 private TaskPrioritizer taskPrioritizer;
072 private AdditionalCheckerProvider additionalCheckerProvider;
073
074 @Inject
075 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
076 this.expressionTypingServices = expressionTypingServices;
077 }
078
079 @Inject
080 public void setTypeResolver(@NotNull TypeResolver typeResolver) {
081 this.typeResolver = typeResolver;
082 }
083
084 @Inject
085 public void setCandidateResolver(@NotNull CandidateResolver candidateResolver) {
086 this.candidateResolver = candidateResolver;
087 }
088
089 @Inject
090 public void setArgumentTypeResolver(@NotNull ArgumentTypeResolver argumentTypeResolver) {
091 this.argumentTypeResolver = argumentTypeResolver;
092 }
093
094 @Inject
095 public void setCallCompleter(@NotNull CallCompleter callCompleter) {
096 this.callCompleter = callCompleter;
097 }
098
099 @Inject
100 public void setTaskPrioritizer(@NotNull TaskPrioritizer taskPrioritizer) {
101 this.taskPrioritizer = taskPrioritizer;
102 }
103
104 @Inject
105 public void setAdditionalCheckerProvider(AdditionalCheckerProvider additionalCheckerProvider) {
106 this.additionalCheckerProvider = additionalCheckerProvider;
107 }
108
109 @NotNull
110 public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
111 JetExpression calleeExpression = context.call.getCalleeExpression();
112 assert calleeExpression instanceof JetSimpleNameExpression;
113 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
114 Name referencedName = nameExpression.getReferencedNameAsName();
115 CallableDescriptorCollectors<VariableDescriptor> callableDescriptorCollectors;
116 if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
117 referencedName = Name.identifier(referencedName.asString().substring(1));
118 callableDescriptorCollectors = CallableDescriptorCollectors.PROPERTIES;
119 }
120 else {
121 callableDescriptorCollectors = CallableDescriptorCollectors.VARIABLES;
122 }
123 return computeTasksAndResolveCall(
124 context, referencedName, nameExpression,
125 callableDescriptorCollectors, CallTransformer.VARIABLE_CALL_TRANSFORMER);
126 }
127
128 @NotNull
129 public OverloadResolutionResults<CallableDescriptor> resolveCallForMember(
130 @NotNull JetSimpleNameExpression nameExpression,
131 @NotNull BasicCallResolutionContext context
132 ) {
133 return computeTasksAndResolveCall(
134 context, nameExpression.getReferencedNameAsName(), nameExpression,
135 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.MEMBER_CALL_TRANSFORMER);
136 }
137
138 @NotNull
139 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName(
140 @NotNull ExpressionTypingContext context,
141 @NotNull Call call,
142 @NotNull JetReferenceExpression functionReference,
143 @NotNull Name name
144 ) {
145 BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED);
146 return computeTasksAndResolveCall(
147 callResolutionContext, name, functionReference,
148 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
149 }
150
151 @NotNull
152 public OverloadResolutionResults<FunctionDescriptor> resolveCallForInvoke(
153 @NotNull BasicCallResolutionContext context,
154 @NotNull TracingStrategy tracing
155 ) {
156 return computeTasksAndResolveCall(
157 context, OperatorConventions.INVOKE, tracing,
158 CallableDescriptorCollectors.FUNCTIONS, CallTransformer.FUNCTION_CALL_TRANSFORMER);
159 }
160
161 @NotNull
162 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
163 @NotNull BasicCallResolutionContext context,
164 @NotNull Name name,
165 @NotNull JetReferenceExpression referenceExpression,
166 @NotNull CallableDescriptorCollectors<D> collectors,
167 @NotNull CallTransformer<D, F> callTransformer
168 ) {
169 TracingStrategy tracing = TracingStrategyImpl.create(referenceExpression, context.call);
170 return computeTasksAndResolveCall(context, name, tracing, collectors, callTransformer);
171 }
172
173 @NotNull
174 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksAndResolveCall(
175 @NotNull BasicCallResolutionContext context,
176 @NotNull Name name,
177 @NotNull TracingStrategy tracing,
178 @NotNull CallableDescriptorCollectors<D> collectors,
179 @NotNull CallTransformer<D, F> callTransformer
180 ) {
181 List<ResolutionTask<D, F>> tasks = taskPrioritizer.<D, F>computePrioritizedTasks(context, name, tracing, collectors);
182 return doResolveCallOrGetCachedResults(context, tasks, callTransformer, tracing);
183 }
184
185 @NotNull
186 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
187 @NotNull BasicCallResolutionContext context,
188 @NotNull JetReferenceExpression referenceExpression,
189 @NotNull Collection<ResolutionCandidate<D>> candidates,
190 @NotNull CallTransformer<D, F> callTransformer
191 ) {
192 return computeTasksFromCandidatesAndResolvedCall(context, candidates, callTransformer,
193 TracingStrategyImpl.create(referenceExpression, context.call));
194 }
195
196 @NotNull
197 private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> computeTasksFromCandidatesAndResolvedCall(
198 @NotNull BasicCallResolutionContext context,
199 @NotNull Collection<ResolutionCandidate<D>> candidates,
200 @NotNull CallTransformer<D, F> callTransformer,
201 @NotNull TracingStrategy tracing
202 ) {
203 List<ResolutionTask<D, F>> prioritizedTasks =
204 taskPrioritizer.<D, F>computePrioritizedTasksFromCandidates(context, candidates, tracing);
205 return doResolveCallOrGetCachedResults(context, prioritizedTasks, callTransformer, tracing);
206 }
207
208 @NotNull
209 public OverloadResolutionResults<FunctionDescriptor> resolveBinaryCall(
210 ExpressionTypingContext context,
211 ExpressionReceiver receiver,
212 JetBinaryExpression binaryExpression,
213 Name name
214 ) {
215 return resolveCallWithGivenName(
216 context,
217 CallMaker.makeCall(receiver, binaryExpression),
218 binaryExpression.getOperationReference(),
219 name
220 );
221 }
222
223 @NotNull
224 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(
225 @NotNull BindingTrace trace,
226 @NotNull JetScope scope,
227 @NotNull Call call,
228 @NotNull JetType expectedType,
229 @NotNull DataFlowInfo dataFlowInfo,
230 boolean isAnnotationContext
231 ) {
232 return resolveFunctionCall(
233 BasicCallResolutionContext.create(
234 trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
235 additionalCheckerProvider.getCallChecker(), additionalCheckerProvider.getSymbolUsageValidator(),
236 additionalCheckerProvider.getTypeChecker(), isAnnotationContext)
237 );
238 }
239
240 @NotNull
241 public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicCallResolutionContext context) {
242 ProgressIndicatorProvider.checkCanceled();
243
244 JetExpression calleeExpression = context.call.getCalleeExpression();
245 if (calleeExpression instanceof JetSimpleNameExpression) {
246 JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression;
247 return computeTasksAndResolveCall(
248 context, expression.getReferencedNameAsName(), expression,
249 CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
250 }
251 if (calleeExpression instanceof JetConstructorCalleeExpression) {
252 return resolveCallForConstructor(context, (JetConstructorCalleeExpression) calleeExpression);
253 }
254 else if (calleeExpression == null) {
255 return checkArgumentTypesAndFail(context);
256 }
257
258 // Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
259 JetType calleeType = expressionTypingServices.safeGetType(
260 context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace);
261 ExpressionReceiver expressionReceiver = new ExpressionReceiver(calleeExpression, calleeType);
262
263 Call call = new CallTransformer.CallForImplicitInvoke(context.call.getExplicitReceiver(), expressionReceiver, context.call);
264 TracingStrategyForInvoke tracingForInvoke = new TracingStrategyForInvoke(calleeExpression, call, calleeType);
265 return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke);
266 }
267
268 private OverloadResolutionResults<FunctionDescriptor> resolveCallForConstructor(
269 @NotNull BasicCallResolutionContext context,
270 @NotNull JetConstructorCalleeExpression expression
271 ) {
272 assert !context.call.getExplicitReceiver().exists() :
273 "Constructor can't be invoked with explicit receiver: " + context.call.getCallElement().getText();
274
275 JetReferenceExpression functionReference = expression.getConstructorReferenceExpression();
276 JetTypeReference typeReference = expression.getTypeReference();
277 if (functionReference == null || typeReference == null) {
278 return checkArgumentTypesAndFail(context); // No type there
279 }
280 JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true);
281 if (constructedType.isError()) {
282 return checkArgumentTypesAndFail(context);
283 }
284
285 DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor();
286 if (!(declarationDescriptor instanceof ClassDescriptor)) {
287 context.trace.report(NOT_A_CLASS.on(expression));
288 return checkArgumentTypesAndFail(context);
289 }
290 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
291 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
292 if (constructors.isEmpty()) {
293 context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
294 return checkArgumentTypesAndFail(context);
295 }
296 Collection<ResolutionCandidate<CallableDescriptor>> candidates =
297 taskPrioritizer.<CallableDescriptor>convertWithImpliedThisAndNoReceiver(context.scope, constructors, context.call);
298
299 return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
300 }
301
302 @Nullable
303 public OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
304 @NotNull BindingTrace trace, @NotNull JetScope scope, @NotNull DataFlowInfo dataFlowInfo,
305 @NotNull ConstructorDescriptor constructorDescriptor,
306 @NotNull JetConstructorDelegationCall call, @NotNull CallChecker callChecker
307 ) {
308 // Method returns `null` when there is nothing to resolve in trivial cases like `null` call expression or
309 // when super call should be conventional enum constructor and super call should be empty
310
311 BasicCallResolutionContext context = BasicCallResolutionContext.create(
312 trace, scope,
313 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
314 NO_EXPECTED_TYPE,
315 dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
316 callChecker, additionalCheckerProvider.getSymbolUsageValidator(), additionalCheckerProvider.getTypeChecker(), false);
317
318 if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
319
320 if (constructorDescriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS && call.isImplicit()) {
321 return null;
322 }
323
324 return resolveConstructorDelegationCall(
325 context,
326 call,
327 call.getCalleeExpression(),
328 constructorDescriptor
329 );
330 }
331
332 @NotNull
333 private OverloadResolutionResults<FunctionDescriptor> resolveConstructorDelegationCall(
334 @NotNull BasicCallResolutionContext context,
335 @NotNull JetConstructorDelegationCall call,
336 @NotNull JetConstructorDelegationReferenceExpression calleeExpression,
337 @NotNull ConstructorDescriptor calleeConstructor
338 ) {
339 ClassDescriptor currentClassDescriptor = calleeConstructor.getContainingDeclaration();
340
341 boolean isThisCall = calleeExpression.isThis();
342 if (currentClassDescriptor.getKind() == ClassKind.ENUM_CLASS && !isThisCall) {
343 context.trace.report(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(calleeExpression));
344 return checkArgumentTypesAndFail(context);
345 }
346
347 ClassDescriptor delegateClassDescriptor = isThisCall ? currentClassDescriptor :
348 DescriptorUtilPackage.getSuperClassOrAny(currentClassDescriptor);
349 Collection<ConstructorDescriptor> constructors = delegateClassDescriptor.getConstructors();
350
351 if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
352 if (DescriptorUtils.canHaveDeclaredConstructors(currentClassDescriptor)) {
353 // Diagnostic is meaningless when reporting on interfaces and object
354 context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
355 (JetConstructorDelegationCall) calleeExpression.getParent()
356 ));
357 }
358 if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound();
359 }
360
361 if (constructors.isEmpty()) {
362 context.trace.report(NO_CONSTRUCTOR.on(CallUtilPackage.getValueArgumentListOrElement(context.call)));
363 return checkArgumentTypesAndFail(context);
364 }
365
366 List<ResolutionCandidate<CallableDescriptor>> candidates = Lists.newArrayList();
367 ReceiverValue constructorDispatchReceiver = !delegateClassDescriptor.isInner() ? ReceiverValue.NO_RECEIVER :
368 ((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()).
369 getThisAsReceiverParameter().getValue();
370
371 JetType expectedType = isThisCall ?
372 calleeConstructor.getContainingDeclaration().getDefaultType() :
373 DescriptorUtils.getSuperClassType(currentClassDescriptor);
374
375 TypeSubstitutor knownTypeParametersSubstitutor = TypeSubstitutor.create(expectedType);
376 for (CallableDescriptor descriptor : constructors) {
377 candidates.add(ResolutionCandidate.create(
378 context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER,
379 ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
380 knownTypeParametersSubstitutor));
381 }
382
383 TracingStrategy tracing = call.isImplicit() ?
384 new TracingStrategyForImplicitConstructorDelegationCall(call, context.call) :
385 TracingStrategyImpl.create(calleeExpression, context.call);
386
387 return computeTasksFromCandidatesAndResolvedCall(context, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
388 }
389
390 public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate(
391 @NotNull Call call,
392 @NotNull TracingStrategy tracing,
393 @NotNull ResolutionContext<?> context,
394 @NotNull ResolutionCandidate<CallableDescriptor> candidate,
395 @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
396 ) {
397 BasicCallResolutionContext basicCallResolutionContext =
398 BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
399
400 List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
401 taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
402 basicCallResolutionContext, Collections.singleton(candidate), tracing);
403 return doResolveCallOrGetCachedResults(basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, tracing);
404 }
405
406 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCallOrGetCachedResults(
407 @NotNull BasicCallResolutionContext context,
408 @NotNull List<ResolutionTask<D, F>> prioritizedTasks,
409 @NotNull CallTransformer<D, F> callTransformer,
410 @NotNull TracingStrategy tracing
411 ) {
412 Call call = context.call;
413 tracing.bindCall(context.trace, call);
414
415 OverloadResolutionResultsImpl<F> results = null;
416 TemporaryBindingTrace traceToResolveCall = TemporaryBindingTrace.create(context.trace, "trace to resolve call", call);
417 if (!CallResolverUtil.isInvokeCallOnVariable(call)) {
418 ResolutionResultsCache.CachedData data = context.resolutionResultsCache.get(call);
419 if (data != null) {
420 DelegatingBindingTrace deltasTraceForResolve = data.getResolutionTrace();
421 deltasTraceForResolve.addAllMyDataTo(traceToResolveCall);
422 //noinspection unchecked
423 results = (OverloadResolutionResultsImpl<F>) data.getResolutionResults();
424 }
425 }
426 if (results == null) {
427 BasicCallResolutionContext newContext = context.replaceBindingTrace(traceToResolveCall);
428 recordScopeAndDataFlowInfo(newContext, newContext.call.getCalleeExpression());
429 results = doResolveCall(newContext, prioritizedTasks, callTransformer, tracing);
430 DelegatingBindingTrace deltasTraceForTypeInference = ((OverloadResolutionResultsImpl) results).getTrace();
431 if (deltasTraceForTypeInference != null) {
432 deltasTraceForTypeInference.addAllMyDataTo(traceToResolveCall);
433 }
434 completeTypeInferenceDependentOnFunctionLiterals(newContext, results, tracing);
435 cacheResults(context, results, traceToResolveCall, tracing);
436 }
437 traceToResolveCall.commit();
438
439 if (context.contextDependency == ContextDependency.INDEPENDENT) {
440 results = callCompleter.completeCall(context, results, tracing);
441 }
442
443 return results;
444 }
445
446 private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
447 @NotNull BasicCallResolutionContext context,
448 @NotNull OverloadResolutionResultsImpl<D> results,
449 @NotNull TracingStrategy tracing
450 ) {
451 if (CallResolverUtil.isInvokeCallOnVariable(context.call)) return;
452 if (!results.isSingleResult()) {
453 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
454 argumentTypeResolver.checkTypesWithNoCallee(context, RESOLVE_FUNCTION_ARGUMENTS);
455 }
456 return;
457 }
458
459 CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
460 results.getResultingCall(), context, tracing);
461 candidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
462 }
463
464 private static <F extends CallableDescriptor> void cacheResults(
465 @NotNull BasicCallResolutionContext context,
466 @NotNull OverloadResolutionResultsImpl<F> results,
467 @NotNull DelegatingBindingTrace traceToResolveCall,
468 @NotNull TracingStrategy tracing
469 ) {
470 Call call = context.call;
471 if (CallResolverUtil.isInvokeCallOnVariable(call)) return;
472
473 DelegatingBindingTrace deltasTraceToCacheResolve = new DelegatingBindingTrace(
474 BindingContext.EMPTY, "delta trace for caching resolve of", context.call);
475 traceToResolveCall.addAllMyDataTo(deltasTraceToCacheResolve);
476
477 context.resolutionResultsCache.record(call, results, context, tracing, deltasTraceToCacheResolve);
478 }
479
480 private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> checkArgumentTypesAndFail(BasicCallResolutionContext context) {
481 argumentTypeResolver.checkTypesWithNoCallee(context);
482 return OverloadResolutionResultsImpl.nameNotFound();
483 }
484
485 @NotNull
486 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> doResolveCall(
487 @NotNull BasicCallResolutionContext context,
488 @NotNull List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
489 @NotNull CallTransformer<D, F> callTransformer,
490 @NotNull TracingStrategy tracing
491 ) {
492 if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
493 argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
494 }
495 Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
496 OverloadResolutionResultsImpl<F> successfulResults = null;
497 TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
498 OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
499 for (ResolutionTask<D, F> task : prioritizedTasks) {
500 if (task.getCandidates().isEmpty()) continue;
501
502 TemporaryBindingTrace taskTrace =
503 TemporaryBindingTrace.create(context.trace, "trace to resolve a task for", task.call.getCalleeExpression());
504 OverloadResolutionResultsImpl<F> results = performResolution(task.replaceBindingTrace(taskTrace), callTransformer);
505
506
507 allCandidates.addAll(task.getResolvedCalls());
508
509 if (successfulResults != null) continue;
510
511 if (results.isSuccess() || results.isAmbiguity()) {
512 taskTrace.commit();
513 successfulResults = results;
514 }
515 if (results.getResultCode() == INCOMPLETE_TYPE_INFERENCE) {
516 results.setTrace(taskTrace);
517 successfulResults = results;
518 }
519 boolean updateResults = traceForFirstNonemptyCandidateSet == null
520 || (resultsForFirstNonemptyCandidateSet.getResultCode() == CANDIDATES_WITH_WRONG_RECEIVER
521 && results.getResultCode() != CANDIDATES_WITH_WRONG_RECEIVER);
522 if (!task.getCandidates().isEmpty() && !results.isNothing() && updateResults) {
523 traceForFirstNonemptyCandidateSet = taskTrace;
524 resultsForFirstNonemptyCandidateSet = results;
525 }
526
527 if (successfulResults != null && !context.collectAllCandidates) break;
528 }
529 OverloadResolutionResultsImpl<F> results;
530 if (successfulResults != null) {
531 results = successfulResults;
532 }
533 else if (traceForFirstNonemptyCandidateSet == null) {
534 tracing.unresolvedReference(context.trace);
535 argumentTypeResolver.checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
536 results = OverloadResolutionResultsImpl.<F>nameNotFound();
537 }
538 else {
539 traceForFirstNonemptyCandidateSet.commit();
540 results = resultsForFirstNonemptyCandidateSet;
541 }
542 results.setAllCandidates(context.collectAllCandidates ? allCandidates : null);
543 return results;
544 }
545
546 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
547
548 @NotNull
549 private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(
550 @NotNull ResolutionTask<D, F> task,
551 @NotNull CallTransformer<D, F> callTransformer
552 ) {
553
554 for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
555 TemporaryBindingTrace candidateTrace = TemporaryBindingTrace.create(
556 task.trace, "trace to resolve candidate");
557 Collection<CallCandidateResolutionContext<D>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, candidateTrace);
558 for (CallCandidateResolutionContext<D> context : contexts) {
559
560 candidateResolver.performResolutionForCandidateCall(context, task);
561
562 /* important for 'variable as function case': temporary bind reference to descriptor (will be rewritten)
563 to have a binding to variable while 'invoke' call resolve */
564 task.tracing.bindReference(context.candidateCall.getTrace(), context.candidateCall);
565
566 Collection<MutableResolvedCall<F>> resolvedCalls = callTransformer.transformCall(context, this, task);
567
568 for (MutableResolvedCall<F> resolvedCall : resolvedCalls) {
569 BindingTrace trace = resolvedCall.getTrace();
570 task.tracing.bindReference(trace, resolvedCall);
571 task.tracing.bindResolvedCall(trace, resolvedCall);
572 task.addResolvedCall(resolvedCall);
573 }
574 }
575 }
576
577 OverloadResolutionResultsImpl<F> results = ResolutionResultsHandler.INSTANCE.computeResultAndReportErrors(
578 task, task.getResolvedCalls());
579 if (!results.isSingleResult() && !results.isIncomplete()) {
580 argumentTypeResolver.checkTypesWithNoCallee(task.toBasic());
581 }
582 return results;
583 }
584 }