/******************************************************************************* * Copyright (c) 2004, 2015 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 implementation *******************************************************************************/ 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; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; /** * A variable value editor that prompts the user to set a primitive's value. */ public class JavaPrimitiveValueEditor implements IVariableValueEditor { /** * The signature of the edited variable. */ private String fSignature= null; /** * Creates a new editor for a variable with the given signature * @param signature the signature of the primitive to be edited */ public JavaPrimitiveValueEditor(String signature) { fSignature= signature; } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IVariableValueEditor#editVariable(org.eclipse.debug.core.model.IVariable, org.eclipse.swt.widgets.Shell) */ @Override public boolean editVariable(IVariable variable, Shell shell) { try { String name= variable.getName(); String title= ActionMessages.JavaPrimitiveValueEditor_0; String message= NLS.bind(ActionMessages.JavaPrimitiveValueEditor_1, new String[] {name}); String initialValue= variable.getValue().getValueString(); PrimitiveValidator validator= new PrimitiveValidator(); InputDialog dialog= new InputDialog(shell, title, message, initialValue, validator){ @Override protected Control createDialogArea(Composite parent) { IWorkbench workbench = PlatformUI.getWorkbench(); 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); if (i != Integer.MAX_VALUE) { stringValue= new String(new char[] { (char) i }); } } variable.setValue(stringValue); } } catch (DebugException e) { JDIDebugUIPlugin.errorDialog(shell, ActionMessages.JavaPrimitiveValueEditor_2, ActionMessages.JavaPrimitiveValueEditor_3, e); // } return true; } /* (non-Javadoc) * @see org.eclipse.debug.ui.actions.IVariableValueEditor#saveVariable(org.eclipse.debug.core.model.IVariable, java.lang.String, org.eclipse.swt.widgets.Shell) */ @Override 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 */ protected class PrimitiveValidator implements IInputValidator { /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String) */ @Override public String isValid(String newText) { String type= null; switch (fSignature.charAt(0)) { case 'B': try { Byte.parseByte(newText); } catch (NumberFormatException e) { type= "byte"; //$NON-NLS-1$ } break; case 'C': if (newText.length() > 1 && newText.charAt(0) == '\\') { // Possibly an escaped character if (isSpecialCharacter(newText) || isOctalEscape(newText) || isUnicode(newText)) { break; } } if (newText.length() != 1) { type="char"; //$NON-NLS-1$ } break; case 'D': try { Double.parseDouble(ASTInstructionCompiler.removePrefixZerosAndUnderscores(newText, false)); } catch (NumberFormatException e) { type="double"; //$NON-NLS-1$ } break; case 'F': try { Float.parseFloat(ASTInstructionCompiler.removePrefixZerosAndUnderscores(newText, false)); } catch (NumberFormatException e) { type="float"; //$NON-NLS-1$ } break; case 'I': try { ASTInstructionCompiler.parseIntValue(newText); } catch (NumberFormatException e) { type="int"; //$NON-NLS-1$ } break; case 'J': try { ASTInstructionCompiler.parseLongValue(newText); } catch (NumberFormatException e) { type="long"; //$NON-NLS-1$ } break; case 'S': try { ASTInstructionCompiler.parseShortValue(newText); } catch (NumberFormatException e) { type="short"; //$NON-NLS-1$ } break; case 'Z': if (!("true".equals(newText) || "false".equals(newText))) { //$NON-NLS-1$ //$NON-NLS-2$ type="boolean"; //$NON-NLS-1$ } break; } if (type != null) { return NLS.bind(ActionMessages.JavaPrimitiveValueEditor_4, new String[] { type }); } return null; } private boolean isUnicode(String newText) { if (newText.length() == 6) { if (newText.charAt(1) == 'u') { char[] chars = newText.toCharArray(); for (int i = 2; i < chars.length; i++) { if (!isHexDigit(chars[i])) { return false; } } return true; } } return false; } private boolean isOctalEscape(String newText) { char[] chars= newText.toCharArray(); if (chars.length < 4) { for (int i = 1; i < chars.length; i++) { if (!isOctalDigit(chars[i])) { return false; } } return true; } else if (chars.length == 4) { char ch= chars[1]; if (ch < '0' || ch > '3') { return false; } for (int i = 2; i < chars.length; i++) { if (!isOctalDigit(chars[i])) { return false; } } return true; } return false; } private boolean isSpecialCharacter(String newText) { char ch= newText.charAt(1); return newText.length() == 2 && (ch == 'b' || ch == 't' || ch == 'n' || ch == 'f' || ch == 'r' || ch == '"' || ch == '\'' || ch == '\\'); } private boolean isOctalDigit(char ch) { return Character.digit(ch, 8) != -1; } private boolean isHexDigit(char ch) { return Character.digit(ch, 16) != -1; } /** * Returns the integer value specified by the given string, which * 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) { return ASTInstructionCompiler.parseIntValue(string); } } }