Refactor to regex and tests.

Closes Debugger lists immediate array dimension last #606.
This commit is contained in:
A Samuel Pottinger
2023-05-09 18:12:27 +00:00
parent 5ec4cdc295
commit 2fdd3e5f36
2 changed files with 122 additions and 29 deletions

View File

@@ -29,6 +29,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
@@ -52,13 +55,16 @@ public class VariableNode implements MutableTreeNode {
public static final int TYPE_SHORT = 10;
public static final int TYPE_VOID = 11;
private static final Pattern ARRAY_REGEX = Pattern.compile(
"^(?<prefix>[^\\]]+)(?<unbounded>(\\[\\])*)(?<bounded>(\\[\\d+\\])+).*$"
);
protected String type;
protected String name;
protected Value value;
protected List<MutableTreeNode> children = new ArrayList<>();
protected MutableTreeNode parent;
/**
* Construct a {@link VariableNode}.
* @param name the name
@@ -88,35 +94,21 @@ public class VariableNode implements MutableTreeNode {
* @return a String representing the value.
*/
public String getStringValue() {
String str;
if (value != null) {
if (getType() == TYPE_OBJECT) {
str = "instance of " + type;
} else if (getType() == TYPE_ARRAY) {
//instance of int[5] (id=998) --> instance of int[5]
str = value.toString().substring(0, value.toString().lastIndexOf(" "));
/*
*formats multidimensional array values to have the size of the first array in
*the first bracket eg.int[][5]-->int[5][]
*/
// resolves issue #606: https://github.com/processing/processing4/issues/606
if (str.contains("][")) {
String brackets = str.substring(str.indexOf('['));
int arrayDimensions = 0;
String num = brackets.replaceAll("[^\\d]", "");
arrayDimensions = (brackets.length() - num.length()) / 2;
brackets = "[" + num + "]" + "[]".repeat(arrayDimensions - 1);
str = str.substring(0, str.indexOf('[')) + brackets;
}
} else if (getType() == TYPE_STRING) {
str = ((StringReference) value).value(); // use original string value (without quotes)
} else {
str = value.toString();
}
} else {
str = "null";
if (value == null) {
return "null";
}
int typeDescriptor = getType();
if (typeDescriptor == TYPE_OBJECT) {
return "instance of " + type;
} else if (typeDescriptor == TYPE_ARRAY) {
return describeArray(value.toString());
} else if (typeDescriptor == TYPE_STRING) {
// use original string value (without quotes)
return ((StringReference) value).value();
} else {
return value.toString();
}
return str;
}
@@ -393,4 +385,24 @@ public class VariableNode implements MutableTreeNode {
hash = 97 * hash + (this.value != null ? this.value.hashCode() : 0);
return hash;
}
/**
* Describe an array in a human friendly description.
*
* @see Issue #606
* @param fullDescrition The full description of the array like "instance of
* int[5] (id=998)" or "instance of int[][5] (id=998)"
* @return Human-friendly description like "instance of int[5]" or
* "instance of int[5][]".
*/
private String describeArray(String fullDescription) {
Matcher matcher = ARRAY_REGEX.matcher(fullDescription);
StringJoiner joiner = new StringJoiner("");
System.out.println(matcher.matches());
joiner.add(matcher.group("prefix")); // Type without brackets
joiner.add(matcher.group("bounded")); // Brackets with numbers
joiner.add(matcher.group("unbounded")); // Brackets without numbers
return joiner.toString();
}
}

View File

@@ -0,0 +1,81 @@
package processing.mode.java.debug;
import com.sun.jdi.StringReference;
import com.sun.jdi.Value;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class VariableNodeTests {
@Test
public void describeInt() {
Value value = buildMockValue("5");
VariableNode node = new VariableNode("test", "int", value);
Assert.assertEquals(node.getStringValue(), "5");
}
@Test
public void describeFloat() {
Value value = buildMockValue("5.5");
VariableNode node = new VariableNode("test", "float", value);
Assert.assertEquals(node.getStringValue(), "5.5");
}
@Test
public void describeObject() {
Value value = buildMockValue("5.5");
VariableNode node = new VariableNode("test", "Other", value);
Assert.assertEquals(node.getStringValue(), "instance of Other");
}
@Test
public void describeString() {
Value value = buildMockString("testing");
VariableNode node = new VariableNode("test", "java.lang.String", value);
Assert.assertEquals(node.getStringValue(), "testing");
}
@Test
public void describeSimpleArray() {
Value value = buildMockValue("instance of int[5] (id=998)");
VariableNode node = new VariableNode("test", "int[]", value);
Assert.assertEquals(node.getStringValue(), "instance of int[5]");
}
@Test
public void describeNestedArraySingleDimensionUnknown() {
Value value = buildMockValue("instance of int[][5] (id=998)");
VariableNode node = new VariableNode("test", "int[][]", value);
Assert.assertEquals(node.getStringValue(), "instance of int[5][]");
}
@Test
public void describeNestedArrayMultiDimensionUnknown() {
Value value = buildMockValue("instance of int[][][5] (id=998)");
VariableNode node = new VariableNode("test", "int[][][]", value);
Assert.assertEquals(node.getStringValue(), "instance of int[5][][]");
}
@Test
public void describeNestedArrayMixed() {
Value value = buildMockValue("instance of int[][][5][7] (id=998)");
VariableNode node = new VariableNode("test", "int[][][][]", value);
Assert.assertEquals(node.getStringValue(), "instance of int[5][7][][]");
}
private Value buildMockValue(String toStringValue) {
Value value = Mockito.mock(Value.class);
Mockito.when(value.toString()).thenReturn(toStringValue);
return value;
}
private StringReference buildMockString(String innerValue) {
StringReference value = Mockito.mock(StringReference.class);
Mockito.when(value.value()).thenReturn(innerValue);
return value;
}
}