postpone automake if at the process launch moment there are unsaved documents or the IDE is not "idle" (needed for IDEA-141128 and related IDEA-189558)

This commit is contained in:
Eugene Zhuravlev
2018-04-13 17:14:11 +02:00
parent 361cc6ceae
commit 0aa8f6f663
2 changed files with 38 additions and 17 deletions
@@ -528,27 +528,33 @@ public class BuildManager implements Disposable {
if (project == null || !canStartAutoMake(project)) {
return;
}
// todo: check if the system is in the idle state. If yes, run the make, if not, postpone and re-schedule it
final List<TargetTypeBuildScope> scopes = CmdlineProtoUtil.createAllModulesScopes(false);
final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project);
final TaskFuture future = scheduleBuild(
project, false, true, false, scopes, Collections.emptyList(), Collections.emptyMap(),
handler
);
if (future != null) {
myAutomakeFutures.put(future, project);
try {
future.waitFor();
}
finally {
myAutomakeFutures.remove(future);
if (handler.unprocessedFSChangesDetected()) {
scheduleAutoMake();
if (shouldPostponeAutomake()) {
// the system cannot be considered idle. Re-schedule the automake in order not to interfere with the user's activity
scheduleAutoMake();
}
else {
// run automake
final List<TargetTypeBuildScope> scopes = CmdlineProtoUtil.createAllModulesScopes(false);
final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project);
final TaskFuture future = scheduleBuild(
project, false, true, false, scopes, Collections.emptyList(), Collections.emptyMap(),
handler
);
if (future != null) {
myAutomakeFutures.put(future, project);
try {
future.waitFor();
}
finally {
myAutomakeFutures.remove(future);
if (handler.unprocessedFSChangesDetected()) {
scheduleAutoMake();
}
}
}
}
}
private static boolean canStartAutoMake(@NotNull Project project) {
if (project.isDisposed()) {
return false;
@@ -560,6 +566,18 @@ public class BuildManager implements Disposable {
return config.allowAutoMakeWhileRunningApplication() || !hasRunningProcess(project);
}
private static boolean shouldPostponeAutomake() {
// Heuristics for postpone-decision:
// 1. There are unsaved documents OR
// 2. The IDE is not idle: the last activity happened less than 3 seconds ago (registry-configurable)
if (FileDocumentManager.getInstance().getUnsavedDocuments().length > 0) {
return true;
}
final long threshold = (long)Registry.intValue("compiler.automake.postpone.when.idle.less.than", 3000); // todo: UI option instead of registry?
final long idleSinceLastActivity = ApplicationManager.getApplication().getIdleTime();
return idleSinceLastActivity < threshold;
}
@Nullable
private Project getCurrentContextProject() {
return getContextProject(null);
@@ -441,6 +441,9 @@ compiler.process.debug.port.description=Specifies build port at which build proc
compiler.automake.trigger.delay=300
compiler.automake.trigger.delay.description=Delay in milliseconds before triggering auto-make in response to file system events
compiler.automake.postpone.when.idle.less.than=3000
compiler.automake.postpone.when.idle.less.than.description=If at the moment the autobuild is about to start the IDE is idle for less than specified milliseconds, the the automatic build will be postponed in order not to interfere with teh user's activity
compiler.automake.allow.when.app.running=false
compiler.automake.allow.when.app.running.description=Allow auto-make to start even if developed application is currently running. Note that automatically started make may eventually delete some classes that are required by the application.