diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 55e47fe10f4..60b9f4fed45 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -536,8 +536,8 @@ public class BodyResolver { propertyDescriptor, parentScopeForAccessor, descriptorResolver, trace); JetExpression calleeExpression = JetPsiUtil.getCalleeExpressionIfAny(delegateExpression); - ConstraintSystemCompleter completer = - createConstraintSystemCompleter(jetProperty, propertyDescriptor, delegateExpression, accessorScope); + ConstraintSystemCompleter completer = delegatedPropertyResolver.createConstraintSystemCompleter( + jetProperty, propertyDescriptor, delegateExpression, accessorScope, trace); if (calleeExpression != null) { traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer); } @@ -559,75 +559,6 @@ public class BodyResolver { } } - private ConstraintSystemCompleter createConstraintSystemCompleter( - JetProperty property, - final PropertyDescriptor propertyDescriptor, - final JetExpression delegateExpression, - final JetScope accessorScope - ) { - final JetType expectedType = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; - return new ConstraintSystemCompleter() { - @Override - public void completeConstraintSystem( - @NotNull ConstraintSystem constraintSystem, @NotNull ResolvedCall resolvedCall - ) { - JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType(); - if (returnType == null) return; - - TemporaryBindingTrace traceToResolveConventionMethods = - TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods"); - OverloadResolutionResults - getMethodResults = delegatedPropertyResolver.getDelegatedPropertyConventionMethod( - propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, accessorScope, true); - - if (conventionMethodFound(getMethodResults)) { - FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor(); - JetType returnTypeOfGetMethod = descriptor.getReturnType(); - if (returnTypeOfGetMethod != null) { - constraintSystem.addSupertypeConstraint(expectedType, returnTypeOfGetMethod, ConstraintPosition.FROM_COMPLETER); - } - addConstraintForThisValue(constraintSystem, descriptor); - } - if (!propertyDescriptor.isVar()) return; - - OverloadResolutionResults setMethodResults = - delegatedPropertyResolver.getDelegatedPropertyConventionMethod( - propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, accessorScope, false); - - if (conventionMethodFound(setMethodResults)) { - FunctionDescriptor descriptor = setMethodResults.getResultingDescriptor(); - List valueParameters = descriptor.getValueParameters(); - if (valueParameters.size() == 3) { - ValueParameterDescriptor valueParameterForThis = valueParameters.get(2); - - constraintSystem.addSubtypeConstraint(expectedType, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER); - addConstraintForThisValue(constraintSystem, descriptor); - } - } - } - - private boolean conventionMethodFound(@NotNull OverloadResolutionResults results) { - return results.isSuccess() || - (results.isSingleResult() && results.getResultCode() == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH); - } - - private void addConstraintForThisValue(ConstraintSystem constraintSystem, FunctionDescriptor resultingDescriptor) { - ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter(); - ReceiverParameterDescriptor thisObject = propertyDescriptor.getExpectedThisObject(); - JetType typeOfThis = - receiverParameter != null ? receiverParameter.getType() : - thisObject != null ? thisObject.getType() : - KotlinBuiltIns.getInstance().getNullableNothingType(); - - List valueParameters = resultingDescriptor.getValueParameters(); - if (valueParameters.isEmpty()) return; - ValueParameterDescriptor valueParameterForThis = valueParameters.get(0); - - constraintSystem.addSubtypeConstraint(typeOfThis, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER); - } - }; - } - public void resolvePropertyInitializer( @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyResolver.java index f16fc52fa8f..7b57990dbf3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DelegatedPropertyResolver.java @@ -20,19 +20,17 @@ import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.rendering.Renderers; -import org.jetbrains.jet.lang.psi.Call; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetReferenceExpression; -import org.jetbrains.jet.lang.psi.ValueArgument; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemCompleter; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; @@ -52,6 +50,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.psi.JetPsiFactory.createExpression; import static org.jetbrains.jet.lang.psi.JetPsiFactory.createSimpleName; import static org.jetbrains.jet.lang.resolve.BindingContext.*; +import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType; public class DelegatedPropertyResolver { @@ -207,4 +206,77 @@ public class DelegatedPropertyResolver { builder.append(")"); return builder.toString(); } + + @NotNull + public ConstraintSystemCompleter createConstraintSystemCompleter( + @NotNull JetProperty property, + @NotNull final PropertyDescriptor propertyDescriptor, + @NotNull final JetExpression delegateExpression, + @NotNull final JetScope accessorScope, + @NotNull final BindingTrace trace + ) { + final JetType expectedType = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; + return new ConstraintSystemCompleter() { + @Override + public void completeConstraintSystem( + @NotNull ConstraintSystem constraintSystem, @NotNull ResolvedCall resolvedCall + ) { + JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType(); + if (returnType == null) return; + + TemporaryBindingTrace traceToResolveConventionMethods = + TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods"); + OverloadResolutionResults + getMethodResults = getDelegatedPropertyConventionMethod( + propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, accessorScope, true); + + if (conventionMethodFound(getMethodResults)) { + FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor(); + JetType returnTypeOfGetMethod = descriptor.getReturnType(); + if (returnTypeOfGetMethod != null) { + constraintSystem.addSupertypeConstraint(expectedType, returnTypeOfGetMethod, ConstraintPosition.FROM_COMPLETER); + } + addConstraintForThisValue(constraintSystem, descriptor); + } + if (!propertyDescriptor.isVar()) return; + + OverloadResolutionResults setMethodResults = + getDelegatedPropertyConventionMethod( + propertyDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, accessorScope, false); + + if (conventionMethodFound(setMethodResults)) { + FunctionDescriptor descriptor = setMethodResults.getResultingDescriptor(); + List valueParameters = descriptor.getValueParameters(); + if (valueParameters.size() == 3) { + ValueParameterDescriptor valueParameterForThis = valueParameters.get(2); + + constraintSystem + .addSubtypeConstraint(expectedType, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER); + addConstraintForThisValue(constraintSystem, descriptor); + } + } + } + + private boolean conventionMethodFound(@NotNull OverloadResolutionResults results) { + return results.isSuccess() || + (results.isSingleResult() && + results.getResultCode() == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH); + } + + private void addConstraintForThisValue(ConstraintSystem constraintSystem, FunctionDescriptor resultingDescriptor) { + ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter(); + ReceiverParameterDescriptor thisObject = propertyDescriptor.getExpectedThisObject(); + JetType typeOfThis = + receiverParameter != null ? receiverParameter.getType() : + thisObject != null ? thisObject.getType() : + KotlinBuiltIns.getInstance().getNullableNothingType(); + + List valueParameters = resultingDescriptor.getValueParameters(); + if (valueParameters.isEmpty()) return; + ValueParameterDescriptor valueParameterForThis = valueParameters.get(0); + + constraintSystem.addSubtypeConstraint(typeOfThis, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER); + } + }; + } }