2 * Copyright 2000-2015 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.intellij.unscramble;
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.*;
27 import com.intellij.execution.ui.actions.CloseAction;
28 import com.intellij.ide.DataManager;
29 import com.intellij.openapi.Disposable;
30 import com.intellij.openapi.actionSystem.*;
31 import com.intellij.openapi.actionSystem.ex.ActionUtil;
32 import com.intellij.openapi.application.ApplicationManager;
33 import com.intellij.openapi.command.CommandProcessor;
34 import com.intellij.openapi.editor.Document;
35 import com.intellij.openapi.editor.Editor;
36 import com.intellij.openapi.editor.EditorFactory;
37 import com.intellij.openapi.editor.EditorSettings;
38 import com.intellij.openapi.extensions.ExtensionPointName;
39 import com.intellij.openapi.extensions.Extensions;
40 import com.intellij.openapi.ide.CopyPasteManager;
41 import com.intellij.openapi.project.Project;
42 import com.intellij.openapi.util.Disposer;
43 import com.intellij.openapi.util.text.StringUtil;
44 import com.intellij.openapi.wm.IdeFocusManager;
45 import com.intellij.util.ui.JBUI;
46 import com.intellij.util.ui.update.UiNotifyConnector;
47 import org.jetbrains.annotations.NotNull;
48 import org.jetbrains.annotations.Nullable;
52 import java.awt.datatransfer.DataFlavor;
53 import java.awt.event.ActionEvent;
54 import java.awt.event.ActionListener;
59 public class AnalyzeStacktraceUtil {
60 public static final ExtensionPointName<Filter> EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter");
62 private AnalyzeStacktraceUtil() {
65 public static void printStacktrace(@NotNull ConsoleView consoleView, @NotNull String unscrambledTrace) {
66 ApplicationManager.getApplication().assertIsDispatchThread();
67 String text = unscrambledTrace + "\n";
68 String consoleText = ((ConsoleViewImpl)consoleView).getText();
69 if (!text.equals(consoleText)) {
71 consoleView.print(text, ConsoleViewContentType.ERROR_OUTPUT);
72 consoleView.scrollTo(0);
77 public static String getTextInClipboard() {
78 return CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
81 public interface ConsoleFactory {
82 JComponent createConsoleComponent(ConsoleView consoleView, DefaultActionGroup toolbarActions);
85 public static void addConsole(Project project, @Nullable ConsoleFactory consoleFactory, final String tabTitle, String text) {
86 addConsole(project, consoleFactory, tabTitle, text, null);
89 public static RunContentDescriptor addConsole(Project project,
90 @Nullable ConsoleFactory consoleFactory,
91 final String tabTitle,
93 @Nullable Icon icon) {
94 final TextConsoleBuilder builder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
95 builder.filters(Extensions.getExtensions(EP_NAME, project));
96 final ConsoleView consoleView = builder.getConsole();
98 final DefaultActionGroup toolbarActions = new DefaultActionGroup();
99 JComponent consoleComponent = consoleFactory != null
100 ? consoleFactory.createConsoleComponent(consoleView, toolbarActions)
101 : new MyConsolePanel(consoleView, toolbarActions);
102 final RunContentDescriptor descriptor =
103 new RunContentDescriptor(consoleView, null, consoleComponent, tabTitle, icon) {
105 public boolean isContentReuseProhibited() {
109 registerReplaceAction(project, descriptor, consoleView, text);
111 final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
112 for (AnAction action: consoleView.createConsoleActions()) {
113 toolbarActions.add(action);
115 final ConsoleViewImpl console = (ConsoleViewImpl)consoleView;
116 console.getEditor().getSettings().setCaretRowShown(true);
117 toolbarActions.add(new AnnotateStackTraceAction(console.getEditor(), console.getHyperlinks()));
118 toolbarActions.add(new CloseAction(executor, descriptor, project));
119 ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
120 consoleView.allowHeavyFilters();
121 if (consoleFactory == null) {
122 printStacktrace(consoleView, text);
128 * Regular "Replace" editor action is unavailable for console editors (see com.intellij.openapi.editor.actions.IncrementalFindAction.Handler#isEnabled).
129 * However, it can be convenient to be able to replace user-specific paths with local paths
130 * if stacktrace links involves absolute paths (e.g. Node.js stack-traces contain absolute paths).
134 private static void registerReplaceAction(@NotNull Project project,
135 @NotNull RunContentDescriptor descriptor,
136 @NotNull ConsoleView consoleView,
137 @NotNull String stacktrace) {
138 AnAction replaceAction = ActionManager.getInstance().getAction("Replace");
139 if (replaceAction == null) {
142 ActionUtil.registerForEveryKeyboardShortcut(consoleView.getComponent(), new ActionListener() {
144 public void actionPerformed(ActionEvent e) {
145 AnalyzeStacktraceDialog dialog = new AnalyzeStacktraceDialog(project) {
147 protected JComponent createCenterPanel() {
148 JComponent result = super.createCenterPanel();
149 myEditorPanel.setText(stacktrace);
150 UiNotifyConnector.doWhenFirstShown(myEditorPanel, new Runnable() {
153 performReplaceAction(project, replaceAction, myEditorPanel);
160 protected void doOKAction() {
162 RunContentManager contentManager = ExecutionManager.getInstance(project).getContentManager();
163 contentManager.removeRunContent(DefaultRunExecutor.getRunExecutorInstance(), descriptor);
168 }, replaceAction.getShortcutSet());
171 private static void performReplaceAction(@NotNull Project project, @NotNull AnAction replaceAction,
172 @NotNull JComponent contextComponent) {
173 IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
176 DataContext context = DataManager.getInstance().getDataContext(contextComponent);
177 AnActionEvent actionEvent = AnActionEvent.createFromAnAction(replaceAction, null, ActionPlaces.UNKNOWN, context);
178 replaceAction.update(actionEvent);
179 if (actionEvent.getPresentation().isEnabledAndVisible()) {
180 ActionUtil.performActionDumbAware(replaceAction, actionEvent);
184 //ApplicationManager.getApplication().invokeLater(new Runnable() {
186 // public void run() {
188 //}, ModalityState.stateForComponent(contextComponent));
191 private static final class MyConsolePanel extends JPanel {
192 public MyConsolePanel(ExecutionConsole consoleView, ActionGroup toolbarActions) {
193 super(new BorderLayout());
194 JPanel toolbarPanel = new JPanel(new BorderLayout());
195 toolbarPanel.add(ActionManager.getInstance()
196 .createActionToolbar(ActionPlaces.ANALYZE_STACKTRACE_PANEL_TOOLBAR, toolbarActions, false)
198 add(toolbarPanel, BorderLayout.WEST);
199 add(consoleView.getComponent(), BorderLayout.CENTER);
203 public static StacktraceEditorPanel createEditorPanel(Project project, @NotNull Disposable parentDisposable) {
204 EditorFactory editorFactory = EditorFactory.getInstance();
205 Document document = editorFactory.createDocument("");
206 Editor editor = editorFactory.createEditor(document, project);
207 EditorSettings settings = editor.getSettings();
208 settings.setFoldingOutlineShown(false);
209 settings.setLineMarkerAreaShown(false);
210 settings.setIndentGuidesShown(false);
211 settings.setLineNumbersShown(false);
212 settings.setRightMarginShown(false);
214 StacktraceEditorPanel editorPanel = new StacktraceEditorPanel(project, editor);
215 editorPanel.setPreferredSize(JBUI.size(600, 400));
216 Disposer.register(parentDisposable, editorPanel);
220 public static final class StacktraceEditorPanel extends JPanel implements DataProvider, Disposable {
221 private final Project myProject;
222 private final Editor myEditor;
224 public StacktraceEditorPanel(Project project, Editor editor) {
225 super(new BorderLayout());
228 add(myEditor.getComponent());
232 public Object getData(String dataId) {
233 if (CommonDataKeys.EDITOR.is(dataId)) {
239 public Editor getEditor() {
243 public final void setText(@NotNull final String text) {
244 Runnable runnable = new Runnable() {
247 ApplicationManager.getApplication().runWriteAction(new Runnable() {
250 final Document document = myEditor.getDocument();
251 document.replaceString(0, document.getTextLength(), StringUtil.convertLineSeparators(text));
256 CommandProcessor.getInstance().executeCommand(myProject, runnable, "", this);
259 public void pasteTextFromClipboard() {
260 String text = getTextInClipboard();
268 public void dispose() {
269 EditorFactory.getInstance().releaseEditor(myEditor);
272 public String getText() {
273 return myEditor.getDocument().getText();
276 public JComponent getEditorComponent() {
277 return myEditor.getContentComponent();