@NotNull public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty( @NotNull BasicCallResolutionContext context) { JetExpression calleeExpression = context.call.getCalleeExpression(); assert calleeExpression instanceof JetSimpleNameExpression; JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression; Name referencedName = nameExpression.getReferencedNameAsName(); List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList(); if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { referencedName = Name.identifier(referencedName.asString().substring(1)); callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES); } else { callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES); } List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = TaskPrioritizer.<VariableDescriptor, VariableDescriptor>computePrioritizedTasks( context, referencedName, nameExpression, callableDescriptorCollectors); return doResolveCallOrGetCachedResults( ResolutionResultsCache.PROPERTY_MEMBER_TYPE, context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression); }
@NotNull public OverloadResolutionResults<FunctionDescriptor> resolveCallWithGivenName( @NotNull BasicCallResolutionContext context, @NotNull JetReferenceExpression functionReference, @NotNull Name name) { List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = TaskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasks( context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES); return doResolveCallOrGetCachedResults( ResolutionResultsCache.FUNCTION_MEMBER_TYPE, context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference); }
public OverloadResolutionResults<FunctionDescriptor> resolveCallWithKnownCandidate( @NotNull Call call, @Nullable TracingStrategy tracing, @NotNull JetReferenceExpression reference, @NotNull ResolutionContext<?> context, @NotNull ResolutionCandidate<CallableDescriptor> candidate, @Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments) { BasicCallResolutionContext basicCallResolutionContext = BasicCallResolutionContext.create( context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments); List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = TaskPrioritizer .<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates( basicCallResolutionContext, reference, Collections.singleton(candidate), tracing); return doResolveCallOrGetCachedResults( ResolutionResultsCache.FUNCTION_MEMBER_TYPE, basicCallResolutionContext, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, reference); }
private static <D extends CallableDescriptor, F extends D> void doComputeTasks( @NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Name name, @NotNull ResolutionTaskHolder<D, F> result, @NotNull BasicResolutionContext context, @NotNull CallableDescriptorCollector<? extends D> callableDescriptorCollector) { ProgressIndicatorProvider.checkCanceled(); AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext()); List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList(); scope.getImplicitReceiversHierarchy(implicitReceivers); boolean hasExplicitThisObject = context.call.getThisObject().exists(); if (hasExplicitThisObject) { implicitReceivers.add(context.call.getThisObject()); } if (receiver.exists()) { List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver); Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis( scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(scope, name)); List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList(); List<ResolutionCandidate<D>> locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.<D>splitLexicallyLocalDescriptors( extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals); Collection<ResolutionCandidate<D>> members = Lists.newArrayList(); for (ReceiverDescriptor variant : variantsForExplicitReceiver) { Collection<? extends D> membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), name); convertWithReceivers( membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members, hasExplicitThisObject); } result.addLocalExtensions(locals); result.addMembers(members); for (ReceiverDescriptor implicitReceiver : implicitReceivers) { Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName( implicitReceiver.getType().getMemberScope(), name); List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver); result.addNonLocalExtensions( convertWithReceivers( memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver, hasExplicitThisObject)); } result.addNonLocalExtensions(nonlocals); } else { Collection<ResolutionCandidate<D>> functions = convertWithImpliedThis( scope, Collections.singletonList(receiver), callableDescriptorCollector.getNonExtensionsByName(scope, name)); List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList(); List<ResolutionCandidate<D>> locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.<D>splitLexicallyLocalDescriptors( functions, scope.getContainingDeclaration(), locals, nonlocals); result.addLocalExtensions(locals); result.addNonLocalExtensions(nonlocals); for (ReceiverDescriptor implicitReceiver : implicitReceivers) { doComputeTasks(scope, implicitReceiver, name, result, context, callableDescriptorCollector); } } }
@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); }