Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-08-21 08:06:05 +02:00
21 changed files with 199 additions and 74 deletions
+3 -1
View File
@@ -43,7 +43,8 @@ setProperty("pluginFilter", [
"python-uml", "localization",
"python-localization",
"rest", "python-rest",
"pycharm-flask"
"pycharm-flask",
"pycharm-numpy"
])
private List<String> pycharmPlatformApiModules() {
@@ -219,6 +220,7 @@ private layoutPlugins() {
layouts.layoutPlugin("rest")
layouts.layoutPlugin("python-rest")
layouts.layoutPlugin("pycharm-flask")
layouts.layoutPlugin("pycharm-numpy")
}
layouts.layoutPlugins()
+1
View File
@@ -35,6 +35,7 @@
<orderEntry type="module" module-name="python-localization" />
<orderEntry type="module" module-name="python-rest" />
<orderEntry type="module" module-name="pycharm-flask" />
<orderEntry type="module" module-name="pycharm-numpy" />
<orderEntry type="module" module-name="python-helpers" />
<orderEntry type="module" module-name="sql" />
</component>
@@ -50,7 +50,7 @@ public class PyJavaTypeProvider extends PyTypeProviderBase {
return null;
}
public PyType getParameterType(final PyNamedParameter param, final PyFunction func, TypeEvalContext context) {
public PyType getParameterType(@NotNull final PyNamedParameter param, @NotNull final PyFunction func, @NotNull TypeEvalContext context) {
if (!(param.getParent() instanceof PyParameterList)) return null;
List<PyNamedParameter> params = ParamHelper.collectNamedParameters((PyParameterList) param.getParent());
final int index = params.indexOf(param);
@@ -80,6 +80,11 @@ public class PyNames {
public static final String SEQUENCE = "Sequence";
public static final String MAPPING = "Mapping";
public static final String COMPLEX = "Complex";
public static final String REAL = "Real";
public static final String RATIONAL = "Rational";
public static final String INTEGRAL = "Integral";
public static final String CONTAINS = "__contains__";
public static final String HASH = "__hash__";
public static final String ITER = "__iter__";
@@ -328,7 +333,7 @@ public class PyNames {
);
public static Set<String> BuiltinInterfaces = ImmutableSet.of(
CALLABLE, HASHABLE, ITERABLE, ITERATOR, SIZED, CONTAINER, SEQUENCE, MAPPING
CALLABLE, HASHABLE, ITERABLE, ITERATOR, SIZED, CONTAINER, SEQUENCE, MAPPING, COMPLEX, REAL, RATIONAL, INTEGRAL
);
/**
@@ -7,9 +7,12 @@ import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author yole
*/
@@ -24,8 +27,18 @@ public abstract class PyPsiFacade {
@Nullable
public abstract PyClass findClass(String qName);
@NotNull
public abstract PyClassType createClassType(@NotNull PyClass pyClass, boolean isDefinition);
@Nullable
public abstract String findShortestImportableName(PsiElement importer, VirtualFile targetFile);
public abstract PyType createUnionType(@NotNull Collection<PyType> members);
@Nullable
public abstract PyType createTupleType(@NotNull Collection<PyType> members, @NotNull PsiElement anchor);
@Nullable
public abstract PyType parseTypeAnnotation(@NotNull String annotation, @NotNull PsiElement anchor);
@Nullable
public abstract String findShortestImportableName(@NotNull VirtualFile targetFile, @NotNull PsiElement anchor);
}
@@ -21,10 +21,10 @@ public interface PyTypeProvider {
PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor);
@Nullable
PyType getParameterType(PyNamedParameter param, final PyFunction func, TypeEvalContext context);
PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context);
@Nullable
PyType getReturnType(PyFunction function, @Nullable PyQualifiedExpression callSite, TypeEvalContext context);
PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context);
@Nullable
PyType getIterationType(PyClass iterable);
@@ -21,7 +21,7 @@ public abstract class PyModuleMembersProvider {
public Collection<PyDynamicMember> getMembers(PyFile module, PointInImport point) {
final VirtualFile vFile = module.getVirtualFile();
if (vFile != null) {
final String qName = PyPsiFacade.getInstance(module.getProject()).findShortestImportableName(module, vFile);
final String qName = PyPsiFacade.getInstance(module.getProject()).findShortestImportableName(vFile, module);
if (qName != null) {
return getMembersByQName(module, qName);
}
@@ -75,12 +75,12 @@ public class PyTypeProviderBase implements PyTypeProvider {
}
@Override
public PyType getParameterType(PyNamedParameter param, PyFunction func, TypeEvalContext context) {
public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) {
return null;
}
@Override
public PyType getReturnType(PyFunction function, @Nullable PyQualifiedExpression callSite, TypeEvalContext context) {
public PyType getReturnType(@NotNull PyFunction function, @Nullable PyQualifiedExpression callSite, @NotNull TypeEvalContext context) {
ReturnTypeDescriptor descriptor;
synchronized (myMethodToReturnTypeMap) {
descriptor = myMethodToReturnTypeMap.get(function.getName());
@@ -104,7 +104,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
@Nullable
@Override
public PyType getParameterType(PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) {
public PyType getParameterType(@NotNull PyNamedParameter param, @NotNull PyFunction func, @NotNull TypeEvalContext context) {
final String name = param.getName();
final String qname = getQualifiedName(func, param);
if (qname != null && name != null) {
@@ -3,7 +3,6 @@
## 2. Built-in functions
__builtin__.abs = \
:type number: int or long or float or complex \n\
:rtype: int \n\
__builtin__.all = \
@@ -1577,72 +1576,72 @@ collections.Iterator.next = \
## 9.2 math
math.acos = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.acosh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.asin = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.asinh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.atan = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.atan2 = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.atanh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.ceil = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.copysign = \
:type x: int or long or float \n\
:type y: int or long or float \n\
:type x: float or numbers.Real \n\
:type y: float or numbers.Real \n\
:rtype: float \n\
math.cos = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.cosh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.degrees = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.erf = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.erfc = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.exp = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.expm1 = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.fabs = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.factorial = \
@@ -1650,16 +1649,16 @@ math.factorial = \
:rtype: int \n\
math.floor = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.fmod = \
:type x: int or long or float \n\
:type y: int or long or float \n\
:type x: float or numbers.Real \n\
:type y: float or numbers.Real \n\
:rtype: float \n\
math.frexp = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: (float, int) \n\
math.fsum = \
@@ -1667,79 +1666,79 @@ math.fsum = \
:rtype: float \n\
math.gamma = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.hypot = \
:type x: int or long or float \n\
:type y: int or long or float \n\
:type x: float or numbers.Real \n\
:type y: float or numbers.Real \n\
:rtype: float \n\
math.isinf = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: bool \n\
math.isnan = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: bool \n\
math.ldexp = \
:type x: int or long or float \n\
:type y: int or long or float \n\
:type x: float or numbers.Real \n\
:type y: float or numbers.Real \n\
:rtype: float \n\
math.lgamma = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.log = \
:type x: int or long or float \n\
:type base: int or long or float \n\
:type x: float or numbers.Real \n\
:type base: float or numbers.Real \n\
:rtype: float \n\
math.log10 = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.log1p = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.modf = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: (float, float) \n\
math.pow = \
:type x: int or long or float \n\
:type y: int or long or float \n\
:type x: float or numbers.Real \n\
:type y: float or numbers.Real \n\
:rtype: float \n\
math.radians = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.sin = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.sinh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.sqrt = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.tan = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.tanh = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: float \n\
math.trunc = \
:type x: int or long or float \n\
:type x: float or numbers.Real \n\
:rtype: int \n\
@@ -3,12 +3,13 @@ package com.jetbrains.python.debugger;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyNamedParameter;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
/**
* @author traff
*/
public class PyCallSignatureTypeProvider extends PyTypeProviderBase {
public PyType getParameterType(final PyNamedParameter param, final PyFunction func, TypeEvalContext context) {
public PyType getParameterType(@NotNull final PyNamedParameter param, @NotNull final PyFunction func, @NotNull TypeEvalContext context) {
final String name = param.getName();
if (name != null) {
final String typeName = ((PySignatureCacheManagerImpl)PySignatureCacheManager.getInstance(param.getProject())).findParameterType(func, name);
@@ -318,8 +318,7 @@ public class PyBuiltinCache {
synchronized (myStdlibTypeCache) {
final Ref<PyType> ref = myStdlibTypeCache.get(key);
if (ref != null) {
final PyType pyType = ref.get();
if (pyType instanceof PyClassType && !((PyClassType)pyType).isValid()) {
if (!isValid(ref.get())) {
myStdlibTypeCache.clear();
return null;
}
@@ -328,6 +327,31 @@ public class PyBuiltinCache {
}
}
private static boolean isValid(@Nullable PyType type) {
if (type instanceof PyCollectionType) {
final PyType elementType = ((PyCollectionType)type).getElementType(TypeEvalContext.fastStubOnly(null));
if (!isValid(elementType)) {
return false;
}
}
if (type instanceof PyClassType) {
return ((PyClassType)type).isValid();
}
else if (type instanceof PyUnionType) {
for (PyType member : ((PyUnionType)type).getMembers()) {
if (!isValid(member)) {
return false;
}
}
return true;
}
else if (type instanceof PyFunctionType) {
return ((PyFunctionType)type).getFunction().isValid();
}
return true;
}
public void storeStdlibType(@NotNull String key, @Nullable PyType result) {
synchronized (myStdlibTypeCache) {
myStdlibTypeCache.put(key, new Ref<PyType>(result));
@@ -204,7 +204,7 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
}
@Nullable
private PyType getGenericReturnType(TypeEvalContext typeEvalContext, @Nullable PyQualifiedExpression callSite) {
private PyType getGenericReturnType(@NotNull TypeEvalContext typeEvalContext, @Nullable PyQualifiedExpression callSite) {
if (typeEvalContext.maySwitchToAST(this)) {
PyAnnotation anno = getAnnotation();
if (anno != null) {
@@ -9,11 +9,12 @@ import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.resolve.QualifiedNameResolverImpl;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyClassTypeImpl;
import com.jetbrains.python.psi.types.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author yole
*/
@@ -40,6 +41,7 @@ public class PyPsiFacadeImpl extends PyPsiFacade {
return PyClassNameIndex.findClass(qName, myProject);
}
@NotNull
@Override
public PyClassType createClassType(@NotNull PyClass pyClass, boolean isDefinition) {
return new PyClassTypeImpl(pyClass, isDefinition);
@@ -47,7 +49,25 @@ public class PyPsiFacadeImpl extends PyPsiFacade {
@Nullable
@Override
public String findShortestImportableName(PsiElement importer, VirtualFile targetFile) {
return QualifiedNameFinder.findShortestImportableName(importer, targetFile);
public PyType createUnionType(@NotNull Collection<PyType> members) {
return PyUnionType.union(members);
}
@Nullable
@Override
public PyType createTupleType(@NotNull Collection<PyType> members, @NotNull PsiElement anchor) {
return PyTupleType.create(anchor, members.toArray(new PyType[members.size()]));
}
@Nullable
@Override
public PyType parseTypeAnnotation(@NotNull String annotation, @NotNull PsiElement anchor) {
return PyTypeParser.getTypeByName(anchor, annotation);
}
@Nullable
@Override
public String findShortestImportableName(@NotNull VirtualFile targetFile, @NotNull PsiElement anchor) {
return QualifiedNameFinder.findShortestImportableName(anchor, targetFile);
}
}
@@ -31,7 +31,7 @@ public class QualifiedNameFinder {
* the name with fewest qualifiers is selected.
*/
@Nullable
public static String findShortestImportableName(PsiElement foothold, @NotNull VirtualFile vfile) {
public static String findShortestImportableName(@NotNull PsiElement foothold, @NotNull VirtualFile vfile) {
final PyQualifiedName qName = findShortestImportableQName(foothold, vfile);
return qName == null ? null : qName.toString();
}
@@ -53,6 +53,15 @@ public class PyABCUtil {
if (PyNames.MAPPING.equals(superClassName)) {
return isSized && hasIter && isContainer && hasGetItem && hasMethod(subClass, PyNames.KEYS, inherited);
}
if (PyNames.COMPLEX.equals(superClassName)) {
return hasMethod(subClass, "__complex__", inherited);
}
if (PyNames.REAL.equals(superClassName)) {
return hasMethod(subClass, "__float__", inherited);
}
if (PyNames.INTEGRAL.equals(superClassName)) {
return hasMethod(subClass, "__int__", inherited);
}
return false;
}
@@ -50,9 +50,6 @@ public class PyTypeChecker {
if (actual instanceof PyTypeReference) {
return match(expected, ((PyTypeReference)actual).resolve(null, context), context, substitutions, false);
}
if (isUnknown(actual)) {
return true;
}
if (expected instanceof PyGenericType && substitutions != null) {
final PyGenericType generic = (PyGenericType)expected;
final PyType subst = substitutions.get(generic);
@@ -72,6 +69,9 @@ public class PyTypeChecker {
return true;
}
}
if (isUnknown(actual)) {
return true;
}
if (actual instanceof PyUnionType) {
for (PyType m : ((PyUnionType)actual).getMembers()) {
if (!match(expected, m, context, substitutions, recursive)) {
@@ -149,7 +149,7 @@ public class PyTypeChecker {
}
public static boolean isUnknown(@Nullable PyType type) {
if (type == null || type instanceof PyTypeReference) {
if (type == null || type instanceof PyTypeReference || type instanceof PyGenericType) {
return true;
}
if (type instanceof PyUnionType) {
@@ -165,29 +165,34 @@ public class PyTypeChecker {
public static boolean hasGenerics(@Nullable PyType type, @NotNull TypeEvalContext context) {
final Set<PyGenericType> collected = new HashSet<PyGenericType>();
collectGenerics(type, context, collected);
collectGenerics(type, context, collected, new HashSet<PyType>());
return !collected.isEmpty();
}
private static void collectGenerics(@Nullable PyType type, @NotNull TypeEvalContext context, @NotNull Set<PyGenericType> collected) {
private static void collectGenerics(@Nullable PyType type, @NotNull TypeEvalContext context, @NotNull Set<PyGenericType> collected,
@NotNull Set<PyType> visited) {
if (visited.contains(type)) {
return;
}
visited.add(type);
if (type instanceof PyGenericType) {
collected.add((PyGenericType)type);
}
else if (type instanceof PyUnionType) {
final PyUnionType union = (PyUnionType)type;
for (PyType t : union.getMembers()) {
collectGenerics(t, context, collected);
collectGenerics(t, context, collected, visited);
}
}
else if (type instanceof PyCollectionType) {
final PyCollectionType collection = (PyCollectionType)type;
collectGenerics(collection.getElementType(context), context, collected);
collectGenerics(collection.getElementType(context), context, collected, visited);
}
else if (type instanceof PyTupleType) {
final PyTupleType tuple = (PyTupleType)type;
final int n = tuple.getElementCount();
for (int i = 0; i < n; i++) {
collectGenerics(tuple.getElementType(i), context, collected);
collectGenerics(tuple.getElementType(i), context, collected, visited);
}
}
}
@@ -252,7 +257,7 @@ public class PyTypeChecker {
// Collect generic params of object type
final Set<PyGenericType> generics = new LinkedHashSet<PyGenericType>();
final PyType qualifierType = receiver != null ? receiver.getType(context) : null;
collectGenerics(qualifierType, context, generics);
collectGenerics(qualifierType, context, generics, new HashSet<PyType>());
for (PyGenericType t : generics) {
substitutions.put(t, t);
}
@@ -0,0 +1,18 @@
class B(object):
def __init__(self, x):
"""
:type x: T
:rtype: B of T
"""
self._x = x
def foo(self):
"""
:rtype: T
"""
return self._x
class C(B):
def bar(self):
expr = self.foo()
return 'foo' + expr #pass
@@ -0,0 +1,18 @@
class B(object):
def __init__(self, x):
"""
:type x: T
:rtype: B of T
"""
self._x = x
def foo(self):
"""
:rtype: T
"""
return self._x
class C(B):
def bar(self):
expr = self.foo()
return expr.upper() #pass
@@ -140,4 +140,9 @@ public class PyTypeCheckerInspectionTest extends PyTestCase {
public void testAssignedOperator() {
doTest();
}
// PY-7244
public void testGenericArguments() {
doTest();
}
}
@@ -175,6 +175,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
// PY-7244
public void testAttributesOfGenerics() {
doTest();
}
private void doTest() {
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);