mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Show instance attributes in structure view (PY-3371)
This commit is contained in:
@@ -17,9 +17,7 @@ import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.join;
|
||||
import static com.intellij.openapi.util.text.StringUtil.notNullize;
|
||||
@@ -75,7 +73,8 @@ public class PyStructureViewElement implements StructureViewTreeElement {
|
||||
myElement.acceptChildren(new PyElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (isWorthyClassItem(element)) {
|
||||
if (element instanceof PyClass || element instanceof PyFunction ||
|
||||
(!(myElement instanceof PyClass) && isWorthyItem(element))) {
|
||||
childrenElements.add((PyElement)element);
|
||||
}
|
||||
else {
|
||||
@@ -83,47 +82,68 @@ public class PyStructureViewElement implements StructureViewTreeElement {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
StructureViewTreeElement[] children = new StructureViewTreeElement[childrenElements.size()];
|
||||
int i = 0;
|
||||
final Collection<StructureViewTreeElement> children = new ArrayList<StructureViewTreeElement>();
|
||||
for (PyElement element : childrenElements) {
|
||||
// look at functions and predefined __names__
|
||||
Visibility vis = Visibility.NORMAL;
|
||||
final Visibility vis;
|
||||
if (PsiTreeUtil.getParentOfType(element, PyFunction.class) != null) {
|
||||
// whatever is defined inside a def, is hidden
|
||||
vis = Visibility.INVISIBLE;
|
||||
}
|
||||
else {
|
||||
String name = element.getName();
|
||||
if (name != null && name.startsWith("__")) {
|
||||
if (PyNames.UnderscoredAttributes.contains(name)) {
|
||||
vis = Visibility.PREDEFINED;
|
||||
}
|
||||
else {
|
||||
vis = Visibility.PRIVATE;
|
||||
}
|
||||
}
|
||||
vis = getVisibilityByName(element.getName());
|
||||
}
|
||||
children[i] = new PyStructureViewElement(element, vis);
|
||||
final PyStructureViewElement e = new PyStructureViewElement(element, vis);
|
||||
children.add(e);
|
||||
if (element instanceof PyClass && element.isValid()) {
|
||||
PyClass the_exception = PyBuiltinCache.getInstance(element).getClass("Exception");
|
||||
final PyClass cls = (PyClass)element;
|
||||
for (PyClass anc : cls.iterateAncestorClasses()) {
|
||||
if (anc == the_exception) {
|
||||
((PyStructureViewElement)(children[i])).setIcon(Icons.EXCEPTION_CLASS_ICON);
|
||||
e.setIcon(Icons.EXCEPTION_CLASS_ICON);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return children;
|
||||
final Collection<PyTargetExpression> attrs = new ArrayList<PyTargetExpression>();
|
||||
if (myElement instanceof PyClass) {
|
||||
final PyClass c = (PyClass)myElement;
|
||||
final Comparator<PyTargetExpression> comparator = new Comparator<PyTargetExpression>() {
|
||||
@Override
|
||||
public int compare(PyTargetExpression e1, PyTargetExpression e2) {
|
||||
final String n1 = e1.getName();
|
||||
final String n2 = e2.getName();
|
||||
return (n1 != null && n2 != null) ? n1.compareTo(n2) : 0;
|
||||
}
|
||||
};
|
||||
final List<PyTargetExpression> instanceAttrs = c.getInstanceAttributes();
|
||||
final List<PyTargetExpression> classAttrs = c.getClassAttributes();
|
||||
Collections.sort(instanceAttrs, comparator);
|
||||
Collections.sort(classAttrs, comparator);
|
||||
attrs.addAll(classAttrs);
|
||||
attrs.addAll(instanceAttrs);
|
||||
}
|
||||
for (PyTargetExpression e : attrs) {
|
||||
if (e.isValid()) {
|
||||
children.add(new PyStructureViewElement(e, getVisibilityByName(e.getName())));
|
||||
}
|
||||
}
|
||||
return children.toArray(new StructureViewTreeElement[children.size()]);
|
||||
}
|
||||
|
||||
static boolean isWorthyClassItem(PsiElement element) {
|
||||
if (element instanceof PyClass) return true;
|
||||
if (element instanceof PyFunction) return true;
|
||||
private static Visibility getVisibilityByName(@Nullable String name) {
|
||||
if (name != null && name.startsWith("__")) {
|
||||
if (PyNames.UnderscoredAttributes.contains(name)) {
|
||||
return Visibility.PREDEFINED;
|
||||
}
|
||||
else {
|
||||
return Visibility.PRIVATE;
|
||||
}
|
||||
}
|
||||
return Visibility.NORMAL;
|
||||
}
|
||||
|
||||
private static boolean isWorthyItem(PsiElement element) {
|
||||
if ((element instanceof PyTargetExpression) && ((PyTargetExpression)element).getQualifier() == null) {
|
||||
PsiElement e = element.getParent();
|
||||
if (e instanceof PyAssignmentStatement) {
|
||||
@@ -142,8 +162,6 @@ public class PyStructureViewElement implements StructureViewTreeElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ItemPresentation getPresentation() {
|
||||
return new ItemPresentation() {
|
||||
public String getPresentableText() {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
class B(object):
|
||||
c1 = 0
|
||||
|
||||
def f(self, x):
|
||||
self.i1 = x
|
||||
l1 = self.i1
|
||||
self.i2 = l1
|
||||
|
||||
def __init__(self, x, y):
|
||||
self.i2 = x
|
||||
self.i3 = y
|
||||
|
||||
@classmethod
|
||||
def g(cls, x):
|
||||
cls.c2 = cls.c1
|
||||
|
||||
g1 = "foo"
|
||||
|
||||
class C(B):
|
||||
c2 = -1
|
||||
|
||||
def __init__(self, x, y):
|
||||
super(C, self).__init__(x, y)
|
||||
self.i3 = -2
|
||||
self.i4 = -3
|
||||
|
||||
def h(self):
|
||||
self.i5 = self.i6
|
||||
|
||||
c3 = -4
|
||||
|
||||
g2 = "bar"
|
||||
@@ -2,7 +2,7 @@ import lib1
|
||||
|
||||
class B1:
|
||||
def f(self, x):
|
||||
return x + self.y
|
||||
return x
|
||||
|
||||
class B2(object):
|
||||
@staticmethod
|
||||
|
||||
@@ -10,21 +10,51 @@ import static com.intellij.testFramework.PlatformTestUtil.assertTreeEqual;
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyStructureViewTest extends PyLightFixtureTestCase {
|
||||
private static String TEST_DIRECTORY = "structureView/";
|
||||
|
||||
public void testBaseClassNames() {
|
||||
myFixture.configureByFiles("structureView/baseClassNames.py",
|
||||
"structureView/lib1.py");
|
||||
myFixture.configureByFiles(TEST_DIRECTORY + "baseClassNames.py",
|
||||
TEST_DIRECTORY + "lib1.py");
|
||||
doTest("-baseClassNames.py\n" +
|
||||
" -B1\n" +
|
||||
" f(self, x)\n" +
|
||||
" -B2(object)\n" +
|
||||
" g(x)\n" +
|
||||
" C(B1, B2)\n" +
|
||||
" D1(C)\n" +
|
||||
" D2(C)\n" +
|
||||
" D3(lib1.C)\n");
|
||||
}
|
||||
|
||||
public void testAttributes() { // PY-3371
|
||||
myFixture.configureByFile(TEST_DIRECTORY + "attributes.py");
|
||||
doTest("-attributes.py\n" +
|
||||
" -B(object)\n" +
|
||||
" f(self, x)\n" +
|
||||
" __init__(self, x, y)\n" +
|
||||
" g(cls, x)\n" +
|
||||
" c1\n" +
|
||||
" c2\n" +
|
||||
" i1\n" +
|
||||
" i2\n" +
|
||||
" i3\n" +
|
||||
" g1\n" +
|
||||
" -C(B)\n" +
|
||||
" __init__(self, x, y)\n" +
|
||||
" h(self)\n" +
|
||||
" c2\n" +
|
||||
" c3\n" +
|
||||
" i3\n" +
|
||||
" i4\n" +
|
||||
" i5\n" +
|
||||
" g2\n");
|
||||
}
|
||||
|
||||
private void doTest(final String expected) {
|
||||
myFixture.testStructureView(new Consumer<StructureViewComponent>() {
|
||||
@Override
|
||||
public void consume(StructureViewComponent component) {
|
||||
assertTreeEqual(component.getTree(), "-baseClassNames.py\n" +
|
||||
" -B1\n" +
|
||||
" f(self, x)\n" +
|
||||
" -B2(object)\n" +
|
||||
" g(x)\n" +
|
||||
" C(B1, B2)\n" +
|
||||
" D1(C)\n" +
|
||||
" D2(C)\n" +
|
||||
" D3(lib1.C)\n");
|
||||
assertTreeEqual(component.getTree(), expected);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user