mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[ByteCodeViewer] IDEA-375353 Synchronize the class file being shown with the source file open in the main editor
This is optional, the user can toggle/untoggle this behavior. GitOrigin-RevId: 6e7b8420db67b6b2fd6b36426e6f2a1478fee5bd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c98c8991d4
commit
6304c351f6
@@ -1,5 +1,6 @@
|
||||
action.BytecodeViewer.text=Show Bytecode
|
||||
action.show.debug.action.name=Show Debug Info
|
||||
action.sync.with.editor.name=Sync With Editor
|
||||
deserialization.error=Could not read class file
|
||||
bytecode.not.found.title=Could not find bytecode
|
||||
please.build.project=Please build the project and try again.
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.byteCodeViewer
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.ui.content.Content
|
||||
|
||||
/**
|
||||
* Synchronizes the bytecode viewer with the currently active editor.
|
||||
* When the user switches between files in the editor, this service will
|
||||
* automatically switch to the corresponding bytecode in the bytecode viewer.
|
||||
*/
|
||||
@Service(Service.Level.PROJECT)
|
||||
class BytecodeEditorSynchronizer(private val project: Project) : FileEditorManagerListener {
|
||||
|
||||
/**
|
||||
* Called when the selected editor changes.
|
||||
* If sync with editor is enabled, this will switch to the corresponding bytecode.
|
||||
*/
|
||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||
if (!BytecodeViewerSettings.getInstance().state.syncWithEditor) return
|
||||
|
||||
val virtualFile = event.newFile ?: return
|
||||
val toolWindow = ToolWindowManager.getInstance(project).getToolWindow(BytecodeToolWindowPanel.TOOL_WINDOW_ID) ?: return
|
||||
if (!toolWindow.isVisible) return
|
||||
val content = findContentForSourceFile(toolWindow.contentManager.contents, virtualFile) ?: return
|
||||
toolWindow.contentManager.setSelectedContent(content)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the content pane (tab) in the bytecode viewer tool window that corresponds to the given `sourceFile`.
|
||||
*/
|
||||
private fun findContentForSourceFile(contents: Array<Content>, sourceFile: VirtualFile): Content? {
|
||||
val psiFile = PsiManager.getInstance(project).findFile(sourceFile) ?: return null
|
||||
if (psiFile !is PsiJavaFile) return null
|
||||
for (psiClass in psiFile.classes) {
|
||||
val classFile = ByteCodeViewerManager.findClassFile(psiClass) ?: continue
|
||||
val content = contents.firstOrNull { it.getUserData(JAVA_CLASS_FILE) == classFile } ?: continue
|
||||
return content
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): BytecodeEditorSynchronizer {
|
||||
return project.getService(BytecodeEditorSynchronizer::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,10 @@ import com.intellij.openapi.components.*
|
||||
@Service(Service.Level.APP)
|
||||
@State(name = "BytecodeViewerSettings", storages = [Storage(StoragePathMacros.NON_ROAMABLE_FILE)])
|
||||
internal class BytecodeViewerSettings : PersistentStateComponent<BytecodeViewerSettings.State> {
|
||||
data class State(var showDebugInfo: Boolean = true)
|
||||
data class State(
|
||||
var showDebugInfo: Boolean = true,
|
||||
var syncWithEditor: Boolean = true,
|
||||
)
|
||||
|
||||
private var myState = State()
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.icons.AllIcons
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.wm.IdeFocusManager
|
||||
@@ -34,6 +35,12 @@ internal class ShowBytecodeAction : AnAction() {
|
||||
}
|
||||
BytecodeToolWindowService.getInstance(project).ensureContentManagerListenerRegistered(toolWindow)
|
||||
|
||||
// Register the editor synchronizer if not already registered
|
||||
project.messageBus.connect(toolWindow.disposable).subscribe(
|
||||
topic = FileEditorManagerListener.FILE_EDITOR_MANAGER,
|
||||
handler = BytecodeEditorSynchronizer.getInstance(project),
|
||||
)
|
||||
|
||||
val editor = event.getData(CommonDataKeys.EDITOR) ?: return
|
||||
val psiFile = event.getData(CommonDataKeys.PSI_FILE) ?: return
|
||||
val psiElement = psiFile.findElementAt(editor.caretModel.offset) ?: return
|
||||
@@ -85,7 +92,7 @@ internal class ShowBytecodeAction : AnAction() {
|
||||
}
|
||||
|
||||
private fun createActionGroup(): ActionGroup {
|
||||
val action = object : ToggleAction(BytecodeViewerBundle.messagePointer("action.show.debug.action.name")) {
|
||||
val showDebugAction = object : ToggleAction(BytecodeViewerBundle.messagePointer("action.show.debug.action.name")) {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
||||
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
@@ -102,6 +109,19 @@ internal class ShowBytecodeAction : AnAction() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return DefaultActionGroup(action)
|
||||
|
||||
val syncWithEditorAction = object : ToggleAction(BytecodeViewerBundle.messagePointer("action.sync.with.editor.name")) {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.EDT
|
||||
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
return BytecodeViewerSettings.getInstance().state.syncWithEditor
|
||||
}
|
||||
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
BytecodeViewerSettings.getInstance().state.syncWithEditor = state
|
||||
}
|
||||
}
|
||||
|
||||
return DefaultActionGroup(showDebugAction, syncWithEditorAction)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user