Skip to content

Commit

Permalink
visualizer/JTree: make subclasses of ObjectTreeNode handle null values (
Browse files Browse the repository at this point in the history
  • Loading branch information
wilcoxjay authored Nov 8, 2023
1 parent 5ba97c9 commit c2ad906
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
import dslabs.framework.testing.LocalAddress;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.swing.JLabel;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -132,6 +134,26 @@ public void diffTest() {
f2.v03 = null;
f2.v04 = new int[]{1, 2, 3, 4};
f2.v05 = null;
f2.v06 = null;
f2.v06v1 = new LocalAddress(("jkjkjk"));
f2.v0not7v1 = null;
f2.v0not7v2 = new LinkedList<>() {
@Override
public String toString() {
return "[]";
}
};
f2.v08 = null;
f2.v09 = new Integer[]{17, 42};
f2.v11 = null;
f2.v12 = new HashMap<>();
f2.v12.put("a", 3);
f2.v12.put("b", 47);
f2.v13 = null;
f2.v14 = new HashSet<>();
f2.v14.add("a");
f2.v14.add("b");


t.update(f2);

Expand Down Expand Up @@ -163,26 +185,42 @@ class Foo extends Node {
int[] v04 = null;
int[] v05 = new int[3];
Address v06 = new LocalAddress("asdf");
Address v06v1 = null;
List<Object> v07 = new LinkedList<>() {
@Override
public String toString() {
return "[]";
}
};
// carefully avoid "v07" regex match in these field names because the tests
// look for that to match the previous field.
List<Object> v0not7v1 = new LinkedList<>() {
@Override
public String toString() {
return "[]";
}
};
List<Object> v0not7v2 = null;

Integer[] v08 = new Integer[]{0, 5, 3};
Integer[] v09 = null;

Object[] v10 = new Object[]{"foo", 4, new int[]{1, 2, 3}};

Map<String, Integer> v11 = new HashMap<>();
Map<String, Integer> v12 = null;
Set<String> v13 = new HashSet<>();
Set<String> v14 = null;

{
v07.add("qwerty");
v07.add(9876);

v11.put("lbskj", 78525);
v11.put("asiudb", 98623578);

v13.add("wreuio");
v13.add("097");
}

protected Foo(@NonNull Address address) {
Expand Down
35 changes: 24 additions & 11 deletions framework/tst/dslabs/framework/testing/visualization/JTrees.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import lombok.Setter;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ClassUtils;
import org.checkerframework.checker.nullness.qual.Nullable;

import static dslabs.framework.testing.visualization.Utils.makeIcon;

Expand Down Expand Up @@ -140,7 +141,7 @@ void setTreeDisplayType(JTreeDisplayType jTreeDisplayType) {
* Specialized JTree which displays arbitrary Java objects. These objects can be
* arbitrarily nested and can even contain circular references. Objects are
* expanded on demand. Objects given to a {@code JObjectTree} should not be
* modified in any after creation of the tree.
* modified in any way after creation of the tree.
*/
class ObjectJTree extends BaseJTree {
private static class ObjectJTreeCellRenderer extends BaseJTreeCellRenderer {
Expand Down Expand Up @@ -295,11 +296,6 @@ static protected ObjectTreeNode createNode(Object value,
@SneakyThrows
static protected ObjectTreeNode createNode(Class<?> clz, Object value,
ObjectJTree tree) {
// Non-default tree nodes don't handle null values
if (value == null) {
return new DefaultObjectNode(null, tree);
}

for (Class<?> c : NODE_TYPES_IN_PRIORITY_ORDER) {
if ((Boolean) c.getDeclaredMethod("canHandle", Class.class)
.invoke(null, clz)) {
Expand Down Expand Up @@ -353,7 +349,7 @@ enum DiffStatus {
}

private KeyInstance keyInstance;
@Getter(AccessLevel.PROTECTED) private Object valueObj;
@Getter(AccessLevel.PROTECTED) @Nullable private Object valueObj;
private ObjectTreeNode diffTarget;
private boolean isDiffed = false;
private boolean hasExpanded = false;
Expand Down Expand Up @@ -751,6 +747,9 @@ static boolean canHandle(Class<?> clz) {

@Override
protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {
if (valueObj() == null) {
return;
}
for (Entry<?, ?> entry : ((Map<?, ?>) valueObj()).entrySet()) {
childAdder.accept(new DefaultChildKey(entry.getKey()),
new MapEntryNode(entry.getValue(), tree()));
Expand Down Expand Up @@ -816,6 +815,9 @@ public String renderKey() {

@Override
protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {
if (valueObj() == null) {
return;
}
int i = 0;
for (Object item : (List<?>) valueObj()) {
childAdder.accept(new ListKey(i), createNode(item));
Expand Down Expand Up @@ -887,6 +889,9 @@ protected String treeCellTextInternal() {
@Override
protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {
Object o = valueObj();
if (o == null) {
return;
}
int i = 0;
if (o instanceof byte[]) {
for (byte item : (byte[]) valueObj()) {
Expand Down Expand Up @@ -967,6 +972,9 @@ public String renderKey() {

@Override
protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {
if (valueObj() == null) {
return;
}
for (Object item : (Set<?>) valueObj()) {
childAdder.accept(new SetKey(item), createNode(item));
}
Expand Down Expand Up @@ -1011,8 +1019,8 @@ protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {

@Override
protected String treeCellTextInternal() {
Class<?> primitiveClass =
ClassUtils.wrapperToPrimitive(valueObj().getClass());
assert valueObj() != null; // primitives cannot be null
Class<?> primitiveClass = ClassUtils.wrapperToPrimitive(valueObj().getClass());

StringBuilder sb = new StringBuilder();
if (keyObj() != null) {
Expand Down Expand Up @@ -1057,15 +1065,20 @@ protected void expand(BiConsumer<ChildKey, ObjectTreeNode> childAdder) {

@Override
protected String treeCellTextInternal() {
assert valueObj() != null && valueObj() instanceof Address;
assert valueObj() == null || valueObj() instanceof Address;

StringBuilder sb = new StringBuilder();
if (keyObj() != null) {
sb.append(renderKey());
}
sb.append(String.format("<font color='%s'>(Address)</font>",
secondaryColor()));
sb.append(valueObj());
if (valueObj() != null) {
sb.append(valueObj());
} else {
sb.append(String.format("<font color='%s'>null</font>",
secondaryColor()));
}

return sb.toString();
}
Expand Down

0 comments on commit c2ad906

Please sign in to comment.