From 1eeb202a1af2f3bd21166f18d4d9d876f15c7277 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 24 May 2018 14:00:14 +0300 Subject: [PATCH] Use background task for Kotlin decompiler (KT-23981) #KT-23981 Fixed --- .../internal/KotlinDecompilerServiceImpl.kt | 14 ++++-- .../idea/internal/KotlinDecompilerAdapter.kt | 49 +++++++++++++------ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerServiceImpl.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerServiceImpl.kt index fa16bd65d37..83b79eefd04 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerServiceImpl.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerServiceImpl.kt @@ -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 ByteArray> = runReadAction { + when { + file.canBeDecompiledToJava() -> bytecodeMapForExistingClassfile(file.virtualFile) + !file.isCompiled -> bytecodeMapForSourceFile(file) + else -> null + } + } ?: return null + val resultSaver = KotlinResultSaver() val options = hashMapOf( IFernflowerPreferences.REMOVE_BRIDGE to "0" diff --git a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerAdapter.kt b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerAdapter.kt index 5fd1269bbdd..7632d8c57ee 100644 --- a/idea/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerAdapter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/internal/KotlinDecompilerAdapter.kt @@ -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) + } + } } }