mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
auto test manager: rerun on process termination if changes were made during test run
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.execution;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.AppTopics;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
@@ -55,7 +54,7 @@ public class DelayedDocumentWatcher {
|
||||
private final Project myProject;
|
||||
private final Alarm myAlarm;
|
||||
private final int myDelayMillis;
|
||||
private final Consumer<Set<VirtualFile>> myConsumer;
|
||||
private final Consumer<Integer> myModificationStampConsumer;
|
||||
private final Condition<VirtualFile> myChangedFileFilter;
|
||||
private final MyDocumentAdapter myListener;
|
||||
private final Runnable myAlarmRunnable;
|
||||
@@ -63,16 +62,16 @@ public class DelayedDocumentWatcher {
|
||||
private final Set<VirtualFile> myChangedFiles = new THashSet<VirtualFile>();
|
||||
private boolean myDocumentSavingInProgress = false;
|
||||
private MessageBusConnection myConnection;
|
||||
private int myEventCount = 0;
|
||||
private int myModificationStamp = 0;
|
||||
|
||||
public DelayedDocumentWatcher(@NotNull Project project,
|
||||
int delayMillis,
|
||||
@NotNull Consumer<Set<VirtualFile>> consumer,
|
||||
@NotNull Consumer<Integer> modificationStampConsumer,
|
||||
@Nullable Condition<VirtualFile> changedFileFilter) {
|
||||
myProject = project;
|
||||
myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myProject);
|
||||
myDelayMillis = delayMillis;
|
||||
myConsumer = consumer;
|
||||
myModificationStampConsumer = modificationStampConsumer;
|
||||
myChangedFileFilter = changedFileFilter;
|
||||
myListener = new MyDocumentAdapter();
|
||||
myAlarmRunnable = new MyRunnable();
|
||||
@@ -110,6 +109,10 @@ public class DelayedDocumentWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUpToDate(int modificationStamp) {
|
||||
return myModificationStamp == modificationStamp;
|
||||
}
|
||||
|
||||
private class MyDocumentAdapter extends DocumentAdapter {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent event) {
|
||||
@@ -136,19 +139,18 @@ public class DelayedDocumentWatcher {
|
||||
|
||||
myAlarm.cancelRequest(myAlarmRunnable);
|
||||
myAlarm.addRequest(myAlarmRunnable, myDelayMillis);
|
||||
myEventCount++;
|
||||
myModificationStamp++;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
final int oldEventCount = myEventCount;
|
||||
final Set<VirtualFile> copy = ImmutableSet.copyOf(myChangedFiles);
|
||||
asyncCheckErrors(copy, new Consumer<Boolean>() {
|
||||
final int oldModificationStamp = myModificationStamp;
|
||||
asyncCheckErrors(myChangedFiles, new Consumer<Boolean>() {
|
||||
@Override
|
||||
public void consume(Boolean errorsFound) {
|
||||
if (myEventCount != oldEventCount) {
|
||||
if (myModificationStamp != oldModificationStamp) {
|
||||
// 'documentChanged' event was raised during async checking files for errors
|
||||
// Do nothing in that case, this method will be invoked subsequently.
|
||||
return;
|
||||
@@ -159,7 +161,7 @@ public class DelayedDocumentWatcher {
|
||||
return;
|
||||
}
|
||||
myChangedFiles.clear();
|
||||
myConsumer.consume(copy);
|
||||
myModificationStampConsumer.consume(myModificationStamp);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -218,5 +220,4 @@ public class DelayedDocumentWatcher {
|
||||
}
|
||||
return WolfTheProblemSolver.getInstance(myProject).hasSyntaxErrors(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+61
-10
@@ -16,13 +16,18 @@
|
||||
package com.intellij.execution.testframework.autotest;
|
||||
|
||||
import com.intellij.execution.DelayedDocumentWatcher;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessListener;
|
||||
import com.intellij.execution.runners.ExecutionUtil;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -32,6 +37,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.WeakHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
@@ -43,6 +50,7 @@ import java.util.Set;
|
||||
public class AutoTestManager {
|
||||
static final Key<Boolean> AUTOTESTABLE = Key.create("auto.test.manager.supported");
|
||||
public static final String AUTO_TEST_MANAGER_DELAY = "auto.test.manager.delay";
|
||||
private static final Key<ProcessListener> ON_TERMINATION_RESTARTER_KEY = Key.create("auto.test.manager.on.termination.restarter");
|
||||
|
||||
private final Project myProject;
|
||||
|
||||
@@ -63,11 +71,11 @@ public class AutoTestManager {
|
||||
}
|
||||
|
||||
private DelayedDocumentWatcher createWatcher() {
|
||||
return new DelayedDocumentWatcher(myProject, myDelay, new Consumer<Set<VirtualFile>>() {
|
||||
return new DelayedDocumentWatcher(myProject, myDelay, new Consumer<Integer>() {
|
||||
@Override
|
||||
public void consume(Set<VirtualFile> files) {
|
||||
public void consume(Integer modificationStamp) {
|
||||
for (Content content : myEnabledDescriptors) {
|
||||
runAutoTest(content);
|
||||
runAutoTest(content, modificationStamp, myDocumentWatcher);
|
||||
}
|
||||
}
|
||||
}, new Condition<VirtualFile>() {
|
||||
@@ -79,13 +87,14 @@ public class AutoTestManager {
|
||||
});
|
||||
}
|
||||
|
||||
public void setAutoTestEnabled(RunContentDescriptor descriptor, boolean enabled) {
|
||||
public void setAutoTestEnabled(@NotNull RunContentDescriptor descriptor, boolean enabled) {
|
||||
Content content = descriptor.getAttachedContent();
|
||||
if (enabled) {
|
||||
myEnabledDescriptors.add(content);
|
||||
myDocumentWatcher.activate();
|
||||
}
|
||||
else {
|
||||
clearRestarterListener(descriptor.getProcessHandler());
|
||||
myEnabledDescriptors.remove(content);
|
||||
if (myEnabledDescriptors.isEmpty()) {
|
||||
myDocumentWatcher.deactivate();
|
||||
@@ -93,11 +102,21 @@ public class AutoTestManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearRestarterListener(@Nullable ProcessHandler processHandler) {
|
||||
if (processHandler != null) {
|
||||
ProcessListener restarterListener = ON_TERMINATION_RESTARTER_KEY.get(processHandler, null);
|
||||
if (restarterListener != null) {
|
||||
processHandler.removeProcessListener(restarterListener);
|
||||
ON_TERMINATION_RESTARTER_KEY.set(processHandler, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAutoTestEnabled(RunContentDescriptor descriptor) {
|
||||
return myEnabledDescriptors.contains(descriptor.getAttachedContent());
|
||||
}
|
||||
|
||||
private static void runAutoTest(Content content) {
|
||||
private static void runAutoTest(@NotNull Content content, int modificationStamp, @NotNull DelayedDocumentWatcher documentWatcher) {
|
||||
JComponent component = content.getComponent();
|
||||
if (component != null) {
|
||||
DataContext dataContext = DataManager.getInstance().getDataContext(component);
|
||||
@@ -105,16 +124,48 @@ public class AutoTestManager {
|
||||
if (descriptor != null) {
|
||||
ProcessHandler processHandler = descriptor.getProcessHandler();
|
||||
if (processHandler != null && !processHandler.isProcessTerminated()) {
|
||||
return;
|
||||
scheduleRestartOnTermination(descriptor, content, processHandler, modificationStamp, documentWatcher);
|
||||
}
|
||||
else {
|
||||
restart(descriptor, content);
|
||||
}
|
||||
|
||||
descriptor.setActivateToolWindowWhenAdded(false);
|
||||
descriptor.setReuseToolWindowActivation(true);
|
||||
ExecutionUtil.restart(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleRestartOnTermination(@NotNull final RunContentDescriptor descriptor,
|
||||
@NotNull final Content content,
|
||||
@NotNull final ProcessHandler processHandler,
|
||||
final int modificationStamp,
|
||||
@NotNull final DelayedDocumentWatcher documentWatcher) {
|
||||
ProcessListener restarterListener = ON_TERMINATION_RESTARTER_KEY.get(processHandler);
|
||||
if (restarterListener != null) {
|
||||
return;
|
||||
}
|
||||
restarterListener = new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
clearRestarterListener(processHandler);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (documentWatcher.isUpToDate(modificationStamp)) {
|
||||
restart(descriptor, content);
|
||||
}
|
||||
}
|
||||
}, ModalityState.any());
|
||||
}
|
||||
};
|
||||
ON_TERMINATION_RESTARTER_KEY.set(processHandler, restarterListener);
|
||||
processHandler.addProcessListener(restarterListener);
|
||||
}
|
||||
|
||||
private static void restart(@NotNull RunContentDescriptor descriptor, @NotNull Content content) {
|
||||
descriptor.setActivateToolWindowWhenAdded(false);
|
||||
descriptor.setReuseToolWindowActivation(true);
|
||||
ExecutionUtil.restart(content);
|
||||
}
|
||||
|
||||
int getDelay() {
|
||||
return myDelay;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user