blob: 08f2e05c2835271a27d51e6d41340b25024a1b39 [file] [log] [blame]
/*
* Copyright 2000-2009 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.impl.watch;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.settings.ThreadsViewSettings;
import com.intellij.debugger.ui.tree.StackFrameDescriptor;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.ui.FileColorManager;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.ui.TextTransferable;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
/**
* Nodes of this type cannot be updated, because StackFrame objects become invalid as soon as VM has been resumed
*/
public class StackFrameDescriptorImpl extends NodeDescriptorImpl implements StackFrameDescriptor{
private final StackFrameProxyImpl myFrame;
private int myUiIndex;
private String myName = null;
private Location myLocation;
private final XStackFrame myXStackFrame;
private MethodsTracker.MethodOccurrence myMethodOccurrence;
private boolean myIsSynthetic;
private boolean myIsInLibraryContent;
private ObjectReference myThisObject;
private Color myBackgroundColor;
private SourcePosition mySourcePosition;
private Icon myIcon = AllIcons.Debugger.StackFrame;
public StackFrameDescriptorImpl(@NotNull StackFrameProxyImpl frame, @NotNull MethodsTracker tracker) {
myFrame = frame;
try {
myUiIndex = frame.getFrameIndex();
myLocation = frame.location();
myThisObject = frame.thisObject();
myMethodOccurrence = tracker.getMethodOccurrence(myUiIndex, myLocation.method());
myIsSynthetic = DebuggerUtils.isSynthetic(myMethodOccurrence.getMethod());
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
mySourcePosition = ContextUtil.getSourcePosition(StackFrameDescriptorImpl.this);
final PsiFile file = mySourcePosition != null? mySourcePosition.getFile() : null;
if (file == null) {
myIsInLibraryContent = true;
}
else {
myBackgroundColor = FileColorManager.getInstance(file.getProject()).getFileColor(file);
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(getDebugProcess().getProject()).getFileIndex();
final VirtualFile vFile = file.getVirtualFile();
myIsInLibraryContent = vFile != null && (projectFileIndex.isInLibraryClasses(vFile) || projectFileIndex.isInLibrarySource(vFile));
}
}
});
}
catch (InternalException e) {
LOG.info(e);
myLocation = null;
myMethodOccurrence = tracker.getMethodOccurrence(0, null);
myIsSynthetic = false;
myIsInLibraryContent = false;
}
catch (EvaluateException e) {
LOG.info(e);
myLocation = null;
myMethodOccurrence = tracker.getMethodOccurrence(0, null);
myIsSynthetic = false;
myIsInLibraryContent = false;
}
myXStackFrame = myLocation == null ? null : ((DebugProcessImpl)getDebugProcess()).getPositionManager().createStackFrame(frame, (DebugProcessImpl)getDebugProcess(), myLocation);
}
@Nullable
public XStackFrame getXStackFrame() {
return myXStackFrame;
}
public int getUiIndex() {
return myUiIndex;
}
@Override
@NotNull
public StackFrameProxyImpl getFrameProxy() {
return myFrame;
}
@NotNull
@Override
public DebugProcess getDebugProcess() {
return myFrame.getVirtualMachine().getDebugProcess();
}
@Override
public Color getBackgroundColor() {
return myBackgroundColor;
}
@Nullable
public Method getMethod() {
return myMethodOccurrence.getMethod();
}
public int getOccurrenceIndex() {
return myMethodOccurrence.getIndex();
}
public boolean isRecursiveCall() {
return myMethodOccurrence.isRecursive();
}
@Nullable
public ValueMarkup getValueMarkup() {
if (myThisObject != null) {
DebugProcess process = myFrame.getVirtualMachine().getDebugProcess();
if (process instanceof DebugProcessImpl) {
XDebugSession session = ((DebugProcessImpl)process).getSession().getXDebugSession();
if (session instanceof XDebugSessionImpl) {
XValueMarkers<?, ?> markers = ((XDebugSessionImpl)session).getValueMarkers();
if (markers != null) {
return markers.getAllMarkers().get(myThisObject);
}
}
}
}
return null;
}
@Override
public String getName() {
return myName;
}
@Override
protected String calcRepresentation(EvaluationContextImpl context, DescriptorLabelListener descriptorLabelListener) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
if (myXStackFrame != null) {
TextTransferable.ColoredStringBuilder builder = new TextTransferable.ColoredStringBuilder();
myXStackFrame.customizePresentation(builder);
return builder.getBuilder().toString();
}
if (myLocation == null) {
return "";
}
ThreadsViewSettings settings = ThreadsViewSettings.getInstance();
final StringBuilder label = StringBuilderSpinAllocator.alloc();
try {
Method method = myMethodOccurrence.getMethod();
if (method != null) {
myName = method.name();
label.append(myName);
label.append("()");
}
if (settings.SHOW_LINE_NUMBER) {
String lineNumber;
try {
lineNumber = Integer.toString(myLocation.lineNumber());
}
catch (InternalError e) {
lineNumber = e.toString();
}
if (lineNumber != null) {
label.append(':');
label.append(lineNumber);
}
}
if (settings.SHOW_CLASS_NAME) {
String name;
try {
ReferenceType refType = myLocation.declaringType();
name = refType != null ? refType.name() : null;
}
catch (InternalError e) {
name = e.toString();
}
if (name != null) {
label.append(", ");
int dotIndex = name.lastIndexOf('.');
if (dotIndex < 0) {
label.append(name);
}
else {
label.append(name.substring(dotIndex + 1));
label.append(" {");
label.append(name.substring(0, dotIndex));
label.append("}");
}
}
}
if (settings.SHOW_SOURCE_NAME) {
try {
String sourceName;
try {
sourceName = myLocation.sourceName();
}
catch (InternalError e) {
sourceName = e.toString();
}
label.append(", ");
label.append(sourceName);
}
catch (AbsentInformationException ignored) {
}
}
return label.toString();
}
finally {
StringBuilderSpinAllocator.dispose(label);
}
}
public final boolean stackFramesEqual(StackFrameDescriptorImpl d) {
return getFrameProxy().equals(d.getFrameProxy());
}
@Override
public boolean isExpandable() {
return true;
}
@Override
public final void setContext(EvaluationContextImpl context) {
myIcon = calcIcon();
}
public boolean isSynthetic() {
return myIsSynthetic;
}
public boolean isInLibraryContent() {
return myIsInLibraryContent;
}
public Location getLocation() {
return myLocation;
}
public SourcePosition getSourcePosition() {
return mySourcePosition;
}
private Icon calcIcon() {
try {
if(myFrame.isObsolete()) {
return AllIcons.Debugger.Db_obsolete;
}
}
catch (EvaluateException ignored) {
}
return AllIcons.Debugger.StackFrame;
}
public Icon getIcon() {
return myIcon;
}
}