From 0aa8f6f6634440be5d28dcc760408576d71c7a5a Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 13 Apr 2018 17:12:58 +0200 Subject: [PATCH] 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) --- .../compiler/server/BuildManager.java | 52 +++++++++++++------ .../util/resources/misc/registry.properties | 3 ++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index e452f20f1d13..c9805d59c7f1 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -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 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 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); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 3914d3e8bc5a..e90d27634550 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -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.