|
1 | 1 | /******************************************************************************* |
2 | | -* Copyright (c) 2017 Microsoft Corporation and others. |
| 2 | +* Copyright (c) 2017-2019 Microsoft Corporation and others. |
3 | 3 | * All rights reserved. This program and the accompanying materials |
4 | 4 | * are made available under the terms of the Eclipse Public License v1.0 |
5 | 5 | * which accompanies this distribution, and is available at |
|
20 | 20 | import java.util.Map; |
21 | 21 | import java.util.Set; |
22 | 22 | import java.util.concurrent.CompletableFuture; |
| 23 | +import java.util.concurrent.ExecutionException; |
23 | 24 | import java.util.stream.Collectors; |
24 | 25 |
|
| 26 | +import org.apache.commons.lang3.StringUtils; |
| 27 | + |
25 | 28 | import com.microsoft.java.debug.core.DebugSettings; |
26 | 29 | import com.microsoft.java.debug.core.adapter.AdapterUtils; |
27 | 30 | import com.microsoft.java.debug.core.adapter.ErrorCode; |
28 | 31 | import com.microsoft.java.debug.core.adapter.IDebugAdapterContext; |
29 | 32 | import com.microsoft.java.debug.core.adapter.IDebugRequestHandler; |
| 33 | +import com.microsoft.java.debug.core.adapter.IEvaluationProvider; |
30 | 34 | import com.microsoft.java.debug.core.adapter.IStackFrameManager; |
31 | 35 | import com.microsoft.java.debug.core.adapter.variables.IVariableFormatter; |
| 36 | +import com.microsoft.java.debug.core.adapter.variables.JavaLogicalStructure; |
| 37 | +import com.microsoft.java.debug.core.adapter.variables.JavaLogicalStructure.LogicalVariable; |
| 38 | +import com.microsoft.java.debug.core.adapter.variables.JavaLogicalStructureManager; |
32 | 39 | import com.microsoft.java.debug.core.adapter.variables.StackFrameReference; |
33 | 40 | import com.microsoft.java.debug.core.adapter.variables.Variable; |
34 | 41 | import com.microsoft.java.debug.core.adapter.variables.VariableProxy; |
|
41 | 48 | import com.microsoft.java.debug.core.protocol.Types; |
42 | 49 | import com.sun.jdi.AbsentInformationException; |
43 | 50 | import com.sun.jdi.ArrayReference; |
| 51 | +import com.sun.jdi.IntegerValue; |
44 | 52 | import com.sun.jdi.InternalException; |
45 | 53 | import com.sun.jdi.InvalidStackFrameException; |
46 | 54 | import com.sun.jdi.ObjectReference; |
@@ -81,7 +89,7 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments, |
81 | 89 | } |
82 | 90 |
|
83 | 91 | VariableProxy containerNode = (VariableProxy) container; |
84 | | - List<Variable> childrenList; |
| 92 | + List<Variable> childrenList = new ArrayList<>(); |
85 | 93 | IStackFrameManager stackFrameManager = context.getStackFrameManager(); |
86 | 94 | if (containerNode.getProxiedVariable() instanceof StackFrameReference) { |
87 | 95 | StackFrameReference stackFrameReference = (StackFrameReference) containerNode.getProxiedVariable(); |
@@ -109,10 +117,41 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments, |
109 | 117 | } else { |
110 | 118 | try { |
111 | 119 | ObjectReference containerObj = (ObjectReference) containerNode.getProxiedVariable(); |
112 | | - if (varArgs.count > 0) { |
113 | | - childrenList = VariableUtils.listFieldVariables(containerObj, varArgs.start, varArgs.count); |
114 | | - } else { |
115 | | - childrenList = VariableUtils.listFieldVariables(containerObj, showStaticVariables); |
| 120 | + if (DebugSettings.getCurrent().showLogicalStructure) { |
| 121 | + JavaLogicalStructure logicalStructure = JavaLogicalStructureManager.getLogicalStructure(containerObj); |
| 122 | + IEvaluationProvider evaluationEngine = context.getProvider(IEvaluationProvider.class); |
| 123 | + if (logicalStructure != null && evaluationEngine != null) { |
| 124 | + String expression = logicalStructure.getValue(); |
| 125 | + LogicalVariable[] logicalVariables = logicalStructure.getVariables(); |
| 126 | + try { |
| 127 | + if (StringUtils.isNotEmpty(expression)) { |
| 128 | + Value value = evaluationEngine.evaluate(expression, containerObj, |
| 129 | + containerNode.getThread()).get(); |
| 130 | + if (value instanceof ObjectReference) { |
| 131 | + containerObj = (ObjectReference) value; |
| 132 | + } else { |
| 133 | + childrenList = Arrays.asList(new Variable("logical structure", value)); |
| 134 | + } |
| 135 | + } else if (logicalVariables != null && logicalVariables.length > 0) { |
| 136 | + for (LogicalVariable logicalVariable : logicalVariables) { |
| 137 | + String name = logicalVariable.getName(); |
| 138 | + Value value = evaluationEngine.evaluate(logicalVariable.getValue(), containerObj, |
| 139 | + containerNode.getThread()).get(); |
| 140 | + childrenList.add(new Variable(name, value)); |
| 141 | + } |
| 142 | + } |
| 143 | + } catch (InterruptedException | ExecutionException e) { |
| 144 | + // do nothing. |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + if (childrenList.isEmpty() && VariableUtils.hasChildren(containerObj, showStaticVariables)) { |
| 150 | + if (varArgs.count > 0) { |
| 151 | + childrenList = VariableUtils.listFieldVariables(containerObj, varArgs.start, varArgs.count); |
| 152 | + } else { |
| 153 | + childrenList = VariableUtils.listFieldVariables(containerObj, showStaticVariables); |
| 154 | + } |
116 | 155 | } |
117 | 156 | } catch (AbsentInformationException e) { |
118 | 157 | throw AdapterUtils.createCompletionException( |
@@ -162,17 +201,35 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments, |
162 | 201 | if (variableNameMap.containsKey(javaVariable)) { |
163 | 202 | name = variableNameMap.get(javaVariable); |
164 | 203 | } |
| 204 | + int indexedVariables = -1; |
| 205 | + if (value instanceof ArrayReference) { |
| 206 | + indexedVariables = ((ArrayReference) value).length(); |
| 207 | + } else if (DebugSettings.getCurrent().showLogicalStructure |
| 208 | + && value instanceof ObjectReference |
| 209 | + && JavaLogicalStructureManager.isIndexedVariable((ObjectReference) value)) { |
| 210 | + String logicalSizeExpression = JavaLogicalStructureManager.getLogicalSize((ObjectReference) value); |
| 211 | + IEvaluationProvider evaluationEngine = context.getProvider(IEvaluationProvider.class); |
| 212 | + if (StringUtils.isNotBlank(logicalSizeExpression) && evaluationEngine != null) { |
| 213 | + try { |
| 214 | + Value size = evaluationEngine.evaluate(logicalSizeExpression, (ObjectReference) value, |
| 215 | + containerNode.getThread()).get(); |
| 216 | + if (size instanceof IntegerValue) { |
| 217 | + indexedVariables = ((IntegerValue) size).value(); |
| 218 | + } |
| 219 | + } catch (InterruptedException | ExecutionException e) { |
| 220 | + // do nothing. |
| 221 | + } |
| 222 | + } |
| 223 | + } |
165 | 224 | int referenceId = 0; |
166 | | - if (value instanceof ObjectReference && VariableUtils.hasChildren(value, showStaticVariables)) { |
| 225 | + if (indexedVariables > 0 || (indexedVariables < 0 && VariableUtils.hasChildren(value, showStaticVariables))) { |
167 | 226 | VariableProxy varProxy = new VariableProxy(containerNode.getThread(), containerNode.getScope(), value); |
168 | 227 | referenceId = context.getRecyclableIdPool().addObject(containerNode.getThreadId(), varProxy); |
169 | 228 | } |
170 | 229 | Types.Variable typedVariables = new Types.Variable(name, variableFormatter.valueToString(value, options), |
171 | 230 | variableFormatter.typeToString(value == null ? null : value.type(), options), |
172 | 231 | referenceId, null); |
173 | | - if (javaVariable.value instanceof ArrayReference) { |
174 | | - typedVariables.indexedVariables = ((ArrayReference) javaVariable.value).length(); |
175 | | - } |
| 232 | + typedVariables.indexedVariables = Math.max(indexedVariables, 0); |
176 | 233 | list.add(typedVariables); |
177 | 234 | } |
178 | 235 | response.body = new Responses.VariablesResponseBody(list); |
|
0 commit comments