(IJPL-163509) Return tests to intellij.ml.llm.embeddings.searchEverywhere.tests.iml, keep empty package in old location

GitOrigin-RevId: e3b4c19836973383551e747d60d4300d7d1a4ce0
This commit is contained in:
Evgeny Abramov
2024-10-14 19:50:03 +03:00
committed by intellij-monorepo-bot
parent b8be743193
commit 0b8126f12e
15 changed files with 1 additions and 708 deletions

2
.idea/modules.xml generated
View File

@@ -905,8 +905,8 @@
<module fileurl="file://$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/java/intellij.searchEverywhereMl.ranking.java.iml" filepath="$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/java/intellij.searchEverywhereMl.ranking.java.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/vcs/intellij.searchEverywhereMl.ranking.vcs.iml" filepath="$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/vcs/intellij.searchEverywhereMl.ranking.vcs.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/yaml/intellij.searchEverywhereMl.ranking.yaml.iml" filepath="$PROJECT_DIR$/plugins/search-everywhere-ml/ranking/yaml/intellij.searchEverywhereMl.ranking.yaml.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/search-everywhere-ml/semantics/tests/intellij.searchEverywhereMl.semantics.tests.iml" filepath="$PROJECT_DIR$/plugins/search-everywhere-ml/semantics/tests/intellij.searchEverywhereMl.semantics.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml" filepath="$PROJECT_DIR$/plugins/search-everywhere-ml/typos/intellij.searchEverywhereMl.typos.iml" />
<module fileurl="file://$PROJECT_DIR$/community/plugins/search-everywhere-ml/semantics/tests/intellij.searchEverywhereMl.semantics.tests.iml" filepath="$PROJECT_DIR$/community/plugins/search-everywhere-ml/semantics/tests/intellij.searchEverywhereMl.semantics.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/settings-repository/intellij.settingsRepository.iml" filepath="$PROJECT_DIR$/plugins/settings-repository/intellij.settingsRepository.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/settings-repository/intellij.settingsRepository.tests.iml" filepath="$PROJECT_DIR$/plugins/settings-repository/intellij.settingsRepository.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/settings-sync/intellij.settingsSync.iml" filepath="$PROJECT_DIR$/plugins/settings-sync/intellij.settingsSync.iml" />

View File

@@ -4,21 +4,11 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/testData" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/testResources" type="java-test-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<orderEntry type="module" module-name="intellij.ml.llm.embeddings.searchEverywhere" scope="TEST" />
<orderEntry type="module" module-name="intellij.java.testFramework" scope="TEST" />
<orderEntry type="module" module-name="intellij.ml.llm.embeddings.java" scope="TEST" />
<orderEntry type="module" module-name="intellij.ml.llm.embeddings.kotlin" scope="TEST" />
<orderEntry type="library" scope="PROVIDED" name="kotlinc.kotlin-compiler-common" level="project" />
<orderEntry type="module" module-name="intellij.kotlin.plugin.community.main" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.searchEverywhereMl" scope="TEST" />
<orderEntry type="module" module-name="intellij.ml.llm.embeddings.core" scope="TEST" />
<orderEntry type="module" module-name="intellij.ml.llm" scope="TEST" />
<orderEntry type="library" scope="TEST" name="kotlinx-coroutines-test" level="project" />
</component>
</module>

View File

