Parcourir la source

JetBrains: enhance terminal widget content retrieval for compatibility with 2025.3+

paviko il y a 2 mois
Parent
commit
ead9d6cfb9

+ 40 - 9
hosts/jetbrains-plugin/src/main/kotlin/paviko/opencode/backendprocess/BackendLauncher.kt

@@ -508,18 +508,37 @@ object BackendLauncher {
     }
 
     /**
-     * Helper to find the ToolWindow Content associated with a terminal widget.
-     * Replaces TerminalToolWindowManager.getContainer(...) which was removed in 2025.3.
-     */
+      * Helper to find the ToolWindow Content associated with a terminal widget.
+      * In 2025.3+ `TerminalToolWindowManager#getContainer(TerminalWidget)` exists, but reflection must
+      * not rely on the widget's concrete class (the method parameter is the `TerminalWidget` interface).
+      * For older builds, fall back to mapping via Swing hierarchy.
+      */
     private fun getContentForWidget(project: Project, widget: Any): com.intellij.ui.content.Content? {
-        // First try the old API if it exists (via reflection to avoid compilation/runtime errors if missing)
+        // First try the API on TerminalToolWindowManager if it exists.
+        // In 2025.3+ the public method is `getContainer(TerminalWidget)`.
+        // Earlier versions used different signatures and/or required mapping via Swing hierarchy.
         try {
             val manager = TerminalToolWindowManager.getInstance(project)
-            val method = manager.javaClass.getMethod("getContainer", widget.javaClass)
-            val container = method.invoke(manager, widget)
+            val direct = manager.javaClass.methods.firstOrNull { m ->
+                m.name == "getContainer" &&
+                    m.parameterCount == 1 &&
+                    m.parameterTypes.first().isAssignableFrom(widget.javaClass)
+            } ?: manager.javaClass.declaredMethods.firstOrNull { m ->
+                m.name == "getContainer" &&
+                    m.parameterCount == 1 &&
+                    m.parameterTypes.first().isAssignableFrom(widget.javaClass)
+            }?.apply { isAccessible = true }
+
+            val container = direct?.invoke(manager, widget)
             if (container != null) {
-                val contentMethod = container.javaClass.getMethod("getContent")
-                return contentMethod.invoke(container) as? com.intellij.ui.content.Content
+                val contentMethod = container.javaClass.methods.firstOrNull { m ->
+                    m.name == "getContent" && m.parameterCount == 0
+                } ?: container.javaClass.declaredMethods.firstOrNull { m ->
+                    m.name == "getContent" && m.parameterCount == 0
+                }?.apply { isAccessible = true }
+
+                val content = contentMethod?.invoke(container)
+                if (content is com.intellij.ui.content.Content) return content
             }
         } catch (e: Exception) {
             // Method missing or failed, proceed to fallback
@@ -542,7 +561,19 @@ object BackendLauncher {
         val toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Terminal") ?: return null
         val contentManager = toolWindow.contentManager
 
-        for (content in contentManager.contents) {
+        val contents = try {
+            val m = contentManager.javaClass.methods.firstOrNull { it.name == "getContentsRecursively" && it.parameterCount == 0 }
+            val result = m?.invoke(contentManager)
+            when (result) {
+                is Array<*> -> result.filterIsInstance<com.intellij.ui.content.Content>()
+                is Iterable<*> -> result.filterIsInstance<com.intellij.ui.content.Content>()
+                else -> contentManager.contents.toList()
+            }
+        } catch (_: Exception) {
+            contentManager.contents.toList()
+        }
+
+        for (content in contents) {
             if (SwingUtilities.isDescendingFrom(component, content.component)) {
                 return content
             }