|
11 | 11 |
|
12 | 12 | package com.microsoft.java.debug.core.adapter.variables; |
13 | 13 |
|
| 14 | +import java.util.Collections; |
14 | 15 | import java.util.List; |
15 | 16 | import java.util.Objects; |
| 17 | +import java.util.concurrent.ExecutionException; |
16 | 18 |
|
17 | | -import org.apache.commons.lang3.StringUtils; |
18 | | - |
| 19 | +import com.microsoft.java.debug.core.adapter.IEvaluationProvider; |
| 20 | +import com.sun.jdi.ClassNotLoadedException; |
19 | 21 | import com.sun.jdi.ClassType; |
| 22 | +import com.sun.jdi.Field; |
| 23 | +import com.sun.jdi.IncompatibleThreadStateException; |
20 | 24 | import com.sun.jdi.InterfaceType; |
| 25 | +import com.sun.jdi.InvalidTypeException; |
| 26 | +import com.sun.jdi.InvocationException; |
| 27 | +import com.sun.jdi.Method; |
21 | 28 | import com.sun.jdi.ObjectReference; |
| 29 | +import com.sun.jdi.ThreadReference; |
22 | 30 | import com.sun.jdi.Type; |
| 31 | +import com.sun.jdi.Value; |
23 | 32 |
|
24 | 33 | public class JavaLogicalStructure { |
25 | 34 | private final String type; |
26 | | - private final String value; |
27 | | - private final String size; |
| 35 | + private final LogicalStructureExpression valueExpression; |
| 36 | + private final LogicalStructureExpression sizeExpression; |
28 | 37 | private final LogicalVariable[] variables; |
29 | 38 |
|
30 | 39 | /** |
31 | 40 | * Constructor. |
32 | 41 | */ |
33 | | - public JavaLogicalStructure(String type, String value, String size, LogicalVariable[] variables) { |
34 | | - this.value = value; |
| 42 | + public JavaLogicalStructure(String type, LogicalStructureExpression valueExpression, LogicalStructureExpression sizeExpression, |
| 43 | + LogicalVariable[] variables) { |
| 44 | + this.valueExpression = valueExpression; |
35 | 45 | this.type = type; |
36 | | - this.size = size; |
| 46 | + this.sizeExpression = sizeExpression; |
37 | 47 | this.variables = variables; |
38 | 48 | } |
39 | 49 |
|
40 | | - public String getValue() { |
41 | | - return value; |
42 | | - } |
43 | | - |
44 | 50 | public String getType() { |
45 | 51 | return type; |
46 | 52 | } |
47 | 53 |
|
48 | | - public String getSize() { |
49 | | - return size; |
| 54 | + public LogicalStructureExpression getValueExpression() { |
| 55 | + return valueExpression; |
| 56 | + } |
| 57 | + |
| 58 | + public LogicalStructureExpression getSizeExpression() { |
| 59 | + return sizeExpression; |
50 | 60 | } |
51 | 61 |
|
52 | 62 | public LogicalVariable[] getVariables() { |
@@ -81,25 +91,110 @@ public boolean providesLogicalStructure(ObjectReference obj) { |
81 | 91 | return false; |
82 | 92 | } |
83 | 93 |
|
84 | | - public boolean isIndexedVariable() { |
85 | | - return StringUtils.isNotBlank(size); |
| 94 | + /** |
| 95 | + * Return the logical size of the specified thisObject. |
| 96 | + */ |
| 97 | + public Value getSize(ObjectReference thisObject, ThreadReference thread, IEvaluationProvider evaluationEngine) |
| 98 | + throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, |
| 99 | + InterruptedException, ExecutionException, UnsupportedOperationException { |
| 100 | + if (sizeExpression == null) { |
| 101 | + throw new UnsupportedOperationException("The object hasn't defined the logical size operation."); |
| 102 | + } |
| 103 | + |
| 104 | + return getValue(thisObject, sizeExpression, thread, evaluationEngine); |
| 105 | + } |
| 106 | + |
| 107 | + /** |
| 108 | + * Return the logical value of the specified thisObject. |
| 109 | + */ |
| 110 | + public Value getValue(ObjectReference thisObject, ThreadReference thread, IEvaluationProvider evaluationEngine) |
| 111 | + throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, |
| 112 | + InterruptedException, ExecutionException { |
| 113 | + return getValue(thisObject, valueExpression, thread, evaluationEngine); |
| 114 | + } |
| 115 | + |
| 116 | + private static Value getValue(ObjectReference thisObject, LogicalStructureExpression expression, ThreadReference thread, |
| 117 | + IEvaluationProvider evaluationEngine) |
| 118 | + throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, |
| 119 | + InterruptedException, ExecutionException { |
| 120 | + if (expression.type == LogicalStructureExpressionType.METHOD) { |
| 121 | + return getValueByMethod(thisObject, expression.value, thread); |
| 122 | + } else if (expression.type == LogicalStructureExpressionType.FIELD) { |
| 123 | + return getValueByField(thisObject, expression.value, thread); |
| 124 | + } else { |
| 125 | + return evaluationEngine.evaluate(expression.value, thisObject, thread).get(); |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + private static Value getValueByMethod(ObjectReference thisObject, String methodName, ThreadReference thread) |
| 130 | + throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException { |
| 131 | + List<Method> methods = thisObject.referenceType().allMethods(); |
| 132 | + Method targetMethod = null; |
| 133 | + for (Method method : methods) { |
| 134 | + if (Objects.equals(method.name(), methodName) && method.argumentTypeNames().isEmpty()) { |
| 135 | + targetMethod = method; |
| 136 | + break; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + if (targetMethod == null) { |
| 141 | + return null; |
| 142 | + } |
| 143 | + |
| 144 | + return thisObject.invokeMethod(thread, targetMethod, Collections.EMPTY_LIST, ObjectReference.INVOKE_SINGLE_THREADED); |
| 145 | + } |
| 146 | + |
| 147 | + private static Value getValueByField(ObjectReference thisObject, String filedName, ThreadReference thread) { |
| 148 | + List<Field> fields = thisObject.referenceType().allFields(); |
| 149 | + Field targetField = null; |
| 150 | + for (Field field : fields) { |
| 151 | + if (Objects.equals(field.name(), filedName)) { |
| 152 | + targetField = field; |
| 153 | + break; |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + if (targetField == null) { |
| 158 | + return null; |
| 159 | + } |
| 160 | + |
| 161 | + return thisObject.getValue(targetField); |
86 | 162 | } |
87 | 163 |
|
88 | 164 | public static class LogicalVariable { |
89 | 165 | private final String name; |
90 | | - private final String value; |
| 166 | + private final LogicalStructureExpression valueExpression; |
91 | 167 |
|
92 | | - public LogicalVariable(String name, String value) { |
| 168 | + public LogicalVariable(String name, LogicalStructureExpression valueExpression) { |
93 | 169 | this.name = name; |
94 | | - this.value = value; |
| 170 | + this.valueExpression = valueExpression; |
95 | 171 | } |
96 | 172 |
|
97 | 173 | public String getName() { |
98 | 174 | return name; |
99 | 175 | } |
100 | 176 |
|
101 | | - public String getValue() { |
102 | | - return value; |
| 177 | + public Value getValue(ObjectReference thisObject, ThreadReference thread, IEvaluationProvider evaluationEngine) |
| 178 | + throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException, |
| 179 | + InterruptedException, ExecutionException { |
| 180 | + return JavaLogicalStructure.getValue(thisObject, valueExpression, thread, evaluationEngine); |
103 | 181 | } |
104 | 182 | } |
| 183 | + |
| 184 | + public static class LogicalStructureExpression { |
| 185 | + public LogicalStructureExpressionType type; |
| 186 | + public String value; |
| 187 | + |
| 188 | + /** |
| 189 | + * Constructor. |
| 190 | + */ |
| 191 | + public LogicalStructureExpression(LogicalStructureExpressionType type, String value) { |
| 192 | + this.type = type; |
| 193 | + this.value = value; |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | + public static enum LogicalStructureExpressionType { |
| 198 | + FIELD, METHOD, EVALUATION_SNIPPET |
| 199 | + } |
105 | 200 | } |
0 commit comments