820c9a75a6d3952e22d944c172de456cb26eac97
[idea/community.git] / platform / lang-impl / src / com / intellij / unscramble / AnalyzeStacktraceUtil.java
1 /*
2  * Copyright 2000-2015 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
17 package com.intellij.unscramble;
18
19 import com.intellij.execution.ExecutionManager;
20 import com.intellij.execution.Executor;
21 import com.intellij.execution.executors.DefaultRunExecutor;
22 import com.intellij.execution.filters.Filter;
23 import com.intellij.execution.filters.TextConsoleBuilder;
24 import com.intellij.execution.filters.TextConsoleBuilderFactory;
25 import com.intellij.execution.impl.ConsoleViewImpl;
26 import com.intellij.execution.ui.ConsoleView;
27 import com.intellij.execution.ui.ConsoleViewContentType;
28 import com.intellij.execution.ui.ExecutionConsole;
29 import com.intellij.execution.ui.RunContentDescriptor;
30 import com.intellij.execution.ui.actions.CloseAction;
31 import com.intellij.openapi.Disposable;
32 import com.intellij.openapi.actionSystem.*;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.command.CommandProcessor;
35 import com.intellij.openapi.editor.Document;
36 import com.intellij.openapi.editor.Editor;
37 import com.intellij.openapi.editor.EditorFactory;
38 import com.intellij.openapi.editor.EditorSettings;
39 import com.intellij.openapi.extensions.ExtensionPointName;
40 import com.intellij.openapi.extensions.Extensions;
41 import com.intellij.openapi.ide.CopyPasteManager;
42 import com.intellij.openapi.project.Project;
43 import com.intellij.openapi.util.Condition;
44 import com.intellij.openapi.util.Disposer;
45 import com.intellij.openapi.util.text.StringUtil;
46 import com.intellij.util.ui.JBUI;
47 import org.jetbrains.annotations.NotNull;
48 import org.jetbrains.annotations.Nullable;
49
50 import javax.swing.*;
51 import java.awt.*;
52 import java.awt.datatransfer.DataFlavor;
53
54 /**
55  * @author yole
56  */
57 public class AnalyzeStacktraceUtil {
58   public static final ExtensionPointName<Filter> EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter");
59
60   private AnalyzeStacktraceUtil() {
61   }
62
63   public static void printStacktrace(@NotNull final ConsoleView consoleView, @NotNull String unscrambledTrace) {
64     ApplicationManager.getApplication().assertIsDispatchThread();
65     final String text = unscrambledTrace + "\n";
66     final String consoleText = ((ConsoleViewImpl)consoleView).getText();
67     if (!text.equals(consoleText)) {
68       consoleView.clear();
69       // make sure other "clear" requests stuck in EDT are performed before our print next stacktrace
70       ApplicationManager.getApplication().invokeLater(new Runnable() {
71         @Override
72         public void run() {
73           try {
74             consoleView.print(text, ConsoleViewContentType.ERROR_OUTPUT);
75             consoleView.scrollTo(0);
76           }
77           catch (Exception e) {
78             throw new RuntimeException(e);
79           }
80         }
81       }, new Condition() {
82         @Override
83         public boolean value(Object o) {
84           return !((ConsoleViewImpl)consoleView).isVisible();
85         }
86       });
87     }
88   }
89
90   @Nullable
91   public static String getTextInClipboard() {
92     return CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
93   }
94
95   public interface ConsoleFactory {
96     JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions);
97   }
98
99   public static void addConsole(Project project, @Nullable ConsoleFactory consoleFactory, final String tabTitle, String text) {
100     addConsole(project, consoleFactory, tabTitle, text, null);
101   }
102
103   public static RunContentDescriptor addConsole(Project project,
104                                                 @Nullable ConsoleFactory consoleFactory,
105                                                 final String tabTitle,
106                                                 String text,
107                                                 @Nullable Icon icon) {
108     final TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
109     builder.filters(Extensions.getExtensions(EP_NAME, project));
110     final ConsoleView consoleView = builder.getConsole();
111
112     final DefaultActionGroup toolbarActions = new DefaultActionGroup();
113     JComponent consoleComponent = consoleFactory != null
114                                   ? consoleFactory.createConsoleComponent(consoleView, toolbarActions)
115                                   : new MyConsolePanel(consoleView, toolbarActions);
116     final RunContentDescriptor descriptor =
117       new RunContentDescriptor(consoleView, null, consoleComponent, tabTitle, icon) {
118       @Override
119       public boolean isContentReuseProhibited() {
120         return true;
121       }
122     };
123
124     final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
125     for (AnAction action: consoleView.createConsoleActions()) {
126       toolbarActions.add(action);
127     }
128     final ConsoleViewImpl console = (ConsoleViewImpl)consoleView;
129     console.getEditor().getSettings().setCaretRowShown(true);
130     toolbarActions.add(new AnnotateStackTraceAction(console.getEditor(), console.getHyperlinks()));
131     toolbarActions.add(new CloseAction(executor, descriptor, project));
132     ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
133     consoleView.allowHeavyFilters();
134     if (consoleFactory == null) {
135       printStacktrace(consoleView, text);
136     }
137     return descriptor;
138   }
139
140   private static final class MyConsolePanel extends JPanel {
141     public MyConsolePanel(ExecutionConsole consoleView, ActionGroup toolbarActions) {
142       super(new BorderLayout());
143       JPanel toolbarPanel = new JPanel(new BorderLayout());
144       toolbarPanel.add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions,false).getComponent());
145       add(toolbarPanel, BorderLayout.WEST);
146       add(consoleView.getComponent(), BorderLayout.CENTER);
147     }
148   }
149
150   public static StacktraceEditorPanel createEditorPanel(Project project, @NotNull Disposable parentDisposable) {
151     EditorFactory editorFactory = EditorFactory.getInstance();
152     Document document = editorFactory.createDocument("");
153     Editor editor = editorFactory.createEditor(document, project);
154     EditorSettings settings = editor.getSettings();
155     settings.setFoldingOutlineShown(false);
156     settings.setLineMarkerAreaShown(false);
157     settings.setIndentGuidesShown(false);
158     settings.setLineNumbersShown(false);
159     settings.setRightMarginShown(false);
160
161     StacktraceEditorPanel editorPanel = new StacktraceEditorPanel(project, editor);
162     editorPanel.setPreferredSize(JBUI.size(600, 400));
163     Disposer.register(parentDisposable, editorPanel);
164     return editorPanel;
165   }
166
167   public static final class StacktraceEditorPanel extends JPanel implements DataProvider, Disposable {
168     private final Project myProject;
169     private final Editor myEditor;
170
171     public StacktraceEditorPanel(Project project, Editor editor) {
172       super(new BorderLayout());
173       myProject = project;
174       myEditor = editor;
175       add(myEditor.getComponent());
176     }
177
178     @Override
179     public Object getData(String dataId) {
180       if (CommonDataKeys.EDITOR.is(dataId)) {
181         return myEditor;
182       }
183       return null;
184     }
185
186     public Editor getEditor() {
187       return myEditor;
188     }
189
190     public final void setText(@NotNull final String text) {
191       Runnable runnable = new Runnable() {
192         @Override
193         public void run() {
194           ApplicationManager.getApplication().runWriteAction(new Runnable() {
195             @Override
196             public void run() {
197               final Document document = myEditor.getDocument();
198               document.replaceString(0, document.getTextLength(), StringUtil.convertLineSeparators(text));
199             }
200           });
201         }
202       };
203       CommandProcessor.getInstance().executeCommand(myProject, runnable, "", this);
204     }
205
206     public void pasteTextFromClipboard() {
207       String text = getTextInClipboard();
208       if (text != null) {
209         setText(text);
210       }
211
212     }
213
214     @Override
215     public void dispose() {
216       EditorFactory.getInstance().releaseEditor(myEditor);
217     }
218
219     public String getText() {
220       return myEditor.getDocument().getText();
221     }
222
223     public JComponent getEditorComponent() {
224       return myEditor.getContentComponent();
225     }
226   }
227 }