mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
1. ensure sessionTerminated is called _after_ all build messages are processed
2. in order not to depend on message processing speed in IDEA, when processing compiler messages, submit them to CompileContext from a separate thread maintaining message order
This commit is contained in:
@@ -86,6 +86,7 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.concurrency.SequentialTaskExecutor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -104,6 +105,7 @@ import org.jetbrains.jps.incremental.Utils;
|
||||
import javax.swing.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
|
||||
@@ -443,22 +445,36 @@ public class CompileDriver {
|
||||
final BuildManager buildManager = BuildManager.getInstance();
|
||||
buildManager.cancelAutoMakeTasks(myProject);
|
||||
return buildManager.scheduleBuild(myProject, compileContext.isRebuild(), compileContext.isMake(), scopes, paths, builderParams, new DefaultMessageHandler(myProject) {
|
||||
private final SequentialTaskExecutor myContextUpdater = new SequentialTaskExecutor(new Executor() {
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(command);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
public void sessionTerminated(final UUID sessionId) {
|
||||
if (compileContext.shouldUpdateProblemsView()) {
|
||||
final ProblemsView view = ProblemsViewImpl.SERVICE.getInstance(myProject);
|
||||
view.clearProgress();
|
||||
view.clearOldMessages(compileContext.getCompileScope(), sessionId);
|
||||
myContextUpdater.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myProject.isDisposed()) {
|
||||
final ProblemsView view = ProblemsViewImpl.SERVICE.getInstance(myProject);
|
||||
view.clearProgress();
|
||||
view.clearOldMessages(compileContext.getCompileScope(), sessionId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
|
||||
compileContext.addMessage(CompilerMessageCategory.ERROR, failure.getDescription(), null, -1, -1);
|
||||
submitMessage(CompilerMessageCategory.ERROR, failure.getDescription(), null, -1, -1);
|
||||
final String trace = failure.getStacktrace();
|
||||
if (trace != null) {
|
||||
LOG.info(trace);
|
||||
@@ -471,9 +487,10 @@ public class CompileDriver {
|
||||
protected void handleCompileMessage(UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.CompileMessage message) {
|
||||
final CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind kind = message.getKind();
|
||||
//System.out.println(compilerMessage.getText());
|
||||
final String messageText = message.getText();
|
||||
if (kind == CmdlineRemoteProto.Message.BuilderMessage.CompileMessage.Kind.PROGRESS) {
|
||||
final ProgressIndicator indicator = compileContext.getProgressIndicator();
|
||||
indicator.setText(message.getText());
|
||||
indicator.setText(messageText);
|
||||
if (message.hasDone()) {
|
||||
indicator.setFraction(message.getDone());
|
||||
}
|
||||
@@ -489,12 +506,19 @@ public class CompileDriver {
|
||||
final long line = message.hasLine() ? message.getLine() : -1;
|
||||
final long column = message.hasColumn() ? message.getColumn() : -1;
|
||||
final String srcUrl = sourceFilePath != null ? VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, sourceFilePath) : null;
|
||||
compileContext.addMessage(
|
||||
category, message.getText(), srcUrl, (int)line, (int)column
|
||||
);
|
||||
submitMessage(category, messageText, srcUrl, (int)line, (int)column);
|
||||
}
|
||||
}
|
||||
|
||||
private void submitMessage(final CompilerMessageCategory category, final String messageText, final String srcUrl, final int line, final int column) {
|
||||
myContextUpdater.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
compileContext.addMessage(category, messageText, srcUrl, line, column);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleBuildEvent(UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.BuildEvent event) {
|
||||
final CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Type eventType = event.getEventType();
|
||||
|
||||
@@ -506,16 +506,25 @@ public class BuildManager implements ApplicationComponent{
|
||||
CmdlineProtoUtil.createForceCompileRequest(projectPath, scopes, paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
|
||||
myMessageDispatcher.registerBuildMessageHandler(sessionId, handler, params);
|
||||
myMessageDispatcher.registerBuildMessageHandler(sessionId, new BuilderMessageHandlerWrapper(handler) {
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
try {
|
||||
super.sessionTerminated(sessionId);
|
||||
}
|
||||
finally {
|
||||
future.setDone();
|
||||
}
|
||||
}
|
||||
}, params);
|
||||
|
||||
try {
|
||||
projectTaskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ExecutionException execFailure = null;
|
||||
try {
|
||||
if (project.isDisposed()) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
handler.sessionTerminated(sessionId);
|
||||
return;
|
||||
}
|
||||
myBuildsInProgress.put(projectPath, future);
|
||||
@@ -528,14 +537,6 @@ public class BuildManager implements ApplicationComponent{
|
||||
};
|
||||
final StringBuilder stdErrOutput = new StringBuilder();
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
final BuilderMessageHandler handler = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (handler != null) {
|
||||
handler.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
// re-translate builder's output to idea.log
|
||||
@@ -561,30 +562,39 @@ public class BuildManager implements ApplicationComponent{
|
||||
else {
|
||||
msg.append("unknown error");
|
||||
}
|
||||
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
}
|
||||
}
|
||||
else {
|
||||
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
}
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
handler.sessionTerminated(sessionId);
|
||||
execFailure = e;
|
||||
}
|
||||
finally {
|
||||
myBuildsInProgress.remove(projectPath);
|
||||
future.setDone();
|
||||
if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) {
|
||||
// either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process.
|
||||
// in this case the session cannot be unregistered by the message dispatcher
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
if (execFailure != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure));
|
||||
}
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
handler.sessionTerminated(sessionId);
|
||||
future.setDone();
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -905,6 +915,34 @@ public class BuildManager implements ApplicationComponent{
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static class BuilderMessageHandlerWrapper implements BuilderMessageHandler {
|
||||
private final DefaultMessageHandler myHandler;
|
||||
|
||||
public BuilderMessageHandlerWrapper(DefaultMessageHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
myHandler.buildStarted(sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
|
||||
myHandler.handleBuildMessage(channel, sessionId, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
|
||||
myHandler.handleFailure(sessionId, failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
myHandler.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
private class ProjectWatcher extends ProjectManagerAdapter {
|
||||
private final Map<Project, MessageBusConnection> myConnections = new HashMap<Project, MessageBusConnection>();
|
||||
|
||||
|
||||
@@ -61,14 +61,14 @@ class BuildMessageDispatcher extends SimpleChannelHandler {
|
||||
|
||||
@Nullable
|
||||
public Channel getConnectedChannel(final UUID sessionId) {
|
||||
final Channel channel = getAssociatedChannel(sessionId);
|
||||
return channel != null && channel.isConnected()? channel : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Channel getAssociatedChannel(final UUID sessionId) {
|
||||
final SessionData data = myMessageHandlers.get(sessionId);
|
||||
if (data != null) {
|
||||
final Channel channel = data.channel;
|
||||
if (channel != null && channel.isConnected()) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return data != null? data.channel : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user