@@ -1,134 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.ide.actions.searcheverywhere.ActionSearchEverywhereContributor
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI.SINGLE_CONTRIBUTOR_ELEMENTS_LIMIT
import com.intellij.ide.util.gotoByName.GotoActionModel
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.readAction
import com.intellij.openapi.util.Disposer
import com.intellij.ml.llm.embeddings.core.actions.ActionEmbeddingStorageManager
import com.intellij.ml.llm.embeddings.core.indexer.IndexId
import com.intellij.ml.llm.embeddings.core.indexer.configuration.EmbeddingsConfiguration
import com.intellij.ml.llm.embeddings.searchEverywhere.contributors.SemanticActionSearchEverywhereContributor
import com.intellij.ml.llm.embeddings.searchEverywhere.settings.SearchEverywhereSemanticSettings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
class SemanticActionSearchTest : SemanticSearchBaseTestCase() {
private val storageWrapper
get() = EmbeddingsConfiguration.getStorageManagerWrapper(IndexId.ACTIONS)
fun `test basic semantics`() = runTest {
setupTest("java/IndexProjectAction.java") // open file in the editor to make all actions indexable
var neighbours = storageWrapper.search(null, "delete all breakpoints", 10, 0.5f).map { it.id }.toSet()
assertContainsElements(neighbours, "Debugger.RemoveAllBreakpoints", "Debugger.RemoveAllBreakpointsInFile")
neighbours = storageWrapper.search(null, "fix ide", 10, 0.5f).map { it.id }.toSet()
assertContainsElements(
neighbours,
"CallSaul", // 'Repair IDE' action (don't ask why)
"ExportImportGroup" // 'Manage IDE Settings' action
)
neighbours = storageWrapper.search(null, "web explorer", 10, 0.5f).map { it.id }.toSet()
assertContainsElements(neighbours, "WebBrowser", "BrowseWeb")
}
fun `test search everywhere contributor`() = runTest(
timeout = 1.minutes // time to generate action embeddings
) {
setupTest("java/IndexProjectAction.java")
val standardActionContributor = ActionSearchEverywhereContributor.Factory()
.createContributor(createEvent()) as ActionSearchEverywhereContributor
val searchEverywhereUI = runBlocking(Dispatchers.EDT) {
SearchEverywhereUI(project, listOf(SemanticActionSearchEverywhereContributor(standardActionContributor)), { _ -> null }, null)
}
Disposer.register(project, searchEverywhereUI)
val elements = runOnEdt { searchEverywhereUI.findElementsForPattern("delete all breakpoints") }.await()
val items = elements.filterIsInstance<GotoActionModel.MatchedValue>().map { (it.value as GotoActionModel.ActionWrapper).actionText }
assertContainsElements(items, "Remove All Breakpoints", "Remove All Breakpoints In The Current File")
}
fun `test empty query`() = runTest(timeout = 10.seconds) {
val semanticActionContributor = readAction {
SemanticActionSearchEverywhereContributor(
ActionSearchEverywhereContributor.Factory().createContributor(createEvent()) as ActionSearchEverywhereContributor)
}
val semanticSearchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI(project, listOf(semanticActionContributor)) }
Disposer.register(project, semanticSearchEverywhereUI)
val results = runOnEdt { semanticSearchEverywhereUI.findElementsForPattern("") }.await()
assertEquals("expected no results from semantic contributor for empty query",
0, results.filterIsInstance<GotoActionModel.MatchedValue>().mapNotNull { it.value as? GotoActionModel.MatchedValue }.size)
}
fun `test semantic and standard contributor results match`() = runTest(timeout = 5.minutes) {
setupTest("java/IndexProjectAction.java")
// Contributors do not share the same GotoActionModel:
val standardActionContributor = readAction { ActionSearchEverywhereContributor.Factory()
.createContributor(createEvent()) as ActionSearchEverywhereContributor }
val semanticActionContributor = readAction {
SemanticActionSearchEverywhereContributor(
ActionSearchEverywhereContributor.Factory().createContributor(createEvent()) as ActionSearchEverywhereContributor)
}
val standardSearchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI(project, listOf(standardActionContributor)) }
Disposer.register(project, standardSearchEverywhereUI)
val semanticSearchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI(project, listOf(semanticActionContributor)) }
Disposer.register(project, semanticSearchEverywhereUI)
val prefixes = ('a'..'z').map { it.toString() }.toMutableList()
var lastAdded = prefixes.toList()
repeat(2) {
lastAdded = lastAdded.flatMap { prefix -> ('a'..'z').map { prefix + it } }
prefixes.addAll(lastAdded)
}
suspend fun findResultsFromUI(ui: SearchEverywhereUI, query: String): List<String> {
return runOnEdt { ui.findElementsForPattern(query) }.await()
.filterIsInstance<GotoActionModel.MatchedValue>()
.mapNotNull { it.value as? GotoActionModel.ActionWrapper }
// 'Include disabled actions' checkbox is automatically set in standard search when no results found.
// Since there are fewer cases when lookup is empty, disabled actions might not appear in semantic search results, and that's fine:
.filter { it.isAvailable }
.map { it.actionText }
}
val iterations = 1200
for (query in prefixes.take(iterations)) {
val semanticResults = findResultsFromUI(semanticSearchEverywhereUI, query)
val standardResults = findResultsFromUI(standardSearchEverywhereUI, query)
assert(standardResults.toSet().minus(semanticResults.toSet()).isEmpty() ||
(standardResults.size == semanticResults.size && semanticResults.size == SINGLE_CONTRIBUTOR_ELEMENTS_LIMIT)) {
"""
Not all elements from standard contributor are present in semantic contributor results
query: $query
standard results (len = ${standardResults.size}): $standardResults
semantic results (len = ${semanticResults.size}): $semanticResults
removed results: ${standardResults.toSet().minus(semanticResults.toSet())}
added results: ${semanticResults.toSet().minus(standardResults.toSet())}
""".trimIndent()
}
}
}
private suspend fun setupTest(vararg filePaths: String) {
myFixture.configureByFiles(*filePaths)
SearchEverywhereSemanticSettings.getInstance().enabledInActionsTab = true
storageWrapper.clearStorage(null)
ActionEmbeddingStorageManager.getInstance().prepareForSearch().join()
}
}

