IDEA-338011 cleanup

GitOrigin-RevId: d2c47516160c4496a66f17b50a40e3532ab3a0fa
This commit is contained in:
Vladimir Krivosheev
2023-11-20 13:32:02 +01:00
committed by intellij-monorepo-bot
parent c0150a09ca
commit 378e147165
4 changed files with 83 additions and 79 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.java.decompiler
import com.intellij.application.options.CodeStyle
@@ -39,81 +39,55 @@ import java.util.concurrent.Callable
import java.util.concurrent.Future
import java.util.jar.Manifest
const val IDEA_DECOMPILER_BANNER: String = "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by FernFlower decompiler)\n//\n\n"
class IdeaDecompiler : ClassFileDecompilers.Light() {
companion object {
const val BANNER: String = "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by FernFlower decompiler)\n//\n\n"
private const val LEGAL_NOTICE_KEY = "decompiler.legal.notice.accepted"
private const val POSTPONE_EXIT_CODE = DialogWrapper.CANCEL_EXIT_CODE
private const val DECLINE_EXIT_CODE = DialogWrapper.NEXT_USER_EXIT_CODE
private val TASK_KEY: Key<Future<CharSequence>> = Key.create("java.decompiler.optimistic.task")
private fun getOptions(): Map<String, Any> {
val options = CodeStyle.getDefaultSettings().getIndentOptions(JavaFileType.INSTANCE)
val indent = StringUtil.repeat(" ", options.INDENT_SIZE)
return mapOf(
IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR to "0",
IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1",
IFernflowerPreferences.REMOVE_SYNTHETIC to "1",
IFernflowerPreferences.REMOVE_BRIDGE to "1",
IFernflowerPreferences.NEW_LINE_SEPARATOR to "1",
IFernflowerPreferences.BANNER to BANNER,
IFernflowerPreferences.MAX_PROCESSING_METHOD to 60,
IFernflowerPreferences.INDENT_STRING to indent,
IFernflowerPreferences.IGNORE_INVALID_BYTECODE to "1",
IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES to "1",
//IFernflowerPreferences.UNIT_TEST_MODE to if (ApplicationManager.getApplication().isUnitTestMode) "1" else "0"
)
}
private fun canWork(): Boolean =
ApplicationManager.getApplication().isUnitTestMode || PropertiesComponent.getInstance().isValueSet(LEGAL_NOTICE_KEY)
}
class LegalBurden : FileEditorManagerListener.Before {
private var myShowNotice = !canWork()
private var showNotice = !canWork()
override fun beforeFileOpened(source: FileEditorManager, file: VirtualFile) {
if (myShowNotice && file.fileType === JavaClassFileType.INSTANCE) {
val decompiler = ClassFileDecompilers.getInstance().find(file, ClassFileDecompilers.Light::class.java)
if (decompiler is IdeaDecompiler) {
TASK_KEY.set(file, ApplicationManager.getApplication().executeOnPooledThread(Callable { decompiler.decompile(file) }))
if (!showNotice || file.fileType !== JavaClassFileType.INSTANCE) {
return
}
val title = IdeaDecompilerBundle.message("legal.notice.title", StringUtil.last(file.path, 40, true))
val message = IdeaDecompilerBundle.message("legal.notice.text")
val result = LegalNoticeDialog.build(title, message)
.withCancelText(IdeaDecompilerBundle.message("legal.notice.action.postpone"))
.withCustomAction(IdeaDecompilerBundle.message("legal.notice.action.reject"), DECLINE_EXIT_CODE)
.show()
when (result) {
DialogWrapper.OK_EXIT_CODE -> {
myShowNotice = false
PropertiesComponent.getInstance().setValue(LEGAL_NOTICE_KEY, true)
ApplicationManager.getApplication().invokeLater { FileContentUtilCore.reparseFiles(file) }
}
val decompiler = ClassFileDecompilers.getInstance().find(file, ClassFileDecompilers.Light::class.java)
if (decompiler !is IdeaDecompiler) {
return
}
DECLINE_EXIT_CODE -> {
myShowNotice = false
TASK_KEY.set(file, null)
TASK_KEY.set(file, ApplicationManager.getApplication().executeOnPooledThread(Callable { decompiler.decompile(file) }))
val id = PluginId.getId("org.jetbrains.java.decompiler")
PluginManagerCore.disablePlugin(id)
val title = IdeaDecompilerBundle.message("legal.notice.title", StringUtil.last(file.path, 40, true))
val message = IdeaDecompilerBundle.message("legal.notice.text")
val result = LegalNoticeDialog.build(title, message)
.withCancelText(IdeaDecompilerBundle.message("legal.notice.action.postpone"))
.withCustomAction(IdeaDecompilerBundle.message("legal.notice.action.reject"), DECLINE_EXIT_CODE)
.show()
when (result) {
DialogWrapper.OK_EXIT_CODE -> {
showNotice = false
PropertiesComponent.getInstance().setValue(LEGAL_NOTICE_KEY, true)
ApplicationManager.getApplication().invokeLater { FileContentUtilCore.reparseFiles(file) }
}
val plugin = PluginManagerCore.getPlugin(id)
if (plugin is IdeaPluginDescriptorImpl && DynamicPlugins.allowLoadUnloadWithoutRestart(plugin)) {
ApplicationManager.getApplication().invokeLater {
DynamicPlugins.unloadPlugin(plugin, DynamicPlugins.UnloadPluginOptions(save = false))
}
}
}
DECLINE_EXIT_CODE -> {
showNotice = false
TASK_KEY.set(file, null)
POSTPONE_EXIT_CODE -> {
TASK_KEY.set(file, null)
val id = PluginId.getId("org.jetbrains.java.decompiler")
PluginManagerCore.disablePlugin(id)
val plugin = PluginManagerCore.getPlugin(id)
if (plugin is IdeaPluginDescriptorImpl && DynamicPlugins.allowLoadUnloadWithoutRestart(plugin)) {
ApplicationManager.getApplication().invokeLater {
DynamicPlugins.unloadPlugin(plugin, DynamicPlugins.UnloadPluginOptions(save = false))
}
}
}
POSTPONE_EXIT_CODE -> {
TASK_KEY.set(file, null)
}
}
}
}
@@ -174,12 +148,12 @@ class IdeaDecompiler : ClassFileDecompilers.Light() {
throw e
}
val mapping = saver.myMapping
val mapping = saver.mapping
if (mapping != null) {
file.putUserData(LineNumbersMapping.LINE_NUMBERS_MAPPING_KEY, LineNumbersMapping.ArrayBasedMapping(mapping))
}
return saver.myResult
return saver.result
}
catch (e: ProcessCanceledException) {
throw e
@@ -204,13 +178,13 @@ class IdeaDecompiler : ClassFileDecompilers.Light() {
}
private class MyResultSaver : IResultSaver {
var myResult = ""
var myMapping: IntArray? = null
var result = ""
var mapping: IntArray? = null
override fun saveClassFile(path: String, qualifiedName: String, entryName: String, content: String, mapping: IntArray?) {
if (myResult.isEmpty()) {
myResult = content
myMapping = mapping
if (result.isEmpty()) {
result = content
this.mapping = mapping
}
}
@@ -235,3 +209,32 @@ class IdeaDecompiler : ClassFileDecompilers.Light() {
return value
}
}
private const val LEGAL_NOTICE_KEY = "decompiler.legal.notice.accepted"
private const val POSTPONE_EXIT_CODE = DialogWrapper.CANCEL_EXIT_CODE
private const val DECLINE_EXIT_CODE = DialogWrapper.NEXT_USER_EXIT_CODE
private val TASK_KEY: Key<Future<CharSequence>> = Key.create("java.decompiler.optimistic.task")
private fun getOptions(): Map<String, Any> {
val options = CodeStyle.getDefaultSettings().getIndentOptions(JavaFileType.INSTANCE)
val indent = " ".repeat(options.INDENT_SIZE)
return mapOf(
IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR to "0",
IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES to "1",
IFernflowerPreferences.REMOVE_SYNTHETIC to "1",
IFernflowerPreferences.REMOVE_BRIDGE to "1",
IFernflowerPreferences.NEW_LINE_SEPARATOR to "1",
IFernflowerPreferences.BANNER to IDEA_DECOMPILER_BANNER,
IFernflowerPreferences.MAX_PROCESSING_METHOD to 60,
IFernflowerPreferences.INDENT_STRING to indent,
IFernflowerPreferences.IGNORE_INVALID_BYTECODE to "1",
IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES to "1",
//IFernflowerPreferences.UNIT_TEST_MODE to if (ApplicationManager.getApplication().isUnitTestMode) "1" else "0"
)
}
private fun canWork(): Boolean {
return ApplicationManager.getApplication().isUnitTestMode || PropertiesComponent.getInstance().isValueSet(LEGAL_NOTICE_KEY)
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.java.decompiler
import com.intellij.JavaTestUtil
@@ -55,7 +55,7 @@ class IdeaDecompilerTest : LightJavaCodeInsightFixtureTestCase() {
fun testSimple() {
val file = getTestFile("${IdeaTestUtil.getMockJdk18Path().path}/jre/lib/rt.jar!/java/lang/String.class")
val decompiled = IdeaDecompiler().getText(file).toString()
assertTrue(decompiled, decompiled.startsWith("${IdeaDecompiler.BANNER}package java.lang;\n"))
assertTrue(decompiled, decompiled.startsWith("${IDEA_DECOMPILER_BANNER}package java.lang;\n"))
assertTrue(decompiled, decompiled.contains("public final class String"))
assertTrue(decompiled, decompiled.contains("@deprecated"))
assertTrue(decompiled, decompiled.contains("private static class CaseInsensitiveComparator"))
@@ -222,7 +222,7 @@ class IdeaDecompilerTest : LightJavaCodeInsightFixtureTestCase() {
}
val decompiled = psiFile.mirror.text
assertTrue(file.path, decompiled.startsWith(IdeaDecompiler.BANNER) || file.name.endsWith("-info.class"))
assertTrue(file.path, decompiled.startsWith(IDEA_DECOMPILER_BANNER) || file.name.endsWith("-info.class"))
// check that no mapped line number is on an empty line
val prefix = "// "