mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-189563 LSP: support multi-entry per line for code vision and extract codeVisionTestFixture from java-tests
GitOrigin-RevId: 49dd70e32e5734b91c9b564507feeda82fc1ee1b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8d442c78c9
commit
33db93e4b3
+2
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight.codeVision
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.JavaInheritorsCodeVisionProvider
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.writeAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.platform.testFramework.junit5.codeInsight.fixture.codeVisionFixture
|
||||
import com.intellij.platform.testFramework.junit5.projectStructure.fixture.withSharedSourceEnabled
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.impl.file.impl.sharedSourceRootFixture
|
||||
|
||||
@@ -120,6 +120,7 @@ c:com.intellij.codeInsight.actions.VcsFacade
|
||||
- a:getName():java.lang.String
|
||||
- getPlaceholderCollector(com.intellij.openapi.editor.Editor,com.intellij.psi.PsiFile):com.intellij.codeInsight.codeVision.CodeVisionPlaceholderCollector
|
||||
- a:getRelativeOrderings():java.util.List
|
||||
- getSingleEntryPerLine():Z
|
||||
- handleClick(com.intellij.openapi.editor.Editor,com.intellij.openapi.util.TextRange,com.intellij.codeInsight.codeVision.CodeVisionEntry):V
|
||||
- handleExtraAction(com.intellij.openapi.editor.Editor,com.intellij.openapi.util.TextRange,com.intellij.codeInsight.codeVision.CodeVisionEntry,java.lang.String):V
|
||||
- handleExtraAction(com.intellij.openapi.editor.Editor,com.intellij.openapi.util.TextRange,java.lang.String):V
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.codeVision
|
||||
|
||||
import com.intellij.codeInsight.codeVision.settings.PlatformCodeVisionIds
|
||||
@@ -112,6 +112,16 @@ interface CodeVisionProvider<T> {
|
||||
val id: String
|
||||
|
||||
|
||||
/**
|
||||
* Whether only a single entry per line should be displayed for this provider.
|
||||
*
|
||||
* When `true`, if multiple entries from this provider appear on the same line,
|
||||
* only the last one will be shown. When `false`, all entries are displayed.
|
||||
*/
|
||||
val singleEntryPerLine: Boolean
|
||||
get() = true
|
||||
|
||||
|
||||
/**
|
||||
* Used to group provider in the settings panel and to share same behavior (like position and ext.) and description.
|
||||
* To group different provider implement [com.intellij.codeInsight.codeVision.settings.CodeVisionGroupSettingProvider].
|
||||
|
||||
+10
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.codeVision
|
||||
|
||||
import com.intellij.codeInsight.codeVision.ui.CodeVisionView
|
||||
@@ -131,7 +131,15 @@ open class EditorCodeVisionContext(
|
||||
continue
|
||||
}
|
||||
|
||||
val lastFilteredLineLenses = lineLenses.groupBy { it.codeVisionEntryOrThrow.providerId }.map { it.value.last() }
|
||||
val lastFilteredLineLenses = lineLenses.groupBy { it.codeVisionEntryOrThrow.providerId }.flatMap { (providerId, lenses) ->
|
||||
val provider = codeVisionHost.getProviderById(providerId)
|
||||
if (provider?.singleEntryPerLine == true) {
|
||||
listOf(lenses.last())
|
||||
}
|
||||
else {
|
||||
lenses
|
||||
}
|
||||
}
|
||||
val groupedLenses = lastFilteredLineLenses.groupBy { codeVisionHost.getAnchorForEntry(it.codeVisionEntryOrThrow) }
|
||||
|
||||
val anchoringRange = groupedLenses.first().value.first()
|
||||
|
||||
@@ -19,6 +19,9 @@ jvm_library(
|
||||
"//platform/testFramework/junit5",
|
||||
"//platform/core-api:core",
|
||||
"//platform/core-ui",
|
||||
"//platform/lang-impl",
|
||||
"//platform/lang-api:lang",
|
||||
"//platform/projectModel-api:projectModel",
|
||||
]
|
||||
)
|
||||
### auto-generated section `build intellij.platform.testFramework.junit5.codeInsight` end
|
||||
+3
@@ -13,5 +13,8 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.testFramework.junit5" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core" />
|
||||
<orderEntry type="module" module-name="intellij.platform.core.ui" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
|
||||
<orderEntry type="module" module-name="intellij.platform.lang" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel" />
|
||||
</component>
|
||||
</module>
|
||||
+5
@@ -1,5 +1,10 @@
|
||||
<idea-plugin>
|
||||
<dependencies>
|
||||
<!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->
|
||||
<module name="intellij.platform.lang"/>
|
||||
<module name="intellij.platform.lang.impl"/>
|
||||
<module name="intellij.platform.projectModel"/>
|
||||
<module name="intellij.platform.testFramework.junit5"/>
|
||||
<!-- endregion -->
|
||||
</dependencies>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.testFramework.junit5.codeInsight.fixture
|
||||
|
||||
import com.intellij.codeInsight.codeVision.CodeVisionHost
|
||||
import com.intellij.codeInsight.codeVision.CodeVisionInitializer
|
||||
import com.intellij.codeInsight.codeVision.settings.CodeVisionSettings
|
||||
import com.intellij.codeInsight.codeVision.ui.model.CodeVisionListData
|
||||
import com.intellij.codeInsight.codeVision.ui.renderers.CodeVisionInlayRenderer
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.codeInsight.hints.InlayDumpUtil
|
||||
import com.intellij.codeInsight.multiverse.CodeInsightContext
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.application.writeIntentReadAction
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.waitForSmartMode
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.testFramework.TestModeFlags
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase.assertEquals
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
||||
import com.intellij.testFramework.junit5.fixture.TestFixture
|
||||
import com.intellij.testFramework.junit5.fixture.testFixture
|
||||
import com.intellij.util.ArrayUtilRt
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
@TestOnly
|
||||
class CodeVisionTestFixture(
|
||||
private val editor: Editor,
|
||||
private val virtualFile: VirtualFile,
|
||||
private val project: Project,
|
||||
private val disposable: Disposable,
|
||||
private val onlyCodeVisionHintsAllowed: Boolean = false,
|
||||
) {
|
||||
|
||||
fun doHighlighting(file: PsiFile): List<HighlightInfo> =
|
||||
CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, ArrayUtilRt.EMPTY_INT_ARRAY, false, false)
|
||||
|
||||
@TestOnly
|
||||
suspend fun testProviders(
|
||||
context: CodeInsightContext,
|
||||
expectedText: String,
|
||||
vararg enabledProviderGroupIds: String,
|
||||
beforeAssert: suspend () -> Unit = {},
|
||||
) {
|
||||
val sourceText = InlayDumpUtil.removeInlays(expectedText)
|
||||
project.waitForSmartMode()
|
||||
val codeVisionHost = readAction { CodeVisionInitializer.getInstance(project).getCodeVisionHost() }
|
||||
|
||||
withContext(Dispatchers.EDT) {
|
||||
writeIntentReadAction {
|
||||
val settings = CodeVisionSettings.getInstance()
|
||||
val file = requireNotNull(PsiManager.getInstance(project).findFile(virtualFile, context))
|
||||
codeVisionHost.providers.map { it.groupId }.toSet().forEach {
|
||||
settings.setProviderEnabled(it, enabledProviderGroupIds.contains(it))
|
||||
}
|
||||
TestModeFlags.set(CodeVisionHost.isCodeVisionTestKey, true, disposable)
|
||||
codeVisionHost.providers.forEach {
|
||||
if (it.id == "vcs.code.vision" && enabledProviderGroupIds.contains(it.groupId)) {
|
||||
it.preparePreview(editor, file)
|
||||
}
|
||||
}
|
||||
val document =
|
||||
requireNotNull(FileDocumentManager.getInstance().getDocument(virtualFile))
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
document.setText(sourceText)
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.document)
|
||||
}
|
||||
val newFile = requireNotNull(PsiDocumentManager.getInstance(project).getPsiFile(document, context))
|
||||
doHighlighting(newFile)
|
||||
codeVisionHost.calculateCodeVisionSync(editor, disposable)
|
||||
}
|
||||
}
|
||||
beforeAssert()
|
||||
assertText(expectedText)
|
||||
}
|
||||
|
||||
private suspend fun assertText(expectedText: String) {
|
||||
val sourceText = InlayDumpUtil.removeInlays(expectedText)
|
||||
val actualText = withContext(Dispatchers.EDT) {
|
||||
writeIntentReadAction {
|
||||
dumpCodeVisionHints(sourceText)
|
||||
}
|
||||
}
|
||||
assertEquals(expectedText, actualText)
|
||||
}
|
||||
|
||||
|
||||
private fun dumpCodeVisionHints(sourceText: String): String {
|
||||
return InlayDumpUtil.dumpInlays(
|
||||
sourceText, editor,
|
||||
filter = {
|
||||
val rendererSupported = it.renderer is CodeVisionInlayRenderer
|
||||
if (onlyCodeVisionHintsAllowed && !rendererSupported) error("renderer not supported")
|
||||
rendererSupported
|
||||
},
|
||||
renderer = { _, inlay ->
|
||||
inlay.getUserData(CodeVisionListData.KEY)!!.visibleLens.joinToString(prefix = "[",
|
||||
postfix = "]",
|
||||
separator = " ") { it.longPresentation }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun codeVisionFixture(editorFixture: TestFixture<Editor>, fileFixture: TestFixture<PsiFile>): TestFixture<CodeVisionTestFixture> =
|
||||
testFixture("code-vision-fixture") {
|
||||
val disposable = Disposer.newDisposable()
|
||||
val editor = editorFixture.init()
|
||||
val file = fileFixture.init()
|
||||
|
||||
val codeVisionFixture = CodeVisionTestFixture(editor, file.virtualFile, file.project, disposable)
|
||||
|
||||
initialized(codeVisionFixture) {
|
||||
// cleanup
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user