mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Support for @DynamicAttrs annotation in the docstring of a class (PY-4600)
This commit is contained in:
@@ -658,14 +658,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
if (hasUnresolvedAncestors(cls)) {
|
||||
return true;
|
||||
}
|
||||
if (cls.getDecoratorList() != null) {
|
||||
if (isDecoratedAsDynamic(cls, true)) {
|
||||
return true;
|
||||
}
|
||||
for (PyClass base : cls.iterateAncestorClasses()) {
|
||||
if (base.getDecoratorList() != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qtype instanceof CythonBuiltinType ||
|
||||
(qtype instanceof CythonType && reference instanceof PyOperatorReference)) {
|
||||
@@ -680,6 +675,29 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isDecoratedAsDynamic(@NotNull PyClass cls, boolean inherited) {
|
||||
if (inherited) {
|
||||
if (isDecoratedAsDynamic(cls, false)) {
|
||||
return true;
|
||||
}
|
||||
for (PyClass base : cls.iterateAncestorClasses()) {
|
||||
if (base != null && isDecoratedAsDynamic(base, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (cls.getDecoratorList() != null) {
|
||||
return true;
|
||||
}
|
||||
final String docString = cls.getDocStringValue();
|
||||
if (docString != null && docString.indexOf("@DynamicAttrs") != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasUnresolvedAncestors(PyClass cls) {
|
||||
for (PyClassRef classRef : cls.iterateAncestors()) {
|
||||
if (classRef.getPyClass() == null && classRef.getType() == null) {
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
class B(object):
|
||||
def foo(self):
|
||||
pass
|
||||
|
||||
|
||||
class C(object):
|
||||
"""
|
||||
@DynamicAttrs
|
||||
"""
|
||||
def bar(self):
|
||||
pass
|
||||
|
||||
|
||||
class D(C):
|
||||
def baz(self):
|
||||
pass
|
||||
|
||||
|
||||
b = B()
|
||||
b.foo(), b.<warning descr="Unresolved attribute reference 'spam' for class 'B'">spam</warning>()
|
||||
|
||||
c = C()
|
||||
c.bar(), c.spam()
|
||||
|
||||
d = D()
|
||||
d.bar(), d.baz(), d.spam(), d.eggs()
|
||||
+5
@@ -237,6 +237,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-4600
|
||||
public void testDynamicAttrsAnnotation() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
myFixture.configureByFile(TEST_DIRECTORY + getTestName(true) + ".py");
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
|
||||
Reference in New Issue
Block a user