From b1799dcc24fd9310afc50d3754463b7ad729c146 Mon Sep 17 00:00:00 2001 From: Bartek Pacia Date: Fri, 31 Oct 2025 21:26:20 +0100 Subject: [PATCH] [ByteCodeViewer] IDEA-375559 make Bytecode Viewer work for Kotlin and Groovy sources Probably it works for Scala sources too, but I didn't have any sample Scala project at hand (and have never written a line of Scala). Previously, the Bytecode Viewer didn't work if triggered for Kotlin, Groovy, or Scala source file (though it worked if it was invoked on a .class file generated from their sources). This potentially obsoletes the Kotlin's completely separate implementation of a bytecode viewer, accessible through the "Show Kotlin Bytecode" action. Kudos to Nikita Skvortsov for telling me about the CompilerPaths#getOutputPaths method! GitOrigin-RevId: 365fe2305c04536055f616f8d165a325f14ece8b --- .../byteCodeViewer/ByteCodeViewerManager.kt | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.kt b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.kt index c5a2e3721393..e4d70b38640b 100644 --- a/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.kt +++ b/plugins/ByteCodeViewer/src/com/intellij/byteCodeViewer/ByteCodeViewerManager.kt @@ -2,12 +2,13 @@ package com.intellij.byteCodeViewer import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.openapi.compiler.CompilerPaths import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.fileTypes.FileTypeRegistry -import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.resolveFromRootOrRelative import com.intellij.psi.PsiClass import com.intellij.psi.PsiClassOwner @@ -17,6 +18,7 @@ import com.intellij.psi.util.ClassUtil import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.parentsOfType +import java.nio.file.Path import java.util.* public object ByteCodeViewerManager { @@ -47,15 +49,17 @@ public object ByteCodeViewerManager { // source code; looking for a .class file in compiler output val fileIndex = ProjectFileIndex.getInstance(psiClass.project) val module = fileIndex.getModuleForFile(file) ?: return null - val compilerModuleExtension = CompilerModuleExtension.getInstance(module) ?: return null - val classRoot = when (fileIndex.isInTestSourceContent(file)) { - true -> compilerModuleExtension.compilerOutputPathForTests - false -> compilerModuleExtension.compilerOutputPath + for (compilerOutputPath in CompilerPaths.getOutputPaths(arrayOf(module))) { + if (compilerOutputPath == null) continue + val classRoot = VirtualFileManager.getInstance().findFileByNioPath(Path.of(compilerOutputPath)) ?: continue + val relativeClassFilePath = jvmClassName.replace('.', '/') + ".class" + val classFile = classRoot.resolveFromRootOrRelative(relativeClassFilePath) + if (classFile != null) { + return classFile + } } - if (classRoot == null) return null - val relativeClassFilePath = jvmClassName.replace('.', '/') + ".class" - return classRoot.resolveFromRootOrRelative(relativeClassFilePath) } + return null } @Deprecated(message = "Use findClassFile instead")