Evaluate parameter types only when needed

This commit is contained in:
Andrey Vlasovskikh
2013-08-05 15:14:40 +04:00
parent 8b0b58901f
commit 3d2c8f555c
7 changed files with 25 additions and 17 deletions
@@ -12,7 +12,7 @@ public interface PyCallableParameter {
String getName();
@Nullable
PyType getType();
PyType getType(@NotNull TypeEvalContext context);
@Nullable
PyParameter getParameter();
@@ -209,7 +209,7 @@ public class PyTypeModelBuilder {
if (parameters != null) {
parameterModels = new ArrayList<TypeModel>();
for (PyCallableParameter parameter : parameters) {
parameterModels.add(new ParamType(parameter.getName(), build(parameter.getType(), true)));
parameterModels.add(new ParamType(parameter.getName(), build(parameter.getType(myContext), true)));
}
}
final PyType ret = type.getCallType(myContext, null);
@@ -1,6 +1,8 @@
package com.jetbrains.python.psi.types;
import com.jetbrains.python.psi.PyNamedParameter;
import com.jetbrains.python.psi.PyParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -17,9 +19,9 @@ public class PyCallableParameterImpl implements PyCallableParameter {
myElement = null;
}
public PyCallableParameterImpl(@Nullable PyParameter element, @Nullable PyType type) {
public PyCallableParameterImpl(@Nullable PyParameter element) {
myName = null;
myType = type;
myType = null;
myElement = element;
}
@@ -37,8 +39,14 @@ public class PyCallableParameterImpl implements PyCallableParameter {
@Nullable
@Override
public PyType getType() {
return myType;
public PyType getType(@NotNull TypeEvalContext context) {
if (myType != null) {
return myType;
}
else if (myElement instanceof PyNamedParameter) {
return context.getType((PyNamedParameter)myElement);
}
return null;
}
@Nullable
@@ -70,7 +70,7 @@ public class PyCallableTypeImpl implements PyCallableType {
if (param != null) {
final StringBuilder builder = new StringBuilder();
final String name = param.getName();
final PyType type = param.getType();
final PyType type = param.getType(context);
if (name != null) {
builder.append(name);
if (type != null) {
@@ -39,8 +39,7 @@ public class PyFunctionType implements PyCallableType {
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
final List<PyCallableParameter> result = new ArrayList<PyCallableParameter>();
for (PyParameter parameter : myCallable.getParameterList().getParameters()) {
final PyType type = parameter instanceof PyTypedElement ? context.getType((PyTypedElement)parameter) : null;
result.add(new PyCallableParameterImpl(parameter, type));
result.add(new PyCallableParameterImpl(parameter));
}
return result;
}
@@ -152,7 +152,7 @@ public class PyTypeChecker {
final PyCallableParameter expectedParam = expectedParameters.get(i);
final PyCallableParameter actualParam = actualParameters.get(i);
// TODO: Check named and star params, not only positional ones
if (!match(expectedParam.getType(), actualParam.getType(), context, substitutions, recursive)) {
if (!match(expectedParam.getType(context), actualParam.getType(context), context, substitutions, recursive)) {
return false;
}
}
@@ -237,7 +237,7 @@ public class PyTypeChecker {
if (parameters != null) {
for (PyCallableParameter parameter : parameters) {
if (parameter != null) {
collectGenerics(parameter.getType(), context, collected, visited);
collectGenerics(parameter.getType(context), context, collected, visited);
}
}
}
@@ -284,9 +284,9 @@ public class PyTypeChecker {
if (parameters != null) {
substParams = new ArrayList<PyCallableParameter>();
for (PyCallableParameter parameter : parameters) {
final PyType substType = substitute(parameter.getType(), substitutions, context);
final PyType substType = substitute(parameter.getType(context), substitutions, context);
final PyCallableParameter subst = parameter.getParameter() != null ?
new PyCallableParameterImpl(parameter.getParameter(), substType) :
new PyCallableParameterImpl(parameter.getParameter()) :
new PyCallableParameterImpl(parameter.getName(), substType);
substParams.add(subst);
}
@@ -234,15 +234,16 @@ public class PyTypeParserTest extends PyTestCase {
assertInstanceOf(type, PyCallableType.class);
final PyCallableType callableType = (PyCallableType)type;
assertNotNull(callableType);
final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
final TypeEvalContext context = getTypeEvalContext();
final PyType returnType = callableType.getCallType(context, null);
assertInstanceOf(returnType, PyGenericType.class);
final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
final List<PyCallableParameter> parameterTypes = callableType.getParameters(context);
assertNotNull(parameterTypes);
assertEquals(2, parameterTypes.size());
final PyType type0 = parameterTypes.get(0).getType();
final PyType type0 = parameterTypes.get(0).getType(context);
assertNotNull(type0);
assertEquals("int", type0.getName());
final PyType type1 = parameterTypes.get(1).getType();
final PyType type1 = parameterTypes.get(1).getType(context);
assertNotNull(type1);
assertEquals("T", type1.getName());
}