Merge branch 'python-fixes'

This commit is contained in:
Andrey Vlasovskikh
2015-10-20 15:04:16 +03:00
5 changed files with 43 additions and 62 deletions
@@ -20,6 +20,7 @@ import com.jetbrains.python.codeInsight.PyCustomMember;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.types.PyClassMembersProviderBase;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyOverridingAncestorsClassMembersProvider;
@@ -42,7 +43,7 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB
final PyClass cls = classType.getPyClass();
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
if (skeleton != null) {
return getClassMembers(skeleton);
return getClassMembers(skeleton, classType.isDefinition());
}
return Collections.emptyList();
}
@@ -53,19 +54,25 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB
final PyClass cls = classType.getPyClass();
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
if (skeleton != null) {
return findClassMember(skeleton, name);
return findClassMember(skeleton, name, classType.isDefinition());
}
return null;
}
private static PsiElement findClassMember(@NotNull PyClass cls, @NotNull String name) {
public static PsiElement findClassMember(@NotNull PyClass cls, @NotNull String name, boolean isDefinition) {
final PyFunction function = cls.findMethodByName(name, false);
if (function != null) {
return function;
final PyUtil.MethodFlags methodFlags = PyUtil.MethodFlags.of(function);
final boolean instanceMethod = methodFlags == null || methodFlags.isInstanceMethod();
if (isDefinition ^ instanceMethod) {
return function;
}
}
final PyTargetExpression instanceAttribute = cls.findInstanceAttribute(name, false);
if (instanceAttribute != null) {
return instanceAttribute;
if (!isDefinition) {
final PyTargetExpression instanceAttribute = cls.findInstanceAttribute(name, false);
if (instanceAttribute != null) {
return instanceAttribute;
}
}
final PyTargetExpression classAttribute = cls.findClassAttribute(name, false);
if (classAttribute != null) {
@@ -74,18 +81,22 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB
return null;
}
private static Collection<PyCustomMember> getClassMembers(@NotNull PyClass cls) {
public static Collection<PyCustomMember> getClassMembers(@NotNull PyClass cls, boolean isDefinition) {
final List<PyCustomMember> result = new ArrayList<PyCustomMember>();
for (PyFunction function : cls.getMethods(false)) {
final String name = function.getName();
if (name != null) {
final PyUtil.MethodFlags methodFlags = PyUtil.MethodFlags.of(function);
final boolean instanceMethod = methodFlags == null || methodFlags.isInstanceMethod();
if (name != null && (isDefinition ^ instanceMethod)) {
result.add(new PyCustomMember(name, function));
}
}
for (PyTargetExpression attribute : cls.getInstanceAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyCustomMember(name, attribute));
if (!isDefinition) {
for (PyTargetExpression attribute : cls.getInstanceAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyCustomMember(name, attribute));
}
}
}
for (PyTargetExpression attribute : cls.getClassAttributes()) {
@@ -214,7 +214,7 @@ public class PyTypeChecker {
@NotNull
public static Set<String> getClassTypeAttributes(@NotNull PyClassType type, boolean inherited, @NotNull TypeEvalContext context) {
final Set<String> attributes = getClassAttributes(type.getPyClass(), inherited, context);
final Set<String> attributes = getClassAttributes(type.getPyClass(), inherited, type.isDefinition(), context);
for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) {
final Collection<PyCustomMember> members = provider.getMembers(type, null);
for (PyCustomMember member : members) {
@@ -225,7 +225,10 @@ public class PyTypeChecker {
}
@NotNull
private static Set<String> getClassAttributes(@NotNull PyClass cls, boolean inherited, @NotNull TypeEvalContext context) {
private static Set<String> getClassAttributes(@NotNull PyClass cls,
boolean inherited,
boolean isDefinition,
@NotNull TypeEvalContext context) {
final Set<String> attributes = new HashSet<String>();
for (PyFunction function : cls.getMethods(false)) {
attributes.add(function.getName());
@@ -239,8 +242,11 @@ public class PyTypeChecker {
if (inherited) {
for (PyClass ancestor : cls.getAncestorClasses(null)) {
final PyType ancestorType = context.getType(ancestor);
if (ancestorType instanceof PyClassType) {
attributes.addAll(getClassTypeAttributes((PyClassType)ancestorType, false, context));
if (ancestorType instanceof PyClassLikeType) {
final PyClassLikeType classType = isDefinition ? (PyClassLikeType)ancestorType : ((PyClassLikeType)ancestorType).toInstance();
if (classType instanceof PyClassType) {
attributes.addAll(getClassTypeAttributes((PyClassType)classType, false, context));
}
}
}
}
@@ -17,9 +17,8 @@ package com.jetbrains.python.pyi;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.codeInsight.PyCustomMember;
import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsClassMembersProvider;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.types.PyClassMembersProviderBase;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyOverridingAncestorsClassMembersProvider;
@@ -27,10 +26,8 @@ import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author vlan
@@ -42,7 +39,7 @@ public class PyiClassMembersProvider extends PyClassMembersProviderBase implemen
final PyClass cls = classType.getPyClass();
final PsiElement pythonStub = PyiUtil.getPythonStub(cls);
if (pythonStub instanceof PyClass) {
return getClassMembers((PyClass)pythonStub);
return PyUserSkeletonsClassMembersProvider.getClassMembers((PyClass)pythonStub, classType.isDefinition());
}
return Collections.emptyList();
}
@@ -54,47 +51,8 @@ public class PyiClassMembersProvider extends PyClassMembersProviderBase implemen
final PyClass cls = classType.getPyClass();
final PsiElement pythonStub = PyiUtil.getPythonStub(cls);
if (pythonStub instanceof PyClass) {
return findClassMember((PyClass)pythonStub, name);
return PyUserSkeletonsClassMembersProvider.findClassMember((PyClass)pythonStub, name, classType.isDefinition());
}
return null;
}
private static PsiElement findClassMember(@NotNull PyClass cls, @NotNull String name) {
final PyFunction function = cls.findMethodByName(name, false);
if (function != null) {
return function;
}
final PyTargetExpression instanceAttribute = cls.findInstanceAttribute(name, false);
if (instanceAttribute != null) {
return instanceAttribute;
}
final PyTargetExpression classAttribute = cls.findClassAttribute(name, false);
if (classAttribute != null) {
return classAttribute;
}
return null;
}
private static Collection<PyCustomMember> getClassMembers(@NotNull PyClass cls) {
final List<PyCustomMember> result = new ArrayList<PyCustomMember>();
for (PyFunction function : cls.getMethods(false)) {
final String name = function.getName();
if (name != null) {
result.add(new PyCustomMember(name, function));
}
}
for (PyTargetExpression attribute : cls.getInstanceAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyCustomMember(name, attribute));
}
}
for (PyTargetExpression attribute : cls.getClassAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyCustomMember(name, attribute));
}
}
return result;
}
}
@@ -0,0 +1,2 @@
x = list<warning descr="Class 'type' does not define '__getitem__', so the '[]' operator cannot be used on its instances">[</warning>int]
x = [][0]
@@ -515,6 +515,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doTest();
}
public void testBuiltinListGetItem() {
doTest();
}
@NotNull
@Override
protected Class<? extends PyInspection> getInspectionClass() {