mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[command-completion] IDEA-370147 Reimplement AI action for command completion
GitOrigin-RevId: b9a19b9f6b598af6e08745c72f5871fef033b17c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d821b16af8
commit
e78808cc18
@@ -286,6 +286,11 @@ c:com.intellij.codeInsight.actions.VcsFacade
|
||||
- getPriority():java.lang.Integer
|
||||
- getSynonyms():java.util.List
|
||||
- f:setActionId(java.lang.String):V
|
||||
*:com.intellij.codeInsight.completion.command.commands.ErrorFixCommandProvider
|
||||
- com.intellij.openapi.project.PossiblyDumbAware
|
||||
- *sf:Companion:com.intellij.codeInsight.completion.command.commands.ErrorFixCommandProvider$Companion
|
||||
- a:getCommands(com.intellij.psi.PsiFile,java.util.List,I):java.util.List
|
||||
*f:com.intellij.codeInsight.completion.command.commands.ErrorFixCommandProvider$Companion
|
||||
*:com.intellij.codeInsight.completion.command.commands.IntentionCommandOffsetProvider
|
||||
- *sf:Companion:com.intellij.codeInsight.completion.command.commands.IntentionCommandOffsetProvider$Companion
|
||||
- findOffsets(com.intellij.psi.PsiFile,I):java.util.List
|
||||
|
||||
+27
-49
@@ -34,15 +34,14 @@ import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx
|
||||
import com.intellij.openapi.editor.impl.DocumentMarkupModel
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.progress.jobToIndicator
|
||||
import com.intellij.openapi.progress.runBlockingCancellable
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.openapi.project.PossiblyDumbAware
|
||||
import com.intellij.openapi.project.ProjectTypeService
|
||||
import com.intellij.openapi.util.Iconable
|
||||
import com.intellij.openapi.util.Iconable.ICON_FLAG_VISIBILITY
|
||||
@@ -51,7 +50,6 @@ import com.intellij.openapi.util.ProperTextRange
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager.Companion.getInstance
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageEditorUtil
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
@@ -316,7 +314,6 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
TextRange(injectedLanguageManager.injectedToHost(psiFile, 0),
|
||||
injectedLanguageManager.injectedToHost(psiFile, psiFile.fileDocument.textLength)))
|
||||
}
|
||||
var attemptToAddAi = false
|
||||
val lazyQuickFixUpdater = LazyQuickFixUpdater.getInstance(psiFile.project)
|
||||
for (info: HighlightInfo? in errorHighlightings) {
|
||||
if (info == null) continue
|
||||
@@ -326,20 +323,6 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
info.updateLazyFixesPsiTimeStamp(PsiModificationTracker.getInstance(psiFile.project).modificationCount)
|
||||
lazyQuickFixUpdater.waitQuickFixesSynchronously(psiFile, editor, info)
|
||||
}
|
||||
if (!attemptToAddAi && info.severity == HighlightSeverity.ERROR) {
|
||||
val intentionsInfo: IntentionsInfo? = tryToAddAI(info, psiFile, editor, offset)
|
||||
if (intentionsInfo != null) {
|
||||
val intentionsCache = CachedIntentions(psiFile.project, psiFile, editor)
|
||||
intentionsCache.wrapAndUpdateActions(intentionsInfo, false)
|
||||
for (descriptor in intentionsCache.errorFixes) {
|
||||
val command = IntentionCompletionCommand(descriptor, 50, AllIcons.Actions.QuickfixBulb,
|
||||
HighlightInfoLookup(TextRange(info.startOffset, info.endOffset),
|
||||
CodeInsightColors.ERRORS_ATTRIBUTES, 100), offset) { null }
|
||||
result.add(command)
|
||||
}
|
||||
}
|
||||
attemptToAddAi = true
|
||||
}
|
||||
val fixes: MutableList<IntentionActionDescriptor> = ArrayList()
|
||||
ShowIntentionsPass.addAvailableFixesForGroups(info, topLevelEditor, topLevelFile, fixes, -1, offset, false)
|
||||
for (descriptor in fixes) {
|
||||
@@ -362,6 +345,7 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
result.add(command)
|
||||
}
|
||||
}
|
||||
result.addAll(errorFixesWithHighlighting(psiFile, errorHighlightings, offset))
|
||||
}
|
||||
catch (e: Exception) {
|
||||
if (e is ControlFlowException || e is CancellationException) {
|
||||
@@ -374,34 +358,15 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* temporary workaround for fix with AI
|
||||
*/
|
||||
private fun tryToAddAI(info: HighlightInfo, psiFile: PsiFile, editor: Editor, offset: Int): IntentionsInfo? {
|
||||
val copyFile = PsiFileFactory.getInstance(editor.project)
|
||||
.createFileFromText(psiFile.getName(), psiFile.getLanguage(), psiFile.fileDocument.text, true, true, false, psiFile.virtualFile)
|
||||
val markup = DocumentMarkupModel.forDocument(copyFile.fileDocument, psiFile.project, true) as? MarkupModelEx ?: return null
|
||||
val textAttributesKey = if (info.forcedTextAttributesKey == null) info.type.getAttributesKey() else info.forcedTextAttributesKey
|
||||
val highlighter = markup.addRangeHighlighter(textAttributesKey, info.startOffset, info.endOffset, 5000, HighlighterTargetArea.EXACT_RANGE)
|
||||
highlighter.errorStripeTooltip = info
|
||||
val dumbService = DumbService.getInstance(psiFile.project)
|
||||
val intentions = IntentionsInfo()
|
||||
val copyEditor = MyEditor(copyFile, editor.settings)
|
||||
copyEditor.caretModel.moveToOffset(offset)
|
||||
for (extension in IntentionMenuContributor.EP_NAME.extensionList) {
|
||||
if (extension.javaClass.name != "com.intellij.ml.llm.inlinePromptDetector.fixWithAi.FixWithAiIntentionMenuContributor") continue
|
||||
ProgressManager.checkCanceled()
|
||||
try {
|
||||
if (dumbService.isUsableInCurrentContext(extension)) {
|
||||
extension.collectActions(copyEditor, copyFile, intentions, -1, offset)
|
||||
}
|
||||
}
|
||||
catch (_: IntentionPreviewUnsupportedOperationException) {
|
||||
//can collect action on a mock memory editor and produce exceptions - ignore
|
||||
}
|
||||
private fun errorFixesWithHighlighting(psiFile: PsiFile, errorHighlightings: List<HighlightInfo?>, offset: Int): Collection<CompletionCommand> {
|
||||
val project = psiFile.project
|
||||
val dumbService = DumbService.getInstance(project)
|
||||
val result = mutableListOf<CompletionCommand>()
|
||||
val highlightInfos = errorHighlightings.filterNotNull()
|
||||
for (provider in dumbService.filterByDumbAwareness(ErrorFixCommandProvider.EP_NAME.extensionList)) {
|
||||
result.addAll(provider.getCommands(psiFile, highlightInfos, offset))
|
||||
}
|
||||
|
||||
return intentions
|
||||
return result
|
||||
}
|
||||
|
||||
private fun CoroutineScope.asyncIntentions(
|
||||
@@ -448,9 +413,7 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
try {
|
||||
ProgressManager.checkCanceled()
|
||||
if (!dumbService.isUsableInCurrentContext(intention) ||
|
||||
!intention.action.isAvailable(originalFile.project, editor, psiFile) &&
|
||||
//todo temporary workaround for AI
|
||||
intention.action.familyName !in ("AI Actions…") ||
|
||||
!intention.action.isAvailable(originalFile.project, editor, psiFile) ||
|
||||
!filter.test(intention.action)) {
|
||||
toRemove.add(intention)
|
||||
}
|
||||
@@ -532,6 +495,21 @@ private fun getInspectionTools(profile: InspectionProfileWrapper, file: PsiFile)
|
||||
return enabled
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class allows language plugins to contribute specialized error fix commands to IntelliJ's completion system.
|
||||
* These commands are displayed when errors are detected in the code and provide context-specific fixes.
|
||||
*
|
||||
*/
|
||||
interface ErrorFixCommandProvider : PossiblyDumbAware {
|
||||
|
||||
fun getCommands(psiFile: PsiFile, errorHighlightings: List<HighlightInfo>, offset: Int): List<CompletionCommand>
|
||||
|
||||
companion object {
|
||||
internal val EP_NAME: ExtensionPointName<ErrorFixCommandProvider> = ExtensionPointName.create("com.intellij.codeInsight.completion.error.intention")
|
||||
}
|
||||
}
|
||||
|
||||
interface IntentionCommandSkipper {
|
||||
companion object {
|
||||
internal val EP_NAME: LanguageExtension<IntentionCommandSkipper> = LanguageExtension<IntentionCommandSkipper>("com.intellij.codeInsight.completion.intention.skipper")
|
||||
|
||||
@@ -767,6 +767,7 @@
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
|
||||
<with attribute="implementationClass" implements="com.intellij.codeInsight.completion.command.commands.IntentionCommandSkipper"/>
|
||||
</extensionPoint>
|
||||
<extensionPoint name="codeInsight.completion.error.intention" interface="com.intellij.codeInsight.completion.command.commands.ErrorFixCommandProvider" dynamic="true"/>
|
||||
|
||||
<extensionPoint qualifiedName="com.intellij.codeInsight.completion.intention.offset.provider"
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint" dynamic="true">
|
||||
|
||||
Reference in New Issue
Block a user