mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-18 23:42:49 +00:00
fix: compatibility issues
This commit is contained in:
parent
1f9f1fd5b8
commit
ef4991e2ea
9 changed files with 90 additions and 121 deletions
|
|
@ -6,7 +6,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComponentContainer;
|
||||
import com.intellij.openapi.wm.RegisterToolWindowTask;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
|
|
@ -17,6 +16,7 @@ import ee.carlrobert.codegpt.completions.ConversationType;
|
|||
import ee.carlrobert.codegpt.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.settings.prompts.PromptsSettings;
|
||||
import ee.carlrobert.codegpt.toolwindow.ProxyAIToolWindowFactory;
|
||||
import ee.carlrobert.codegpt.toolwindow.ToolWindowInitialState;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
|
@ -113,13 +113,18 @@ public final class ChatToolWindowContentManager {
|
|||
public @NotNull ToolWindow getToolWindow() {
|
||||
var toolWindowManager = ToolWindowManager.getInstance(project);
|
||||
var toolWindow = toolWindowManager.getToolWindow("ProxyAI");
|
||||
// https://intellij-support.jetbrains.com/hc/en-us/community/posts/11533368171026/comments/11538403084562
|
||||
return Objects.requireNonNullElseGet(toolWindow, () -> toolWindowManager
|
||||
.registerToolWindow(RegisterToolWindowTask.closable(
|
||||
"ProxyAI",
|
||||
() -> CodeGPTBundle.get("project.label"),
|
||||
Icons.DefaultSmall,
|
||||
ToolWindowAnchor.RIGHT)));
|
||||
if (toolWindow != null) {
|
||||
return toolWindow;
|
||||
}
|
||||
|
||||
var registeredToolWindow = toolWindowManager.registerToolWindow(
|
||||
"ProxyAI",
|
||||
true,
|
||||
ToolWindowAnchor.RIGHT);
|
||||
registeredToolWindow.setIcon(Icons.DefaultSmall);
|
||||
registeredToolWindow.setStripeTitle(CodeGPTBundle.get("project.label"));
|
||||
new ProxyAIToolWindowFactory().createToolWindowContent(project, registeredToolWindow);
|
||||
return registeredToolWindow;
|
||||
}
|
||||
|
||||
private Optional<Content> tryFindFirstChatTabContent() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package ee.carlrobert.codegpt.diagnostics
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
|
|
@ -101,14 +102,8 @@ class ProjectDiagnosticsService(
|
|||
error = "No PSI file found for: ${virtualFile.path}"
|
||||
)
|
||||
|
||||
val rangeHighlights = DaemonCodeAnalyzerImpl.getHighlights(
|
||||
document,
|
||||
filter.minimumSeverity(),
|
||||
project
|
||||
)
|
||||
|
||||
val fileLevel = getFileLevelHighlights(psiFile)
|
||||
val highlights = (rangeHighlights.asSequence() + fileLevel.asSequence())
|
||||
val highlights = collectHighlights(document, filter.minimumSeverity())
|
||||
.asSequence()
|
||||
.filter { filter.includes(it.severity) }
|
||||
.mapNotNull { highlight ->
|
||||
extractMessage(highlight)?.let { message ->
|
||||
|
|
@ -181,20 +176,22 @@ class ProjectDiagnosticsService(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getFileLevelHighlights(psiFile: com.intellij.psi.PsiFile): List<HighlightInfo> {
|
||||
return try {
|
||||
val method = DaemonCodeAnalyzerImpl::class.java.methods.firstOrNull {
|
||||
it.name == "getFileLevelHighlights" && it.parameterCount == 2
|
||||
}
|
||||
if (method != null) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
method.invoke(null, project, psiFile) as? List<HighlightInfo> ?: emptyList()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
emptyList()
|
||||
private fun collectHighlights(
|
||||
document: Document,
|
||||
minimumSeverity: HighlightSeverity
|
||||
): List<HighlightInfo> {
|
||||
val highlights = mutableListOf<HighlightInfo>()
|
||||
DaemonCodeAnalyzerEx.processHighlights(
|
||||
document,
|
||||
project,
|
||||
minimumSeverity,
|
||||
0,
|
||||
document.textLength
|
||||
) { highlight ->
|
||||
highlights.add(highlight)
|
||||
true
|
||||
}
|
||||
return highlights
|
||||
}
|
||||
|
||||
private fun extractMessage(info: HighlightInfo): String? {
|
||||
|
|
|
|||
|
|
@ -3,22 +3,11 @@ package ee.carlrobert.codegpt.inlineedit
|
|||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import ee.carlrobert.codegpt.CodeGPTKeys
|
||||
import java.awt.event.InputEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import javax.swing.KeyStroke
|
||||
|
||||
/**
|
||||
* Keyboard shortcuts for Inline Edit diff feature.
|
||||
*/
|
||||
class AcceptAllInlineEditAction : AnAction() {
|
||||
init {
|
||||
val keyStroke = KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_ENTER,
|
||||
InputEvent.META_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK
|
||||
)
|
||||
shortcutSet = CustomShortcutSet(KeyboardShortcut(keyStroke, null))
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
val session =
|
||||
|
|
@ -53,14 +42,6 @@ class AcceptAllInlineEditAction : AnAction() {
|
|||
}
|
||||
|
||||
class RejectAllInlineEditAction : AnAction() {
|
||||
init {
|
||||
val keyStroke = KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_BACK_SPACE,
|
||||
InputEvent.META_DOWN_MASK or InputEvent.SHIFT_DOWN_MASK
|
||||
)
|
||||
shortcutSet = CustomShortcutSet(KeyboardShortcut(keyStroke, null))
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
val session =
|
||||
|
|
@ -89,11 +70,6 @@ class RejectAllInlineEditAction : AnAction() {
|
|||
}
|
||||
|
||||
class RejectInlineEditAction : AnAction() {
|
||||
init {
|
||||
val keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)
|
||||
shortcutSet = CustomShortcutSet(KeyboardShortcut(keyStroke, null))
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
editor.getUserData(CodeGPTKeys.EDITOR_INLINE_EDIT_RENDERER)?.rejectNext()
|
||||
|
|
@ -110,14 +86,6 @@ class RejectInlineEditAction : AnAction() {
|
|||
}
|
||||
|
||||
class AcceptCurrentInlineEditAction : AnAction() {
|
||||
init {
|
||||
val keyStroke = KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_ENTER,
|
||||
InputEvent.META_DOWN_MASK
|
||||
)
|
||||
shortcutSet = CustomShortcutSet(KeyboardShortcut(keyStroke, null))
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
editor.getUserData(CodeGPTKeys.EDITOR_INLINE_EDIT_RENDERER)?.acceptNext()
|
||||
|
|
@ -134,14 +102,6 @@ class AcceptCurrentInlineEditAction : AnAction() {
|
|||
}
|
||||
|
||||
class RejectCurrentInlineEditAction : AnAction() {
|
||||
init {
|
||||
val keyStroke = KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_BACK_SPACE,
|
||||
InputEvent.META_DOWN_MASK
|
||||
)
|
||||
shortcutSet = CustomShortcutSet(KeyboardShortcut(keyStroke, null))
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
|
||||
editor.getUserData(CodeGPTKeys.EDITOR_INLINE_EDIT_RENDERER)?.rejectNext()
|
||||
|
|
|
|||
|
|
@ -7,26 +7,14 @@ import com.intellij.openapi.wm.ToolWindow
|
|||
import com.intellij.openapi.wm.ToolWindowFactory
|
||||
import com.intellij.ui.content.ContentManagerEvent
|
||||
import com.intellij.ui.content.ContentManagerListener
|
||||
import ee.carlrobert.codegpt.conversations.Conversation
|
||||
import ee.carlrobert.codegpt.settings.configuration.ChatMode
|
||||
import ee.carlrobert.codegpt.toolwindow.agent.AgentToolWindowPanel
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.ChatToolWindowPanel
|
||||
import ee.carlrobert.codegpt.toolwindow.history.ChatHistoryToolWindow
|
||||
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagDetails
|
||||
import javax.swing.JComponent
|
||||
|
||||
data class ToolWindowInitialState @JvmOverloads constructor(
|
||||
val conversation: Conversation,
|
||||
val tags: List<TagDetails> = emptyList(),
|
||||
val chatMode: ChatMode? = null,
|
||||
)
|
||||
|
||||
class ProxyAIToolWindowFactory : ToolWindowFactory, DumbAware {
|
||||
|
||||
override fun createToolWindowContent(
|
||||
project: Project,
|
||||
toolWindow: ToolWindow
|
||||
) {
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val agentToolWindowPanel = AgentToolWindowPanel(project).also {
|
||||
Disposer.register(toolWindow.disposable, it)
|
||||
}
|
||||
|
|
@ -51,8 +39,7 @@ class ProxyAIToolWindowFactory : ToolWindowFactory, DumbAware {
|
|||
}
|
||||
|
||||
private fun addContent(toolWindow: ToolWindow, panel: JComponent, displayName: String) {
|
||||
toolWindow.contentManager.let {
|
||||
it.addContent(it.factory.createContent(panel, displayName, false))
|
||||
}
|
||||
val contentManager = toolWindow.contentManager
|
||||
contentManager.addContent(contentManager.factory.createContent(panel, displayName, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package ee.carlrobert.codegpt.toolwindow
|
||||
|
||||
import ee.carlrobert.codegpt.conversations.Conversation
|
||||
import ee.carlrobert.codegpt.settings.configuration.ChatMode
|
||||
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagDetails
|
||||
|
||||
data class ToolWindowInitialState @JvmOverloads constructor(
|
||||
val conversation: Conversation,
|
||||
val tags: List<TagDetails> = emptyList(),
|
||||
val chatMode: ChatMode? = null,
|
||||
)
|
||||
|
|
@ -1,17 +1,16 @@
|
|||
package ee.carlrobert.codegpt.toolwindow.chat.editor.header
|
||||
|
||||
import com.intellij.codeInsight.documentation.DocumentationHintEditorPane
|
||||
import com.intellij.lang.documentation.DocumentationImageResolver
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.popup.JBPopup
|
||||
import com.intellij.ui.popup.PopupFactoryImpl
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.ui.components.JBScrollPane
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import ee.carlrobert.codegpt.CodeGPTBundle
|
||||
import java.awt.Image
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JEditorPane
|
||||
import javax.swing.Timer
|
||||
|
||||
class ErrorPopoverHandler(
|
||||
|
|
@ -54,24 +53,23 @@ class ErrorPopoverHandler(
|
|||
if (errorContent == null) return
|
||||
if (errorPopup?.isVisible == true) return
|
||||
|
||||
val documentationHint = DocumentationHintEditorPane(
|
||||
project,
|
||||
emptyMap(),
|
||||
object : DocumentationImageResolver {
|
||||
override fun resolveImage(url: String): Image? = null
|
||||
}
|
||||
).apply {
|
||||
setText(errorContent)
|
||||
val contentPane = JEditorPane("text/html", formatContent(errorContent)).apply {
|
||||
isEditable = false
|
||||
isOpaque = true
|
||||
border = JBUI.Borders.emptyTop(10)
|
||||
foreground = UIUtil.getToolTipForeground()
|
||||
background = UIUtil.getToolTipActionBackground()
|
||||
font = UIUtil.getToolTipFont()
|
||||
putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true)
|
||||
}
|
||||
val scrollPane = JBScrollPane(contentPane).apply {
|
||||
border = JBUI.Borders.empty()
|
||||
viewport.background = UIUtil.getToolTipActionBackground()
|
||||
background = UIUtil.getToolTipActionBackground()
|
||||
}
|
||||
|
||||
val popup = PopupFactoryImpl.getInstance()
|
||||
.createComponentPopupBuilder(documentationHint, null)
|
||||
val popup = JBPopupFactory.getInstance()
|
||||
.createComponentPopupBuilder(scrollPane, null)
|
||||
.setRequestFocus(false)
|
||||
.setResizable(true)
|
||||
.setMovable(true)
|
||||
|
|
@ -80,9 +78,7 @@ class ErrorPopoverHandler(
|
|||
.setCancelOnClickOutside(true)
|
||||
.createPopup()
|
||||
|
||||
documentationHint.setHint(popup)
|
||||
|
||||
documentationHint.addMouseListener(object : MouseAdapter() {
|
||||
val popupHoverListener = object : MouseAdapter() {
|
||||
override fun mouseEntered(e: MouseEvent) {
|
||||
errorLabel.putClientProperty("popupMouseInside", true)
|
||||
}
|
||||
|
|
@ -91,9 +87,33 @@ class ErrorPopoverHandler(
|
|||
errorLabel.putClientProperty("popupMouseInside", false)
|
||||
schedulePopupCloseIfNeeded()
|
||||
}
|
||||
})
|
||||
}
|
||||
contentPane.addMouseListener(popupHoverListener)
|
||||
scrollPane.addMouseListener(popupHoverListener)
|
||||
|
||||
errorPopup = popup
|
||||
popup.showUnderneathOf(errorLabel)
|
||||
}
|
||||
|
||||
private fun formatContent(content: String): String {
|
||||
return if (content.trimStart().startsWith("<html", ignoreCase = true)) {
|
||||
content
|
||||
} else {
|
||||
val escaped = buildString(content.length) {
|
||||
content.forEach { ch ->
|
||||
append(
|
||||
when (ch) {
|
||||
'<' -> "<"
|
||||
'>' -> ">"
|
||||
'&' -> "&"
|
||||
'"' -> """
|
||||
else -> ch
|
||||
}
|
||||
)
|
||||
}
|
||||
}.replace("\n", "<br/>")
|
||||
|
||||
"<html><body>$escaped</body></html>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.intellij.codeInsight.completion.PrioritizedLookupElement
|
|||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.codeStyle.NameUtil
|
||||
import com.intellij.codeInsight.lookup.LookupElementRenderer
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ abstract class AbstractLookupItem : LookupItem {
|
|||
presentation: LookupElementPresentation
|
||||
) {
|
||||
setPresentation(element, presentation)
|
||||
highlightMatches(presentation, searchText)
|
||||
emphasizeMatch(presentation, searchText)
|
||||
}
|
||||
})
|
||||
.apply {
|
||||
|
|
@ -28,7 +27,7 @@ abstract class AbstractLookupItem : LookupItem {
|
|||
return PrioritizedLookupElement.withPriority(lookupElement, 1.0)
|
||||
}
|
||||
|
||||
private fun highlightMatches(
|
||||
private fun emphasizeMatch(
|
||||
presentation: LookupElementPresentation,
|
||||
searchText: String
|
||||
) {
|
||||
|
|
@ -38,14 +37,9 @@ abstract class AbstractLookupItem : LookupItem {
|
|||
}
|
||||
|
||||
val matcher = NameUtil.buildMatcher("*$normalizedSearchText").build()
|
||||
matcher.matchingFragments(displayName)
|
||||
?.asReversed()
|
||||
?.forEach { range: TextRange ->
|
||||
presentation.decorateItemTextRange(
|
||||
range,
|
||||
LookupElementPresentation.LookupItemDecoration.HIGHLIGHT_MATCHED
|
||||
)
|
||||
}
|
||||
if (matcher.matchingFragments(displayName) != null) {
|
||||
presentation.isItemTextBold = true
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun getLookupString(): String
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
<depends optional="true" config-file="plugin-kotlin.xml">org.jetbrains.kotlin</depends>
|
||||
<depends optional="true" config-file="plugin-java.xml">com.intellij.modules.java</depends>
|
||||
<depends optional="true" config-file="plugin-javascript.xml">JavaScript</depends>
|
||||
<depends optional="true" config-file="plugin-cpp.xml">com.intellij.modules.cpp</depends>
|
||||
<!-- <depends optional="true" config-file="plugin-go.xml">org.jetbrains.plugins.go</depends>-->
|
||||
<!-- <depends optional="true" config-file="plugin-ruby.xml">com.intellij.modules.ruby</depends>-->
|
||||
<!-- <depends optional="true" config-file="plugin-php.xml">com.jetbrains.php</depends>-->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue