Introduced Callable.getCallType() instead of PyFunctionImpl.getReturnTypeWithoutCallSite()

This commit is contained in:
Andrey Vlasovskikh
2014-03-03 14:56:50 +04:00
parent 032ad71073
commit dd898e2d02
4 changed files with 43 additions and 31 deletions
@@ -20,6 +20,8 @@ import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* Something that can be called, passed parameters to, and return something back.
@@ -45,6 +47,14 @@ public interface Callable extends PyTypedElement, PyQualifiedNameOwner {
@Nullable
PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite);
/**
* Returns the type of the call to the callable where the call site is specified by the optional receiver and the arguments to parameters
* mapping.
*/
@Nullable
PyType getCallType(@Nullable PyExpression receiver, @NotNull Map<PyExpression, PyNamedParameter> parameters,
@NotNull TypeEvalContext context);
/**
* @return a methods returns itself, non-method callables return null.
*/
@@ -15,7 +15,6 @@
*/
package com.jetbrains.python.psi.impl;
import com.google.common.collect.Maps;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pair;
@@ -235,36 +234,25 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
return type;
}
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, context);
if (PyTypeChecker.hasGenerics(type, context)) {
if (results != null) {
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(results.getReceiver(), results.getArguments(),
context);
type = substitutions != null ? PyTypeChecker.substitute(type, substitutions, context) : null;
}
else {
type = null;
}
}
if (results != null) {
type = replaceSelf(type, results.getReceiver(), context);
}
if (results != null && isDynamicallyEvaluated(results.getArguments().values(), context)) {
return PyUnionType.createWeakType(type);
return analyzeCallType(type, results.getReceiver(), results.getArguments(), context);
}
return type;
}
@Nullable
/**
* Suits when there is no call site(e.g. implicit __iter__ call in statement for)
*/
public PyType getReturnTypeWithoutCallSite(@NotNull TypeEvalContext context,
@Nullable PyExpression receiver) {
PyType type = getReturnType(context);
@Override
public PyType getCallType(@Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> parameters,
@NotNull TypeEvalContext context) {
return analyzeCallType(getReturnType(context), receiver, parameters, context);
}
@Nullable
private PyType analyzeCallType(@Nullable PyType type, @Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> parameters, @NotNull TypeEvalContext context) {
if (PyTypeChecker.hasGenerics(type, context)) {
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver,
Maps.<PyExpression, PyNamedParameter>newHashMap(),
context);
final Map<PyGenericType, PyType> substitutions = PyTypeChecker.unifyGenericCall(receiver, parameters, context);
if (substitutions != null) {
type = PyTypeChecker.substitute(type, substitutions, context);
}
@@ -272,7 +260,13 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
type = null;
}
}
return replaceSelf(type, receiver, context);
if (receiver != null) {
type = replaceSelf(type, receiver, context);
}
if (type != null && isDynamicallyEvaluated(parameters.values(), context)) {
type = PyUnionType.createWeakType(type);
}
return type;
}
@Nullable
@@ -28,6 +28,8 @@ import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
/**
* @author yole
*/
@@ -82,6 +84,14 @@ public class PyLambdaExpressionImpl extends PyElementImpl implements PyLambdaExp
return getReturnType(context);
}
@Nullable
@Override
public PyType getCallType(@Nullable PyExpression receiver,
@NotNull Map<PyExpression, PyNamedParameter> parameters,
@NotNull TypeEvalContext context) {
return getReturnType(context);
}
@Nullable
public PyExpression getBody() {
return PsiTreeUtil.getChildOfType(this, PyExpression.class);
@@ -54,6 +54,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -243,8 +244,8 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
if (exprType instanceof PyClassType) {
final PyClass cls = ((PyClassType)exprType).getPyClass();
final PyFunction enter = cls.findMethodByName(PyNames.ENTER, true);
if (enter instanceof PyFunctionImpl) {
final PyType enterType = ((PyFunctionImpl)enter).getReturnTypeWithoutCallSite(context, expression);
if (enter != null) {
final PyType enterType = enter.getCallType(expression, Collections.<PyExpression, PyNamedParameter>emptyMap(), context);
if (enterType != null) {
return enterType;
}
@@ -438,10 +439,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
@Nullable
private static PyType getContextSensitiveType(@NotNull PyFunction function, @NotNull TypeEvalContext context,
@Nullable PyExpression source) {
if (function instanceof PyFunctionImpl) {
return ((PyFunctionImpl)function).getReturnTypeWithoutCallSite(context, source);
}
return function.getCallType(context, null);
return function.getCallType(source, Collections.<PyExpression, PyNamedParameter>emptyMap(), context);
}
@Nullable