aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCurtis Windatt2011-10-06 12:09:07 (EDT)
committermrennie2011-10-06 12:09:07 (EDT)
commit8b6f1e922a8f4da928a077076d903b8f70739592 (patch)
tree26420c2df158fcafc996b3e4974e60bbf9c1b059
parent30e67bdab40464609fc0eb16878b2f8a532a75a4 (diff)
downloadeclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.zip
eclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.tar.gz
eclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.tar.bz2
Bug 352413 - [1.7] Debugger should support binary literals and
underscores while setting literals
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java87
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java9
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java12
-rw-r--r--org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LiteralTests17.java339
-rw-r--r--org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaPrimitiveValueEditor.java48
-rw-r--r--org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java185
6 files changed, 623 insertions, 57 deletions
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
index 5da9575..f12b3ec 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,12 +21,14 @@ import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
@@ -96,11 +98,17 @@ import org.eclipse.jdt.debug.testplugin.DebugElementEventWaiter;
import org.eclipse.jdt.debug.testplugin.DebugElementKindEventDetailWaiter;
import org.eclipse.jdt.debug.testplugin.DebugElementKindEventWaiter;
import org.eclipse.jdt.debug.testplugin.DebugEventWaiter;
+import org.eclipse.jdt.debug.testplugin.JavaProjectHelper;
+import org.eclipse.jdt.debug.testplugin.JavaTestPlugin;
import org.eclipse.jdt.debug.tests.refactoring.MemberParser;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine;
import org.eclipse.jdt.internal.debug.ui.BreakpointUtils;
import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadPositionCategoryException;
@@ -250,6 +258,51 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation
}
/**
+ * Creates a new {@link IJavaProject} with the given name and optionally initializing it from the given
+ * resource path from the testing bundle.
+ * <br><br>
+ * The project has the default <code>src</code> and <code>bin</code> folders. It is also created with a default
+ * <code>launchConfigurations</code> folder.
+ *
+ * @param name the name for the project
+ * @param contentpath the path within the jdt.debug test bundle to initialize the source from
+ * @param ee the level of execution environment to use
+ * @param if an existing project should be deleted
+ * @return the new Java project
+ * @throws Exception
+ */
+ protected IJavaProject createProject(String name, String contentpath, String ee, boolean delete) throws Exception {
+ IProject pro = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
+ if (pro.exists() && delete) {
+ try {
+ pro.delete(true, true, null);
+ }
+ catch(Exception e) {}
+ }
+ // create project and import source
+ IJavaProject jp = JavaProjectHelper.createJavaProject(name, "bin");
+ IPackageFragmentRoot src = JavaProjectHelper.addSourceContainer(jp, "src");
+ File root = JavaTestPlugin.getDefault().getFileInPlugin(new Path(contentpath));
+ JavaProjectHelper.importFilesFromDirectory(root, src.getPath(), null);
+
+ // add the EE library
+ IVMInstall vm = JavaRuntime.getDefaultVMInstall();
+ assertNotNull("No default JRE", vm);
+ IExecutionEnvironment environment = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(ee);
+ assertNotNull("The EE ["+ee+"] does not exist", environment);
+ IPath containerPath = JavaRuntime.newJREContainerPath(environment);
+ JavaProjectHelper.addContainerEntry(jp, containerPath);
+ pro = jp.getProject();
+
+ // create launch configuration folder
+ IFolder folder = pro.getFolder("launchConfigurations");
+ if (!folder.exists()) {
+ folder.create(true, true, null);
+ }
+ return jp;
+ }
+
+ /**
* Returns the launch shortcut with the given id
* @param id
* @return the <code>LaunchShortcutExtension</code> with the given id,
@@ -1464,6 +1517,38 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation
}
/**
+ * Runs an evaluation using an embedded listener and the {@link #DEFAULT_TIMEOUT} for the operation
+ * @param snippet the snippet to evaluate
+ * @param thread the suspended thread to run the evaluation on
+ * @return the {@link IEvaluationResult}
+ * @throws Exception
+ * @since 3.1.200
+ */
+ protected IEvaluationResult evaluate(String snippet, IJavaThread thread) throws Exception {
+ class Listener implements IEvaluationListener {
+ IEvaluationResult fResult;
+ public void evaluationComplete(IEvaluationResult result) {
+ fResult= result;
+ }
+ }
+ Listener listener= new Listener();
+ IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame();
+ assertNotNull("There should be a stackframe", frame);
+ ASTEvaluationEngine engine = new ASTEvaluationEngine(getJavaProject(), (IJavaDebugTarget) thread.getDebugTarget());
+ try {
+ engine.evaluate(snippet, frame, listener, DebugEvent.EVALUATION_IMPLICIT, false);
+ long timeout = System.currentTimeMillis()+DEFAULT_TIMEOUT;
+ while(listener.fResult == null && System.currentTimeMillis() < timeout) {
+ Thread.sleep(100);
+ }
+ return listener.fResult;
+ }
+ finally {
+ engine.dispose();
+ }
+ }
+
+ /**
* @see IEvaluationListener#evaluationComplete(IEvaluationResult)
*/
public void evaluationComplete(IEvaluationResult result) {
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 4f73f41..21bedaf 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -58,6 +58,7 @@ import org.eclipse.jdt.debug.tests.core.JDWPTests;
import org.eclipse.jdt.debug.tests.core.JavaDebugTargetTests;
import org.eclipse.jdt.debug.tests.core.JavaLibraryPathTests;
import org.eclipse.jdt.debug.tests.core.LineTrackerTests;
+import org.eclipse.jdt.debug.tests.core.LiteralTests17;
import org.eclipse.jdt.debug.tests.core.LocalVariableTests;
import org.eclipse.jdt.debug.tests.core.ProcessTests;
import org.eclipse.jdt.debug.tests.core.RuntimeClasspathEntryTests;
@@ -186,6 +187,9 @@ public class AutomatedSuite extends DebugSuite {
addTest(new TestSuite(ArrayTests.class));
addTest(new TestSuite(TestLogicalStructures.class));
addTest(new TestSuite(TestInstanceRetrieval.class));
+ if(isJ2SE17Compatible()) {
+ addTest(new TestSuite(LiteralTests17.class));
+ }
//Stepping tests
addTest(new TestSuite(StepFilterTests.class));
@@ -281,5 +285,8 @@ public class AutomatedSuite extends DebugSuite {
return ProjectCreationDecorator.isJ2SE16Compatible();
}
+ protected static boolean isJ2SE17Compatible() {
+ return ProjectCreationDecorator.isJ2SE17Compatible();
+ }
}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
index 40d4e17..b4b246d 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
@@ -60,6 +60,7 @@ public class ProjectCreationDecorator extends AbstractDebugTest {
public static boolean fgReady = false;
private static boolean fgIsJ2SE15Compatible = false;
private static boolean fgIsJ2SE16Compatible = false;
+ private static boolean fgIsJ2SE17Compatible = false;
{
String version = System.getProperty("java.specification.version");
@@ -76,6 +77,9 @@ public class ProjectCreationDecorator extends AbstractDebugTest {
if (minor >= 6) {
fgIsJ2SE16Compatible = true;
}
+ if(minor >= 7) {
+ fgIsJ2SE17Compatible = true;
+ }
}
} catch (NumberFormatException e) {
}
@@ -409,9 +413,9 @@ public class ProjectCreationDecorator extends AbstractDebugTest {
if (severity != null && severity.intValue() >= IMarker.SEVERITY_ERROR) {
errors++;
}
- }
+ }
assertTrue("Unexpected compile errors in project. Expected 1, found " + markers.length, errors == 1);
- }
+ }
/**
* @throws Exception
@@ -444,4 +448,8 @@ public class ProjectCreationDecorator extends AbstractDebugTest {
protected static boolean isJ2SE16Compatible() {
return fgIsJ2SE16Compatible;
}
+
+ protected static boolean isJ2SE17Compatible() {
+ return fgIsJ2SE17Compatible;
+ }
}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LiteralTests17.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LiteralTests17.java
new file mode 100644
index 0000000..0f9876e
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/core/LiteralTests17.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.core;
+
+import java.io.File;
+
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.eval.IEvaluationResult;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+import org.eclipse.jdt.internal.debug.core.model.JDIPrimitiveValue;
+
+/**
+ * Tests that the new forms allowed in literals in Java 7 work as expected
+ *
+ * @since 3.1.200
+ */
+public class LiteralTests17 extends AbstractDebugTest {
+
+ private String typename = "Literals17";
+ private IJavaProject project = null;
+
+ /**
+ * Constructor
+ */
+ public LiteralTests17() {
+ super("Tests for Java 1.7 literal support in evaluations");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.tests.AbstractDebugTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ project = createProject("OneSeven", "testprograms"+File.separator+"java7", "JavaSE-1.7", false);
+ createLaunchConfiguration(project, typename);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.debug.tests.AbstractDebugTest#getJavaProject()
+ */
+ protected IJavaProject getJavaProject() {
+ return project;
+ }
+
+ /**
+ * Perform the evaluation on the given snippet and return the value
+ * @param snippet
+ * @return returns the evaluation value or <code>null</code>
+ * @throws Exception
+ */
+ IValue doEval(String snippet) throws Exception {
+ ILineBreakpoint bp = createLineBreakpoint(25, typename);
+ IJavaThread thread = null;
+ try {
+ thread = launchToLineBreakpoint(typename, bp);
+ IEvaluationResult result = evaluate(snippet, thread);
+ assertNotNull("There must be an evaluation result", result);
+ assertTrue("There must be no errors in the result", !result.hasErrors());
+ return result.getValue();
+ }
+ finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ /**
+ * Runs evaluations on the two given snippets returning the value from the second snippet. This method allows us to
+ * run two snippets on the same thread where the second snippet may or may not depend on the state change from the
+ * first snippet
+ *
+ * @param snippet
+ * @param snippet2
+ * @return the {@link IEvaluationResult}
+ * @throws Exception
+ */
+ IValue doEval(String snippet, String snippet2) throws Exception {
+ ILineBreakpoint bp = createLineBreakpoint(25, typename);
+ IJavaThread thread = null;
+ try {
+ thread = launchToLineBreakpoint(typename, bp);
+ IEvaluationResult result = evaluate(snippet, thread);
+ assertNotNull("There must be an evaluation result", result);
+ assertTrue("There must be no errors in the result", !result.hasErrors());
+ result = evaluate(snippet2, thread);
+ assertNotNull("There must be an evaluation result", result);
+ assertTrue("There must be no errors in the result", !result.hasErrors());
+ return result.getValue();
+ }
+ finally {
+ terminateAndRemove(thread);
+ removeAllBreakpoints();
+ }
+ }
+
+ /**
+ * Tests that an addition evaluation with an int with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreIntEval() throws Exception {
+ IValue value = doEval("literals.x1 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 11", val.getIntValue() == 11);
+ }
+
+ /**
+ * Tests that we can assign a variable value to an int with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreIntVarAssignment() throws Exception {
+ IValue value = doEval("literals.x1 = 1_______1;", "literals.x1 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 12", val.getIntValue() == 12);
+ }
+
+ /**
+ * Tests that an addition evaluation with a short with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreShortEval() throws Exception {
+ IValue value = doEval("literals.x9 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new short value should be 11", val.getShortValue() == 11);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a short with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreShortVarAssignment() throws Exception {
+ IValue value = doEval("literals.x9 = 1_______1;", "literals.x9 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new short value should be 12", val.getShortValue() == 12);
+ }
+
+ /**
+ * Tests that an addition evaluation with a byte with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreByteEval() throws Exception {
+ IValue value = doEval("literals.x10 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new byte value should be 9", val.getByteValue() == 9);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a short with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreByteVarAssignment() throws Exception {
+ IValue value = doEval("literals.x10 = 1_______1;", "literals.x10 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new byte value should be 12", val.getByteValue() == 12);
+ }
+
+ /**
+ * Tests that an addition evaluation with a long with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreLongEval() throws Exception {
+ IValue value = doEval("literals.x8 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new long value should be 11", val.getLongValue() == 11);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a long with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreLongVarAssignment() throws Exception {
+ IValue value = doEval("literals.x8 = 1_______1L;", "literals.x8 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new long value should be 12", val.getLongValue() == 12);
+ }
+
+ /**
+ * Tests that an addition evaluation with a float with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreFloatEval() throws Exception {
+ IValue value = doEval("literals.x6 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new float value should be 4.1415", val.getFloatValue() == 4.1415F);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a float with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreFloatVarAssignment() throws Exception {
+ IValue value = doEval("literals.x6 = 6.1_4_1_5F;", "literals.x6 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new float value should be 7.1415", val.getFloatValue() == 7.1415F);
+ }
+
+ /**
+ * Tests that an addition evaluation with a double with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreDoubleEval() throws Exception {
+ IValue value = doEval("literals.x5 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new double value should be 11.556", val.getDoubleValue() == 11.556D);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a double with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreDoubleVarAssignment() throws Exception {
+ IValue value = doEval("literals.x5 = 1_5.5_5_6D;", "literals.x5 + 1.000D");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new double value should be 16.556", val.getDoubleValue() == 16.555999999999997D);
+ }
+
+ /**
+ * Tests that an addition evaluation with a binary literal with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreBinaryEval() throws Exception {
+ IValue value = doEval("literals.x4 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 9", val.getIntValue() == 9);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a binary literal with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreBinaryVarAssignment() throws Exception {
+ IValue value = doEval("literals.x4 = 0b1_0_0_0_0;", "literals.x4 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 17", val.getIntValue() == 17);
+ }
+
+ /**
+ * Tests that an addition evaluation with a hex with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreHexEval() throws Exception {
+ IValue value = doEval("literals.x2 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 17", val.getIntValue() == 17);
+ }
+
+ /**
+ * Tests that we can assign a variable value to a hex with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreHexVarAssignment() throws Exception {
+ IValue value = doEval("literals.x2 = 0x1_0_0;", "literals.x2 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 257", val.getIntValue() == 257);
+ }
+
+ /**
+ * Tests that an addition evaluation with an octal with underscores in it works
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreOctEval() throws Exception {
+ IValue value = doEval("literals.x3 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 9", val.getIntValue() == 9);
+ }
+
+ /**
+ * Tests that we can assign a variable value to an octal with underscores
+ *
+ * @throws Exception
+ */
+ public void testUnderscoreOctVarAssignment() throws Exception {
+ IValue value = doEval("literals.x3 = 0_100;", "literals.x3 + 1");
+ assertNotNull("The value should not be null", value);
+ assertTrue("The underlying value must be a primitive value", value instanceof JDIPrimitiveValue);
+ JDIPrimitiveValue val = (JDIPrimitiveValue) value;
+ assertTrue("The new integer value should be 65", val.getIntValue() == 65);
+ }
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaPrimitiveValueEditor.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaPrimitiveValueEditor.java
index dbd10fa..7387a4c 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaPrimitiveValueEditor.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/JavaPrimitiveValueEditor.java
@@ -13,6 +13,7 @@ package org.eclipse.jdt.internal.debug.ui.actions;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.actions.IVariableValueEditor;
+import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTInstructionCompiler;
import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jface.dialogs.IInputValidator;
@@ -57,14 +58,13 @@ public class JavaPrimitiveValueEditor implements IVariableValueEditor {
InputDialog dialog= new InputDialog(shell, title, message, initialValue, validator){
protected Control createDialogArea(Composite parent) {
IWorkbench workbench = PlatformUI.getWorkbench();
- workbench.getHelpSystem().setHelp(
- parent,
- IJavaDebugHelpContextIds.DEFAULT_INPUT_DIALOG);
+ workbench.getHelpSystem().setHelp(parent, IJavaDebugHelpContextIds.DEFAULT_INPUT_DIALOG);
return super.createDialogArea(parent);
}
};
if (dialog.open() == Window.OK) {
String stringValue = dialog.getValue();
+ stringValue = formatValue(stringValue);
if (stringValue.length() > 1 && stringValue.charAt(0) == '\\') {
// Compute value of octal of hexadecimal escape sequence
int i= validator.getEscapeValue(stringValue);
@@ -86,6 +86,26 @@ public class JavaPrimitiveValueEditor implements IVariableValueEditor {
public boolean saveVariable(IVariable variable, String expression, Shell shell) {
return false;
}
+
+ String formatValue(String value) {
+ try {
+ switch (fSignature.charAt(0)) {
+ case 'I':
+ return Integer.toString(ASTInstructionCompiler.parseIntValue(value));
+ case 'J':
+ return Long.toString(ASTInstructionCompiler.parseLongValue(value));
+ case 'S':
+ return Short.toString(ASTInstructionCompiler.parseShortValue(value));
+ case 'F':
+ case 'D':
+ return ASTInstructionCompiler.removePrefixZerosAndUnderscores(value, false);
+ case 'B':
+ return Byte.toString(ASTInstructionCompiler.parseByteValue(value));
+ }
+ }
+ catch(NumberFormatException nfe) {}
+ return value;
+ }
/**
* Input validator for primitive types
@@ -119,35 +139,35 @@ public class JavaPrimitiveValueEditor implements IVariableValueEditor {
break;
case 'D':
try {
- Double.parseDouble(newText);
+ Double.parseDouble(ASTInstructionCompiler.removePrefixZerosAndUnderscores(newText, false));
} catch (NumberFormatException e) {
type="double"; //$NON-NLS-1$
}
break;
case 'F':
try {
- Float.parseFloat(newText);
+ Float.parseFloat(ASTInstructionCompiler.removePrefixZerosAndUnderscores(newText, false));
} catch (NumberFormatException e) {
type="float"; //$NON-NLS-1$
}
break;
case 'I':
try {
- Integer.parseInt(newText);
+ ASTInstructionCompiler.parseIntValue(newText);
} catch (NumberFormatException e) {
type="int"; //$NON-NLS-1$
}
break;
case 'J':
try {
- Long.parseLong(newText);
+ ASTInstructionCompiler.parseLongValue(newText);
} catch (NumberFormatException e) {
type="long"; //$NON-NLS-1$
}
break;
case 'S':
try {
- Short.parseShort(newText);
+ ASTInstructionCompiler.parseShortValue(newText);
} catch (NumberFormatException e) {
type="short"; //$NON-NLS-1$
}
@@ -216,6 +236,7 @@ public class JavaPrimitiveValueEditor implements IVariableValueEditor {
ch == '\\');
}
+
private boolean isOctalDigit(char ch) {
return Character.digit(ch, 8) != -1;
}
@@ -229,15 +250,12 @@ public class JavaPrimitiveValueEditor implements IVariableValueEditor {
* represents an octal or hexadecimal escape sequence. Returns
* Integer.MAX_VALUE if the given string is not a valid octal or
* hexadecimal escape sequence.
+ *
+ * @param string
+ * @return
*/
protected int getEscapeValue(String string) {
- int i= Integer.MAX_VALUE;
- if (isOctalEscape(string)) {
- i= Integer.parseInt(string.substring(1), 8);
- } else if (isUnicode(string)) {
- i= Integer.parseInt(string.substring(2), 16);
- }
- return i;
+ return ASTInstructionCompiler.parseIntValue(string);
}
}
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
index 9bfb89d..92f63b3 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/ASTInstructionCompiler.java
@@ -2883,6 +2883,12 @@ public class ASTInstructionCompiler extends ASTVisitor {
switch (literalType) {
+ case Instruction.T_byte:
+ push(new PushInt(parseByteValue(token)));
+ break;
+ case Instruction.T_short:
+ push(new PushInt(parseShortValue(token)));
+ break;
case Instruction.T_int:
push(new PushInt(parseIntValue(token)));
break;
@@ -2890,13 +2896,13 @@ public class ASTInstructionCompiler extends ASTVisitor {
push(new PushLong(parseLongValue(subToken)));
break;
case Instruction.T_float:
- push(new PushFloat(Float.parseFloat(subToken)));
+ push(new PushFloat(Float.parseFloat(removePrefixZerosAndUnderscores(subToken, false))));
break;
case Instruction.T_double:
if (lastChar == 'D' || lastChar == 'd') {
- push(new PushDouble(Double.parseDouble(subToken)));
+ push(new PushDouble(Double.parseDouble(removePrefixZerosAndUnderscores(subToken, false))));
} else {
- push(new PushDouble(Double.parseDouble(token)));
+ push(new PushDouble(Double.parseDouble(removePrefixZerosAndUnderscores(token, false))));
}
break;
}
@@ -2905,49 +2911,81 @@ public class ASTInstructionCompiler extends ASTVisitor {
}
/**
- * Method parseIntValue.
- * @param token
+ * Removes all preamble typing and underscores and returns the base integer value
+ *
+ * @param token the token to parse
+ * @return the int value of the token
*/
- private int parseIntValue(String token) {
- int tokenLength= token.length();
- if (tokenLength < 10) {
- // Integer.decode can handle tokens with less than 10 digits
- return Integer.decode(token).intValue();
- }
+ public static int parseIntValue(String token) {
+ token = removePrefixZerosAndUnderscores(token, false);
switch (getBase(token)) {
case 8:
- return (Integer.decode(token.substring(0, tokenLength - 1)).intValue() << 3) | Integer.decode("0" + token.charAt(tokenLength - 1)).intValue(); //$NON-NLS-1$
- case 10:
- return Integer.decode(token).intValue();
+ return Integer.valueOf(token.substring(1), 8).intValue();
case 16:
- return (Integer.decode(token.substring(0, tokenLength - 1)).intValue() << 4) | Integer.decode("0x" + token.charAt(tokenLength - 1)).intValue(); //$NON-NLS-1$
+ return Integer.valueOf(token.substring(2), 16).intValue();
+ case 2:
+ return Integer.valueOf(token.substring(2), 2).intValue();
default:
- // getBase(String) only returns 8, 10, or 16. This code is unreachable
- return 0;
+ return Integer.valueOf(token, 10).intValue();
}
}
+ /**
+ * Removes all preamble typing and underscores and returns the base short value
+ *
+ * @param token the token to parse
+ * @return the short value of the token
+ */
+ public static short parseShortValue(String token) {
+ token = removePrefixZerosAndUnderscores(token, false);
+ switch (getBase(token)) {
+ case 8:
+ return Short.valueOf(token.substring(1), 8).shortValue();
+ case 16:
+ return Short.valueOf(token.substring(2), 16).shortValue();
+ case 2:
+ return Short.valueOf(token.substring(2), 2).shortValue();
+ default:
+ return Short.valueOf(token, 10).shortValue();
+ }
+ }
/**
- * Method parseLongValue.
- * @param token
+ * Removes all preamble typing and underscores and returns the base byte value
+ *
+ * @param token the token to parse
+ * @return the byte value of the token
*/
- private long parseLongValue(String token) {
- int tokenLength= token.length();
- if (tokenLength < 18) {
- // Long.decode can handle tokens with less than 18 digits
- return Long.decode(token).longValue();
- }
+ public static byte parseByteValue(String token) {
+ token = removePrefixZerosAndUnderscores(token, false);
+ switch (getBase(token)) {
+ case 8:
+ return Byte.valueOf(token.substring(1), 8).byteValue();
+ case 16:
+ return Byte.valueOf(token.substring(2), 16).byteValue();
+ case 2:
+ return Byte.valueOf(token.substring(2), 2).byteValue();
+ default:
+ return Byte.valueOf(token, 10).byteValue();
+ }
+ }
+
+ /**
+ * Removes all preamble typing and underscores and returns the base long value
+ * @param token the token to parse
+ * @return the long value of the token
+ */
+ public static long parseLongValue(String token) {
+ token = removePrefixZerosAndUnderscores(token, true);
switch (getBase(token)) {
case 8:
- return (Long.decode(token.substring(0, tokenLength - 1)).longValue() << 3) | Long.decode("0" + token.charAt(tokenLength - 1)).longValue(); //$NON-NLS-1$
- case 10:
- return Long.decode(token).longValue();
+ return Long.valueOf(token.substring(1), 8).longValue();
case 16:
- return (Long.decode(token.substring(0, tokenLength - 1)).longValue() << 4) | Long.decode("0x" + token.charAt(tokenLength - 1)).longValue(); //$NON-NLS-1$
+ return Long.valueOf(token.substring(2), 16).longValue();
+ case 2:
+ return Long.valueOf(token.substring(2), 2).longValue();
default:
- // getBase(String) only returns 8, 10, or 16. This code is unreachable
- return 0;
+ return Long.valueOf(token, 10).longValue();
}
}
@@ -2955,13 +2993,24 @@ public class ASTInstructionCompiler extends ASTVisitor {
* Returns the numeric base for the given token
* according to the Java specification. Returns
* 8, 10, or 16.
- */
- private int getBase(String token) {
- if (token.charAt(0) == '0') {
- if (token.charAt(1) == 'x') {
- return 16; // "0x" prefix: Hexadecimal
- }
- return 8; // "0" prefix: Octal
+ * @param token the token to get the base from
+ * @return the numeric base for the given token
+ */
+ public static int getBase(String token) {
+ if (token.charAt(0) == '0' && (token.length() > 1)) {
+ switch(token.charAt(1)) {
+ case 'x' :
+ case 'X' :
+ // "0x" prefix: Hexadecimal
+ return 16;
+ case 'b' :
+ case 'B' :
+ // "0b" prefix: binary
+ return 2;
+ default :
+ // "0" prefix: Octal
+ return 8;
+ }
}
return 10; // No prefix: Decimal
}
@@ -3955,6 +4004,66 @@ public class ASTInstructionCompiler extends ASTVisitor {
}
+ public static String removePrefixZerosAndUnderscores(String tokenString, boolean isLong) {
+ char[] token = tokenString.toCharArray();
+ int max = token.length;
+ int start = 0;
+ int end = max - 1;
+ if (isLong) {
+ end--; // remove the 'L' or 'l'
+ }
+ if (max > 1 && token[0] == '0') {
+ if (max > 2 && (token[1] == 'x' || token[1] == 'X')) {
+ start = 2;
+ } else if (max > 2 && (token[1] == 'b' || token[1] == 'B')) {
+ start = 2;
+ } else {
+ start = 1;
+ }
+ }
+ boolean modified = false;
+ boolean ignore = true;
+ loop: for (int i = start; i < max; i++) {
+ char currentChar = token[i];
+ switch(currentChar) {
+ case '0' :
+ // this is a prefix '0'
+ if (ignore && !modified && (i < end)) {
+ modified = true;
+ }
+ break;
+ case '_' :
+ modified = true;
+ break loop;
+ default :
+ ignore = false;
+ }
+ }
+ if (!modified) {
+ return tokenString;
+ }
+ ignore = true;
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(token, 0, start);
+ loop: for (int i = start; i < max; i++) {
+ char currentChar = token[i];
+ switch(currentChar) {
+ case '0' :
+ if (ignore && (i < end)) {
+ // this is a prefix '0'
+ continue loop;
+ }
+ break;
+ case '_' :
+ continue loop;
+ default:
+ ignore = false;
+ }
+ buffer.append(currentChar);
+ }
+ return buffer.toString();
+ }
+
/**
* Returns the method signature given the binding and the enclosing type signature (if there is one)
* @param methodBinding the binding to get the signature for