From 5817a7fdacb82ad4e4ebf37e305232ffe98f7dba Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 19 Apr 2018 17:49:29 +0300 Subject: [PATCH] Prevent endless processing of problem pending events If some pending event processing caused exception in PerModulePackageCacheService, log the problem and consider event processed. Otherwise it is going to be stuck there forever. --- .../caches/PerModulePackageCacheService.kt | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt index 1a3568ef6a1..b58e799f28f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt @@ -11,11 +11,13 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.fileTypes.FileTypeRegistry import com.intellij.openapi.module.Module +import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.project.Project import com.intellij.openapi.project.rootManager import com.intellij.openapi.roots.ModuleRootEvent import com.intellij.openapi.roots.ModuleRootListener import com.intellij.openapi.util.Disposer +import com.intellij.openapi.vfs.InvalidVirtualFileAccessException import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager @@ -237,9 +239,8 @@ class PerModulePackageCacheService(private val project: Project) { if (pendingVFileChanges.size + pendingKtFileChanges.size >= FULL_DROP_THRESHOLD) { onTooComplexChange() } else { - - pendingVFileChanges.forEach { event -> - val vfile = event.file ?: return@forEach + pendingVFileChanges.processPending { event -> + val vfile = event.file ?: return@processPending // When VirtualFile !isValid (deleted for example), it impossible to use getModuleInfoByVirtualFile // For directory we must check both is it in some sourceRoot, and is it contains some sourceRoot if (vfile.isDirectory || !vfile.isValid) { @@ -256,18 +257,32 @@ class PerModulePackageCacheService(private val project: Project) { invalidateCacheForModuleSourceInfo(it) } } + implicitPackagePrefixCache.update(event) } - pendingVFileChanges.clear() - pendingKtFileChanges.forEach { file -> + pendingKtFileChanges.processPending { file -> if (file.virtualFile != null && file.virtualFile !in projectScope) { - return@forEach + return@processPending } (file.getNullableModuleInfo() as? ModuleSourceInfo)?.let { invalidateCacheForModuleSourceInfo(it) } implicitPackagePrefixCache.update(file) } - pendingKtFileChanges.clear() + } + } + + private inline fun MutableCollection.processPending(crossinline body: (T) -> Unit) { + this.removeIf { value -> + try { + body(value) + } catch (pce: ProcessCanceledException) { + throw pce + } catch (exc: Exception) { + // Log and proceed. Otherwise pending object processing won't be cleared and exception will be thrown forever. + LOG.error(exc) + } + + return@removeIf true } }