Fixed resolving operator references on classes to their metaclasses (PY-16146)

This commit is contained in:
Andrey Vlasovskikh
2015-09-16 00:44:22 +03:00
parent ea226964e5
commit be5b20c3c8
6 changed files with 38 additions and 4 deletions
@@ -534,10 +534,18 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return;
}
addCreateMemberFromUsageFixes(type, reference, refText, actions);
if (type instanceof PyClassTypeImpl) {
if (type instanceof PyClassType) {
if (reference instanceof PyOperatorReference) {
String className = type.getName();
final PyClassType classType = (PyClassType)type;
if (classType.isDefinition()) {
final PyClassLikeType metaClassType = classType.getMetaClassType(myTypeEvalContext, true);
if (metaClassType != null) {
className = metaClassType.getName();
}
}
description = PyBundle.message("INSP.unresolved.operator.ref",
type.getName(), refName,
className, refName,
((PyOperatorReference)reference).getReadableOperatorName());
}
else {
@@ -22,6 +22,7 @@ import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -142,8 +143,13 @@ public class PyOperatorReference extends PyReferenceImpl {
final ArrayList<RatedResolveResult> results = new ArrayList<RatedResolveResult>();
if (object != null && name != null) {
final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext();
final PyType type = typeEvalContext.getType(object);
PyType type = typeEvalContext.getType(object);
typeEvalContext.trace("Side text is %s, type is %s", object.getText(), type);
if (type instanceof PyClassLikeType) {
if (((PyClassLikeType)type).isDefinition()) {
type = ((PyClassLikeType)type).getMetaClassType(typeEvalContext, true);
}
}
if (type != null) {
List<? extends RatedResolveResult> res = type.resolveMember(name, object, AccessDirection.of(myElement), myContext);
if (res != null && res.size() > 0) {
@@ -0,0 +1,7 @@
from typing import List, Any
def f(x1: List[str],
x2: List['str'],
x3: List[Any]) -> None:
pass
@@ -0,0 +1,5 @@
class Foo(object):
def __getitem__(self, item):
return item
Foo<warning descr="Class 'type' does not define '__getitem__', so the '[]' operator cannot be used on its instances">[</warning>0]
@@ -73,4 +73,9 @@ public class Py3TypeCheckerInspectionTest extends PyTestCase {
public void testTypingIterableForLoop() {
doTest();
}
// PY-16146
public void testTypingListSubscriptionExpression() {
doTest();
}
}
@@ -510,7 +510,10 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doTest();
}
// PY-16146
public void testUnresolvedSubscriptionOnClass() {
doTest();
}
@NotNull
@Override