Search for missing class attributes in user skeletons (PY-9011)

This commit is contained in:
Andrey Vlasovskikh
2013-09-12 19:22:19 +04:00
parent b3d8ec8c43
commit 19668efb41
5 changed files with 97 additions and 0 deletions
@@ -558,6 +558,7 @@
<!-- User skeletons -->
<pyModuleMembersProvider implementation="com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsModuleMembersProvider"/>
<pyClassMembersProvider implementation="com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsClassMembersProvider"/>
<typeProvider implementation="com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsTypeProvider"/>
<typeProvider implementation="com.jetbrains.python.debugger.PyCallSignatureTypeProvider"/>
@@ -0,0 +1,82 @@
package com.jetbrains.python.codeInsight.userSkeletons;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.codeInsight.PyDynamicMember;
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 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
*/
public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase {
@NotNull
@Override
public Collection<PyDynamicMember> getMembers(@NotNull PyClassType classType, PsiElement location) {
final PyClass cls = classType.getPyClass();
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
if (skeleton != null) {
return getClassMembers(skeleton);
}
return Collections.emptyList();
}
@Nullable
@Override
public PsiElement resolveMember(@NotNull PyClassType classType, @NotNull String name, PsiElement location) {
final PyClass cls = classType.getPyClass();
final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls);
if (skeleton != null) {
return findClassMember(skeleton, name);
}
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<PyDynamicMember> getClassMembers(@NotNull PyClass cls) {
final List<PyDynamicMember> result = new ArrayList<PyDynamicMember>();
for (PyFunction function : cls.getMethods()) {
final String name = function.getName();
if (name != null) {
result.add(new PyDynamicMember(name, function));
}
}
for (PyTargetExpression attribute : cls.getInstanceAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyDynamicMember(name, attribute));
}
}
for (PyTargetExpression attribute : cls.getClassAttributes()) {
final String name = attribute.getName();
if (name != null) {
result.add(new PyDynamicMember(name, attribute));
}
}
return result;
}
}
@@ -0,0 +1,5 @@
from datetime import date
print(date.today)
print(date.max)
print(date.<warning descr="Unresolved attribute reference 'foo' for class 'date'">foo</warning>)
@@ -0,0 +1,4 @@
class date(object):
@classmethod
def today(cls):
return date(0, 0, 0)
@@ -58,6 +58,11 @@ public class Py3UnresolvedReferencesInspectionTest extends PyTestCase {
doTest();
}
// PY-9011
public void testDatetimeDateAttributesOutsideClass() {
doMultiFileTest("a.py");
}
public void testObjectNewAttributes() {
doTest();
}