add KotlinJavaScriptDeserializeForDecompiler
This commit is contained in:
+13
-53
@@ -18,24 +18,15 @@ package org.jetbrains.kotlin.idea.decompiler.textBuilder
|
|||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleParameters
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
|
||||||
import org.jetbrains.kotlin.load.kotlin.BinaryClassAnnotationAndConstantLoaderImpl
|
import org.jetbrains.kotlin.load.kotlin.BinaryClassAnnotationAndConstantLoaderImpl
|
||||||
import org.jetbrains.kotlin.load.kotlin.JavaFlexibleTypeCapabilitiesDeserializer
|
import org.jetbrains.kotlin.load.kotlin.JavaFlexibleTypeCapabilitiesDeserializer
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
|
||||||
|
|
||||||
public fun DeserializerForDecompiler(classFile: VirtualFile): DeserializerForDecompiler {
|
public fun DeserializerForDecompiler(classFile: VirtualFile): DeserializerForDecompiler {
|
||||||
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
val kotlinClass = KotlinBinaryClassCache.getKotlinBinaryClass(classFile)
|
||||||
@@ -44,14 +35,22 @@ public fun DeserializerForDecompiler(classFile: VirtualFile): DeserializerForDec
|
|||||||
return DeserializerForDecompiler(classFile.getParent()!!, packageFqName)
|
return DeserializerForDecompiler(classFile.getParent()!!, packageFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeserializerForDecompiler(val packageDirectory: VirtualFile, val directoryPackageFqName: FqName) : ResolverForDecompiler {
|
public class DeserializerForDecompiler(
|
||||||
|
packageDirectory: VirtualFile,
|
||||||
|
directoryPackageFqName: FqName
|
||||||
|
) : DeserializerForDecompilerBase(packageDirectory, directoryPackageFqName) {
|
||||||
|
|
||||||
private val storageManager = LockBasedStorageManager.NO_LOCKS
|
private val classFinder = DirectoryBasedClassFinder(packageDirectory, directoryPackageFqName)
|
||||||
private val moduleDescriptor = createDummyModule("module for building decompiled sources")
|
|
||||||
|
|
||||||
private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, ModuleParameters.Empty)
|
override val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
|
||||||
|
|
||||||
override fun resolveTopLevelClass(classId: ClassId) = deserializationComponents.deserializeClass(classId)
|
override val annotationAndConstantLoader =
|
||||||
|
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, storageManager, classFinder, LoggingErrorReporter(LOG))
|
||||||
|
|
||||||
|
override val deserializationComponents: DeserializationComponents = DeserializationComponents(
|
||||||
|
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
|
||||||
|
ResolveEverythingToKotlinAnyLocalClassResolver, JavaFlexibleTypeCapabilitiesDeserializer
|
||||||
|
)
|
||||||
|
|
||||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
assert(packageFqName == directoryPackageFqName) { "Was called for $packageFqName but only $directoryPackageFqName is expected" }
|
assert(packageFqName == directoryPackageFqName) { "Was called for $packageFqName but only $directoryPackageFqName is expected" }
|
||||||
@@ -71,45 +70,6 @@ public class DeserializerForDecompiler(val packageDirectory: VirtualFile, val di
|
|||||||
return membersScope.getDescriptors()
|
return membersScope.getDescriptors()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val classFinder = DirectoryBasedClassFinder(packageDirectory, directoryPackageFqName)
|
|
||||||
private val classDataFinder = DirectoryBasedDataFinder(classFinder, LOG)
|
|
||||||
|
|
||||||
private val annotationAndConstantLoader =
|
|
||||||
BinaryClassAnnotationAndConstantLoaderImpl(moduleDescriptor, storageManager, classFinder, LoggingErrorReporter(LOG))
|
|
||||||
|
|
||||||
private val packageFragmentProvider = object : PackageFragmentProvider {
|
|
||||||
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
|
|
||||||
return listOf(createDummyPackageFragment(fqName))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
|
|
||||||
throw UnsupportedOperationException("This method is not supposed to be called.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
moduleDescriptor.initialize(packageFragmentProvider)
|
|
||||||
moduleDescriptor.addDependencyOnModule(moduleDescriptor)
|
|
||||||
moduleDescriptor.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule())
|
|
||||||
val moduleContainingMissingDependencies = createDummyModule("module containing missing dependencies for decompiled sources")
|
|
||||||
moduleContainingMissingDependencies.addDependencyOnModule(moduleContainingMissingDependencies)
|
|
||||||
moduleContainingMissingDependencies.initialize(
|
|
||||||
PackageFragmentProviderForMissingDependencies(moduleContainingMissingDependencies)
|
|
||||||
)
|
|
||||||
moduleDescriptor.addDependencyOnModule(moduleContainingMissingDependencies)
|
|
||||||
moduleDescriptor.seal()
|
|
||||||
moduleContainingMissingDependencies.seal()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val deserializationComponents = DeserializationComponents(
|
|
||||||
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
|
|
||||||
ResolveEverythingToKotlinAnyLocalClassResolver, JavaFlexibleTypeCapabilitiesDeserializer
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor {
|
|
||||||
return MutablePackageFragmentDescriptor(moduleDescriptor, fqName)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOG = Logger.getInstance(javaClass<DeserializerForDecompiler>())
|
private val LOG = Logger.getInstance(javaClass<DeserializerForDecompiler>())
|
||||||
}
|
}
|
||||||
|
|||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.decompiler.textBuilder
|
||||||
|
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleParameters
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
|
||||||
|
public abstract class DeserializerForDecompilerBase(
|
||||||
|
val packageDirectory: VirtualFile ,
|
||||||
|
val directoryPackageFqName: FqName
|
||||||
|
) : ResolverForDecompiler {
|
||||||
|
|
||||||
|
protected abstract val deserializationComponents: DeserializationComponents
|
||||||
|
|
||||||
|
protected abstract val classDataFinder: ClassDataFinder
|
||||||
|
|
||||||
|
protected abstract val annotationAndConstantLoader: AnnotationAndConstantLoader<AnnotationDescriptor, CompileTimeConstant<*>>
|
||||||
|
|
||||||
|
protected val storageManager: StorageManager = LockBasedStorageManager.NO_LOCKS
|
||||||
|
|
||||||
|
protected val moduleDescriptor: ModuleDescriptorImpl = createDummyModule("module for building decompiled sources")
|
||||||
|
|
||||||
|
protected val packageFragmentProvider: PackageFragmentProvider = object : PackageFragmentProvider {
|
||||||
|
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
|
||||||
|
return listOf(createDummyPackageFragment(fqName))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
|
||||||
|
throw UnsupportedOperationException("This method is not supposed to be called.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolveTopLevelClass(classId: ClassId) = deserializationComponents.deserializeClass(classId)
|
||||||
|
|
||||||
|
protected fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor =
|
||||||
|
MutablePackageFragmentDescriptor(moduleDescriptor, fqName)
|
||||||
|
|
||||||
|
private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, ModuleParameters.Empty)
|
||||||
|
|
||||||
|
init {
|
||||||
|
moduleDescriptor.initialize(packageFragmentProvider)
|
||||||
|
moduleDescriptor.addDependencyOnModule(moduleDescriptor)
|
||||||
|
moduleDescriptor.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule())
|
||||||
|
val moduleContainingMissingDependencies = createDummyModule("module containing missing dependencies for decompiled sources")
|
||||||
|
moduleContainingMissingDependencies.addDependencyOnModule(moduleContainingMissingDependencies)
|
||||||
|
moduleContainingMissingDependencies.initialize(
|
||||||
|
PackageFragmentProviderForMissingDependencies(moduleContainingMissingDependencies)
|
||||||
|
)
|
||||||
|
moduleDescriptor.addDependencyOnModule(moduleContainingMissingDependencies)
|
||||||
|
moduleDescriptor.seal()
|
||||||
|
moduleContainingMissingDependencies.seal()
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.decompiler.textBuilder
|
||||||
|
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||||
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptAnnotationAndConstantLoader
|
||||||
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
||||||
|
import org.jetbrains.kotlin.serialization.js.toPackageData
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
|
public class KotlinJavaScriptDeserializerForDecompiler(
|
||||||
|
classFile: VirtualFile
|
||||||
|
) : DeserializerForDecompilerBase(classFile.getParent()!!, JsMetaFileUtils.getPackageFqName(classFile)) {
|
||||||
|
|
||||||
|
private val nameResolver = run {
|
||||||
|
val moduleDirectory = JsMetaFileUtils.getModuleDirectory(packageDirectory)
|
||||||
|
val stringsFileName = KotlinJavascriptSerializedResourcePaths.getStringTableFilePath(directoryPackageFqName)
|
||||||
|
val stringsFile = moduleDirectory.findFileByRelativePath(stringsFileName)
|
||||||
|
assert(stringsFile != null, "strings file not found: $stringsFileName")
|
||||||
|
NameResolver.read(ByteArrayInputStream(stringsFile!!.contentsToByteArray(false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val metaFileFinder = DirectoryBasedKotlinJavaScriptMetaFileFinder(packageDirectory, directoryPackageFqName, nameResolver)
|
||||||
|
|
||||||
|
override val classDataFinder = DirectoryBasedKotlinJavaScriptDataFinder(metaFileFinder, LOG)
|
||||||
|
|
||||||
|
override val annotationAndConstantLoader = KotlinJavascriptAnnotationAndConstantLoader(moduleDescriptor)
|
||||||
|
|
||||||
|
override val deserializationComponents = DeserializationComponents(
|
||||||
|
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
|
||||||
|
ResolveEverythingToKotlinAnyLocalClassResolver, FlexibleTypeCapabilitiesDeserializer.Dynamic
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
|
assert(packageFqName == directoryPackageFqName, "Was called for $packageFqName but only $directoryPackageFqName is expected.")
|
||||||
|
val file = metaFileFinder.findKotlinJavascriptMetaFile(PackageClassUtils.getPackageClassId(packageFqName))
|
||||||
|
if (file == null) {
|
||||||
|
LOG.error("Could not read data for $packageFqName")
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val content = file.contentsToByteArray(false)
|
||||||
|
val packageData = content.toPackageData(nameResolver)
|
||||||
|
|
||||||
|
val membersScope = DeserializedPackageMemberScope(
|
||||||
|
createDummyPackageFragment(packageFqName),
|
||||||
|
packageData.getPackageProto(),
|
||||||
|
packageData.getNameResolver(),
|
||||||
|
deserializationComponents
|
||||||
|
) { emptyList() }
|
||||||
|
return membersScope.getDescriptors()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOG = Logger.getInstance(javaClass<KotlinJavaScriptDeserializerForDecompiler>())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user