@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.api.analyze
12
12
import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinPackagePartProviderFactory
13
13
import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol
14
14
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
15
+ import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
15
16
import org.jetbrains.kotlin.idea.references.mainReference
16
17
import org.jetbrains.kotlin.psi.KtFile
17
18
import org.jetbrains.kotlin.psi.KtReferenceExpression
@@ -29,10 +30,23 @@ fun goToDefinitionAction(ktFile: KtFile, position: Position): Location? = analyz
29
30
val ref = ktFile.findReferenceAt(offset) ? : return null
30
31
val element = ref.resolve() ? : return tryResolveFromKotlinLibrary(ktFile, offset)
31
32
val file = element.containingFile ? : return null
33
+
34
+ // It comes from a java .class file
32
35
if (file.viewProvider.document == null ) {
33
- // This comes from a java .class file
34
- // TODO Handle the case of JDK .class files (jrt:// urls)
35
- return tryDecompileJavaClass(file)
36
+ if (file.virtualFile.url.startsWith(" jrt:/" )) {
37
+ // Comes from JDK
38
+ val classFile = File .createTempFile(" jrtClass" , " .class" )
39
+ classFile.writeBytes(file.virtualFile.contentsToByteArray())
40
+ val result = tryDecompileJavaClass(classFile.toPath())
41
+ classFile.delete()
42
+ return result
43
+ } else {
44
+ // Comes from JAR
45
+ val classFile = extractClassFromJar(" ${file.containingDirectory} /${file.containingFile.name} " ) ? : return null
46
+ val result = tryDecompileJavaClass(classFile.toPath())
47
+ classFile.delete()
48
+ return result
49
+ }
36
50
}
37
51
val range = element.textRange.toLspRange(file)
38
52
val folder = file.containingDirectory.toString().removePrefix(" PsiDirectory:" )
@@ -83,18 +97,17 @@ private fun KaSession.tryResolveFromKotlinLibrary(ktFile: KtFile, offset: Int):
83
97
}
84
98
}
85
99
86
- private fun tryDecompileJavaClass (file : PsiFile ): Location ? {
87
- val classFile = extractClassFromJar(" ${file.containingDirectory} /${file.containingFile.name} " ) ? : return null
100
+ private fun tryDecompileJavaClass (path : Path ): Location ? {
88
101
val outputDir = Files .createTempDirectory(" fernflower_output" ).toFile()
89
102
try {
90
103
val args = arrayOf(
91
104
" -jpr=1" ,
92
- classFile.absolutePath ,
105
+ path.absolutePathString() ,
93
106
outputDir.absolutePath
94
107
)
95
108
ConsoleDecompiler .main(args)
96
109
97
- val outName = classFile.toPath() .fileName.replaceExtensionWith(" .java" )
110
+ val outName = path .fileName.replaceExtensionWith(" .java" )
98
111
val outPath = outputDir.toPath().resolve(outName)
99
112
if (! Files .exists(outPath)) return null
100
113
outPath.toFile().setWritable(false )
@@ -109,8 +122,6 @@ private fun tryDecompileJavaClass(file: PsiFile): Location? {
109
122
} catch (e: Exception ) {
110
123
warn(e.message ? : " Unknown fernflower error" )
111
124
return null
112
- } finally {
113
- classFile.delete()
114
125
}
115
126
}
116
127
0 commit comments