diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index 50ea47d93fb8..c7512d3f11b5 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -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 getClassMembers(@NotNull PyClass cls) { + public static Collection getClassMembers(@NotNull PyClass cls, boolean isDefinition) { final List result = new ArrayList(); 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()) { diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index 7452f0d8b494..09aab39c0759 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -214,7 +214,7 @@ public class PyTypeChecker { @NotNull public static Set getClassTypeAttributes(@NotNull PyClassType type, boolean inherited, @NotNull TypeEvalContext context) { - final Set attributes = getClassAttributes(type.getPyClass(), inherited, context); + final Set attributes = getClassAttributes(type.getPyClass(), inherited, type.isDefinition(), context); for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { final Collection members = provider.getMembers(type, null); for (PyCustomMember member : members) { @@ -225,7 +225,10 @@ public class PyTypeChecker { } @NotNull - private static Set getClassAttributes(@NotNull PyClass cls, boolean inherited, @NotNull TypeEvalContext context) { + private static Set getClassAttributes(@NotNull PyClass cls, + boolean inherited, + boolean isDefinition, + @NotNull TypeEvalContext context) { final Set attributes = new HashSet(); 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)); + } } } } diff --git a/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java b/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java index 900e8e9e3fa8..0b01499d95de 100644 --- a/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java +++ b/python/src/com/jetbrains/python/pyi/PyiClassMembersProvider.java @@ -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 getClassMembers(@NotNull PyClass cls) { - final List result = new ArrayList(); - 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; - } } diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/builtinListGetItem.py b/python/testData/inspections/PyUnresolvedReferencesInspection/builtinListGetItem.py new file mode 100644 index 000000000000..9c10c8424c45 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/builtinListGetItem.py @@ -0,0 +1,2 @@ +x = list[int] +x = [][0] diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index eea37a2e7b6a..2af8456ea42f 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -515,6 +515,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doTest(); } + public void testBuiltinListGetItem() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() {