Cache call site independent return types of callables in TypeEvalContext

This commit is contained in:
Andrey Vlasovskikh
2014-03-03 14:22:00 +04:00
parent f90ee78702
commit 9e9e8e5a6a
10 changed files with 37 additions and 18 deletions
@@ -104,7 +104,7 @@ public class PyJavaClassType implements PyClassLikeType {
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
public PyType getReturnType() {
if (myDefinition) {
return new PyJavaClassType(myClass, false);
}
@@ -114,7 +114,7 @@ public class PyJavaClassType implements PyClassLikeType {
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
return getReturnType(context);
return getReturnType();
}
@Nullable
@@ -52,14 +52,14 @@ public class PyJavaMethodType implements PyCallableType {
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
public PyType getReturnType() {
return PyJavaTypeProvider.asPyType(myMethod.getReturnType());
}
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
return getReturnType(context);
return getReturnType();
}
@Nullable
@@ -39,7 +39,7 @@ public interface PyCallableType extends PyType {
* For example, it may return a generic type.
*/
@Nullable
PyType getReturnType(@NotNull TypeEvalContext context);
PyType getReturnType();
/**
* Returns the type which is the result of calling an instance of this type.
@@ -177,6 +177,15 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
final PyType type = context.getType(this);
if (type instanceof PyCallableType) {
return ((PyCallableType)type).getReturnType();
}
return null;
}
@Nullable
private PyType calculateReturnType(@NotNull TypeEvalContext context) {
for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType returnType = typeProvider.getReturnType(this, context);
if (returnType != null) {
@@ -399,8 +408,8 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
return type;
}
}
final PyFunctionType type = new PyFunctionType(this);
if (getDecoratorList() != null) {
final PyFunctionType type = new PyFunctionType(this, calculateReturnType(context));
if (PyUtil.hasCustomDecorators(this) && !PyUtil.isDecoratedAsAbstract(this) && getProperty() == null) {
return PyUnionType.createWeakType(type);
}
return type;
@@ -21,6 +21,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyFunctionType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -46,7 +47,7 @@ public class PyLambdaExpressionImpl extends PyElementImpl implements PyLambdaExp
return type;
}
}
return new PyFunctionType(this);
return new PyFunctionType(this, calculateReturnType(context));
}
@NotNull
@@ -62,6 +63,15 @@ public class PyLambdaExpressionImpl extends PyElementImpl implements PyLambdaExp
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
final PyType type = context.getType(this);
if (type instanceof PyCallableType) {
return ((PyCallableType)type).getReturnType();
}
return null;
}
@Nullable
private PyType calculateReturnType(@NotNull TypeEvalContext context) {
final PyExpression body = getBody();
return body != null ? context.getType(body) : null;
}
@@ -49,8 +49,7 @@ public class PyCallableTypeImpl implements PyCallableType {
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
// TODO: Check that this return type doesn't depend on the call site for all PyCallableTypeImpl objects
public PyType getReturnType() {
return myReturnType;
}
@@ -307,7 +307,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
public PyType getReturnType() {
if (isDefinition()) {
return new PyClassTypeImpl(getPyClass(), false);
}
@@ -317,7 +317,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
return getReturnType(context);
return getReturnType();
}
@Nullable
@@ -34,9 +34,11 @@ import java.util.List;
*/
public class PyFunctionType implements PyCallableType {
@NotNull private final Callable myCallable;
@Nullable private final PyType myReturnType;
public PyFunctionType(@NotNull Callable callable) {
public PyFunctionType(@NotNull Callable callable, @Nullable PyType returnType) {
myCallable = callable;
myReturnType = returnType;
}
@Override
@@ -46,9 +48,8 @@ public class PyFunctionType implements PyCallableType {
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context) {
// TODO: Make Callable.getReturnType() call site independent, extract getCallType()
return myCallable.getCallType(context, null);
public PyType getReturnType() {
return myReturnType;
}
@Nullable
@@ -355,7 +355,7 @@ public class PyTypeChecker {
if (init instanceof PyTypedElement) {
final PyType initType = context.getType((PyTypedElement)init);
if (initType instanceof PyCallableType) {
final PyType initReturnType = ((PyCallableType)initType).getReturnType(context);
final PyType initReturnType = ((PyCallableType)initType).getReturnType();
if (initReturnType != null) {
match(initReturnType, qualifierType, context, substitutions);
}
+1 -1
View File
@@ -1 +1 @@
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#Foo">Foo</a>)&nbsp;-&gt;&nbsp;None<br><br><br>Doc&nbsp;of&nbsp;meth.<br></code></body></html>
<html><body><code><small>class <a href="psi_element://#class#">Foo</a></small><br><br>@<i>deco</i><br>def <b>meth</b>(self)<br>Inferred&nbsp;type:&nbsp;(self:&nbsp;<a href="psi_element://#typename#Foo">Foo</a>)&nbsp;-&gt;&nbsp;unknown<br><br><br>Doc&nbsp;of&nbsp;meth.<br></code></body></html>