Keep compile messages after compilation;

ability to activate and show compilation messages by clicking on a hyperlink in EventLog (IDEA-69971)
This commit is contained in:
Eugene Zhuravlev
2014-08-27 15:36:09 +04:00
parent 574238282d
commit f7f9fe285e
3 changed files with 113 additions and 54 deletions
@@ -55,7 +55,7 @@ import java.util.*;
public class CompileContextImpl extends UserDataHolderBase implements CompileContextEx {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompileContextImpl");
private final Project myProject;
private final CompilerTask myTask;
private final CompilerTask myBuildSession;
private final Map<CompilerMessageCategory, Collection<CompilerMessage>> myMessages = new EnumMap<CompilerMessageCategory, Collection<CompilerMessage>>(CompilerMessageCategory.class);
private final boolean myShouldUpdateProblemsView;
private CompileScope myCompileScope;
@@ -77,7 +77,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
CompileScope compileScope,
boolean isMake, boolean isRebuild) {
myProject = project;
myTask = compilerSession;
myBuildSession = compilerSession;
myCompileScope = compileScope;
myMake = isMake;
myIsRebuild = isRebuild;
@@ -99,6 +99,10 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
myShouldUpdateProblemsView = workspaceConfig.MAKE_PROJECT_ON_SAVE;
}
public CompilerTask getBuildSession() {
return myBuildSession;
}
public boolean shouldUpdateProblemsView() {
return myShouldUpdateProblemsView;
}
@@ -154,7 +158,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
myMessages.put(msg.getCategory(), messages);
}
if (messages.add(msg)) {
myTask.addMessage(msg);
myBuildSession.addMessage(msg);
}
if (myShouldUpdateProblemsView && msg.getCategory() == CompilerMessageCategory.ERROR) {
ProblemsView.SERVICE.getInstance(myProject).addMessage(msg, mySessionId);
@@ -200,7 +204,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
}
public ProgressIndicator getProgressIndicator() {
return myTask.getIndicator();
return myBuildSession.getIndicator();
}
public Module getModuleByFile(VirtualFile file) {
@@ -29,6 +29,8 @@ import com.intellij.compiler.ProblemsView;
import com.intellij.compiler.progress.CompilerTask;
import com.intellij.compiler.server.BuildManager;
import com.intellij.compiler.server.DefaultMessageHandler;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompilerPathsEx;
@@ -53,10 +55,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.*;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.impl.compiler.ArtifactCompilerUtil;
import com.intellij.packaging.impl.compiler.ArtifactsCompiler;
@@ -68,6 +67,7 @@ import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.text.DateFormatUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -79,7 +79,9 @@ import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -502,9 +504,24 @@ public class CompileDriver {
if (duration > ONE_MINUTE_MS && CompilerWorkspaceConfiguration.getInstance(myProject).DISPLAY_NOTIFICATION_POPUP) {
ToolWindowManager.getInstance(myProject).notifyByBalloon(ToolWindowId.MESSAGES_WINDOW, messageType, statusMessage);
}
CompilerManager.NOTIFICATION_GROUP.createNotification(statusMessage, messageType).notify(myProject);
final String wrappedMessage = _status != ExitStatus.UP_TO_DATE? "<a href='#'>" + statusMessage + "</a>" : statusMessage;
final Notification notification = CompilerManager.NOTIFICATION_GROUP.createNotification(
"", wrappedMessage,
messageType.toNotificationType(),
new MessagesActivationListener(compileContext)
);
compileContext.getBuildSession().registerCloseAction(new Runnable() {
@Override
public void run() {
notification.expire();
}
});
notification.notify(myProject);
if (_status != ExitStatus.UP_TO_DATE && compileContext.getMessageCount(null) > 0) {
compileContext.addMessage(CompilerMessageCategory.INFORMATION, statusMessage, null, -1, -1);
final String msg = DateFormatUtil.formatDateTime(new Date()) + " - " + statusMessage;
compileContext.addMessage(CompilerMessageCategory.INFORMATION, msg, null, -1, -1);
}
}
}
@@ -785,4 +802,28 @@ public class CompileDriver {
private void showConfigurationDialog(String moduleNameToSelect, String tabNameToSelect) {
ProjectSettingsService.getInstance(myProject).showModuleConfigurationDialog(moduleNameToSelect, tabNameToSelect);
}
private static class MessagesActivationListener extends NotificationListener.Adapter {
private final WeakReference<Project> myProjectRef;
private final Object myContentId;
public MessagesActivationListener(CompileContextImpl compileContext) {
myProjectRef = new WeakReference<Project>(compileContext.getProject());
myContentId = compileContext.getBuildSession().getContentId();
}
@Override
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
final Project project = myProjectRef.get();
if (project != null && !project.isDisposed() && CompilerTask.showCompilerContent(project, myContentId)) {
final ToolWindow tw = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.MESSAGES_WINDOW);
if (tw != null) {
tw.activate(null, false);
}
}
else {
notification.expire();
}
}
}
}
@@ -22,12 +22,11 @@
package com.intellij.compiler.progress;
import com.intellij.compiler.CompilerManagerImpl;
import com.intellij.compiler.CompilerMessageImpl;
import com.intellij.compiler.impl.CompilerErrorTreeView;
import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
import com.intellij.ide.errorTreeView.impl.ErrorTreeViewConfiguration;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.compiler.*;
@@ -42,6 +41,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
@@ -120,6 +120,26 @@ public class CompilerTask extends Task.Backgroundable {
mySessionId = sessionId;
}
@NotNull
public Object getContentId() {
return myContentId;
}
public void registerCloseAction(final Runnable onClose) {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
Disposer.register(myErrorTreeView, new Disposable() {
@Override
public void dispose() {
onClose.run();
}
});
return;
}
}
onClose.run();
}
@Override
public String getProcessId() {
return "compilation";
@@ -221,13 +241,15 @@ public class CompilerTask extends Task.Backgroundable {
private void addIndicatorDelegate() {
ProgressIndicator indicator = myIndicator;
if (!(indicator instanceof ProgressIndicatorEx)) return;
if (!(indicator instanceof ProgressIndicatorEx)) {
return;
}
((ProgressIndicatorEx)indicator).addStateDelegate(new ProgressIndicatorBase() {
@Override
public void cancel() {
super.cancel();
closeUI();
selectFirstMessage();
stopAppIconProgress();
}
@@ -235,11 +257,26 @@ public class CompilerTask extends Task.Backgroundable {
public void stop() {
super.stop();
if (!isCanceled()) {
closeUI();
selectFirstMessage();
}
stopAppIconProgress();
}
private void selectFirstMessage() {
if (!isHeadlessMode()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
myErrorTreeView.selectFirstMessage();
}
}
}
});
}
}
private void stopAppIconProgress() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -249,7 +286,8 @@ public class CompilerTask extends Task.Backgroundable {
if (myErrorCount > 0) {
appIcon.setErrorBadge(myProject, String.valueOf(myErrorCount));
appIcon.requestAttention(myProject, true);
} else if (!myCompilationStartedAutomatically) {
}
else if (!myCompilationStartedAutomatically) {
appIcon.setOkBadge(myProject, true);
appIcon.requestAttention(myProject, false);
}
@@ -450,18 +488,22 @@ public class CompilerTask extends Task.Backgroundable {
public void showCompilerContent() {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
final MessageView messageView = MessageView.SERVICE.getInstance(myProject);
Content[] contents = messageView.getContentManager().getContents();
for (Content content : contents) {
if (CONTENT_ID_KEY.get(content) == myContentId) {
messageView.getContentManager().setSelectedContent(content);
return;
}
}
showCompilerContent(myProject, myContentId);
}
}
}
public static boolean showCompilerContent(final Project project, final Object contentId) {
final MessageView messageView = MessageView.SERVICE.getInstance(project);
for (Content content : messageView.getContentManager().getContents()) {
if (CONTENT_ID_KEY.get(content) == contentId) {
messageView.getContentManager().setSelectedContent(content);
return true;
}
}
return false;
}
private void removeAllContents(Project project, Content notRemove) {
if (project.isDisposed()) {
return;
@@ -488,7 +530,7 @@ public class CompilerTask extends Task.Backgroundable {
private void activateMessageView() {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
if (myErrorTreeView != null && myProject != null) {
final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.MESSAGES_WINDOW);
if (tw != null) {
tw.activate(null, false);
@@ -497,34 +539,6 @@ public class CompilerTask extends Task.Backgroundable {
}
}
private void closeUI() {
if (isHeadlessMode()) {
return;
}
Window window = getWindow();
ModalityState modalityState = window != null ? ModalityState.stateForComponent(window) : ModalityState.NON_MODAL;
final Application application = ApplicationManager.getApplication();
application.invokeLater(new Runnable() {
@Override
public void run() {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
final boolean shouldRetainView = myErrorCount > 0 || myWarningCount > 0 && !myErrorTreeView.isHideWarnings();
if (shouldRetainView) {
addMessage(new CompilerMessageImpl(myProject, CompilerMessageCategory.STATISTICS, CompilerBundle.message("statistics.error.count", myErrorCount)));
addMessage(new CompilerMessageImpl(myProject, CompilerMessageCategory.STATISTICS, CompilerBundle.message("statistics.warnings.count", myWarningCount)));
//activateMessageView();
myErrorTreeView.selectFirstMessage();
}
else {
removeAllContents(myProject, null);
}
}
}
}
}, modalityState);
}
public Window getWindow(){
return null;
}
@@ -607,7 +621,7 @@ public class CompilerTask extends Task.Backgroundable {
if (event.getContent() == myContent) {
synchronized (myMessageViewLock) {
if (myErrorTreeView != null) {
myErrorTreeView.dispose();
Disposer.dispose(myErrorTreeView);
myErrorTreeView = null;
if (myIndicator.isRunning()) {
cancel();