mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
(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:
committed by
intellij-monorepo-bot
parent
b8be743193
commit
0b8126f12e
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
public class <caret>IndexProjectAction {
|
||||
private boolean isIndexed = false;
|
||||
void run() {
|
||||
isIndexed = true;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
class IndexProjectAction {
|
||||
private var isIndexed = false
|
||||
fun run() {
|
||||
isIndexed = true
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user