From f59534687ca88979e847ddbc9b537e953f7667d3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 28 Jan 2015 15:52:13 +0300 Subject: [PATCH] IDEA-79114 Display all numbers in hex --- .../debugger/engine/JavaValueModifier.java | 9 +- .../DebuggerDataViewsConfigurable.java | 19 ++++- .../settings/NodeRendererSettings.java | 6 +- .../debugger/ui/tree/render/HexRenderer.java | 40 +++++---- .../ui/tree/render/PrimitiveRenderer.java | 85 ++++++++++++++----- .../src/messages/DebuggerBundle.properties | 1 + 6 files changed, 113 insertions(+), 47 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java index 0b482acd4ea9..ed7bf5fad982 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,7 +62,12 @@ public class JavaValueModifier extends XValueModifier { public void calculateInitialValueEditorText(final XInitialValueCallback callback) { final Value value = myJavaValue.getDescriptor().getValue(); if (value instanceof PrimitiveValue) { - callback.setValue(myJavaValue.getValueString()); + String valueString = myJavaValue.getValueString(); + int pos = valueString.lastIndexOf('('); //skip hex presentation if any + if (pos > 1) { + valueString = valueString.substring(0, pos).trim(); + } + callback.setValue(valueString); } else if (value instanceof StringReference) { final EvaluationContextImpl evaluationContext = myJavaValue.getEvaluationContext(); diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java index 23b9fbd29046..7597fb5a68f6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java @@ -19,6 +19,7 @@ import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.ui.JavaDebuggerSupport; import com.intellij.debugger.ui.tree.render.ClassRenderer; +import com.intellij.debugger.ui.tree.render.PrimitiveRenderer; import com.intellij.debugger.ui.tree.render.ToStringRenderer; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.options.SearchableConfigurable; @@ -51,6 +52,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { private JCheckBox myCbShowDeclaredType; private JCheckBox myCbShowFQNames; private JCheckBox myCbShowObjectId; + private JCheckBox myCbHexValue; private StateRestoringCheckBox myCbShowStaticFinalFields; //private final ArrayRendererConfigurable myArrayRendererConfigurable; @@ -120,6 +122,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { myCbShowDeclaredType = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.declared.type")); myCbShowFQNames = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.fq.names")); myCbShowObjectId = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.object.id")); + myCbHexValue = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.hex.value")); myCbEnableToString = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.enable.toString")); myRbAllThatOverride = new JRadioButton(DebuggerBundle.message("label.base.renderer.configurable.all.overriding")); @@ -172,7 +175,8 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { //arraysPanel.add(myCbHideNullArrayElements, BorderLayout.SOUTH); //arraysPanel.setBorder(IdeBorderFactory.createTitledBorder("Arrays", true)); //panel.add(arraysPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - panel.add(myCbHideNullArrayElements, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + panel.add(myCbHexValue, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + panel.add(myCbHideNullArrayElements, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(4, 0, 0, 0), 0, 0)); panel.add(myCbEnableAlternateViews, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 0, 0, 10), 0, 0)); // starting 4-th row @@ -208,9 +212,10 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { toStringRenderer.setUseClassFilters(myRbFromList.isSelected()); toStringRenderer.setClassFilters(myToStringFilterEditor.getFilters()); - myAutoTooltip.save(); + PrimitiveRenderer primitiveRenderer = rendererSettings.getPrimitiveRenderer(); + primitiveRenderer.setShowHexValue(myCbHexValue.isSelected()); - //myArrayRendererConfigurable.apply(); + myAutoTooltip.save(); rendererSettings.fireRenderersChanged(); } @@ -251,7 +256,8 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { myRbFromList.setEnabled(toStringEnabled); myRbAllThatOverride.setEnabled(toStringEnabled); - //myArrayRendererConfigurable.reset(); + PrimitiveRenderer primitiveRenderer = rendererSettings.getPrimitiveRenderer(); + myCbHexValue.setSelected(primitiveRenderer.isShowHexValue()); } @Override @@ -299,6 +305,11 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { return true; } + PrimitiveRenderer primitiveRenderer = rendererSettings.getPrimitiveRenderer(); + if (primitiveRenderer.isShowHexValue() != myCbHexValue.isSelected()) { + return true; + } + return false; } diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java index 5d5bd7681336..32505cc41831 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -172,6 +172,7 @@ public class NodeRendererSettings implements PersistentStateComponent { element.addContent(writeRenderer(myArrayRenderer)); element.addContent(writeRenderer(myToStringRenderer)); element.addContent(writeRenderer(myClassRenderer)); + element.addContent(writeRenderer(myPrimitiveRenderer)); if (myCustomRenderers.getRendererCount() > 0) { final Element custom = new Element(CUSTOM_RENDERERS_TAG_NAME); element.addContent(custom); @@ -213,6 +214,9 @@ public class NodeRendererSettings implements PersistentStateComponent { else if (ClassRenderer.UNIQUE_ID.equals(id)) { myClassRenderer.readExternal(elem); } + else if (PrimitiveRenderer.UNIQUE_ID.equals(id)) { + myPrimitiveRenderer.readExternal(elem); + } } catch (InvalidDataException e) { // ignore diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/HexRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/HexRenderer.java index 6af36f052582..ab5f4634f69d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/HexRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/HexRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiExpression; import com.sun.jdi.*; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; /** * User: lex @@ -57,46 +58,51 @@ public class HexRenderer extends NodeRendererImpl{ @SuppressWarnings({"HardCodedStringLiteral"}) public String calcLabel(ValueDescriptor valueDescriptor, EvaluationContext evaluationContext, DescriptorLabelListener labelListener) { Value value = valueDescriptor.getValue(); - StringBuilder buf = new StringBuilder(16); + StringBuilder buf = new StringBuilder(); - if(value == null) { - buf.append("null"); + if (value == null) { + return "null"; } else if (value instanceof CharValue) { - buf.append("'"); - buf.append(value.toString()); - buf.append("' "); - long longValue = ((PrimitiveValue)value).longValue(); + PrimitiveRenderer.appendCharValue((CharValue)value, buf); + buf.append(' '); + appendHexValue((PrimitiveValue)value, buf); + return buf.toString(); + } + else { + appendHexValue((PrimitiveValue)value, buf); + return buf.toString(); + } + } + + static void appendHexValue(@NotNull PrimitiveValue value, StringBuilder buf) { + if (value instanceof CharValue) { + long longValue = value.longValue(); buf.append("0x").append(Long.toHexString(longValue).toUpperCase()); } else if (value instanceof ByteValue) { - byte val = ((PrimitiveValue)value).byteValue(); - String strValue = Integer.toHexString(val).toUpperCase(); + String strValue = Integer.toHexString(value.byteValue()).toUpperCase(); if (strValue.length() > 2) { strValue = strValue.substring(strValue.length() - 2); } buf.append("0x").append(strValue); } else if (value instanceof ShortValue) { - short val = ((PrimitiveValue)value).shortValue(); - String strValue = Integer.toHexString(val).toUpperCase(); + String strValue = Integer.toHexString(value.shortValue()).toUpperCase(); if (strValue.length() > 4) { strValue = strValue.substring(strValue.length() - 4); } buf.append("0x").append(strValue); } else if (value instanceof IntegerValue) { - int val = ((PrimitiveValue)value).intValue(); - buf.append("0x").append(Integer.toHexString(val).toUpperCase()); + buf.append("0x").append(Integer.toHexString(value.intValue()).toUpperCase()); } else if (value instanceof LongValue) { - long val = ((PrimitiveValue)value).longValue(); - buf.append("0x").append(Long.toHexString(val).toUpperCase()); + buf.append("0x").append(Long.toHexString(value.longValue()).toUpperCase()); } else { LOG.assertTrue(false); } - return buf.toString(); } public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/PrimitiveRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/PrimitiveRenderer.java index ad4c392551ab..79f634b97652 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/PrimitiveRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/PrimitiveRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,19 @@ package com.intellij.debugger.ui.tree.render; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerContext; import com.intellij.debugger.engine.DebuggerManagerThreadImpl; -import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.ui.tree.DebuggerTreeNode; import com.intellij.debugger.ui.tree.NodeDescriptor; import com.intellij.debugger.ui.tree.ValueDescriptor; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.DefaultJDOMExternalizer; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiExpression; import com.sun.jdi.*; +import org.jdom.Element; import org.jetbrains.annotations.NonNls; /** @@ -37,6 +42,8 @@ public class PrimitiveRenderer extends NodeRendererImpl { public static final @NonNls String UNIQUE_ID = "PrimitiveRenderer"; private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.tree.render.PrimitiveRenderer"); + public boolean SHOW_HEX_VALUE = false; + public PrimitiveRenderer() { super("Primitive"); } @@ -63,41 +70,53 @@ public class PrimitiveRenderer extends NodeRendererImpl { public String calcLabel(ValueDescriptor valueDescriptor, EvaluationContext evaluationContext, DescriptorLabelListener labelListener) { Value value = valueDescriptor.getValue(); - if(value == null) { + if (value == null) { //noinspection HardCodedStringLiteral return "null"; } else if (value instanceof PrimitiveValue) { - StringBuilder buf = new StringBuilder(16); if (value instanceof CharValue) { - buf.append("'"); - buf.append(DebuggerUtils.translateStringValue(value.toString())); - buf.append("' "); - long longValue = ((PrimitiveValue)value).longValue(); - buf.append(Long.toString(longValue)); - } - else if (value instanceof ByteValue) { - buf.append(value.toString()); - } - else if (value instanceof ShortValue) { - buf.append(value.toString()); - } - else if (value instanceof IntegerValue) { - buf.append(value.toString()); - } - else if (value instanceof LongValue) { - buf.append(value.toString()); + StringBuilder buf = new StringBuilder(); + appendCharValue((CharValue)value, buf); + if (SHOW_HEX_VALUE) { + appendHexValue((CharValue)value, buf); + } else { + buf.append(' ').append(((PrimitiveValue)value).longValue()); + } + return buf.toString(); } else { - buf.append(value.toString()); + if (SHOW_HEX_VALUE) { + StringBuilder buf = new StringBuilder(); + buf.append(value.toString()); + appendHexValue((PrimitiveValue)value, buf); + return buf.toString(); + } + else { + return value.toString(); + } } - return buf.toString(); } else { return DebuggerBundle.message("label.undefined"); } } + static void appendCharValue(CharValue value, StringBuilder buf) { + buf.append('\''); + String s = value.toString(); + StringUtil.escapeStringCharacters(s.length(), s, buf); + buf.append('\''); + } + + private static void appendHexValue(PrimitiveValue value, StringBuilder buf) { + if (NodeRendererSettings.getInstance().getHexRenderer().isApplicable(value.type())) { + buf.append(" ("); + HexRenderer.appendHexValue(value, buf); + buf.append(')'); + } + } + public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) { DebuggerManagerThreadImpl.assertIsManagerThread(); } @@ -110,4 +129,24 @@ public class PrimitiveRenderer extends NodeRendererImpl { public boolean isExpandable(Value value, EvaluationContext evaluationContext, NodeDescriptor parentDescriptor) { return false; } + + public boolean isShowHexValue() { + return SHOW_HEX_VALUE; + } + + public void setShowHexValue(boolean show) { + this.SHOW_HEX_VALUE = show; + } + + @Override + public void readExternal(Element element) throws InvalidDataException { + super.readExternal(element); + DefaultJDOMExternalizer.readExternal(this, element); + } + + @Override + public void writeExternal(Element element) throws WriteExternalException { + super.writeExternal(element); + DefaultJDOMExternalizer.writeExternal(this, element); + } } diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 1a476a4daabf..22d05d76ab70 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -194,6 +194,7 @@ label.base.renderer.configurable.show.static.final.fields=Static &final fields label.base.renderer.configurable.show.declared.type=Declared &type label.base.renderer.configurable.show.fq.names=Fully &qualified names label.base.renderer.configurable.show.object.id=Object &id +label.base.renderer.configurable.show.hex.value=Show hex value for primitives label.base.renderer.configurable.alternate.view=Enable alternative view for Coll&ections classes label.base.renderer.configurable.enable.toString=Enable 't&oString()' object view: label.base.renderer.configurable.all.overriding=For all classes that override 'toString()' method