Don't read old built-in files in decompiler

This commit is contained in:
Alexander Udalov
2016-02-17 15:27:21 +03:00
committed by Alexander Udalov
parent 996c5848c2
commit 4bacabe354
8 changed files with 63 additions and 150 deletions
@@ -82,7 +82,7 @@ fun buildDecompiledTextForBuiltIns(builtInFile: VirtualFile): DecompiledText {
}
is BuiltInDefinitionFile.Compatible -> {
val packageFqName = file.packageFqName
val resolver = KotlinBuiltInDeserializerForDecompiler(file.packageDirectory, packageFqName, file.nameResolver)
val resolver = KotlinBuiltInDeserializerForDecompiler(file.packageDirectory, packageFqName, file.proto, file.nameResolver)
val declarations = arrayListOf<DeclarationDescriptor>()
declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName))
for (classProto in file.classesToDecompile) {
@@ -19,39 +19,47 @@ package org.jetbrains.kotlin.idea.decompiler.builtIns
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
import org.jetbrains.kotlin.builtins.BuiltInsClassDataFinder
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.decompiler.common.DirectoryBasedClassDataFinder
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompilerBase
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassResolver
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
class KotlinBuiltInDeserializerForDecompiler(
packageDirectory: VirtualFile,
packageFqName: FqName,
private val proto: BuiltInsProtoBuf.BuiltIns,
private val nameResolver: NameResolver
) : DeserializerForDecompilerBase(packageDirectory, packageFqName) {
override val targetPlatform: TargetPlatform get() = TargetPlatform.Default
private val classDataFinder = DirectoryBasedClassDataFinder(
packageDirectory, directoryPackageFqName, nameResolver, BuiltInsSerializedResourcePaths
)
override val deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, classDataFinder, AnnotationAndConstantLoaderImpl(moduleDescriptor, BuiltInSerializerProtocol),
packageFragmentProvider, ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG),
storageManager, moduleDescriptor, BuiltInsClassDataFinder(proto, nameResolver),
AnnotationAndConstantLoaderImpl(moduleDescriptor, BuiltInSerializerProtocol), packageFragmentProvider,
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, ClassDescriptorFactory.EMPTY
)
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
return getDescriptorsFromPackageFile(facadeFqName, BuiltInsSerializedResourcePaths, LOG, nameResolver)
assert(facadeFqName == directoryPackageFqName) {
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
}
val membersScope = DeserializedPackageMemberScope(
createDummyPackageFragment(facadeFqName), proto.`package`, nameResolver, packagePartSource = null,
components = deserializationComponents
) { emptyList() }
return membersScope.getContributedDescriptors().toList()
}
companion object {
private val LOG = Logger.getInstance(KotlinBuiltInDeserializerForDecompiler::class.java)
}
}
}
@@ -16,18 +16,14 @@
package org.jetbrains.kotlin.idea.decompiler.builtIns
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.compiled.ClsStubBuilder
import com.intellij.psi.impl.compiled.ClassFileStubBuilder
import com.intellij.psi.stubs.PsiFileStub
import com.intellij.util.indexing.FileContent
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
import org.jetbrains.kotlin.builtins.BuiltInsClassDataFinder
import org.jetbrains.kotlin.idea.decompiler.common.AnnotationLoaderForStubBuilderImpl
import org.jetbrains.kotlin.idea.decompiler.common.DirectoryBasedClassDataFinder
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
@@ -49,7 +45,11 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() {
val packageProto = file.proto.`package`
val packageFqName = file.packageFqName
val nameResolver = file.nameResolver
val components = createStubBuilderComponents(virtualFile, packageFqName, nameResolver)
val components = ClsStubBuilderComponents(
BuiltInsClassDataFinder(file.proto, nameResolver),
AnnotationLoaderForStubBuilderImpl(BuiltInSerializerProtocol),
virtualFile
)
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
val fileStub = createFileStub(packageFqName)
@@ -65,10 +65,4 @@ class KotlinBuiltInStubBuilder : ClsStubBuilder() {
}
}
}
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, nameResolver: NameResolver): ClsStubBuilderComponents {
val finder = DirectoryBasedClassDataFinder(file.parent!!, packageFqName, nameResolver, BuiltInsSerializedResourcePaths)
val annotationLoader = AnnotationLoaderForStubBuilderImpl(BuiltInSerializerProtocol)
return ClsStubBuilderComponents(finder, annotationLoader, file)
}
}
@@ -1,29 +0,0 @@
/*
* 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.common
import com.google.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.serialization.ProtoBuf
import java.io.ByteArrayInputStream
fun ByteArray.toPackageProto(extensionRegistry: ExtensionRegistryLite): ProtoBuf.Package {
return ProtoBuf.Package.parseFrom(ByteArrayInputStream(this), extensionRegistry)!!
}
fun ByteArray.toClassProto(extensionRegistry: ExtensionRegistryLite): ProtoBuf.Class {
return ProtoBuf.Class.parseFrom(ByteArrayInputStream(this), extensionRegistry)
}
@@ -1,49 +0,0 @@
/*
* 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.common
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.ClassData
import org.jetbrains.kotlin.serialization.ClassDataWithSource
import org.jetbrains.kotlin.serialization.SerializedResourcePaths
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
class DirectoryBasedClassDataFinder(
private val packageDirectory: VirtualFile,
private val directoryPackageFqName: FqName,
private val nameResolver: NameResolver,
private val paths: SerializedResourcePaths
) : ClassDataFinder {
fun findFileForClass(classId: ClassId): VirtualFile? {
if (classId.packageFqName != directoryPackageFqName) return null
val pathRelativeToDir = paths.getClassMetadataPath(classId).substringAfterLast("/")
return packageDirectory.findChild(pathRelativeToDir)
}
override fun findClassData(classId: ClassId): ClassDataWithSource? {
val virtualFile = findFileForClass(classId) ?: return null
val content = virtualFile.contentsToByteArray(false)
val classProto = content.toClassProto(paths.extensionRegistry)
return ClassDataWithSource(ClassData(nameResolver, classProto))
}
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.decompiler.js
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.decompiler.common.DirectoryBasedClassDataFinder
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompilerBase
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassResolver
@@ -27,8 +26,11 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptClassDataFinder
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
import java.io.ByteArrayInputStream
@@ -46,19 +48,37 @@ class KotlinJavaScriptDeserializerForDecompiler(
override val targetPlatform: TargetPlatform get() = JsPlatform
private val finder = DirectoryBasedClassDataFinder(packageDirectory, directoryPackageFqName, nameResolver, KotlinJavascriptSerializedResourcePaths)
private val classDataFinder = KotlinJavascriptClassDataFinder(nameResolver) { path ->
packageDirectory.findChild(path.substringAfterLast("/"))?.inputStream
}
private val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, JsSerializerProtocol)
override val deserializationComponents = DeserializationComponents(
storageManager, moduleDescriptor, finder, annotationAndConstantLoader, packageFragmentProvider,
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG),
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
)
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
val packageFqName = facadeFqName.parent()
return getDescriptorsFromPackageFile(packageFqName, KotlinJavascriptSerializedResourcePaths, LOG, nameResolver)
assert(packageFqName == directoryPackageFqName) {
"Was called for $packageFqName; only members of $directoryPackageFqName package are expected."
}
val packageFilePath = KotlinJavascriptSerializedResourcePaths.getPackageFilePath(directoryPackageFqName).substringAfterLast("/")
val file = packageDirectory.findChild(packageFilePath)
if (file == null) {
LOG.error("Could not read data for package $packageFqName; $packageFilePath absent in $packageDirectory")
return emptyList()
}
val content = file.contentsToByteArray(false)
val packageProto = ProtoBuf.Package.parseFrom(content, KotlinJavascriptSerializedResourcePaths.extensionRegistry)
val membersScope = DeserializedPackageMemberScope(
createDummyPackageFragment(packageFqName), packageProto, nameResolver, packagePartSource = null,
components = deserializationComponents
) { emptyList() }
return membersScope.getContributedDescriptors().toList()
}
companion object {
@@ -22,18 +22,16 @@ import com.intellij.psi.impl.compiled.ClassFileStubBuilder
import com.intellij.psi.stubs.PsiFileStub
import com.intellij.util.indexing.FileContent
import org.jetbrains.kotlin.idea.decompiler.common.AnnotationLoaderForStubBuilderImpl
import org.jetbrains.kotlin.idea.decompiler.common.DirectoryBasedClassDataFinder
import org.jetbrains.kotlin.idea.decompiler.common.toClassProto
import org.jetbrains.kotlin.idea.decompiler.common.toPackageProto
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.ClsStubBuilderComponents
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.createPackageFacadeStub
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.createTopLevelClassStub
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptClassDataFinder
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
import java.io.ByteArrayInputStream
@@ -60,27 +58,25 @@ class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
assert(stringsFile != null) { "strings file not found: $stringsFileName" }
val nameResolver = NameResolverImpl.read(ByteArrayInputStream(stringsFile!!.contentsToByteArray(false)))
val components = createStubBuilderComponents(file, packageFqName, nameResolver)
val components = createStubBuilderComponents(file, nameResolver)
if (isPackageHeader) {
val packageProto = content.toPackageProto(KotlinJavascriptSerializedResourcePaths.extensionRegistry)
val context = components.createContext(
nameResolver, packageFqName, TypeTable(packageProto.typeTable)
)
val packageProto = ProtoBuf.Package.parseFrom(content, KotlinJavascriptSerializedResourcePaths.extensionRegistry)
val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable))
return createPackageFacadeStub(packageProto, packageFqName, context)
}
else {
val classProto = content.toClassProto(KotlinJavascriptSerializedResourcePaths.extensionRegistry)
val classProto = ProtoBuf.Class.parseFrom(content, KotlinJavascriptSerializedResourcePaths.extensionRegistry)
val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable))
val classId = JsMetaFileUtils.getClassId(file)
return createTopLevelClassStub(classId, classProto, context)
}
}
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, nameResolver: NameResolver): ClsStubBuilderComponents {
val classDataFinder = DirectoryBasedClassDataFinder(
file.parent!!, packageFqName, nameResolver, KotlinJavascriptSerializedResourcePaths
)
private fun createStubBuilderComponents(file: VirtualFile, nameResolver: NameResolver): ClsStubBuilderComponents {
val classDataFinder = KotlinJavascriptClassDataFinder(nameResolver) { path ->
file.parent.findChild(path.substringAfterLast("/"))?.inputStream
}
val annotationLoader = AnnotationLoaderForStubBuilderImpl(JsSerializerProtocol)
return ClsStubBuilderComponents(classDataFinder, annotationLoader, file)
}
@@ -16,22 +16,20 @@
package org.jetbrains.kotlin.idea.decompiler.textBuilder
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
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.idea.decompiler.common.toPackageProto
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.serialization.SerializedResourcePaths
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
import org.jetbrains.kotlin.serialization.deserialization.LocalClassResolver
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
@@ -62,31 +60,6 @@ abstract class DeserializerForDecompilerBase(
protected fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor =
MutablePackageFragmentDescriptor(moduleDescriptor, fqName)
protected fun getDescriptorsFromPackageFile(
packageFqName: FqName,
paths: SerializedResourcePaths,
log: Logger,
nameResolver: NameResolver
): List<DeclarationDescriptor> {
assert(packageFqName == directoryPackageFqName) {
"Was called for $packageFqName; only members of $directoryPackageFqName package are expected."
}
val packageFilePath = paths.getPackageFilePath(directoryPackageFqName).substringAfterLast("/")
val file = packageDirectory.findChild(packageFilePath)
if (file == null) {
log.error("Could not read data for package $packageFqName; $packageFilePath absent in $packageDirectory")
return emptyList()
}
val content = file.contentsToByteArray(false)
val packageProto = content.toPackageProto(paths.extensionRegistry)
val membersScope = DeserializedPackageMemberScope(
createDummyPackageFragment(packageFqName), packageProto, nameResolver, packagePartSource = null,
components = deserializationComponents
) { emptyList() }
return membersScope.getContributedDescriptors().toList()
}
private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, ModuleParameters.Empty, targetPlatform.builtIns)
init {