Bug 277278 - Support autoboxing on change-value
During debugging, if the user provides a primitive value, but the variable type is a boxed type
convert the value automatically.
Change-Id: I618dfe3d0b320eed4de903e64cf51ce38d312efb
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.debug/+/187291
Tested-by: JDT Bot <jdt-bot@eclipse.org>
Tested-by: Sarika Sinha <sarika.sinha@in.ibm.com>
Reviewed-by: Sarika Sinha <sarika.sinha@in.ibm.com>
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaObjectValueEditor.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaObjectValueEditor.java
index 1a8646c..c7766a1 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaObjectValueEditor.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaObjectValueEditor.java
@@ -26,15 +26,19 @@
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.actions.IVariableValueEditor;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaClassType;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaPrimitiveValue;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
+import org.eclipse.jdt.internal.debug.eval.EvaluationResult;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
@@ -118,7 +122,7 @@
if (expression == null || expression.length() == 0) {
variable.setValue(expression);
} else {
- IValue newValue = evaluate(expression);
+ IValue newValue = evaluate(expression, variable);
if (newValue != null) {
variable.setValue(newValue);
} else {
@@ -153,7 +157,7 @@
* @param stringValue the snippet to evaluate
* @return the value that was computed or <code>null</code> if any errors occurred.
*/
- private IValue evaluate(String stringValue) throws DebugException {
+ private IValue evaluate(String stringValue, IVariable variable) throws DebugException {
IAdaptable adaptable = DebugUITools.getDebugContext();
IJavaStackFrame frame = adaptable.getAdapter(IJavaStackFrame.class);
if (frame != null) {
@@ -164,9 +168,11 @@
IAstEvaluationEngine engine = JDIDebugPlugin.getDefault().getEvaluationEngine(project, (IJavaDebugTarget) thread.getDebugTarget());
IEvaluationListener listener= new IEvaluationListener() {
@Override
- public void evaluationComplete(IEvaluationResult result) {
+ public void evaluationComplete(IEvaluationResult result) {
+ var convertedResult = convert((EvaluationResult) result, variable, thread);
+
synchronized (JavaObjectValueEditor.this) {
- results[0]= result;
+ results[0] = convertedResult;
JavaObjectValueEditor.this.notifyAll();
}
}
@@ -209,6 +215,73 @@
}
/**
+ * Convert the evaluationResult into an object, which can be stored into variable. Currently, it converts primitive types into the wrapper, boxed
+ * types.
+ */
+ private EvaluationResult convert(EvaluationResult evaluationResult, IVariable variable, IJavaThread thread) {
+ if (evaluationResult.hasErrors()) {
+ return evaluationResult;
+ }
+ var value = evaluationResult.getValue();
+ if (value instanceof IJavaPrimitiveValue) {
+ var primValue = (IJavaPrimitiveValue) value;
+ if (variable instanceof IJavaVariable) {
+ try {
+ var type = ((IJavaVariable) variable).getJavaType();
+ if (type instanceof IJavaClassType) {
+ var classType = (IJavaClassType) type;
+ var javaDebug = thread.getDebugTarget().getAdapter(IJavaDebugTarget.class);
+ switch (classType.getName()) {
+ case "java.lang.Long": //$NON-NLS-1$
+ case "java.math.BigInteger": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getLongValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Integer": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getIntValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Short": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getShortValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Byte": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getByteValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Double": //$NON-NLS-1$
+ case "java.math.BigDecimal": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getDoubleValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Float": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getFloatValue()), classType, thread);
+ break;
+ }
+ case "java.lang.Boolean": { //$NON-NLS-1$
+ updateEvaluation(evaluationResult, javaDebug.newValue(primValue.getBooleanValue()), classType, thread);
+ break;
+ }
+ }
+ }
+ } catch (DebugException e) {
+ evaluationResult.setException(e);
+ }
+ }
+ }
+ return evaluationResult;
+ }
+
+ private void updateEvaluation(EvaluationResult evaluationResult, IJavaValue newValue, IJavaClassType instanceType, IJavaThread thread) throws DebugException {
+ var signature = String.format("(%s)%s", newValue.getSignature(), instanceType.getSignature()); //$NON-NLS-1$
+ updateEvaluation(evaluationResult, newValue, instanceType, "valueOf", signature, thread); //$NON-NLS-1$
+ }
+
+ private void updateEvaluation(EvaluationResult evaluationResult, IJavaValue newValue, IJavaClassType instanceType, String methodName, String signature, IJavaThread thread) throws DebugException {
+ evaluationResult.setValue(instanceType.sendMessage(methodName, signature, new IJavaValue[] { newValue }, thread));
+ }
+
+ /**
* (copied from EvaluateAction)
*/
protected String getExceptionMessage(Throwable exception) {