diff --git a/src/main/kotlin/com/mituuz/fuzzier/grep/FuzzyGrep.kt b/src/main/kotlin/com/mituuz/fuzzier/grep/FuzzyGrep.kt index 18482174..78b87a30 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/grep/FuzzyGrep.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/grep/FuzzyGrep.kt @@ -81,9 +81,7 @@ open class FuzzyGrep : FuzzyAction() { val projectBasePath = project.basePath.toString() currentLaunchJob = actionScope?.launch(Dispatchers.EDT) { - val backendResult: Result = withContext(Dispatchers.IO) { - backendResolver.resolveBackend(commandRunner, projectBasePath) - } + val backendResult: Result = backendResolver.resolveBackend(commandRunner, projectBasePath) if (backendResult.isFailure) { showNotification( "No search command found", "Fuzzy Grep failed: no suitable grep command found", project @@ -92,7 +90,7 @@ open class FuzzyGrep : FuzzyAction() { } val resolvedBackend = backendResult.getOrNull() ?: return@launch - updateBackend(resolvedBackend) + backend = resolvedBackend val popupTitle = grepConfig.getPopupTitle(resolvedBackend.name) yield() @@ -149,7 +147,8 @@ open class FuzzyGrep : FuzzyAction() { searchString, project, changelistManager, - backend + backend, + (component as FuzzyFinderComponent), ) coroutineContext.ensureActive() @@ -170,13 +169,14 @@ open class FuzzyGrep : FuzzyAction() { searchString: String, project: Project, clm: ChangeListManager, - resolvedBackend: BackendStrategy? + resolvedBackend: BackendStrategy?, + fuzzyFinderComponent: FuzzyFinderComponent, ): ListModel { val listModel = DefaultListModel() val projectBasePath = project.basePath if (resolvedBackend != null && projectBasePath != null) { - val secondaryFieldText = (component as FuzzyFinderComponent).getSecondaryText() + val secondaryFieldText = fuzzyFinderComponent.getSecondaryText() resolvedBackend.handleSearch( grepConfig, searchString, secondaryFieldText, commandRunner, listModel, projectBasePath, project ) { vf -> @@ -240,10 +240,6 @@ open class FuzzyGrep : FuzzyAction() { } } - fun updateBackend(resolvedBackend: BackendStrategy?) { - backend = resolvedBackend - } - fun updateGrepConfig(config: GrepConfig) { grepConfig = config } diff --git a/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendResolver.kt b/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendResolver.kt index bef5938e..415921d3 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendResolver.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendResolver.kt @@ -29,19 +29,22 @@ import com.intellij.openapi.components.service import com.mituuz.fuzzier.runner.CommandRunner import com.mituuz.fuzzier.settings.FuzzierGlobalSettingsService import com.mituuz.fuzzier.settings.FuzzierGlobalSettingsService.GrepBackend +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext class BackendResolver(val isWindows: Boolean) { - suspend fun resolveBackend(commandRunner: CommandRunner, projectBasePath: String): Result { - val grepBackendSetting = service().state.grepBackend + suspend fun resolveBackend(commandRunner: CommandRunner, projectBasePath: String): Result = + withContext(Dispatchers.IO) { + val grepBackendSetting = service().state.grepBackend - return when (grepBackendSetting) { - GrepBackend.FUZZIER -> Result.success(FuzzierGrep) - GrepBackend.DYNAMIC -> when { - isInstalled(commandRunner, "rg", projectBasePath) -> Result.success(Ripgrep) - else -> Result.success(FuzzierGrep) + when (grepBackendSetting) { + GrepBackend.FUZZIER -> Result.success(FuzzierGrep) + GrepBackend.DYNAMIC -> when { + isInstalled(commandRunner, "rg", projectBasePath) -> Result.success(Ripgrep) + else -> Result.success(FuzzierGrep) + } } } - } private suspend fun isInstalled( commandRunner: CommandRunner, diff --git a/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendStrategy.kt b/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendStrategy.kt index 95b55d01..a889599d 100644 --- a/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendStrategy.kt +++ b/src/main/kotlin/com/mituuz/fuzzier/grep/backend/BackendStrategy.kt @@ -31,7 +31,7 @@ import com.mituuz.fuzzier.entities.GrepConfig import com.mituuz.fuzzier.runner.CommandRunner import javax.swing.DefaultListModel -sealed interface BackendStrategy { +interface BackendStrategy { val name: String suspend fun handleSearch( diff --git a/src/test/kotlin/com/mituuz/fuzzier/grep/FuzzyGrepTest.kt b/src/test/kotlin/com/mituuz/fuzzier/grep/FuzzyGrepTest.kt index 0341a090..27447f72 100644 --- a/src/test/kotlin/com/mituuz/fuzzier/grep/FuzzyGrepTest.kt +++ b/src/test/kotlin/com/mituuz/fuzzier/grep/FuzzyGrepTest.kt @@ -30,30 +30,30 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.testFramework.TestApplicationManager import com.mituuz.fuzzier.components.FuzzyFinderComponent import com.mituuz.fuzzier.entities.CaseMode +import com.mituuz.fuzzier.entities.FuzzyContainer import com.mituuz.fuzzier.entities.GrepConfig import com.mituuz.fuzzier.grep.backend.BackendStrategy +import com.mituuz.fuzzier.runner.CommandRunner import io.mockk.every import io.mockk.mockk import io.mockk.unmockkAll import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import javax.swing.DefaultListModel class FuzzyGrepTest { private lateinit var fGrep: FuzzyGrep private data class ValidVfContext( - val file: VirtualFile, - val clm: ChangeListManager + val file: VirtualFile, val clm: ChangeListManager ) private data class FindInFilesContext( val project: Project, val component: FuzzyFinderComponent, - val backend: BackendStrategy, val clm: ChangeListManager ) @@ -69,10 +69,7 @@ class FuzzyGrepTest { } private fun createValidVfContext( - isDirectory: Boolean = false, - isBinary: Boolean = false, - isIgnored: Boolean = false, - extension: String? = null + isDirectory: Boolean = false, isBinary: Boolean = false, isIgnored: Boolean = false, extension: String? = null ): ValidVfContext { val file = mockk() val clm = mockk() @@ -88,24 +85,21 @@ class FuzzyGrepTest { } private fun createFindInFilesContext( - projectBasePath: String? = "/tmp/project", - secondaryText: String = "kt" + projectBasePath: String? = "/tmp/project", secondaryText: String = "kt" ): FindInFilesContext { val project = mockk() val component = mockk() - val backend = mockk() val clm = mockk() every { project.basePath } returns projectBasePath every { component.getSecondaryText() } returns secondaryText fGrep.component = component - fGrep.updateBackend(backend) fGrep.updateGrepConfig( GrepConfig(targets = null, caseMode = CaseMode.SENSITIVE, title = "Fuzzy Grep") ) - return FindInFilesContext(project, component, backend, clm) + return FindInFilesContext(project, component, clm) } @Test @@ -158,9 +152,9 @@ class FuzzyGrepTest { @Test fun `findInFiles should skip backend when backend is null`() = runBlocking { - val (project, _, _, clm) = createFindInFilesContext() + val (project, component, clm) = createFindInFilesContext() - val model = fGrep.findInFiles("needle", project, clm, null) + val model = fGrep.findInFiles("needle", project, clm, null, component) assertNotNull(model) assertEquals(0, model.size) @@ -168,11 +162,53 @@ class FuzzyGrepTest { @Test fun `findInFiles should skip backend when project base path is null`() = runBlocking { - val (project, _, backend, clm) = createFindInFilesContext(projectBasePath = null) + val (project, component, clm) = createFindInFilesContext(projectBasePath = null) + val backend = MockBackend() - val model = fGrep.findInFiles("needle", project, clm, backend) + val model = fGrep.findInFiles("needle", project, clm, backend, component) assertNotNull(model) assertEquals(0, model.size) + assertFalse(backend.wasCalled) + } + + @Test + fun `findInFiles calls backend when backend and project base path are available`() = runBlocking { + val (project, component, clm) = createFindInFilesContext(projectBasePath = "not/null") + val backend = MockBackend() + + val model = fGrep.findInFiles("needle", project, clm, backend, component) + + assertNotNull(model) + assertEquals(0, model.size) + assertTrue(backend.wasCalled) + assertEquals("needle", backend.receivedSearchString) + assertEquals("kt", backend.receivedSecondarySearchString) + assertEquals("not/null", backend.receivedProjectBasePath) + } + + private class MockBackend : BackendStrategy { + override val name: String = "Mock" + + var wasCalled = false + var receivedSearchString: String? = null + var receivedSecondarySearchString: String? = null + var receivedProjectBasePath: String? = null + + override suspend fun handleSearch( + grepConfig: GrepConfig, + searchString: String, + secondarySearchString: String?, + commandRunner: CommandRunner, + listModel: DefaultListModel, + projectBasePath: String, + project: Project, + fileFilter: (VirtualFile) -> Boolean + ) { + wasCalled = true + receivedSearchString = searchString + receivedSecondarySearchString = secondarySearchString + receivedProjectBasePath = projectBasePath + } } } \ No newline at end of file