mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
Property access inspection.
This commit is contained in:
@@ -67,22 +67,12 @@ public class PyPropertyAccessInspection extends PyInspection {
|
||||
@Override
|
||||
public void visitPyReferenceExpression(PyReferenceExpression node) {
|
||||
super.visitPyReferenceExpression(node);
|
||||
check(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTargetExpression(PyTargetExpression node) {
|
||||
super.visitPyTargetExpression(node);
|
||||
check(node);
|
||||
}
|
||||
|
||||
private void check(PyQualifiedExpression expr) {
|
||||
PyExpression qualifier = expr.getQualifier();
|
||||
PyExpression qualifier = node.getQualifier();
|
||||
if (qualifier != null) {
|
||||
PyType type = qualifier.getType(TypeEvalContext.fast());
|
||||
if (type instanceof PyClassType) {
|
||||
PyClass cls = ((PyClassType)type).getPyClass();
|
||||
String name = expr.getName();
|
||||
String name = node.getName();
|
||||
if (cls != null && name != null) {
|
||||
Map<Pair<PyClass, String>, Property> cache = PyPropertyAccessInspection.this.myPropertyCache.get();
|
||||
final Pair<PyClass, String> key = new Pair<PyClass, String>(cls, name);
|
||||
@@ -91,19 +81,27 @@ public class PyPropertyAccessInspection extends PyInspection {
|
||||
else property = cls.findProperty(name);
|
||||
cache.put(key, property); // we store nulls, too, to know that a property does not exist
|
||||
if (property != null) {
|
||||
AccessDirection dir = AccessDirection.of(expr);
|
||||
final Maybe<PyFunction> accessor = property.getByDirection(dir);
|
||||
if (accessor.isDefined() && accessor.value() == null) {
|
||||
String message;
|
||||
if (dir == AccessDirection.WRITE) message = PyBundle.message("INSP.property.$0.cant.be.set", name);
|
||||
else if (dir == AccessDirection.DELETE) message = PyBundle.message("INSP.property.$0.cant.be.deleted", name);
|
||||
else message = PyBundle.message("INSP.property.$0.cant.be.read", name);
|
||||
registerProblem(expr, message);
|
||||
AccessDirection dir = AccessDirection.of(node);
|
||||
checkAccessor(node, name, dir, property);
|
||||
if (dir == AccessDirection.READ && node.getParent() instanceof PyAugAssignmentStatement) {
|
||||
checkAccessor(node, name, AccessDirection.WRITE, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAccessor(PyReferenceExpression node, String name, AccessDirection dir, Property property) {
|
||||
Maybe<PyFunction> accessor = property.getByDirection(dir);
|
||||
if (accessor.isDefined() && accessor.value() == null) {
|
||||
String message;
|
||||
if (dir == AccessDirection.WRITE) message = PyBundle.message("INSP.property.$0.cant.be.set", name);
|
||||
else if (dir == AccessDirection.DELETE) message = PyBundle.message("INSP.property.$0.cant.be.deleted", name);
|
||||
else message = PyBundle.message("INSP.property.$0.cant.be.read", name);
|
||||
registerProblem(node, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>23</line>
|
||||
<description>Property 'readonly' cannot be set</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>24</line>
|
||||
<description>Property 'readonly' cannot be deleted</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>28</line>
|
||||
<description>Property 'writeonly' cannot be read</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>29</line>
|
||||
<description>Property 'writeonly' cannot be read</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>30</line>
|
||||
<description>Property 'writeonly' cannot be deleted</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>props.py</file>
|
||||
<line>36</line>
|
||||
<description>Property 'readwrite' cannot be deleted</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -203,4 +203,15 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase {
|
||||
myFixture.enableInspections(PyCallingNonCallableInspection.class);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testPyPropertyAccessInspection() throws Throwable {
|
||||
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), LanguageLevel.PYTHON26);
|
||||
try {
|
||||
LocalInspectionTool inspection = new PyPropertyAccessInspection();
|
||||
doTest(getTestName(false), inspection);
|
||||
}
|
||||
finally {
|
||||
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user