public static <D extends CallableDescriptor> void splitLexicallyLocalDescriptors( @NotNull Collection<ResolutionCandidate<D>> allDescriptors, @NotNull DeclarationDescriptor containerOfTheCurrentLocality, @NotNull Collection<ResolutionCandidate<D>> local, @NotNull Collection<ResolutionCandidate<D>> nonlocal) { for (ResolutionCandidate<D> resolvedCall : allDescriptors) { if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { local.add(resolvedCall); } else { nonlocal.add(resolvedCall); } } }
private static <D extends CallableDescriptor> boolean setImpliedThis( @NotNull JetScope scope, ResolutionCandidate<D> candidate) { ReceiverDescriptor expectedThisObject = candidate.getDescriptor().getExpectedThisObject(); if (!expectedThisObject.exists()) return true; List<ReceiverDescriptor> receivers = Lists.newArrayList(); scope.getImplicitReceiversHierarchy(receivers); for (ReceiverDescriptor receiver : receivers) { if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) { // TODO : Autocasts & nullability candidate.setThisObject(expectedThisObject); return true; } } return false; }
private static <D extends CallableDescriptor> void convertWithReceivers( Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolutionCandidate<D>> result, boolean hasExplicitThisObject) { for (ReceiverDescriptor thisObject : thisObjects) { for (ReceiverDescriptor receiverParameter : receiverParameters) { for (D extension : descriptors) { ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension); candidate.setThisObject(thisObject); candidate.setReceiverArgument(receiverParameter); candidate.setExplicitReceiverKind( hasExplicitThisObject ? ExplicitReceiverKind.BOTH_RECEIVERS : ExplicitReceiverKind.THIS_OBJECT); result.add(candidate); } } } }
public static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithImpliedThis( JetScope scope, Collection<ReceiverDescriptor> receiverParameters, Collection<? extends D> descriptors) { Collection<ResolutionCandidate<D>> result = Lists.newArrayList(); for (ReceiverDescriptor receiverParameter : receiverParameters) { for (D descriptor : descriptors) { ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor); candidate.setReceiverArgument(receiverParameter); candidate.setExplicitReceiverKind( receiverParameter.exists() ? ExplicitReceiverKind.RECEIVER_ARGUMENT : ExplicitReceiverKind.NO_EXPLICIT_RECEIVER); if (setImpliedThis(scope, candidate)) { result.add(candidate); } } } if (receiverParameters.size() == 1 && !receiverParameters.iterator().next().exists()) { for (D descriptor : descriptors) { if (descriptor.getExpectedThisObject().exists() && !descriptor.getReceiverParameter().exists()) { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (descriptor instanceof ConstructorDescriptor) { assert containingDeclaration != null; containingDeclaration = containingDeclaration.getContainingDeclaration(); } if (containingDeclaration != null && isClassObject(containingDeclaration)) { ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor); candidate.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration)); candidate.setExplicitReceiverKind(ExplicitReceiverKind.NO_EXPLICIT_RECEIVER); result.add(candidate); } } } } return result; }
@NotNull private CallTranslator finish() { if (resolvedCall == null) { assert descriptor != null; resolvedCall = ResolvedCallImpl.create( ResolutionCandidate.create( descriptor, DescriptorUtils.safeGetValue(descriptor.getExpectedThisObject()), DescriptorUtils.safeGetValue(descriptor.getReceiverParameter()), ExplicitReceiverKind.THIS_OBJECT, false), TemporaryBindingTrace.create( new BindingTraceContext(), "trace to resolve call (in js)")); } if (descriptor == null) { descriptor = resolvedCall.getCandidateDescriptor().getOriginal(); } assert resolvedCall != null; return new CallTranslator(receiver, callee, args, resolvedCall, descriptor, callType, context); }
@NotNull /*package*/ OverloadResolutionResultsImpl<FunctionDescriptor> resolveFunctionCall( @NotNull BasicCallResolutionContext context) { ProgressIndicatorProvider.checkCanceled(); List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks; JetExpression calleeExpression = context.call.getCalleeExpression(); JetReferenceExpression functionReference; if (calleeExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression expression = (JetSimpleNameExpression) calleeExpression; functionReference = expression; ExpressionTypingUtils.checkCapturingInClosure(expression, context.trace, context.scope); Name name = expression.getReferencedNameAsName(); prioritizedTasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks( context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { @Override public <D extends CallableDescriptor> boolean performAdvancedChecks( D descriptor, BindingTrace trace, TracingStrategy tracing) { if (descriptor instanceof ConstructorDescriptor) { Modality modality = ((ConstructorDescriptor) descriptor).getContainingDeclaration().getModality(); if (modality == Modality.ABSTRACT) { tracing.instantiationOfAbstractClass(trace); return false; } } return true; } }; for (ResolutionTask task : prioritizedTasks) { task.setCheckingStrategy(abstractConstructorCheck); } } else { JetValueArgumentList valueArgumentList = context.call.getValueArgumentList(); PsiElement reportAbsenceOn = valueArgumentList == null ? context.call.getCallElement() : valueArgumentList; if (calleeExpression instanceof JetConstructorCalleeExpression) { assert !context.call.getExplicitReceiver().exists(); JetConstructorCalleeExpression expression = (JetConstructorCalleeExpression) calleeExpression; functionReference = expression.getConstructorReferenceExpression(); if (functionReference == null) { return checkArgumentTypesAndFail(context); // No type there } JetTypeReference typeReference = expression.getTypeReference(); assert typeReference != null; JetType constructedType = typeResolver.resolveType(context.scope, typeReference, context.trace, true); if (constructedType.isError()) { return checkArgumentTypesAndFail(context); } DeclarationDescriptor declarationDescriptor = constructedType.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); if (constructors.isEmpty()) { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } Collection<ResolutionCandidate<CallableDescriptor>> candidates = TaskPrioritizer.<CallableDescriptor>convertWithImpliedThis( context.scope, Collections.<ReceiverValue>singletonList(NO_RECEIVER), constructors); prioritizedTasks = TaskPrioritizer .<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates( context, functionReference, candidates, null); } else { context.trace.report(NOT_A_CLASS.on(calleeExpression)); return checkArgumentTypesAndFail(context); } } else if (calleeExpression instanceof JetThisReferenceExpression) { functionReference = (JetThisReferenceExpression) calleeExpression; DeclarationDescriptor containingDeclaration = context.scope.getContainingDeclaration(); if (containingDeclaration instanceof ConstructorDescriptor) { containingDeclaration = containingDeclaration.getContainingDeclaration(); } assert containingDeclaration instanceof ClassDescriptor; ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); if (constructors.isEmpty()) { context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(context); } List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection( constructors, JetPsiUtil.isSafeCall(context.call)); prioritizedTasks = Collections.singletonList( new ResolutionTask<CallableDescriptor, FunctionDescriptor>( candidates, functionReference, context)); // !! DataFlowInfo.EMPTY } else if (calleeExpression != null) { // Here we handle the case where the callee expression must be something of type function, // e.g. (foo.bar())(1, 2) JetType calleeType = expressionTypingServices.safeGetType( context.scope, calleeExpression, NO_EXPECTED_TYPE, context.dataFlowInfo, context .trace); // We are actually expecting a function, but there seems to be no easy // way of expressing this if (!KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(calleeType)) { // checkTypesWithNoCallee(trace, scope, call); if (!calleeType.isError()) { context.trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType)); } return checkArgumentTypesAndFail(context); } FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor( context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">"), calleeExpression); FunctionDescriptorUtil.initializeFromFunctionType( functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL, Visibilities.LOCAL); ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create( functionDescriptor, JetPsiUtil.isSafeCall(context.call)); resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver()); resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT); // strictly speaking, this is a hack: // we need to pass a reference, but there's no reference in the PSI, // so we wrap what we have into a fake reference and pass it on (unwrap on the other end) functionReference = new JetFakeReference(calleeExpression); prioritizedTasks = Collections.singletonList( new ResolutionTask<CallableDescriptor, FunctionDescriptor>( Collections.singleton(resolutionCandidate), functionReference, context)); } else { // checkTypesWithNoCallee(trace, scope, call); return checkArgumentTypesAndFail(context); } } return doResolveCallOrGetCachedResults( ResolutionResultsCache.FUNCTION_MEMBER_TYPE, context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); }