[auto-reload] smoothed auto-reload

long delay before refresh
show auto-reload notification only for disabled part
don't auto-reload changes during project reload

GitOrigin-RevId: 5b75b0ddc2f0086bba43c3663f03100d20516eb5
This commit is contained in:
Sergei Vorobyov
2020-05-01 19:08:11 +03:00
committed by intellij-monorepo-bot
parent 2604c5a552
commit 840b326d48
4 changed files with 22 additions and 27 deletions

View File

@@ -43,7 +43,8 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
private val debugThrowable = Throwable("Initialized with project=(${project.isDisposed}, ${Disposer.isDisposed(project)}, $project)")
private val LOG = Logger.getInstance("#com.intellij.openapi.externalSystem.autoimport")
private val AUTO_REPARSE_DELAY get() = DaemonCodeAnalyzerSettings.getInstance().autoReparseDelay
private val AUTO_REPARSE_DELAY = DaemonCodeAnalyzerSettings.getInstance().autoReparseDelay
private val AUTO_RELOAD_DELAY = 2000
private val settings get() = ProjectTrackerSettings.getInstance(project)
private val projectStates = ConcurrentHashMap<State.Id, State.Project>()
@@ -53,6 +54,7 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
private val projectChangeOperation = AnonymousParallelOperationTrace(debugName = "Project change operation")
private val projectRefreshOperation = CompoundParallelOperationTrace<String>(debugName = "Project refresh operation")
private val dispatcher = MergingUpdateQueue("AutoImportProjectTracker.dispatcher", AUTO_REPARSE_DELAY, false, null, project)
private val delayDispatcher = MergingUpdateQueue("AutoImportProjectTracker.delayDispatcher", AUTO_RELOAD_DELAY, false, null, project)
private val backgroundExecutor = AppExecutorUtil.createBoundedApplicationPoolExecutor("AutoImportProjectTracker.backgroundExecutor", 1)
override var isAutoReloadExternalChanges by PropertyView(
@@ -91,7 +93,7 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
override fun scheduleProjectRefresh() {
LOG.debug("Schedule project refresh")
dispatcher.queue(PriorityEatUpdate(0) {
refreshProject(doImportDeactivatedProjects = true)
refreshProject(smart = false)
})
}
@@ -109,30 +111,35 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
})
}
private fun delay(action: () -> Unit) {
delayDispatcher.queue(Update.create(this, action))
}
private fun processChanges() {
when (settings.autoReloadType) {
AutoReloadType.ALL -> when (getModificationType()) {
INTERNAL -> refreshProject(doImportDeactivatedProjects = false)
EXTERNAL -> refreshProject(doImportDeactivatedProjects = false)
INTERNAL -> delay { refreshProject(smart = true) }
EXTERNAL -> delay { refreshProject(smart = true) }
null -> updateProjectNotification()
}
AutoReloadType.SELECTIVE -> when (getModificationType()) {
INTERNAL -> updateProjectNotification()
EXTERNAL -> refreshProject(doImportDeactivatedProjects = false)
EXTERNAL -> delay { refreshProject(smart = true) }
null -> updateProjectNotification()
}
AutoReloadType.NONE -> updateProjectNotification()
}
}
private fun refreshProject(doImportDeactivatedProjects: Boolean) {
private fun refreshProject(smart: Boolean) {
LOG.debug("Incremental project refresh")
if (isDisabled.get() || Registry.`is`("external.system.auto.import.disabled")) return
if (!projectChangeOperation.isOperationCompleted()) return
if (smart && !projectRefreshOperation.isOperationCompleted()) return
var isSkippedProjectRefresh = true
for (projectData in projectDataMap.values) {
val projectId = projectData.projectAware.projectId.readableName
val isAllowAutoReload = doImportDeactivatedProjects || projectData.isActivated
val isAllowAutoReload = !smart || projectData.isActivated
if (isAllowAutoReload && !projectData.isUpToDate()) {
isSkippedProjectRefresh = false
LOG.debug("$projectId: Project refresh")
@@ -264,8 +271,12 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
LOG.debug("Project tracker initialization")
val connections = ApplicationManager.getApplication().messageBus.connect(project)
connections.subscribe(BatchFileChangeListener.TOPIC, createProjectChangesListener())
dispatcher.setRestartTimerOnAdd(true)
dispatcher.isPassThrough = !isAsyncChangesProcessing
dispatcher.activate()
delayDispatcher.setRestartTimerOnAdd(true)
delayDispatcher.isPassThrough = !isAsyncChangesProcessing
delayDispatcher.activate()
}
@TestOnly
@@ -296,6 +307,7 @@ class AutoImportProjectTracker(private val project: Project) : ExternalSystemPro
projectChangeOperation.afterOperation { LOG.debug("Project change finished") }
settings.autoReloadTypeProperty.afterChange { scheduleChangeProcessing() }
asyncChangesProcessingProperty.afterChange { dispatcher.isPassThrough = !it }
asyncChangesProcessingProperty.afterChange { delayDispatcher.isPassThrough = !it }
}
private fun ProjectData.getState() = State.Project(status.isDirty(), settingsTracker.getState())

View File

@@ -215,12 +215,7 @@ class ProjectSettingsTracker(
if (!hasChanges(newSettingsFilesCRC)) {
status.markReverted(currentTime())
}
if (applyChangesOperation.isOperationCompleted()) {
projectTracker.scheduleChangeProcessing()
}
else {
projectTracker.scheduleProjectNotificationUpdate()
}
projectTracker.scheduleChangeProcessing()
}
}
}

View File

@@ -44,7 +44,8 @@ class ProjectAware(
}
override fun refreshProject() {
ExternalSystemUtil.refreshProject(projectPath, ImportSpecBuilder(project, systemId).build())
val importSpec = ImportSpecBuilder(project, systemId).dontReportRefreshErrors()
ExternalSystemUtil.refreshProject(projectPath, importSpec)
}
private inner class TaskNotificationListener(

View File

@@ -63,7 +63,6 @@ public class MavenProjectsManagerWatcher {
MessageBusConnection busConnection = myProject.getMessageBus().connect(myDisposable);
busConnection.subscribe(ProjectTopics.MODULES, new MavenIgnoredModulesWatcher());
busConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyRootChangesListener());
myManager.addManagerListener(new MavenProjectWatcher());
registerGeneralSettingsWatcher(myManager, this, myBackgroundExecutor, myDisposable);
myProjectTracker.register(myProjectsAware);
myProjectTracker.activate(myProjectsAware.getProjectId());
@@ -202,16 +201,4 @@ public class MavenProjectsManagerWatcher {
if (mavenProject != null) myManager.setIgnoredState(Collections.singletonList(mavenProject), false);
}
}
private class MavenProjectWatcher implements MavenProjectsManager.Listener {
@Override
public void projectsScheduled() {
scheduleReloadNotificationUpdate();
}
@Override
public void importAndResolveScheduled() {
scheduleReloadNotificationUpdate();
}
}
}