@NotNull public static <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasks( @NotNull BasicResolutionContext context, @NotNull Name name, @NotNull JetReferenceExpression functionReference, @NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors) { ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver(); final JetScope scope; if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) { // Receiver is a namespace scope = explicitReceiver.getType().getMemberScope(); explicitReceiver = NO_RECEIVER; } else { scope = context.scope; } final Predicate<ResolutionCandidate<D>> visibleStrategy = new Predicate<ResolutionCandidate<D>>() { @Override public boolean apply(@Nullable ResolutionCandidate<D> call) { if (call == null) return false; D candidateDescriptor = call.getDescriptor(); if (ErrorUtils.isError(candidateDescriptor)) return true; return Visibilities.isVisible(candidateDescriptor, scope.getContainingDeclaration()); } }; ResolutionTaskHolder<D, F> result = new ResolutionTaskHolder<D, F>(functionReference, context, visibleStrategy); for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : callableDescriptorCollectors) { doComputeTasks(scope, explicitReceiver, name, result, context, callableDescriptorCollector); } return result.getTasks(); }
@Override public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) { checkMayRead(); super.getImplicitReceiversHierarchy(result); // Imported scopes come with their receivers // Example: class member resolution scope imports a scope of it's class object // members of the class object must be able to find it as an implicit receiver for (JetScope scope : getImports()) { ReceiverDescriptor definedReceiver = scope.getImplicitReceiver(); if (definedReceiver.exists()) { result.add(0, definedReceiver); } } }
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; }
/* * Checks if receiver declaration could be resolved to call expected receiver. */ public static boolean checkIsExtensionCallable( @NotNull ReceiverDescriptor expectedReceiver, @NotNull CallableDescriptor receiverArgument) { JetType type = expectedReceiver.getType(); if (checkReceiverResolution(expectedReceiver, type, receiverArgument)) return true; if (type.isNullable()) { JetType notNullableType = TypeUtils.makeNotNullable(type); if (checkReceiverResolution(expectedReceiver, notNullableType, receiverArgument)) return true; } return false; }
@Override public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { renderVisibility(descriptor.getVisibility(), builder); renderModality(descriptor.getModality(), builder); builder.append(renderKeyword("fun")).append(" "); if (renderTypeParameters(descriptor.getTypeParameters(), builder)) { builder.append(" "); } ReceiverDescriptor receiver = descriptor.getReceiverParameter(); if (receiver.exists()) { builder.append(escape(renderType(receiver.getType()))).append("."); } renderName(descriptor, builder); renderValueParameters(descriptor, builder); builder.append(" : ").append(escape(renderType(descriptor.getReturnType()))); renderWhereSuffix(descriptor, builder); return null; }
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; }
private String renderPropertyPrefixAndComputeTypeString( @NotNull StringBuilder builder, @Nullable Boolean isVar, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor receiver, @Nullable JetType outType) { String typeString = lt() + "no type>"; if (outType != null) { if (isVar != null) { builder.append(renderKeyword(isVar ? "var" : "val")).append(" "); } typeString = renderType(outType); } renderTypeParameters(typeParameters, builder); if (receiver.exists()) { builder.append(escape(renderType(receiver.getType()))).append("."); } return typeString; }
private static boolean checkReceiverResolution( @NotNull ReceiverDescriptor expectedReceiver, @NotNull JetType receiverType, @NotNull CallableDescriptor receiverArgument) { ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING); for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); } ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter(); if (expectedReceiver.exists() && receiverParameter.exists()) { constraintSystem.addSubtypingConstraint( ConstraintType.RECEIVER.assertSubtyping(receiverType, receiverParameter.getType())); } else if (expectedReceiver.exists() || receiverParameter.exists()) { // Only one of receivers exist return false; } ConstraintSystemSolution solution = constraintSystem.solve(); return solution.getStatus().isSuccessful(); }
@Override public JetType visitFunctionLiteralExpression( JetFunctionLiteralExpression expression, ExpressionTypingContext context) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); if (bodyExpression == null) return null; JetType expectedType = context.expectedType; boolean functionTypeExpected = expectedType != TypeUtils.NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(expectedType); NamedFunctionDescriptorImpl functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected); List<JetType> parameterTypes = Lists.newArrayList(); List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters(); for (ValueParameterDescriptor valueParameter : valueParameters) { parameterTypes.add(valueParameter.getOutType()); } ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); JetType receiver = receiverParameter != NO_RECEIVER ? receiverParameter.getType() : null; JetType returnType = TypeUtils.NO_EXPECTED_TYPE; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( context.scope, functionDescriptor, context.trace); JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); if (returnTypeRef != null) { returnType = context.getTypeResolver().resolveType(context.scope, returnTypeRef); context .getServices() .checkFunctionReturnType( expression, context .replaceScope(functionInnerScope) .replaceExpectedType(returnType) .replaceExpectedReturnType(returnType) .replaceDataFlowInfo(context.dataFlowInfo)); } else { if (functionTypeExpected) { returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); } returnType = context .getServices() .getBlockReturnedType( functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType)); } JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType; functionDescriptor.setReturnType(safeReturnType); boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null; if (!hasDeclaredValueParameters && functionTypeExpected) { JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); if (JetStandardClasses.isUnit(expectedReturnType)) { functionDescriptor.setReturnType(JetStandardClasses.getUnitType()); return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context); } } return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context); }
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); } } }