diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index a92fc8f3add7..7e976589905f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -311,20 +311,13 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV String value = truncateToMaxLength(myValue); Renderer lastRenderer = myValueDescriptor.getLastRenderer(); - if (lastRenderer instanceof OnDemandRenderer) { - OnDemandRenderer onDemandRenderer = (OnDemandRenderer)lastRenderer; - if (OnDemandRenderer.isCalculated(myValueDescriptor)) { - lastRenderer = onDemandRenderer.getRenderer(); - } - else { - return; - } - } - if (lastRenderer instanceof CompoundTypeRenderer) { lastRenderer = ((CompoundTypeRenderer)lastRenderer).getLabelRenderer(); } if (lastRenderer instanceof ToStringRenderer) { + if (!((ToStringRenderer)lastRenderer).isShowValue(myValueDescriptor, myValueDescriptor.getStoredEvaluationContext())) { + return; // to avoid empty line for not calculated toStrings + } value = StringUtil.wrapWithDoubleQuote(value); } renderer.renderValue(value); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java index a900f2206ca3..17ff0fc7c61f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java @@ -610,4 +610,8 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements } return ""; } + + public EvaluationContextImpl getStoredEvaluationContext() { + return myStoredEvaluationContext; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/actions/ForceOnDemandRenderersAction.kt b/java/debugger/impl/src/com/intellij/debugger/ui/tree/actions/ForceOnDemandRenderersAction.kt new file mode 100644 index 000000000000..2d60e46b69f7 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/actions/ForceOnDemandRenderersAction.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.ui.tree.actions + +import com.intellij.debugger.settings.NodeRendererSettings +import com.intellij.openapi.actionSystem.AnActionEvent +import com.intellij.openapi.actionSystem.ToggleAction +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.util.Key +import com.intellij.xdebugger.XDebuggerManager +import com.intellij.xdebugger.impl.XDebugSessionImpl +import com.intellij.xdebugger.impl.ui.XDebugSessionData + +/** + * @author egor + */ +class ForceOnDemandRenderersAction : ToggleAction(), DumbAware { + + override fun isSelected(e: AnActionEvent): Boolean { + return RENDERERS_ONDEMAND_FORCED.get(getSessionData(e), false) + } + + override fun setSelected(e: AnActionEvent, state: Boolean) { + RENDERERS_ONDEMAND_FORCED.set(getSessionData(e), state) + NodeRendererSettings.getInstance().fireRenderersChanged() + } + + companion object { + private val RENDERERS_ONDEMAND_FORCED = Key.create("RENDERERS_ONDEMAND_FORCED") + + private fun getSessionData(e: AnActionEvent): XDebugSessionData? { + var data = e.getData(XDebugSessionData.DATA_KEY) + if (data == null) { + val project = e.project + if (project != null) { + val session = XDebuggerManager.getInstance(project).currentSession + if (session != null) { + data = (session as XDebugSessionImpl).sessionData + } + } + } + return data + } + + @JvmStatic + fun isForcedOnDemand(session: XDebugSessionImpl): Boolean { + return RENDERERS_ONDEMAND_FORCED.get(session.sessionData, false) + } + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java index 665d2dfbfdea..75055969cdc2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java @@ -18,23 +18,23 @@ package com.intellij.debugger.ui.tree.render; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebuggerUtils; -import com.intellij.debugger.engine.FullValueEvaluatorProvider; -import com.intellij.debugger.engine.evaluation.*; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.TextWithImports; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; -import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; import com.intellij.debugger.ui.tree.ValueDescriptor; import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; -import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.sun.jdi.Value; import org.jdom.Element; import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import javax.swing.*; -public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, FullValueEvaluatorProvider { +public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, OnDemandRenderer { public static final @NonNls String UNIQUE_ID = "LabelRenderer"; public boolean myOnDemand; @@ -62,7 +62,7 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, F public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener labelListener) throws EvaluateException { - if (myOnDemand && !OnDemandRenderer.isCalculated(descriptor)) { + if (!isShowValue(descriptor, evaluationContext)) { return ""; } @@ -92,13 +92,10 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, F return result; } - @Nullable + @NotNull @Override - public XFullValueEvaluator getFullValueEvaluator(EvaluationContextImpl evaluationContext, ValueDescriptorImpl valueDescriptor) { - if (myOnDemand && !OnDemandRenderer.isCalculated(valueDescriptor)) { - return OnDemandRenderer.createFullValueEvaluator("… " + getLabelExpression().getText()); - } - return null; + public String getLinkText() { + return "… " + getLabelExpression().getText(); } public void readExternal(Element element) throws InvalidDataException { @@ -124,6 +121,11 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, F myLabelExpression.setReferenceExpression(expression); } + @Override + public boolean isOnDemand(EvaluationContext evaluationContext) { + return myOnDemand || OnDemandRenderer.super.isOnDemand(evaluationContext); + } + public boolean isOnDemand() { return myOnDemand; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java new file mode 100644 index 000000000000..0b39caa9450b --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2017 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.ui.tree.render; + +import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.engine.FullValueEvaluatorProvider; +import com.intellij.debugger.engine.JavaValue; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.debugger.ui.tree.ValueDescriptor; +import com.intellij.debugger.ui.tree.actions.ForceOnDemandRenderersAction; +import com.intellij.openapi.util.Key; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.frame.XValuePlace; +import com.intellij.xdebugger.impl.XDebugSessionImpl; +import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author egor + */ +public interface OnDemandRenderer extends FullValueEvaluatorProvider { + @Nullable + @Override + default XFullValueEvaluator getFullValueEvaluator(EvaluationContextImpl evaluationContext, + ValueDescriptorImpl valueDescriptor) { + if (isOnDemand(evaluationContext) && !isCalculated(valueDescriptor)) { + return createFullValueEvaluator(getLinkText()); + } + return null; + } + + String getLinkText(); + + default boolean isOnDemand(EvaluationContext evaluationContext) { + return isOnDemandForced(evaluationContext); + } + + default boolean isShowValue(ValueDescriptor valueDescriptor, EvaluationContext evaluationContext) { + return !isOnDemand(evaluationContext) || isCalculated(valueDescriptor); + } + + static XFullValueEvaluator createFullValueEvaluator(String text) { + return new XFullValueEvaluator(text) { + @Override + public void startEvaluation(@NotNull XFullValueEvaluationCallback callback) { + if (callback instanceof HeadlessValueEvaluationCallback) { + XValueNodeImpl node = ((HeadlessValueEvaluationCallback)callback).getNode(); + node.clearFullValueEvaluator(); + setCalculated(((JavaValue)node.getValueContainer()).getDescriptor()); + node.getValueContainer().computePresentation(node, XValuePlace.TREE); + } + callback.evaluated(""); + } + }.setShowValuePopup(false); + } + + Key ON_DEMAND_CALCULATED = Key.create("ON_DEMAND_CALCULATED"); + + static boolean isCalculated(ValueDescriptor descriptor) { + return ON_DEMAND_CALCULATED.get(descriptor, false); + } + + static void setCalculated(ValueDescriptor descriptor) { + ON_DEMAND_CALCULATED.set(descriptor, true); + } + + static boolean isOnDemandForced(EvaluationContext evaluationContext) { + return ForceOnDemandRenderersAction.isForcedOnDemand( + (XDebugSessionImpl)((DebugProcessImpl)evaluationContext.getDebugProcess()).getXdebugProcess().getSession()); + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt deleted file mode 100644 index 41fcf05e600f..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2000-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.ui.tree.render - -import com.intellij.debugger.DebuggerBundle -import com.intellij.debugger.DebuggerContext -import com.intellij.debugger.engine.FullValueEvaluatorProvider -import com.intellij.debugger.engine.JavaValue -import com.intellij.debugger.engine.evaluation.EvaluateException -import com.intellij.debugger.engine.evaluation.EvaluationContext -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl -import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl -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.util.Key -import com.intellij.psi.PsiElement -import com.intellij.xdebugger.frame.XFullValueEvaluator -import com.intellij.xdebugger.frame.XValuePlace -import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback -import com.sun.jdi.Type -import com.sun.jdi.Value -import javax.swing.Icon - -/** - * @author egor - */ -class OnDemandRenderer(val renderer: NodeRendererImpl) : NodeRendererImpl(), FullValueEvaluatorProvider { - init { - isEnabled = true - } - - @Throws(EvaluateException::class) - override fun calcLabel(descriptor: ValueDescriptor, evaluationContext: EvaluationContext, listener: DescriptorLabelListener): String? { - if (!isCalculated(descriptor)) { - return "" - } - return renderer.calcLabel(descriptor, evaluationContext, listener) - } - - override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl?, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? { - if (!isCalculated(valueDescriptor)) { - return createFullValueEvaluator(DebuggerBundle.message("message.node.toString")) - } - return null - } - - override fun buildChildren(value: Value?, builder: ChildrenBuilder?, evaluationContext: EvaluationContext?) { - renderer.buildChildren(value, builder, evaluationContext) - } - - override fun getChildValueExpression(node: DebuggerTreeNode?, context: DebuggerContext?): PsiElement { - return renderer.getChildValueExpression(node, context) - } - - override fun isExpandable(value: Value?, evaluationContext: EvaluationContext?, parentDescriptor: NodeDescriptor?): Boolean { - return renderer.isExpandable(value, evaluationContext, parentDescriptor) - } - - override fun calcValueIcon(descriptor: ValueDescriptor?, - evaluationContext: EvaluationContext?, - listener: DescriptorLabelListener?): Icon? { - return renderer.calcValueIcon(descriptor, evaluationContext, listener) - } - - override fun isApplicable(type: Type?): Boolean { - return renderer.isApplicable(type) - } - - override fun getName(): String { - return "OnDemand" + renderer.getName() - } - - override fun getUniqueId(): String { - return "OnDemand" + renderer.getUniqueId() - } - - companion object { - @JvmStatic - fun createFullValueEvaluator(text: String): XFullValueEvaluator { - return object : XFullValueEvaluator(text) { - override fun startEvaluation(callback: XFullValueEvaluator.XFullValueEvaluationCallback) { - if (callback is HeadlessValueEvaluationCallback) { - val node = callback.node - node.clearFullValueEvaluator() - setCalculated((node.valueContainer as JavaValue).descriptor) - node.valueContainer.computePresentation(node, XValuePlace.TREE) - } - callback.evaluated("") - } - }.setShowValuePopup(false) - } - - @JvmField - val ON_DEMAND_CALCULATED = Key.create("ON_DEMAND_CALCULATED") - - @JvmStatic - fun isCalculated(descriptor: ValueDescriptor): Boolean { - return ON_DEMAND_CALCULATED.get(descriptor, false) - } - - @JvmStatic - fun setCalculated(descriptor: ValueDescriptor) { - ON_DEMAND_CALCULATED.set(descriptor, true) - } - } -} \ No newline at end of file diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java index 0da9267f8d78..5de3c1f16d64 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java @@ -34,10 +34,11 @@ import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.sun.jdi.*; import org.jdom.Element; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING; -public class ToStringRenderer extends NodeRendererImpl { +public class ToStringRenderer extends NodeRendererImpl implements OnDemandRenderer { public static final @NonNls String UNIQUE_ID = "ToStringRenderer"; private boolean USE_CLASS_FILTERS = false; @@ -76,6 +77,11 @@ public class ToStringRenderer extends NodeRendererImpl { @Override public String calcLabel(final ValueDescriptor valueDescriptor, EvaluationContext evaluationContext, final DescriptorLabelListener labelListener) throws EvaluateException { + + if (!isShowValue(valueDescriptor, evaluationContext)) { + return ""; + } + final Value value = valueDescriptor.getValue(); BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) { @Override @@ -96,6 +102,12 @@ public class ToStringRenderer extends NodeRendererImpl { return XDebuggerUIConstants.COLLECTING_DATA_MESSAGE; } + @NotNull + @Override + public String getLinkText() { + return DebuggerBundle.message("message.node.toString"); + } + public boolean isUseClassFilters() { return USE_CLASS_FILTERS; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java index 924b3a567c4a..1729f21bc0dd 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -16,13 +16,14 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.xdebugger.XExpression; import org.jetbrains.annotations.NotNull; /** * @author nik */ -public class XDebugSessionData { +public class XDebugSessionData extends UserDataHolderBase { public static final DataKey DATA_KEY = DataKey.create("XDebugSessionData"); @NotNull diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 3f0a60715dd9..4028593ba02f 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -225,6 +225,9 @@ + + +