Merge branch 'liana/simplified_debugger'
[idea/community.git] / python / src / com / jetbrains / python / debugger / PyStackFrame.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.debugger;
17
18 import com.intellij.icons.AllIcons;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.fileEditor.FileDocumentManager;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.roots.ProjectRootManager;
25 import com.intellij.openapi.vfs.VirtualFile;
26 import com.intellij.ui.ColoredTextContainer;
27 import com.intellij.ui.SimpleTextAttributes;
28 import com.intellij.xdebugger.XSourcePosition;
29 import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
30 import com.intellij.xdebugger.frame.XCompositeNode;
31 import com.intellij.xdebugger.frame.XStackFrame;
32 import com.intellij.xdebugger.frame.XValueChildrenList;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35
36
37 public class PyStackFrame extends XStackFrame {
38
39   private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.pydev.PyStackFrame");
40
41   private static final Object STACK_FRAME_EQUALITY_OBJECT = new Object();
42
43   private Project myProject;
44   private final PyFrameAccessor myDebugProcess;
45   private final PyStackFrameInfo myFrameInfo;
46   private final XSourcePosition myPosition;
47
48   public PyStackFrame(@NotNull Project project,
49                       @NotNull final PyFrameAccessor debugProcess,
50                       @NotNull final PyStackFrameInfo frameInfo, XSourcePosition position) {
51     myProject = project;
52     myDebugProcess = debugProcess;
53     myFrameInfo = frameInfo;
54     myPosition = position;
55   }
56
57   @Override
58   public Object getEqualityObject() {
59     return STACK_FRAME_EQUALITY_OBJECT;
60   }
61
62   @Override
63   public XSourcePosition getSourcePosition() {
64     return myPosition;
65   }
66
67   @Override
68   public XDebuggerEvaluator getEvaluator() {
69     return new PyDebuggerEvaluator(myProject, myDebugProcess);
70   }
71
72   @Override
73   public void customizePresentation(@NotNull ColoredTextContainer component) {
74     component.setIcon(AllIcons.Debugger.StackFrame);
75
76     if (myPosition == null) {
77       component.append("<frame not available>", SimpleTextAttributes.GRAY_ATTRIBUTES);
78       return;
79     }
80
81     boolean isExternal = true;
82     final VirtualFile file = myPosition.getFile();
83     final Document document = FileDocumentManager.getInstance().getDocument(file);
84     if (document != null) {
85       isExternal = !ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(file);
86     }
87
88     component.append(myFrameInfo.getName(), gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
89     component.append(", ", gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
90     component.append(myPosition.getFile().getName(), gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
91     component.append(":", gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
92     component.append(Integer.toString(myPosition.getLine() + 1), gray(SimpleTextAttributes.REGULAR_ATTRIBUTES, isExternal));
93   }
94
95   private static SimpleTextAttributes gray(SimpleTextAttributes attributes, boolean gray) {
96     if (!gray) {
97       return attributes;
98     }
99     else {
100       return getGrayAttributes(attributes);
101     }
102   }
103
104   protected static SimpleTextAttributes getGrayAttributes(SimpleTextAttributes attributes) {
105     return (attributes.getStyle() & SimpleTextAttributes.STYLE_ITALIC) != 0
106            ? SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES;
107   }
108
109   @Override
110   public void computeChildren(@NotNull final XCompositeNode node) {
111     if (node.isObsolete()) return;
112     ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
113       @Override
114       public void run() {
115         try {
116           XValueChildrenList values = myDebugProcess.loadFrame();
117           if (!node.isObsolete()) {
118             addChildren(node, values);
119           }
120         }
121         catch (PyDebuggerException e) {
122           if (!node.isObsolete()) {
123             node.setErrorMessage("Unable to display frame variables");
124           }
125           LOG.warn(e);
126         }
127       }
128     });
129   }
130
131   protected void addChildren(@NotNull final XCompositeNode node, @Nullable final XValueChildrenList children) {
132     node.addChildren(children != null ? children : XValueChildrenList.EMPTY, true);
133   }
134
135   public String getThreadId() {
136     return myFrameInfo.getThreadId();
137   }
138
139   public String getFrameId() {
140     return myFrameInfo.getId();
141   }
142
143   public String getThreadFrameId() {
144     return myFrameInfo.getThreadId() + ":" + myFrameInfo.getId();
145   }
146
147   protected XSourcePosition getPosition() {
148     return myPosition;
149   }
150 }