void (@NotNull AnActionEvent e) { final DataContext dataContext = e.getDataContext(); final Project project = e.getProject(); if (project == null) return; final Editor editor = e.getData(CommonDataKeys.EDITOR); final PsiElement psiElement = getPsiElement(dataContext, project, editor); if (psiElement == null) return; // Some PSI elements could be multiline. Try to be precise about the line we were invoked at. int lineNumber = editor != null ? editor.getCaretModel().getLogicalPosition().line : -1; if (ByteCodeViewerManager.getContainingClass(psiElement) == null) { Messages.showWarningDialog(project, JavaByteCodeViewerBundle.message("bytecode.class.in.selection.message"), JavaByteCodeViewerBundle.message("bytecode.not.found.message")); return; } final String psiElementTitle = ByteCodeViewerManager.getInstance(project).getTitle(psiElement); final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(psiElement); if (virtualFile == null) return; final RelativePoint bestPopupLocation = JBPopupFactory.getInstance().guessBestPopupLocation(dataContext); final SmartPsiElementPointer element = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiElement); ProgressManager.getInstance().run(new Task.Backgroundable(project, JavaByteCodeViewerBundle.message("looking.for.bytecode.progress")) { private String myByteCode; private @Nls String myErrorTitle; @Override public void run(@NotNull ProgressIndicator indicator) { if (ReadAction.compute(() -> ProjectRootManager.getInstance(project).getFileIndex().isInContent(virtualFile)) && isMarkedForCompilation(project, virtualFile)) { myErrorTitle = JavaByteCodeViewerBundle.message("class.file.may.be.out.of.date"); } myByteCode = ReadAction.compute(() -> { PsiElement targetElement = element.getElement(); return targetElement != null ? ByteCodeViewerManager.getByteCode(targetElement) : null; }); } @Override public void onSuccess() { if (project.isDisposed()) return; final PsiElement targetElement = element.getElement(); if (targetElement == null) return; final ByteCodeViewerManager codeViewerManager = ByteCodeViewerManager.getInstance(project); if (codeViewerManager.hasActiveDockedDocWindow()) { codeViewerManager.doUpdateComponent(targetElement, lineNumber, myByteCode); } else { if (myByteCode == null) { Messages.showErrorDialog(project, JavaByteCodeViewerBundle.message("bytecode.parser.failure.message", psiElementTitle), JavaByteCodeViewerBundle.message("bytecode.not.found.title")); return; } final ByteCodeViewerComponent component = new ByteCodeViewerComponent(project); component.setText(myByteCode, targetElement, lineNumber); Processor<JBPopup> pinCallback = popup -> { codeViewerManager.recreateToolWindow(targetElement, targetElement); popup.cancel(); return false; }; if (myErrorTitle != null) { JLabel errorLabel = new JLabel(myErrorTitle); Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.NOTIFICATION_BACKGROUND); if (color != null) { errorLabel.setBorder(new JBEmptyBorder(2)); errorLabel.setBackground(color); errorLabel.setOpaque(true); } component.add(errorLabel, BorderLayout.NORTH); } final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component.getEditorComponent()) .setProject(project) .setDimensionServiceKey(project, ShowByteCodeAction.class.getName(), false) .setResizable(true) .setMovable(true) .setRequestFocus(LookupManager.getActiveLookup(editor) == null) .setTitle(JavaByteCodeViewerBundle.message("popup.title.element.bytecode", psiElementTitle)) .setCouldPin(pinCallback) .createPopup(); Disposer.register(popup, component); if (editor != null) { popup.showInBestPositionFor(editor); } else { popup.show(bestPopupLocation); } } } }); }