Use object instead of pair for describing function type parameters

This commit is contained in:
Andrey Vlasovskikh
2013-08-02 15:41:20 +04:00
parent afd5c68804
commit bbcee93c26
12 changed files with 118 additions and 49 deletions
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.impl;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
@@ -12,6 +11,7 @@ import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.CompletionVariantsProcessor;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -101,7 +101,7 @@ public class PyJavaClassType implements PyClassLikeType {
@Nullable
@Override
public List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context) {
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.impl;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.util.ArrayUtil;
@@ -10,6 +9,7 @@ import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyQualifiedExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyCallableType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -42,7 +42,7 @@ public class PyJavaMethodType implements PyCallableType {
@Nullable
@Override
public List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context) {
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -0,0 +1,19 @@
package com.jetbrains.python.psi.types;
import com.jetbrains.python.psi.PyParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author vlan
*/
public interface PyCallableParameter {
@Nullable
String getName();
@Nullable
PyType getType();
@Nullable
PyParameter getParameter();
}
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.Pair;
import com.jetbrains.python.psi.PyQualifiedExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,8 +31,8 @@ public interface PyCallableType extends PyType {
/**
* Returns the list of parameter types.
*
* @return list of (name, type) pairs or null if not applicable. Name and type in pair may be null.
* @return list of parameter info null if not applicable.
*/
@Nullable
List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context);
List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context);
}
@@ -4,7 +4,6 @@ import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.Callable;
@@ -206,11 +205,11 @@ public class PyTypeModelBuilder {
private TypeModel build(@NotNull PyCallableType type) {
List<TypeModel> parameterModels = null;
final List<Pair<String, PyType>> parameters = type.getParameters(myContext);
final List<PyCallableParameter> parameters = type.getParameters(myContext);
if (parameters != null) {
parameterModels = new ArrayList<TypeModel>();
for (Pair<String, PyType> parameter : parameters) {
parameterModels.add(new ParamType(parameter.getFirst(), build(parameter.getSecond(), true)));
for (PyCallableParameter parameter : parameters) {
parameterModels.add(new ParamType(parameter.getName(), build(parameter.getType(), true)));
}
}
final PyType ret = type.getCallType(myContext, null);
@@ -0,0 +1,49 @@
package com.jetbrains.python.psi.types;
import com.jetbrains.python.psi.PyParameter;
import org.jetbrains.annotations.Nullable;
/**
* @author vlan
*/
public class PyCallableParameterImpl implements PyCallableParameter {
@Nullable private final String myName;
@Nullable private final PyType myType;
@Nullable private final PyParameter myElement;
public PyCallableParameterImpl(@Nullable String name, @Nullable PyType type) {
myName = name;
myType = type;
myElement = null;
}
public PyCallableParameterImpl(@Nullable PyParameter element, @Nullable PyType type) {
myName = null;
myType = type;
myElement = element;
}
@Nullable
@Override
public String getName() {
if (myName != null) {
return myName;
}
else if (myElement != null) {
return myElement.getName();
}
return null;
}
@Nullable
@Override
public PyType getType() {
return myType;
}
@Nullable
@Override
public PyParameter getParameter() {
return myElement;
}
}
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.ProcessingContext;
@@ -19,10 +18,10 @@ import java.util.List;
* @author vlan
*/
public class PyCallableTypeImpl implements PyCallableType {
@Nullable private final List<Pair<String, PyType>> myParameters;
@Nullable private final List<PyCallableParameter> myParameters;
@Nullable private final PyType myReturnType;
public PyCallableTypeImpl(@Nullable List<Pair<String, PyType>> parameters, @Nullable PyType returnType) {
public PyCallableTypeImpl(@Nullable List<PyCallableParameter> parameters, @Nullable PyType returnType) {
myParameters = parameters;
myReturnType = returnType;
}
@@ -40,7 +39,7 @@ public class PyCallableTypeImpl implements PyCallableType {
@Nullable
@Override
public List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context) {
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return myParameters;
}
@@ -61,16 +60,17 @@ public class PyCallableTypeImpl implements PyCallableType {
@Nullable
@Override
public String getName() {
final TypeEvalContext context = TypeEvalContext.codeInsightFallback();
return String.format("(%s) -> %s",
myParameters != null ?
StringUtil.join(myParameters,
new Function<Pair<String, PyType>, String>() {
new Function<PyCallableParameter, String>() {
@Override
public String fun(Pair<String, PyType> param) {
public String fun(PyCallableParameter param) {
if (param != null) {
final StringBuilder builder = new StringBuilder();
final String name = param.getFirst();
final PyType type = param.getSecond();
final String name = param.getName();
final PyType type = param.getType();
if (name != null) {
builder.append(name);
if (type != null) {
@@ -279,7 +279,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
@Nullable
@Override
public List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context) {
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
return null;
}
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.Pair;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
@@ -37,13 +36,11 @@ public class PyFunctionType implements PyCallableType {
@Nullable
@Override
public List<Pair<String, PyType>> getParameters(@NotNull TypeEvalContext context) {
final List<Pair<String, PyType>> result = new ArrayList<Pair<String, PyType>>();
public List<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
final List<PyCallableParameter> result = new ArrayList<PyCallableParameter>();
for (PyParameter parameter : myCallable.getParameterList().getParameters()) {
if (parameter instanceof PyNamedParameter) {
final PyNamedParameter namedParameter = (PyNamedParameter)parameter;
result.add(Pair.create(getParameterName(namedParameter), context.getType(namedParameter)));
}
final PyType type = parameter instanceof PyTypedElement ? context.getType((PyTypedElement)parameter) : null;
result.add(new PyCallableParameterImpl(parameter, type));
}
return result;
}
@@ -1,6 +1,5 @@
package com.jetbrains.python.psi.types;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
@@ -145,15 +144,15 @@ public class PyTypeChecker {
final PyCallableType expectedCallable = (PyCallableType)expected;
final PyCallableType actualCallable = (PyCallableType)actual;
if (expectedCallable.isCallable() && actualCallable.isCallable()) {
final List<Pair<String, PyType>> expectedParameters = expectedCallable.getParameters(context);
final List<Pair<String, PyType>> actualParameters = actualCallable.getParameters(context);
final List<PyCallableParameter> expectedParameters = expectedCallable.getParameters(context);
final List<PyCallableParameter> actualParameters = actualCallable.getParameters(context);
if (expectedParameters != null && actualParameters != null) {
final int size = Math.min(expectedParameters.size(), actualParameters.size());
for (int i = 0; i < size; i++) {
final Pair<String, PyType> expectedParam = expectedParameters.get(i);
final Pair<String, PyType> actualParam = actualParameters.get(i);
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.getSecond(), actualParam.getSecond(), context, substitutions, recursive)) {
if (!match(expectedParam.getType(), actualParam.getType(), context, substitutions, recursive)) {
return false;
}
}
@@ -234,11 +233,11 @@ public class PyTypeChecker {
}
else if (type instanceof PyCallableType) {
final PyCallableType callable = (PyCallableType)type;
final List<Pair<String, PyType>> parameters = callable.getParameters(context);
final List<PyCallableParameter> parameters = callable.getParameters(context);
if (parameters != null) {
for (Pair<String, PyType> parameter : parameters) {
for (PyCallableParameter parameter : parameters) {
if (parameter != null) {
collectGenerics(parameter.getSecond(), context, collected, visited);
collectGenerics(parameter.getType(), context, collected, visited);
}
}
}
@@ -280,12 +279,16 @@ public class PyTypeChecker {
}
else if (type instanceof PyCallableType) {
final PyCallableType callable = (PyCallableType)type;
List<Pair<String, PyType>> substParams = null;
final List<Pair<String, PyType>> parameters = callable.getParameters(context);
List<PyCallableParameter> substParams = null;
final List<PyCallableParameter> parameters = callable.getParameters(context);
if (parameters != null) {
substParams = new ArrayList<Pair<String, PyType>>();
for (Pair<String, PyType> parameter : parameters) {
substParams.add(Pair.create(parameter.getFirst(), substitute(parameter.getSecond(), substitutions, context)));
substParams = new ArrayList<PyCallableParameter>();
for (PyCallableParameter parameter : parameters) {
final PyType substType = substitute(parameter.getType(), substitutions, context);
final PyCallableParameter subst = parameter.getParameter() != null ?
new PyCallableParameterImpl(parameter.getParameter(), substType) :
new PyCallableParameterImpl(parameter.getName(), substType);
substParams.add(subst);
}
}
final PyType substResult = substitute(callable.getCallType(context, null), substitutions, context);
@@ -230,7 +230,7 @@ public class PyTypeParser {
new Function<Pair<Pair<ParseResult, List<ParseResult>>, ParseResult>, ParseResult>() {
@Override
public ParseResult fun(Pair<Pair<ParseResult, List<ParseResult>>, ParseResult> value) {
final List<Pair<String, PyType>> parameters = new ArrayList<Pair<String, PyType>>();
final List<PyCallableParameter> parameters = new ArrayList<PyCallableParameter>();
final ParseResult returnResult = value.getSecond();
ParseResult result;
final Pair<ParseResult, List<ParseResult>> firstPair = value.getFirst();
@@ -238,10 +238,10 @@ public class PyTypeParser {
final ParseResult first = firstPair.getFirst();
final List<ParseResult> second = firstPair.getSecond();
result = first;
parameters.add(Pair.<String, PyType>create(null, first.getType()));
parameters.add(new PyCallableParameterImpl((String)null, first.getType()));
for (ParseResult r : second) {
result = result.merge(r);
parameters.add(Pair.<String, PyType>create(null, r.getType()));
parameters.add(new PyCallableParameterImpl((String)null, r.getType()));
}
result = result.merge(returnResult);
}
@@ -1,6 +1,5 @@
package com.jetbrains.python;
import com.intellij.openapi.util.Pair;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.types.*;
@@ -237,11 +236,15 @@ public class PyTypeParserTest extends PyTestCase {
assertNotNull(callableType);
final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
assertInstanceOf(returnType, PyGenericType.class);
final List<Pair<String, PyType>> parameterTypes = callableType.getParameters(getTypeEvalContext());
final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
assertNotNull(parameterTypes);
assertEquals(2, parameterTypes.size());
assertEquals("int", parameterTypes.get(0).getSecond().getName());
assertEquals("T", parameterTypes.get(1).getSecond().getName());
final PyType type0 = parameterTypes.get(0).getType();
assertNotNull(type0);
assertEquals("int", type0.getName());
final PyType type1 = parameterTypes.get(1).getType();
assertNotNull(type1);
assertEquals("T", type1.getName());
}
public void testCallableWithoutArgs() {
@@ -253,7 +256,7 @@ public class PyTypeParserTest extends PyTestCase {
final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
assertNotNull(returnType);
assertEquals("int", returnType.getName());
final List<Pair<String, PyType>> parameterTypes = callableType.getParameters(getTypeEvalContext());
final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
assertNotNull(parameterTypes);
assertEquals(0, parameterTypes.size());
}