support __metaclass__ attribute on new-style classes (PY-1392)

This commit is contained in:
Dmitry Jemerov
2012-03-02 19:49:46 +01:00
parent f84f5f8923
commit 0eb783c7c8
3 changed files with 31 additions and 2 deletions
@@ -177,7 +177,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
}
}
if (isDefinition() && myClass.isNewStyleClass()) {
PyClassType typeType = PyBuiltinCache.getInstance(myClass).getObjectType("type");
PyClassType typeType = getMetaclassType();
if (typeType != null) {
List<? extends RatedResolveResult> typeMembers = typeType.resolveMember(name, location, direction, resolveContext);
if (typeMembers != null && !typeMembers.isEmpty()) {
@@ -188,6 +188,20 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
return Collections.emptyList();
}
private PyClassType getMetaclassType() {
final PyTargetExpression metaClassAttribute = myClass.findClassAttribute(PyNames.METACLASS, true);
if (metaClassAttribute != null) {
final PyExpression metaclass = metaClassAttribute.findAssignedValue();
if (metaclass instanceof PyReferenceExpression) {
final QualifiedResolveResult result = ((PyReferenceExpression)metaclass).followAssignmentsChain(PyResolveContext.noImplicits());
if (result.getElement() instanceof PyClass) {
return new PyClassType((PyClass) result.getElement(), false);
}
}
}
return PyBuiltinCache.getInstance(myClass).getObjectType("type");
}
@Override
public PyType getCallType() {
if (isDefinition()) {
@@ -265,7 +279,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
}
if (isDefinition() && myClass.isNewStyleClass()) {
PyClassType typeType = PyBuiltinCache.getInstance(myClass).getObjectType("type");
PyClassType typeType = getMetaclassType();
if (typeType != null) {
Collections.addAll(ret, typeType.getCompletionVariants(prefix, location, context));
}
+10
View File
@@ -0,0 +1,10 @@
class PluginMetaclass(type):
def getStore(cls):
pass
class Plugin(object):
__metaclass__ = PluginMetaclass
def foo(self):
Plugin.getStore()
# <ref>
@@ -445,4 +445,9 @@ public class PyResolveTest extends PyResolveTestCase {
PyExpression value = target.findAssignedValue();
assertInstanceOf(value, PyNumericLiteralExpression.class);
}
public void testMetaclass() {
final PyFunction function = assertResolvesTo(PyFunction.class, "getStore");
assertEquals("PluginMetaclass", function.getContainingClass().getName());
}
}