View File

@@ -1,138 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.ide.actions.searcheverywhere.PsiItemWithSimilarity
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.ide.util.gotoByName.GotoClassModel2
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.readAction
import com.intellij.openapi.application.smartReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.util.Disposer
import com.intellij.ml.llm.embeddings.core.indexer.FileBasedEmbeddingIndexer
import com.intellij.ml.llm.embeddings.core.indexer.IndexId
import com.intellij.ml.llm.embeddings.core.indexer.configuration.EmbeddingsConfiguration
import com.intellij.ml.llm.embeddings.core.indexer.entities.IndexableClass
import com.intellij.ml.llm.embeddings.core.jvm.indices.EntityId
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.ml.llm.embeddings.searchEverywhere.contributors.SemanticClassSearchEverywhereContributor
import com.intellij.ml.llm.embeddings.searchEverywhere.settings.SearchEverywhereSemanticSettings
import com.intellij.testFramework.VfsTestUtil
import com.intellij.testFramework.utils.editor.commitToPsi
import com.intellij.testFramework.utils.editor.saveToDisk
import com.intellij.util.TimeoutUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.jetbrains.kotlin.psi.KtClass
import kotlin.time.Duration.Companion.seconds
class SemanticClassSearchTest : SemanticSearchBaseTestCase() {
private val storageWrapper
get() = EmbeddingsConfiguration.getStorageManagerWrapper(IndexId.CLASSES)
private val model
get() = GotoClassModel2(project)
fun `test basic semantics`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction", "ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager"), neighbours)
}
fun `test index ids are not duplicated`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/IndexProjectAction.kt")
assertEquals(1, storageWrapper.getStorageStats(project).size)
}
fun `test search everywhere contributor`() = runTest(
timeout = 45.seconds // increased timeout because of a bug in class index
) {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
val contributor = readAction { SemanticClassSearchEverywhereContributor(createEvent()) }
Disposer.register(project, contributor)
val searchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI(project, listOf(contributor), { _ -> null }, null) }
Disposer.register(project, searchEverywhereUI)
val elements = runOnEdt { searchEverywhereUI.findElementsForPattern("index project job") }.await()
val items: List<PsiElement> = elements.filterIsInstance<PsiItemWithSimilarity<*>>().mapNotNull { extractPsiElement(it) }
assertEquals(2, items.size)
val classes = items.filterIsInstance<PsiClass>().map { readAction { IndexableClass(EntityId(it.name ?: "")) } } +
items.filterIsInstance<KtClass>().map { readAction { IndexableClass(EntityId(it.name ?: "")) } }
assertEquals(2, classes.size)
assertEquals(setOf(EntityId("IndexProjectAction"), EntityId("ProjectIndexingTask")), classes.map { it.id }.toSet())
}
fun `test class renaming changes the index`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction", "ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager"), neighbours)
val nameToReplace = "IndexProjectAction"
val startOffset = myFixture.editor.document.text.indexOf(nameToReplace)
WriteCommandAction.runWriteCommandAction(project) {
myFixture.editor.document.replaceString(startOffset, startOffset + nameToReplace.length, "ScoresFileHandler")
myFixture.editor.document.saveToDisk() // This is how we trigger reindexing
myFixture.editor.document.commitToPsi(project)
}
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(setOf("ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("ScoresFileManager", "ScoresFileHandler"), neighbours)
}
fun `test removal of file with class changes the index`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction", "ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager"), neighbours)
VfsTestUtil.deleteFile(myFixture.editor.virtualFile) // deletes the currently open file: java/IndexProjectAction.java
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(setOf("ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("ScoresFileManager"), neighbours)
}
private suspend fun Iterable<String>.filterByModel(): Set<String> {
return filter {
smartReadAction(project) {
model.getElementsByName(it, false, it).any { element ->
(element as PsiElement).isValid
}
}
}.toSet()
}
private suspend fun setupTest(vararg filePaths: String) {
myFixture.configureByFiles(*filePaths)
SearchEverywhereSemanticSettings.getInstance().enabledInClassesTab = true
storageWrapper.clearStorage(project)
FileBasedEmbeddingIndexer.getInstance().prepareForSearch(project).join()
}
}

View File

@@ -1,161 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.ide.actions.searcheverywhere.PsiItemWithSimilarity
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.ide.util.gotoByName.GotoFileModel
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.readAction
import com.intellij.openapi.application.smartReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.util.Disposer
import com.intellij.ml.llm.embeddings.core.indexer.FileBasedEmbeddingIndexer
import com.intellij.ml.llm.embeddings.core.indexer.IndexId
import com.intellij.ml.llm.embeddings.core.indexer.configuration.EmbeddingsConfiguration
import com.intellij.ml.llm.embeddings.core.indexer.entities.IndexableFile
import com.intellij.ml.llm.embeddings.core.jvm.indices.EntityId
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.ml.llm.embeddings.searchEverywhere.contributors.SemanticFileSearchEverywhereContributor
import com.intellij.ml.llm.embeddings.searchEverywhere.settings.SearchEverywhereSemanticSettings
import com.intellij.testFramework.utils.vfs.deleteRecursively
import com.intellij.util.TimeoutUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import java.io.BufferedReader
import java.nio.file.Path
import kotlin.io.path.inputStream
class SemanticFileSearchTest : SemanticSearchBaseTestCase() {
private val storageWrapper
get() = EmbeddingsConfiguration.getStorageManagerWrapper(IndexId.FILES)
private val model
get() = GotoFileModel(project)
fun `test basic semantics`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction.java", "ProjectIndexingTask.kt"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
}
fun `test index ids are not duplicated`() = runTest {
myFixture.copyFileToProject("java/IndexProjectAction.java", "src/first/IndexProjectAction.java")
myFixture.copyFileToProject("java/IndexProjectAction.java", "src/second/IndexProjectAction.java")
setupTest()
assertEquals(1, storageWrapper.getStorageStats(project).size)
}
fun `test search everywhere contributor`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
val contributor = readAction { SemanticFileSearchEverywhereContributor (createEvent()) }
Disposer.register(project, contributor)
val searchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI (project, listOf(contributor), { _ -> null }, null) }
Disposer.register(project, searchEverywhereUI)
val elements = runOnEdt { searchEverywhereUI.findElementsForPattern("index project job") }.await()
val items: List<PsiElement> = elements.filterIsInstance<PsiItemWithSimilarity<*>>().mapNotNull { extractPsiElement(it) }
assertEquals(2, items.size)
val files = items.filterIsInstance<PsiFile>().map { IndexableFile(it.virtualFile) }
assertEquals(2, files.size)
assertEquals(setOf(EntityId("IndexProjectAction.java"), EntityId("ProjectIndexingTask.kt")), files.map { it.id }.toSet())
}
fun `test file renaming changes the index`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("ProjectIndexingTask.kt", "IndexProjectAction.java"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
WriteCommandAction.runWriteCommandAction(project) {
myFixture.editor.virtualFile.rename(this, "ScoresFileHandler.java")
}
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(setOf("ProjectIndexingTask.kt"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("ScoresFileManager.java", "ScoresFileHandler.java"), neighbours)
}
fun `test file removal changes the index`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/ProjectIndexingTask.kt", "java/ScoresFileManager.java")
assertEquals(3, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction.java", "ProjectIndexingTask.kt"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
WriteCommandAction.runWriteCommandAction(project) {
myFixture.editor.virtualFile.deleteRecursively() // deletes the currently open file: java/IndexProjectAction.java
}
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(setOf("ProjectIndexingTask.kt"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
}
fun `test file creation changes the index`() = runTest {
setupTest("java/IndexProjectAction.java", "java/ScoresFileManager.java")
assertEquals(2, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("IndexProjectAction.java"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
val fileStream = Path.of(testDataPath, "kotlin/ProjectIndexingTask.kt").inputStream()
myFixture.configureByText("ProjectIndexingTask.kt", fileStream.bufferedReader().use(BufferedReader::readText))
TimeoutUtil.sleep(2000) // wait for two seconds for index update
assertEquals(3, storageWrapper.getStorageStats(project).size)
neighbours = storageWrapper.search(project, "index project job", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(setOf("IndexProjectAction.java", "ProjectIndexingTask.kt"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("ScoresFileManager.java"), neighbours)
}
private suspend fun Iterable<String>.filterByModel(): Set<String> {
return filter {
smartReadAction(project) {
model.getElementsByName(it, false, it).any { element ->
(element as PsiElement).isValid
}
}
}.toSet()
}
private suspend fun setupTest(vararg filePaths: String) {
myFixture.configureByFiles(*filePaths)
SearchEverywhereSemanticSettings.getInstance().enabledInFilesTab = true
storageWrapper.clearStorage(project)
FileBasedEmbeddingIndexer.getInstance().prepareForSearch(project).join()
}
}

View File

@@ -1,20 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.ActionUiKind
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.application.PluginPathManager
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
abstract class SemanticSearchBaseTestCase : LightJavaCodeInsightFixtureTestCase() {
override fun getTestDataPath() = PluginPathManager
.getPluginHome("search-everywhere-ml").resolve("semantics/tests/testData").toString()
// .getPluginHome("llm").resolve("embeddings/searchEverywhere/tests/testData").toString()
protected fun createEvent(): AnActionEvent {
return AnActionEvent.createEvent(SimpleDataContext.getProjectContext(project), null, ActionPlaces.UNKNOWN, ActionUiKind.NONE, null)
}
override fun runInDispatchThread(): Boolean = false
}

View File

@@ -1,26 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.ide.actions.searcheverywhere.PSIPresentationBgRendererWrapper
import com.intellij.ide.actions.searcheverywhere.PsiItemWithSimilarity
import com.intellij.openapi.application.EDT
import com.intellij.psi.PsiElement
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.asDeferred
import kotlinx.coroutines.runBlocking
import java.util.concurrent.CompletionStage
import java.util.concurrent.Future
fun extractPsiElement(element: PsiItemWithSimilarity<*>): PsiElement? {
return when (val value = element.value) {
is PSIPresentationBgRendererWrapper.PsiItemWithPresentation -> value.item
is PsiElement -> value
else -> null
}
}
fun <T> runOnEdt(f: () -> Future<T>): Deferred<T> {
val future = runBlocking(Dispatchers.EDT) { f() }
return (future as CompletionStage<T>).asDeferred()
}

View File

@@ -1,145 +0,0 @@
package com.intellij.searchEverywhereMl.semantics.tests
import com.intellij.ide.actions.searcheverywhere.PsiItemWithSimilarity
import com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI
import com.intellij.ide.util.gotoByName.GotoSymbolModel2
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.readAction
import com.intellij.openapi.application.smartReadAction
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.util.Disposer
import com.intellij.ml.llm.embeddings.core.indexer.FileBasedEmbeddingIndexer
import com.intellij.ml.llm.embeddings.core.indexer.IndexId
import com.intellij.ml.llm.embeddings.core.indexer.configuration.EmbeddingsConfiguration
import com.intellij.ml.llm.embeddings.core.indexer.entities.IndexableClass
import com.intellij.ml.llm.embeddings.core.jvm.indices.EntityId
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.ml.llm.embeddings.searchEverywhere.contributors.SemanticSymbolSearchEverywhereContributor
import com.intellij.ml.llm.embeddings.searchEverywhere.settings.SearchEverywhereSemanticSettings
import com.intellij.testFramework.utils.editor.commitToPsi
import com.intellij.testFramework.utils.editor.saveToDisk
import com.intellij.testFramework.utils.vfs.deleteRecursively
import com.intellij.util.TimeoutUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.jetbrains.kotlin.psi.KtFunction
import kotlin.time.Duration.Companion.seconds
class SemanticSymbolSearchTest : SemanticSearchBaseTestCase() {
private val storageWrapper
get() = EmbeddingsConfiguration.getStorageManagerWrapper(IndexId.SYMBOLS)
private val model
get() = GotoSymbolModel2(project, testRootDisposable)
fun `test basic semantics`() = runTest {
setupTest("java/ProjectIndexingTask.java", "kotlin/ScoresFileManager.kt")
assertEquals(5, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "begin indexing", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("startIndexing", "ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("handleScoresFile", "clearFileWithScores"), neighbours)
}
fun `test index ids are not duplicated`() = runTest {
setupTest("java/IndexProjectAction.java", "kotlin/IndexProjectAction.kt")
assertEquals(1, storageWrapper.getStorageStats(project).size)
}
fun `test search everywhere contributor`() = runTest(
timeout = 45.seconds // increased timeout because of a bug in symbol index
) {
setupTest("java/ProjectIndexingTask.java", "kotlin/ScoresFileManager.kt")
val contributor = readAction { SemanticSymbolSearchEverywhereContributor(createEvent()) }
Disposer.register(project, contributor)
val searchEverywhereUI = runBlocking(Dispatchers.EDT) { SearchEverywhereUI(project, listOf(contributor), { _ -> null }, null) }
Disposer.register(project, searchEverywhereUI)
val elements = runOnEdt { searchEverywhereUI.findElementsForPattern("begin indexing") }.await()
val items: List<PsiElement> = elements.filterIsInstance<PsiItemWithSimilarity<*>>().mapNotNull { extractPsiElement(it) }
assertEquals(2, items.size)
val methods = items.filterIsInstance<PsiMethod>().map { IndexableClass(EntityId(it.name)) } +
items.filterIsInstance<KtFunction>().map { IndexableClass(EntityId(it.name ?: "")) } +
items.filterIsInstance<PsiClass>().map {
IndexableClass(EntityId(it.name ?: ""))
} // we might have constructors in the results
assertEquals(2, methods.size)
assertEquals(setOf(EntityId("ProjectIndexingTask"), EntityId("startIndexing")), methods.map { it.id }.toSet())
}
fun `test method renaming changes the index`() = runTest {
setupTest("java/ProjectIndexingTask.java", "kotlin/ScoresFileManager.kt")
assertEquals(5, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "begin indexing", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("ProjectIndexingTask", "startIndexing"), neighbours)
neighbours = storageWrapper.search(project, "helicopter purchase", 10, 0.5f).map { it.id }.toSet()
assertEquals(emptySet<String>(), neighbours)
val nameToReplace = "startIndexing"
val startOffset = myFixture.editor.document.text.indexOf(nameToReplace)
WriteCommandAction.runWriteCommandAction(project) {
myFixture.editor.document.replaceString(startOffset, startOffset + nameToReplace.length, "buyHelicopter")
myFixture.editor.document.saveToDisk() // This is how we trigger reindexing
myFixture.editor.document.commitToPsi(project)
}
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "begin indexing", 10, 0.5f).map{ it.id }.filterByModel()
assertEquals(setOf("ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "helicopter purchase", 10, 0.5f).map{ it.id }.filterByModel()
assertEquals(setOf("buyHelicopter"), neighbours)
}
fun `test removal of file with method changes the index`() = runTest {
setupTest("java/ProjectIndexingTask.java", "kotlin/ScoresFileManager.kt")
assertEquals(5, storageWrapper.getStorageStats(project).size)
var neighbours = storageWrapper.search(project, "begin indexing", 10, 0.5f).map { it.id }.toSet()
assertEquals(setOf("startIndexing", "ProjectIndexingTask"), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.toSet()
assertEquals(setOf("handleScoresFile", "clearFileWithScores"), neighbours)
WriteCommandAction.runWriteCommandAction(project) {
myFixture.editor.virtualFile.deleteRecursively() // deletes the currently open file: java/ProjectIndexingTask.java
}
TimeoutUtil.sleep(2000) // wait for two seconds for index update
neighbours = storageWrapper.search(project, "begin indexing", 10, 0.5f).map { it.id }.filterByModel()
assertEquals(emptySet<String>(), neighbours)
neighbours = storageWrapper.search(project, "handle file with scores", 10, 0.4f).map { it.id }.filterByModel()
assertEquals(setOf("handleScoresFile", "clearFileWithScores"), neighbours)
}
private suspend fun Iterable<String>.filterByModel(): Set<String> {
return filter {
smartReadAction(project) {
model.getElementsByName(it, false, it).any { element ->
(element as PsiElement).isValid
}
}
}.toSet()
}
private suspend fun setupTest(vararg filePaths: String) {
myFixture.configureByFiles(*filePaths)
SearchEverywhereSemanticSettings.getInstance().enabledInSymbolsTab = true
storageWrapper.clearStorage(project)
FileBasedEmbeddingIndexer.getInstance().prepareForSearch(project).join()
}
}

View File

@@ -1,6 +0,0 @@
public class <caret>IndexProjectAction {
private boolean isIndexed = false;
void run() {
isIndexed = true;
}
}

View File

@@ -1,19 +0,0 @@
import java.lang.Thread;
public class ProjectIndexingTask {
private final String project;
public ProjectIndexingTask(String project) {
this.project = project;
}
private static String taskTitle = "Collecting project files...";
public static void startIndexing(long timeout) throws InterruptedException {
Thread.sleep(timeout);
}
private void getUsedMemory() {
System.out.println("too much");
}
}

View File

@@ -1,11 +0,0 @@
import java.io.*;
public class ScoresFileManager {
public void handleScoresFile() {
integer count = 0
for (int i = 0; i < 10; i++) {
System.out.println("score: " + count);
count++;
}
}
}

View File

@@ -1,6 +0,0 @@
class IndexProjectAction {
private var isIndexed = false
fun run() {
isIndexed = true
}
}

View File

@@ -1,16 +0,0 @@
private const val MB = 1024 * 1024
class ProjectIndexingTask(project: String) {
companion object {
private const val taskTitle = "Collecting project files..."
fun startIndexing(timeout: Int) {
Thread.sleep(timeout.toLong())
}
}
private fun getUsedMemory(): Long {
val runtime = Runtime.getRuntime()
return (runtime.totalMemory() - runtime.freeMemory()) / MB
}
}

View File

@@ -1,15 +0,0 @@
class ScoresFileManager {
fun handleScoresFile() {
var count = 0
repeat(10) {
println("score: $count")
count++
}
}
companion object {
fun clearFileWithScores(file: String) {
println("cleared")
}
}
}