Refactoring: move compatibility issue fix in decompiler to separate file
This commit is contained in:
+1
@@ -114,6 +114,7 @@
|
|||||||
<Problem reference="org.jetbrains.org.objectweb.asm.Opcodes#V9" reason="Absent in 172 branch. Use V1_9 while 172 is supported." />
|
<Problem reference="org.jetbrains.org.objectweb.asm.Opcodes#V9" reason="Absent in 172 branch. Use V1_9 while 172 is supported." />
|
||||||
<Problem reference="com.intellij.psi.codeStyle.CommonCodeStyleSettings#getSoftMargins" reason="Absent in 172." />
|
<Problem reference="com.intellij.psi.codeStyle.CommonCodeStyleSettings#getSoftMargins" reason="Absent in 172." />
|
||||||
<Problem reference="com.intellij.util.xmlb.XmlSerializer#serializeInto(java.lang.Object, org.jdom.Element)" reason="Absent in 172." />
|
<Problem reference="com.intellij.util.xmlb.XmlSerializer#serializeInto(java.lang.Object, org.jdom.Element)" reason="Absent in 172." />
|
||||||
|
<Problem reference="org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler#addSpace" reason="Method was replaced with outher methods in 182. Use addSpaceEx instead." />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class KotlinDecompilerServiceImpl : KotlinDecompilerService {
|
|||||||
|
|
||||||
val decompiler = BaseDecompiler(bytecodeProvider, resultSaver, options, IdeaLogger())
|
val decompiler = BaseDecompiler(bytecodeProvider, resultSaver, options, IdeaLogger())
|
||||||
for (path in bytecodeMap.keys) {
|
for (path in bytecodeMap.keys) {
|
||||||
decompiler.addSpace(path, true)
|
decompiler.addSpaceEx(path, true)
|
||||||
}
|
}
|
||||||
decompiler.decompileContext()
|
decompiler.decompileContext()
|
||||||
return resultSaver.resultText
|
return resultSaver.resultText
|
||||||
|
|||||||
-126
@@ -1,126 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.internal
|
|
||||||
|
|
||||||
import com.intellij.openapi.fileTypes.StdFileTypes
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
|
||||||
import com.intellij.openapi.util.io.FileUtilRt
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
|
||||||
import org.jetbrains.java.decompiler.IdeaLogger
|
|
||||||
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler
|
|
||||||
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider
|
|
||||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
|
|
||||||
import org.jetbrains.java.decompiler.main.extern.IResultSaver
|
|
||||||
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.psi.KtFile
|
|
||||||
import java.io.File
|
|
||||||
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 resultSaver = KotlinResultSaver()
|
|
||||||
val options = hashMapOf<String, Any>(
|
|
||||||
IFernflowerPreferences.REMOVE_BRIDGE to "0"
|
|
||||||
)
|
|
||||||
|
|
||||||
val bytecodeProvider = IBytecodeProvider { externalPath, _ ->
|
|
||||||
val path = File(FileUtil.toSystemIndependentName(externalPath))
|
|
||||||
bytecodeMap[path]?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
val decompiler = BaseDecompiler(bytecodeProvider, resultSaver, options, IdeaLogger())
|
|
||||||
for (path in bytecodeMap.keys) {
|
|
||||||
decompiler.addSource(path)
|
|
||||||
}
|
|
||||||
decompiler.decompileContext()
|
|
||||||
return resultSaver.resultText
|
|
||||||
} catch (ex: IdeaLogger.InternalException) {
|
|
||||||
throw DecompileFailedException(ex.message ?: "Unknown error", ex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bytecodeMapForExistingClassfile(file: VirtualFile): Map<File, () -> ByteArray> {
|
|
||||||
val mask = "${file.nameWithoutExtension}$"
|
|
||||||
val files =
|
|
||||||
mapOf(file.path to file) +
|
|
||||||
file.parent.children.filter {
|
|
||||||
it.nameWithoutExtension.startsWith(mask) && it.fileType === StdFileTypes.CLASS
|
|
||||||
}.map { it.path to it }
|
|
||||||
|
|
||||||
return files.entries.associate {
|
|
||||||
Pair(File(it.key), { it.value.contentsToByteArray(false) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bytecodeMapForSourceFile(file: KtFile): Map<File, () -> ByteArray> {
|
|
||||||
val configuration = CompilerConfiguration().apply {
|
|
||||||
languageVersionSettings = file.languageVersionSettings
|
|
||||||
}
|
|
||||||
val generationState = KotlinBytecodeToolWindow.compileSingleFile(file, configuration)
|
|
||||||
|
|
||||||
val bytecodeMap = hashMapOf<File, () -> ByteArray>()
|
|
||||||
generationState.factory.asList().filter { FileUtilRt.extensionEquals(it.relativePath, "class") }.forEach {
|
|
||||||
bytecodeMap[File("/${it.relativePath}").absoluteFile] = { it.asByteArray() }
|
|
||||||
}
|
|
||||||
return bytecodeMap
|
|
||||||
}
|
|
||||||
|
|
||||||
class KotlinResultSaver : IResultSaver {
|
|
||||||
private val decompiledText = mutableMapOf<String, String>()
|
|
||||||
|
|
||||||
val resultText: String
|
|
||||||
get() {
|
|
||||||
decompiledText.values.singleOrNull()?.let { return it }
|
|
||||||
return buildString {
|
|
||||||
for ((filename, content) in decompiledText) {
|
|
||||||
appendln("// $filename")
|
|
||||||
append(content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun saveFolder(path: String?) {}
|
|
||||||
|
|
||||||
override fun closeArchive(path: String?, archiveName: String?) {}
|
|
||||||
|
|
||||||
override fun copyEntry(source: String?, path: String?, archiveName: String?, entry: String?) {}
|
|
||||||
|
|
||||||
override fun createArchive(path: String?, archiveName: String?, manifest: Manifest?) {}
|
|
||||||
|
|
||||||
override fun saveClassFile(path: String?, qualifiedName: String?, entryName: String?, content: String?, mapping: IntArray?) {
|
|
||||||
if (entryName != null && content != null) {
|
|
||||||
decompiledText[entryName] = content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun copyFile(source: String?, path: String?, entryName: String?) {}
|
|
||||||
|
|
||||||
override fun saveClassEntry(path: String?, archiveName: String?, qualifiedName: String?, entryName: String?, content: String?) {}
|
|
||||||
|
|
||||||
override fun saveDirEntry(path: String?, archiveName: String?, entryName: String?) {}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.internal
|
||||||
|
|
||||||
|
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `addSpace` method is deprecated in 182. `addSource` and `addLibrary` were introduced instead.
|
||||||
|
* BUNCH: 182
|
||||||
|
*/
|
||||||
|
@Suppress("IncompatibleAPI")
|
||||||
|
fun BaseDecompiler.addSpaceEx(file: File, isOwn: Boolean) {
|
||||||
|
addSpace(file, isOwn)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.internal
|
||||||
|
|
||||||
|
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `addSpace` method is deprecated in 182. `addSource` and `addLibrary` were introduced instead.
|
||||||
|
* BUNCH: 182
|
||||||
|
*/
|
||||||
|
@Suppress("IncompatibleAPI")
|
||||||
|
fun BaseDecompiler.addSpaceEx(file: File, isOwn: Boolean) {
|
||||||
|
if (isOwn) {
|
||||||
|
addSource(file)
|
||||||
|
} else {
|
||||||
|
addLibrary(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user