Use background task for Kotlin decompiler (KT-23981)

#KT-23981 Fixed
This commit is contained in:
Nikolay Krasko
2018-05-24 14:00:14 +03:00
parent 6c56a7949c
commit 1eeb202a1a
2 changed files with 42 additions and 21 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.idea.actions.canBeDecompiledToJava
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
import java.util.jar.Manifest
@@ -36,11 +37,14 @@ import java.util.jar.Manifest
class KotlinDecompilerServiceImpl : KotlinDecompilerService {
override fun decompile(file: KtFile): String? {
try {
val bytecodeMap = when {
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
!file.isCompiled -> bytecodeMapForSourceFile(file)
else -> return null
}
val bytecodeMap: Map<File, () -> ByteArray> = runReadAction {
when {
file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile)
!file.isCompiled -> bytecodeMapForSourceFile(file)
else -> null
}
} ?: return null
val resultSaver = KotlinResultSaver()
val options = hashMapOf<String, Any>(
IFernflowerPreferences.REMOVE_BRIDGE to "0"
@@ -5,7 +5,11 @@
package org.jetbrains.kotlin.idea.internal
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VfsUtil
@@ -16,25 +20,38 @@ import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFile
fun showDecompiledCode(sourceFile: KtFile) {
val decompilerService = KotlinDecompilerService.getInstance() ?: return
val decompiledCode = try {
decompilerService.decompile(sourceFile)
} catch (e: DecompileFailedException) {
null
}
ProgressManager.getInstance().run(KotlinBytecodeDecompilerTask(sourceFile))
}
if (decompiledCode == null) {
Messages.showErrorDialog("Cannot decompile ${sourceFile.name}", "Decompiler error")
return
}
class KotlinBytecodeDecompilerTask(val file: KtFile) : Task.Backgroundable(file.project, "Decompile kotlin bytecode") {
override fun run(indicator: ProgressIndicator) {
val decompilerService = KotlinDecompilerService.getInstance() ?: return
runWriteAction {
val root = getOrCreateDummyRoot()
val decompiledFileName = FileUtil.getNameWithoutExtension(sourceFile.name) + ".decompiled.java"
val result = DummyFileSystem.getInstance().createChildFile(null, root, decompiledFileName)
VfsUtil.saveText(result, decompiledCode)
indicator.text = "Decompiling ${file.name}"
OpenFileDescriptor(sourceFile.project, result).navigate(true)
val decompiledText = try {
decompilerService.decompile(file)
} catch (e: DecompileFailedException) {
null
}
ApplicationManager.getApplication().invokeLater {
runWriteAction {
if (!file.isValid || file.project.isDisposed) return@runWriteAction
if (decompiledText == null) {
Messages.showErrorDialog("Cannot decompile ${file.name}", "Decompiler error")
return@runWriteAction
}
val root = getOrCreateDummyRoot()
val decompiledFileName = FileUtil.getNameWithoutExtension(file.name) + ".decompiled.java"
val result = DummyFileSystem.getInstance().createChildFile(null, root, decompiledFileName)
VfsUtil.saveText(result, decompiledText)
OpenFileDescriptor(file.project, result).navigate(true)
}
}
}
}