| /* |
| * 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) { |
| if (checkContextNotResumed(node)) return; |
| 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<ObjectReference> 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; |
| } |
| } |