diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java new file mode 100644 index 000000000000..815ddd231f14 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2014 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.actions; + +import com.intellij.debugger.DebuggerContext; +import com.intellij.debugger.engine.JavaValue; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl; +import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.psi.PsiExpression; +import com.intellij.xdebugger.frame.*; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; +import com.sun.jdi.Field; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.Value; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.List; + +public class JavaReferringObjectsValue extends JavaValue { + private static final long MAX_REFERRING = 100; + private final boolean myIsField; + + private JavaReferringObjectsValue(@Nullable JavaValue parent, + @NotNull ValueDescriptorImpl valueDescriptor, + @NotNull EvaluationContextImpl evaluationContext, + NodeManagerImpl nodeManager, + boolean isField) { + super(parent, valueDescriptor, evaluationContext, nodeManager, false); + myIsField = isField; + } + + public JavaReferringObjectsValue(@NotNull JavaValue javaValue, boolean isField) { + super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), null, false); + myIsField = isField; + } + + @Override + public boolean canNavigateToSource() { + return true; + } + + @Override + public void computeChildren(@NotNull final XCompositeNode node) { + getEvaluationContext().getDebugProcess().getManagerThread().schedule( + new SuspendContextCommandImpl(getEvaluationContext().getSuspendContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + + @Override + public void contextAction() throws Exception { + final XValueChildrenList children = new XValueChildrenList(); + + Value value = getDescriptor().getValue(); + List references = ((ObjectReference)value).referringObjects(MAX_REFERRING); + int i = 1; + for (final ObjectReference reference : references) { + // try to find field name + Field field = findField(reference, value); + if (field != null) { + ValueDescriptorImpl descriptor = new FieldDescriptorImpl(getProject(), reference, field) { + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { + return reference; + } + }; + children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, true)); + i++; + } + else { + ValueDescriptorImpl descriptor = new ValueDescriptorImpl(getProject(), reference) { + @Override + public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { + return reference; + } + + @Override + public String getName() { + return "Ref"; + } + + @Override + public String calcValueName() { + return "Ref"; + } + + @Override + public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException { + return null; + } + }; + children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, false)); + } + } + + node.addChildren(children, true); + } + } + ); + } + + @Override + public void computePresentation(@NotNull final XValueNode node, @NotNull final XValuePlace place) { + if (!myIsField) { + super.computePresentation(node, place); + } + else { + super.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() { + @Override + public void applyPresentation(@Nullable Icon icon, @NotNull final XValuePresentation valuePresenter, boolean hasChildren) { + node.setPresentation(icon, new XValuePresentation() { + @NotNull + @Override + public String getSeparator() { + return " in "; + } + + @Nullable + @Override + public String getType() { + return valuePresenter.getType(); + } + + @Override + public void renderValue(@NotNull XValueTextRenderer renderer) { + valuePresenter.renderValue(renderer); + } + }, hasChildren); + } + + @Override + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { + } + + @Override + public boolean isObsolete() { + return false; + } + }, place); + } + } + + private static Field findField(ObjectReference reference, Value value) { + for (Field field : reference.referenceType().allFields()) { + if (reference.getValue(field) == value) { + return field; + } + } + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java deleted file mode 100644 index 5ec58b871989..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2000-2014 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.actions; - -import com.intellij.debugger.DebuggerBundle; -import com.intellij.debugger.DebuggerContext; -import com.intellij.debugger.engine.JavaValue; -import com.intellij.debugger.engine.evaluation.EvaluateException; -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; -import com.intellij.debugger.engine.events.SuspendContextCommandImpl; -import com.intellij.debugger.ui.impl.watch.FieldDescriptorImpl; -import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; -import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.psi.PsiExpression; -import com.intellij.xdebugger.frame.*; -import com.intellij.xdebugger.frame.presentation.XValuePresentation; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; -import com.intellij.xdebugger.impl.ui.tree.XInspectDialog; -import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; -import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; -import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; -import com.sun.jdi.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.util.List; - -/** - * @author egor - */ -public class ShowReferringObjectsAction extends XDebuggerTreeActionBase { - private static final long MAX_REFERRING = 100; - - @Override - protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) { - XValue container = node.getValueContainer(); - if (container instanceof JavaValue) { - JavaValue javaValue = ((JavaValue)container); - XDebuggerTree tree = XDebuggerTree.getTree(e.getDataContext()); - XInspectDialog dialog = new XInspectDialog(tree.getProject(), - tree.getEditorsProvider(), - tree.getSourcePosition(), - nodeName, - new ReferringObjectsValue(javaValue, false), - tree.getValueMarkers()); - dialog.setTitle(DebuggerBundle.message("showReferring.dialog.title", nodeName)); - dialog.show(); - } - } - - private static class ReferringObjectsValue extends JavaValue { - private final boolean myIsField; - - private ReferringObjectsValue(JavaValue parent, - @NotNull ValueDescriptorImpl valueDescriptor, - @NotNull EvaluationContextImpl evaluationContext, - NodeManagerImpl nodeManager, - boolean isField) { - super(parent, valueDescriptor, evaluationContext, nodeManager, false); - myIsField = isField; - } - - public ReferringObjectsValue(JavaValue javaValue, boolean isField) { - super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), null, false); - myIsField = isField; - } - - @Override - public boolean canNavigateToSource() { - return true; - } - - @Override - public void computeChildren(@NotNull final XCompositeNode node) { - getEvaluationContext().getDebugProcess().getManagerThread().schedule( - new SuspendContextCommandImpl(getEvaluationContext().getSuspendContext()) { - @Override - public Priority getPriority() { - return Priority.NORMAL; - } - - @Override - public void contextAction() throws Exception { - final XValueChildrenList children = new XValueChildrenList(); - - Value value = getDescriptor().getValue(); - List references = ((ObjectReference)value).referringObjects(MAX_REFERRING); - int i = 1; - for (final ObjectReference reference : references) { - // try to find field name - Field field = findField(reference, value); - if (field != null) { - ValueDescriptorImpl descriptor = new FieldDescriptorImpl(getProject(), reference, field) { - @Override - public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { - return reference; - } - }; - children.add(new ReferringObjectsValue(null, descriptor, getEvaluationContext(), null, true)); - i++; - } - else { - ValueDescriptorImpl descriptor = new ValueDescriptorImpl(getProject(), reference) { - @Override - public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException { - return reference; - } - - @Override - public String getName() { - return "Ref"; - } - - @Override - public String calcValueName() { - return "Ref"; - } - - @Override - public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException { - return null; - } - }; - children.add("Referrer " + i++, new ReferringObjectsValue(null, descriptor, getEvaluationContext(), null, false)); - } - } - - node.addChildren(children, true); - } - } - ); - } - - @Override - public void computePresentation(@NotNull final XValueNode node, @NotNull final XValuePlace place) { - if (!myIsField) { - super.computePresentation(node, place); - } - else { - super.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() { - @Override - public void applyPresentation(@Nullable Icon icon, @NotNull final XValuePresentation valuePresenter, boolean hasChildren) { - node.setPresentation(icon, new XValuePresentation() { - @NotNull - @Override - public String getSeparator() { - return " in "; - } - - @Nullable - @Override - public String getType() { - return valuePresenter.getType(); - } - - @Override - public void renderValue(@NotNull XValueTextRenderer renderer) { - valuePresenter.renderValue(renderer); - } - }, hasChildren); - } - - @Override - public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { - } - - @Override - public boolean isObsolete() { - return false; - } - }, place); - } - } - - private static Field findField(ObjectReference reference, Value value) { - for (Field field : reference.referenceType().allFields()) { - if (reference.getValue(field) == value) { - return field; - } - } - return null; - } - } -} 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 e1b4b77d9f03..3acf37b646d9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -17,6 +17,7 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.actions.JavaReferringObjectsValue; import com.intellij.debugger.actions.JumpToObjectAction; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; @@ -451,4 +452,14 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV public String getValueText() { return myValueDescriptor.getValueText(); } + @Nullable + @Override + public XReferrersProvider getReferrersProvider() { + return new XReferrersProvider() { + @Override + public XValue getReferringObjectsValue() { + return new JavaReferringObjectsValue(JavaValue.this, false); + } + }; + } } diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 59692f81c790..a1300adfd1bc 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -124,3 +124,5 @@ setting.sort.alphabetically.label=Sort a&lphabetically setting.hide.window.label=Hide debug &window on process termination setting.focus.app.on.breakpoint.label=Focus application on breakpoint settings.show.window.label=Show &debug window on breakpoint + +showReferring.dialog.title=Referring Objects For {0} diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 3b0289f12433..2310267979ff 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -683,6 +683,7 @@ + @@ -709,6 +710,7 @@ + diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XReferrersProvider.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XReferrersProvider.java new file mode 100644 index 000000000000..9f9f3a8bf407 --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XReferrersProvider.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2014 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.xdebugger.frame; + +/** + * @author traff + */ +public interface XReferrersProvider { + T getReferringObjectsValue(); +} diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValue.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValue.java index ff2b3303d4da..9cfa2fb15af4 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValue.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValue.java @@ -87,4 +87,9 @@ public abstract class XValue extends XValueContainer { public void computeTypeSourcePosition(@NotNull XNavigatable navigatable) { navigatable.setSourcePosition(null); } + + @Nullable + public XReferrersProvider getReferrersProvider() { + return null; + } } \ No newline at end of file diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java new file mode 100644 index 000000000000..4c2962f7f576 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 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.xdebugger.impl.ui.tree.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.frame.XReferrersProvider; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; +import com.intellij.xdebugger.impl.ui.tree.XInspectDialog; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; + +/** + * @author egor + */ +public class ShowReferringObjectsAction extends XDebuggerTreeActionBase { + + @Override + protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) { + return node.getValueContainer().getReferrersProvider() != null; + } + + @Override + protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) { + XReferrersProvider referrersProvider = node.getValueContainer().getReferrersProvider(); + if (referrersProvider != null) { + XDebuggerTree tree = XDebuggerTree.getTree(e.getDataContext()); + XInspectDialog dialog = new XInspectDialog(tree.getProject(), + tree.getEditorsProvider(), + tree.getSourcePosition(), + nodeName, + referrersProvider.getReferringObjectsValue(), + tree.getValueMarkers()); + dialog.setTitle(XDebuggerBundle.message("showReferring.dialog.title", nodeName)); + dialog.show(); + } + } +} diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 6c1ccfbb10b1..ac623acc1fbe 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -438,5 +438,4 @@ action.kill.process.text=Kill Process action.kill.process.description=Forcibly terminate debugged application evaluation.error.unknown.method.return.type=Cannot resolve method return type: {0} rule.name.group.by.class=Group by class -rule.name.group.by.package=Group by package -showReferring.dialog.title=Referring Objects For {0} \ No newline at end of file +rule.name.group.by.package=Group by package \ No newline at end of file diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index a54f7da9eec4..81a791f42208 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -162,9 +162,6 @@ - - -