Bug 352413 - [1.7] Debugger should support binary literals and underscores while setting literals
diff --git a/org.eclipse.jdt.debug.tests/testprograms/java7/Literals17.java b/org.eclipse.jdt.debug.tests/testprograms/java7/Literals17.java
new file mode 100644
index 0000000..2b3a7c8
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/java7/Literals17.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+public class Literals17 {
+	int x1 = 1_0;              	// OK (decimal literal)
+	int x2 = 0x1_0;            	// OK (hexadecimal literal)
+	int x3 = 0_10;             	// OK (octal literal)
+	int x4 = 0b10_00;			// OK (binary literal)
+	double x5 = 10.5_56D;		// OK (double literal)
+	float x6 = 	3.14_15F;		// OK (float literal)
+	char x7 = 1_2_3;			// OK (char literal)
+	long x8 = 1_0L;				// OK (long literal)
+	short x9 = 1_0;				// OK (short literal)
+	byte x10 = 0b1_0_0_0;		// OK (byte literal)
+	
+	public static void main(String[] args) {
+		Literals17 literals = new Literals17();
+		System.out.println(literals.x1);
+	}
+}
\ No newline at end of file
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.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.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 @@
 	}
 	
 	/**
+	 * 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 @@
 	}		
 	
 	/**
+	 * 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 fb5dc0e..1c193f7 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
@@ -58,6 +58,7 @@
 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;
@@ -195,6 +196,9 @@
 		addTest(new TestSuite(TestLogicalStructures.class));
 		addTest(new TestSuite(TestInstanceRetrieval.class));
 		addTest(new TestSuite(TestAnonymousInspect.class));
+		if(isJ2SE17Compatible()) {
+			addTest(new TestSuite(LiteralTests17.class));
+		}
 		
 	//Stepping tests
 		addTest(new TestSuite(StepFilterTests.class));
@@ -295,5 +299,8 @@
 		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 c0ba793..93720bc 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
@@ -61,6 +61,7 @@
 	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");
@@ -77,6 +78,9 @@
 						if (minor >= 6) {
 							fgIsJ2SE16Compatible = true;
 						}
+						if(minor >= 7) {
+							fgIsJ2SE17Compatible = true;
+						}
 					}
 				} catch (NumberFormatException e) {
 				}
@@ -417,9 +421,9 @@
             if (severity != null && severity.intValue() >= IMarker.SEVERITY_ERROR) {
                 errors++;
             }
-        }
+    	}
         assertTrue("Unexpected compile errors in project. Expected 1, found " + markers.length, errors == 1);
-    }
+        }
 
     /**
      * @throws Exception
@@ -452,4 +456,8 @@
 	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 @@
 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 @@
             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 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 @@
 	                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 @@
 				ch == '\\');
 		}
 		
+		
 		private boolean isOctalDigit(char ch) {
             return Character.digit(ch, 8) != -1;
 		}
@@ -229,15 +250,12 @@
 		 * 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 @@
 
 
 		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 @@
 				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 @@
 	}
 
 	/**
-	 * 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();
 		}
 	}
 
-
 	/**
-	 * Method parseLongValue.
-	 * @param token
+	 * 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
 	 */
-	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 short parseShortValue(String token) {
+		token = removePrefixZerosAndUnderscores(token, false);
 		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 Short.valueOf(token.substring(1), 8).shortValue();
 			case 16:
-				return (Long.decode(token.substring(0, tokenLength - 1)).longValue() << 4) | Long.decode("0x" + token.charAt(tokenLength - 1)).longValue(); //$NON-NLS-1$
+				return Short.valueOf(token.substring(2), 16).shortValue();
+			case 2:
+				return Short.valueOf(token.substring(2), 2).shortValue();
 			default:
-				// getBase(String) only returns 8, 10, or 16. This code is unreachable
-				return 0;
+				return Short.valueOf(token, 10).shortValue();
+		}
+	}
+
+	/**
+	 * 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
+	 */
+	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.valueOf(token.substring(1), 8).longValue();
+			case 16:
+				return Long.valueOf(token.substring(2), 16).longValue();
+			case 2:
+				return Long.valueOf(token.substring(2), 2).longValue();
+			default:
+				return Long.valueOf(token, 10).longValue();
 		}
 	}
 
@@ -2955,13 +2993,24 @@
 	 * Returns the numeric base for the given token
 	 * according to the Java specification. Returns
 	 * 8, 10, or 16.
+	 * @param token the token to get the base from
+	 * @return the numeric base for the given token
 	 */
-	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
+	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 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