From 1c3af7fa1a94cca88987f30b3901d0dabbb20389 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Sun, 8 Sep 2024 11:09:29 +0300 Subject: [PATCH 1/4] Fix unused exception naming --- src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt | 4 ++-- src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt b/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt index c59beea3..d25ff7bf 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt @@ -184,9 +184,9 @@ open class Fuzzier : FuzzyAction() { component.fileList.setSelectedValue(listModel[0], true) } } - } catch (e: InterruptedException) { + } catch (_: InterruptedException) { return@executeOnPooledThread - } catch (e: CancellationException) { + } catch (_: CancellationException) { return@executeOnPooledThread } } diff --git a/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt b/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt index 6a6ba630..d9608312 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt @@ -224,9 +224,9 @@ class FuzzyMover : FuzzyAction() { component.fileList.setSelectedValue(listModel[0], true) } } - } catch (e: InterruptedException) { + } catch (_: InterruptedException) { return@executeOnPooledThread - } catch (e: CancellationException) { + } catch (_: CancellationException) { return@executeOnPooledThread } } From f76418ec157ff8748157197bf67f07ba0dc27b98 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Sun, 8 Sep 2024 11:56:53 +0300 Subject: [PATCH 2/4] Use multithreading for Fuzzier(VCS) searches --- src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt | 37 ++++++++++++++++--- .../kotlin/com/mituuz/fuzzier/FuzzyMover.kt | 2 + .../com/mituuz/fuzzier/StringEvaluator.kt | 29 +++++++++++++-- .../com/mituuz/fuzzier/util/FuzzierUtil.kt | 25 ++++++++++++- 4 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt b/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt index d25ff7bf..83793d67 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/Fuzzier.kt @@ -48,8 +48,14 @@ import com.intellij.openapi.wm.WindowManager import com.mituuz.fuzzier.components.FuzzyFinderComponent import com.mituuz.fuzzier.entities.FuzzyMatchContainer import com.mituuz.fuzzier.settings.FuzzierSettingsService.RecentFilesMode.NONE +import com.mituuz.fuzzier.util.FuzzierUtil +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext import org.apache.commons.lang3.StringUtils import java.awt.event.* +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Future import javax.swing.* import kotlin.coroutines.cancellation.CancellationException @@ -223,16 +229,37 @@ open class Fuzzier : FuzzyAction() { private fun processProject(project: Project, stringEvaluator: StringEvaluator, searchString: String, listModel: DefaultListModel, task: Future<*>?) { - val contentIterator = stringEvaluator.getContentIterator(project.name, searchString, listModel, task) - ProjectFileIndex.getInstance(project).iterateContent(contentIterator) + val filesToIterate = ConcurrentHashMap.newKeySet() + FuzzierUtil.fileIndexToIterationFile(filesToIterate, ProjectFileIndex.getInstance(project), project.name, task) + processFiles(filesToIterate, stringEvaluator, listModel, searchString, task) } private fun processModules(moduleManager: ModuleManager, stringEvaluator: StringEvaluator, searchString: String, listModel: DefaultListModel, task: Future<*>?) { + val filesToIterate = ConcurrentHashMap.newKeySet() for (module in moduleManager.modules) { - val moduleFileIndex = module.rootManager.fileIndex - val contentIterator = stringEvaluator.getContentIterator(module.name, searchString, listModel, task) - moduleFileIndex.iterateContent(contentIterator) + FuzzierUtil.fileIndexToIterationFile(filesToIterate, module.rootManager.fileIndex, module.name, task) + } + processFiles(filesToIterate, stringEvaluator, listModel, searchString, task) + } + + /** + * Processes a set of IterationFiles concurrently + */ + private fun processFiles( + filesToIterate: ConcurrentHashMap.KeySetView, + stringEvaluator: StringEvaluator, listModel: DefaultListModel, + searchString: String, task: Future<*>? + ) { + runBlocking { + withContext(Dispatchers.IO) { + filesToIterate.forEach { iterationFile -> + if (task?.isCancelled == true) return@forEach + launch { + stringEvaluator.evaluateFile(iterationFile, listModel, searchString) + } + } + } } } diff --git a/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt b/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt index d9608312..cab988f4 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/FuzzyMover.kt @@ -48,9 +48,11 @@ import com.intellij.psi.PsiManager import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil import com.mituuz.fuzzier.components.SimpleFinderComponent import com.mituuz.fuzzier.entities.FuzzyMatchContainer +import com.mituuz.fuzzier.util.FuzzierUtil import org.apache.commons.lang3.StringUtils import java.awt.event.* import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Future import javax.swing.* import kotlin.coroutines.cancellation.CancellationException diff --git a/src/main/kotlin/com/mituuz/fuzzier/StringEvaluator.kt b/src/main/kotlin/com/mituuz/fuzzier/StringEvaluator.kt index 38683567..26d761fd 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/StringEvaluator.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/StringEvaluator.kt @@ -28,6 +28,7 @@ import com.intellij.openapi.vcs.changes.ChangeListManager import com.intellij.openapi.vfs.VirtualFile import com.mituuz.fuzzier.entities.FuzzyMatchContainer import com.mituuz.fuzzier.entities.ScoreCalculator +import com.mituuz.fuzzier.util.FuzzierUtil import java.util.concurrent.Future import javax.swing.DefaultListModel @@ -58,7 +59,7 @@ class StringEvaluator( return@ContentIterator true } if (filePath.isNotBlank()) { - val fuzzyMatchContainer = createFuzzyContainer(filePath, moduleName) + val fuzzyMatchContainer = createFuzzyContainer(filePath, moduleName, scoreCalculator) if (fuzzyMatchContainer != null) { listModel.addElement(fuzzyMatchContainer) } @@ -82,7 +83,7 @@ class StringEvaluator( return@ContentIterator true } if (filePath.isNotBlank()) { - val fuzzyMatchContainer = createFuzzyContainer(filePath, moduleName) + val fuzzyMatchContainer = createFuzzyContainer(filePath, moduleName, scoreCalculator) if (fuzzyMatchContainer != null) { listModel.addElement(fuzzyMatchContainer) } @@ -91,6 +92,27 @@ class StringEvaluator( true } } + + fun evaluateFile(iterationFile: FuzzierUtil.IterationFile, listModel: DefaultListModel, + searchString: String) { + val scoreCalculator = ScoreCalculator(searchString) + val file = iterationFile.file + val moduleName = iterationFile.module + if (!file.isDirectory) { + val moduleBasePath = modules[moduleName] ?: return + + val filePath = file.path.removePrefix(moduleBasePath) + if (isExcluded(file, filePath)) { + return + } + if (filePath.isNotBlank()) { + val fuzzyMatchContainer = createFuzzyContainer(filePath, moduleName, scoreCalculator) + if (fuzzyMatchContainer != null) { + listModel.addElement(fuzzyMatchContainer) + } + } + } + } private fun getDirPath(virtualFile: VirtualFile, basePath: String, module: String): String { var res = virtualFile.path.removePrefix(basePath) @@ -133,7 +155,8 @@ class StringEvaluator( * @param filePath to evaluate * @return null if no match can be found */ - private fun createFuzzyContainer(filePath: String, module: String): FuzzyMatchContainer? { + private fun createFuzzyContainer(filePath: String, module: String, + scoreCalculator: ScoreCalculator): FuzzyMatchContainer? { val filename = filePath.substring(filePath.lastIndexOf("/") + 1) return when (val score = scoreCalculator.calculateScore(filePath)) { null -> { diff --git a/src/main/kotlin/com/mituuz/fuzzier/util/FuzzierUtil.kt b/src/main/kotlin/com/mituuz/fuzzier/util/FuzzierUtil.kt index 6d2b0354..9896c2dd 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/util/FuzzierUtil.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/util/FuzzierUtil.kt @@ -31,13 +31,34 @@ import com.mituuz.fuzzier.entities.FuzzyMatchContainer import com.mituuz.fuzzier.settings.FuzzierSettingsService import java.util.* import javax.swing.DefaultListModel -import kotlin.collections.ArrayList import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.FileIndex +import com.intellij.openapi.vfs.VirtualFile +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Future class FuzzierUtil { private var settingsState = service().state private var listLimit: Int = settingsState.fileListLimit private var prioritizeShorterDirPaths = settingsState.prioritizeShorterDirPaths + + data class IterationFile(val file: VirtualFile, val module: String) + + companion object { + fun fileIndexToIterationFile(iterationFiles: ConcurrentHashMap.KeySetView, + fileIndex: FileIndex, moduleName: String, task: Future<*>?, + isDir: Boolean = false) { + fileIndex.iterateContent { file -> + if (task?.isCancelled == true) { + return@iterateContent false + } + if (file.isDirectory == isDir) { + iterationFiles.add(IterationFile(file, moduleName)) + } + true + } + } + } /** * Process all the elements in the listModel with a priority queue to limit the size @@ -58,7 +79,7 @@ class FuzzierUtil { var minimumScore: Int? = null listModel.elements().toList().forEach { - if (minimumScore == null || it.getScore() > minimumScore!!) { + if (minimumScore == null || it.getScore() > minimumScore) { priorityQueue.add(it) if (priorityQueue.size > listLimit) { priorityQueue.remove() From 38a18aee664854b70815afcd8bb3d214b670054e Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Sun, 8 Sep 2024 12:12:32 +0300 Subject: [PATCH 3/4] Add change notes --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index fcf87b11..714faf14 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,6 +62,7 @@ intellijPlatform { changeNotes = """

Version $currentVersion

- Improve task cancelling to avoid InterruptedException and reduce cancelling delay
+ - Run searches with concurrency
""".trimIndent() ideaVersion { From d94478df9355c399c4e8f0b988236d4569376ba8 Mon Sep 17 00:00:00 2001 From: Mitja Leino Date: Sun, 8 Sep 2024 12:20:38 +0300 Subject: [PATCH 4/4] Add explicit instructions on how to get the most out of the plugin --- build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 714faf14..abd740c6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,7 +62,9 @@ intellijPlatform { changeNotes = """

Version $currentVersion

- Improve task cancelling to avoid InterruptedException and reduce cancelling delay
- - Run searches with concurrency
+ - Run searches with concurrency

+ To have the most fluid experience it is recommended to NOT use the styled filename type and use a lower + debounce period (10 feels pretty good for me). """.trimIndent() ideaVersion {