mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fixed callable check for reference to lambda in property definition (PY-7680)
This commit is contained in:
@@ -22,6 +22,7 @@ import com.jetbrains.python.psi.impl.PyQualifiedName;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyNoneType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.PyTypeChecker;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -135,8 +136,9 @@ public class PyPropertyDefinitionInspection extends PyInspection {
|
||||
Callable callable = null;
|
||||
if (argument instanceof PyReferenceExpression) {
|
||||
PsiElement resolved = ((PyReferenceExpression)argument).getReference(resolveWithoutImplicits()).resolve();
|
||||
if (resolved instanceof PyFunction) callable = (PyFunction)resolved;
|
||||
else if (resolved instanceof PyLambdaExpression) callable = (PyLambdaExpression)resolved;
|
||||
if (resolved instanceof Callable) {
|
||||
callable = (Callable)resolved;
|
||||
}
|
||||
else {
|
||||
reportNonCallableArg(resolved, argument);
|
||||
return;
|
||||
@@ -161,19 +163,19 @@ public class PyPropertyDefinitionInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
|
||||
private void reportNonCallableArg(PsiElement resolved, PsiElement being_checked) {
|
||||
if (! PyUtil.instanceOf(resolved, PySubscriptionExpression.class, PyNoneLiteralExpression.class)) {
|
||||
boolean is_not_callable = true;
|
||||
if (resolved instanceof PyExpression) {
|
||||
PyType expr_type = ((PyExpression)resolved).getType(myTypeEvalContext);
|
||||
if (expr_type instanceof PyClassType) {
|
||||
final PyClassType cls_type = (PyClassType)expr_type;
|
||||
PyClass cls = cls_type.getPyClass();
|
||||
if (!cls_type.isDefinition()) is_not_callable = cls.findMethodByName("__call__", true) == null;
|
||||
}
|
||||
private void reportNonCallableArg(PsiElement resolved, PsiElement element) {
|
||||
if (resolved instanceof PySubscriptionExpression || resolved instanceof PyNoneLiteralExpression) {
|
||||
return;
|
||||
}
|
||||
if (PyNames.NONE.equals(element.getText())) {
|
||||
return;
|
||||
}
|
||||
if (resolved instanceof PyTypedElement) {
|
||||
final PyType type = ((PyTypedElement)resolved).getType(myTypeEvalContext);
|
||||
final Boolean isCallable = PyTypeChecker.isCallable(type);
|
||||
if (isCallable != null && !isCallable) {
|
||||
registerProblem(element, PyBundle.message("INSP.strange.arg.want.callable"));
|
||||
}
|
||||
if (is_not_callable && !"None".equals(being_checked.getText()))
|
||||
registerProblem(being_checked, PyBundle.message("INSP.strange.arg.want.callable"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,5 @@
|
||||
<line>48</line>
|
||||
<description>Getter should return something</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>prop_test.py</file>
|
||||
<line>76</line>
|
||||
<description>Strange argument; a callable expected</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ gb = Ghostbusters()
|
||||
class B(object):
|
||||
x = property(gb) # pass
|
||||
y = property(Ghostbusters()) # pass
|
||||
z = property(Ghostbusters) # fail: not callable
|
||||
z = property(Ghostbusters) # pass
|
||||
|
||||
class Eternal(object):
|
||||
def give(self):
|
||||
|
||||
@@ -59,3 +59,7 @@ class A(object):
|
||||
def xoo(self, x):
|
||||
self._x = x
|
||||
return
|
||||
|
||||
get_foo2 = lambda self: 'foo2'
|
||||
|
||||
foo2 = property(get_foo2)
|
||||
|
||||
Reference in New Issue
Block a user