Merge remote-tracking branch 'origin/master'

This commit is contained in:
anna
2012-07-05 19:30:41 +02:00
6 changed files with 185 additions and 119 deletions
@@ -117,7 +117,7 @@ public class BuildManager implements ApplicationComponent{
ApplicationManager.getApplication().executeOnPooledThread(command);
}
};
private final SequentialTaskExecutor myEventsProcessor = new SequentialTaskExecutor(myPooledThreadExecutor);
private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(myPooledThreadExecutor);
private final Map<String, ProjectData> myProjectDataMap = Collections.synchronizedMap(new HashMap<String, ProjectData>());
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
@@ -187,7 +187,7 @@ public class BuildManager implements ApplicationComponent{
private void doNotify(final Collection<String> paths, final boolean notifyDeletion) {
// ensure events processed in the order they arrived
myEventsProcessor.submit(new Runnable() {
myRequestsProcessor.submit(new Runnable() {
@Override
public void run() {
synchronized (myProjectDataMap) {
@@ -364,7 +364,7 @@ public class BuildManager implements ApplicationComponent{
final Collection<String> modules,
final Collection<String> artifacts,
final Collection<String> paths,
final Map<String, String> userData, DefaultMessageHandler handler) {
final Map<String, String> userData, final DefaultMessageHandler handler) {
final String projectPath = getProjectPath(project);
final UUID sessionId = UUID.randomUUID();
@@ -375,127 +375,153 @@ public class BuildManager implements ApplicationComponent{
myListenPort = startListening();
}
catch (Exception e) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.sessionTerminated();
return null;
}
}
final CmdlineRemoteProto.Message.ControllerMessage params;
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = myGlobals;
if (globals == null) {
globals = buildGlobalSettings();
myGlobals = globals;
}
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges = null;
final SequentialTaskExecutor projectTaskQueue;
synchronized (myProjectDataMap) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data == null) {
data = new ProjectData(new SequentialTaskExecutor(myPooledThreadExecutor));
myProjectDataMap.put(projectPath, data);
}
if (isRebuild) {
data.dropChanges();
}
if (IS_UNIT_TEST_MODE) {
LOG.info("Scheduling build for " + projectPath + "; CHANGED: " + data.myChanged + "; DELETED: " + data.myDeleted);
}
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
projectTaskQueue = data.taskQueue;
}
if (isRebuild) {
params = CmdlineProtoUtil.createRebuildRequest(projectPath, userData, globals);
}
else {
params = isMake ?
CmdlineProtoUtil.createMakeRequest(projectPath, modules, artifacts, userData, globals, currentFSChanges) :
CmdlineProtoUtil.createForceCompileRequest(projectPath, modules, artifacts, paths, userData, globals, currentFSChanges);
}
myMessageDispatcher.registerBuildMessageHandler(sessionId, handler, params);
final RequestFuture<BuilderMessageHandler> future = new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
@Override
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
myMessageDispatcher.cancelSession(future.getRequestID());
}
});
projectTaskQueue.submit(new Runnable() {
@Override
public void run() {
try {
if (project.isDisposed()) {
future.cancel(false);
try {
final RequestFuture<BuilderMessageHandler> future = new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
@Override
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
myMessageDispatcher.cancelSession(future.getRequestID());
}
});
// by using the same queue that processes events we ensure that
// the build will be aware of all events that have happened before this request
myRequestsProcessor.submit(new Runnable() {
@Override
public void run() {
if (future.isCancelled() || project.isDisposed()) {
handler.sessionTerminated();
future.setDone();
return;
}
myBuildsInProgress.put(projectPath, future);
final Process process = launchBuildProcess(project, myListenPort, sessionId);
final OSProcessHandler processHandler = new OSProcessHandler(process, null) {
@Override
protected boolean shouldDestroyProcessRecursively() {
return true;
}
};
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();
}
}
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
// re-translate builder's output to idea.log
final String text = event.getText();
if (!StringUtil.isEmptyOrSpaces(text)) {
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) {
stdErrOutput.append(text);
}
}
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = myGlobals;
if (globals == null) {
globals = buildGlobalSettings();
myGlobals = globals;
}
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges = null;
final SequentialTaskExecutor projectTaskQueue;
synchronized (myProjectDataMap) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data == null) {
data = new ProjectData(new SequentialTaskExecutor(myPooledThreadExecutor));
myProjectDataMap.put(projectPath, data);
}
});
processHandler.startNotify();
final boolean terminated = processHandler.waitFor();
if (terminated) {
final int exitValue = processHandler.getProcess().exitValue();
if (exitValue != 0) {
final StringBuilder msg = new StringBuilder();
msg.append("Abnormal build process termination: ");
if (stdErrOutput.length() > 0) {
msg.append("\n").append(stdErrOutput);
}
else {
msg.append("unknown error");
}
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
if (isRebuild) {
data.dropChanges();
}
if (IS_UNIT_TEST_MODE) {
LOG.info("Scheduling build for " + projectPath + "; CHANGED: " + new HashSet<String>(data.myChanged) + "; DELETED: " + new HashSet<String>(data.myDeleted));
}
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
projectTaskQueue = data.taskQueue;
}
final CmdlineRemoteProto.Message.ControllerMessage params;
if (isRebuild) {
params = CmdlineProtoUtil.createRebuildRequest(projectPath, userData, globals);
}
else {
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
params = isMake ?
CmdlineProtoUtil.createMakeRequest(projectPath, modules, artifacts, userData, globals, currentFSChanges) :
CmdlineProtoUtil.createForceCompileRequest(projectPath, modules, artifacts, paths, userData, globals, currentFSChanges);
}
myMessageDispatcher.registerBuildMessageHandler(sessionId, handler, params);
try {
projectTaskQueue.submit(new Runnable() {
@Override
public void run() {
try {
if (project.isDisposed()) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
handler.sessionTerminated();
return;
}
myBuildsInProgress.put(projectPath, future);
final Process process = launchBuildProcess(project, myListenPort, sessionId);
final OSProcessHandler processHandler = new OSProcessHandler(process, null) {
@Override
protected boolean shouldDestroyProcessRecursively() {
return true;
}
};
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();
}
}
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
// re-translate builder's output to idea.log
final String text = event.getText();
if (!StringUtil.isEmptyOrSpaces(text)) {
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) {
stdErrOutput.append(text);
}
}
}
});
processHandler.startNotify();
final boolean terminated = processHandler.waitFor();
if (terminated) {
final int exitValue = processHandler.getProcess().exitValue();
if (exitValue != 0) {
final StringBuilder msg = new StringBuilder();
msg.append("Abnormal build process termination: ");
if (stdErrOutput.length() > 0) {
msg.append("\n").append(stdErrOutput);
}
else {
msg.append("unknown error");
}
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
}
}
else {
future.getMessageHandler().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();
}
finally {
myBuildsInProgress.remove(projectPath);
future.setDone();
}
}
});
}
catch (Throwable e) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
handler.sessionTerminated();
future.setDone();
}
}
catch (ExecutionException e) {
myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
future.getMessageHandler().handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
future.getMessageHandler().sessionTerminated();
}
finally {
myBuildsInProgress.remove(projectPath);
future.setDone();
}
}
});
});
return future;
return future;
}
catch (Throwable e) {
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.sessionTerminated();
}
return null;
}
@Override
@@ -21,6 +21,9 @@ import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.impl.watch.*;
import com.intellij.debugger.ui.tree.ValueDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.editor.SyntaxHighlighterColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.RowIcon;
@@ -194,16 +197,30 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer {
valueLabel = DebuggerUtilsEx.truncateString(valueLabel);
final SimpleTextAttributes valueLabelAttribs;
if (valueDescriptor.isDirty()) {
valueLabelAttribs = XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES;
}
else {
TextAttributes highlightingAttribs = null;
if (valueDescriptor.isNull()){
highlightingAttribs = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(SyntaxHighlighterColors.KEYWORD);
}
else if (valueDescriptor.isString()) {
highlightingAttribs = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(SyntaxHighlighterColors.STRING);
}
valueLabelAttribs = highlightingAttribs != null? SimpleTextAttributes.fromTextAttributes(highlightingAttribs) : DEFAULT_ATTRIBUTES;
}
final EvaluateException exception = descriptor.getEvaluateException();
if(exception != null) {
final String errorMessage = exception.getMessage();
if(valueLabel.endsWith(errorMessage)) {
appendValueTextWithEscapesRendering(descriptorText, valueLabel.substring(0, valueLabel.length() - errorMessage.length()), DEFAULT_ATTRIBUTES);
appendValueTextWithEscapesRendering(descriptorText, valueLabel.substring(0, valueLabel.length() - errorMessage.length()), valueLabelAttribs);
descriptorText.append(errorMessage, XDebuggerUIConstants.EXCEPTION_ATTRIBUTES);
}
else {
appendValueTextWithEscapesRendering(descriptorText, valueLabel, valueDescriptor.isDirty() ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : DEFAULT_ATTRIBUTES);
appendValueTextWithEscapesRendering(descriptorText, valueLabel, valueLabelAttribs);
descriptorText.append(errorMessage, XDebuggerUIConstants.EXCEPTION_ATTRIBUTES);
}
}
@@ -212,7 +229,7 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer {
descriptorText.append(XDebuggerUIConstants.COLLECTING_DATA_MESSAGE, XDebuggerUIConstants.COLLECTING_DATA_HIGHLIGHT_ATTRIBUTES);
}
else {
appendValueTextWithEscapesRendering(descriptorText, valueLabel, valueDescriptor.isDirty() ? XDebuggerUIConstants.CHANGED_VALUE_ATTRIBUTES : DEFAULT_ATTRIBUTES);
appendValueTextWithEscapesRendering(descriptorText, valueLabel, valueLabelAttribs);
}
}
}
@@ -226,7 +243,7 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer {
}
private static void appendValueTextWithEscapesRendering(SimpleColoredText descriptorText, String valueText, final SimpleTextAttributes attribs) {
final SimpleTextAttributes boldAttribs = attribs.derive(SimpleTextAttributes.STYLE_BOLD, null, Color.lightGray, null);
SimpleTextAttributes escapeAttribs = null;
final StringBuilder buf = new StringBuilder();
boolean slashFound = false;
for (int idx= 0; idx < valueText.length(); idx++) {
@@ -238,10 +255,21 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer {
descriptorText.append(buf.toString(), attribs);
buf.setLength(0);
}
if (ch != '\\' && ch != '\"') {
descriptorText.append("\\", boldAttribs);
if (escapeAttribs == null) { // lazy init
final TextAttributes fromHighlighter = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(SyntaxHighlighterColors.VALID_STRING_ESCAPE);
if (fromHighlighter != null) {
escapeAttribs = SimpleTextAttributes.fromTextAttributes(fromHighlighter);
}
else {
escapeAttribs = DEFAULT_ATTRIBUTES.derive(SimpleTextAttributes.STYLE_BOLD, Color.gray, null, null);
}
}
descriptorText.append(String.valueOf(ch), boldAttribs);
if (ch != '\\' && ch != '\"') {
descriptorText.append("\\", escapeAttribs);
}
descriptorText.append(String.valueOf(ch), escapeAttribs);
}
else {
buf.append('\\').append(ch);
@@ -93,8 +93,13 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
public boolean isNull() {
return myValue == null;
}
public boolean isPrimitive() {
@Override
public boolean isString() {
return myValue instanceof StringReference;
}
public boolean isPrimitive() {
return myValue instanceof PrimitiveValue;
}
@@ -40,6 +40,7 @@ public interface ValueDescriptor extends NodeDescriptor{
boolean isLvalue();
boolean isNull();
boolean isPrimitive();
boolean isString();
@Nullable
ValueMarkup getMarkup(final DebugProcess debugProcess);
@@ -53,6 +53,8 @@ public class BegTableUI extends BasicTableUI {
public void installUI(JComponent c) {
super.installUI(c);
c.getActionMap().put(START_EDITING_ACTION_KEY, new StartEditingAction());
// fix missing escape shortcut
c.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("pressed ESCAPE"), "cancel");
}
protected KeyListener createKeyListener() {
@@ -1,9 +1,13 @@
<idea-plugin version="2">
<name>Plugin name here</name>
<description>short description of the plugin</description>
<version>1.0</version>
<vendor>YourCompany</vendor>
<description><![CDATA[
Enter short description for your plugin here.<br>
<small>most HTML tags may be used</small>
]]></description>
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="107.105"/>