diff options
author | Curtis Windatt | 2011-10-06 16:09:07 +0000 |
---|---|---|
committer | mrennie | 2011-10-06 16:09:07 +0000 |
commit | 8b6f1e922a8f4da928a077076d903b8f70739592 (patch) | |
tree | 26420c2df158fcafc996b3e4974e60bbf9c1b059 | |
parent | 30e67bdab40464609fc0eb16878b2f8a532a75a4 (diff) | |
download | eclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.tar.gz eclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.tar.xz eclipse.jdt.debug-8b6f1e922a8f4da928a077076d903b8f70739592.zip |
Bug 352413 - [1.7] Debugger should support binary literals and
underscores while setting literals
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 5da957590..f12b3ec63 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 4f73f412e..21bedaf3f 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 40d4e1773..b4b246d98 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 000000000..0f9876e79 --- /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 dbd10fa21..7387a4c1b 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 9bfb89dd4..92f63b3c3 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 |