Decompile builtins (kotlin_class and kotlin_package files)
The main purpose of this is to be able to index builtin declarations and enable go to symbol/class functionality in ide Also it makes sense to show builtin classes (Any, Int ...) as classes when browsing kotlin-runtime.jar Refactor decompiler code to eliminate existing and potential duplication Share the code between js (kjsm) decompilation and builtin decompilation heavily
This commit is contained in:
+3
-3
@@ -30,9 +30,9 @@ public object BuiltInsSerializedResourcePaths : SerializedResourcePaths() {
|
||||
BuiltInsProtoBuf.registerAllExtensions(extensionRegistry)
|
||||
}
|
||||
|
||||
private val CLASS_METADATA_FILE_EXTENSION = "kotlin_class"
|
||||
private val PACKAGE_FILE_EXTENSION = "kotlin_package"
|
||||
private val STRING_TABLE_FILE_EXTENSION = "kotlin_string_table"
|
||||
val CLASS_METADATA_FILE_EXTENSION = "kotlin_class"
|
||||
val PACKAGE_FILE_EXTENSION = "kotlin_package"
|
||||
val STRING_TABLE_FILE_EXTENSION = "kotlin_string_table"
|
||||
|
||||
public override fun getClassMetadataPath(classId: ClassId): String {
|
||||
return packageFqNameToPath(classId.getPackageFqName()) + "/" + classId.getRelativeClassName().asString() +
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.builtIns
|
||||
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.FileViewProvider
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.compiled.ClassFileDecompilers
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
|
||||
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
|
||||
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.common.toClassProto
|
||||
import org.jetbrains.kotlin.idea.decompiler.common.toPackageProto
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||
|
||||
class KotlinBuiltInDecompiler : ClassFileDecompilers.Full() {
|
||||
private val stubBuilder = KotlinBuiltInStubBuilder()
|
||||
|
||||
override fun accepts(file: VirtualFile): Boolean {
|
||||
return file.fileType == KotlinBuiltInClassFileType || file.fileType == KotlinBuiltInPackageFileType
|
||||
}
|
||||
|
||||
override fun getStubBuilder() = stubBuilder
|
||||
|
||||
override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider {
|
||||
return KotlinDecompiledFileViewProvider(manager, file, physical) { provider ->
|
||||
if (isInternalBuiltInFile(provider.virtualFile)) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
KtDecompiledFile(provider) { file ->
|
||||
buildDecompiledTextForBuiltIns(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LOG = Logger.getInstance(KotlinBuiltInDecompiler::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private val decompilerRendererForBuiltIns = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||
|
||||
public fun buildDecompiledTextForBuiltIns(
|
||||
builtInFile: VirtualFile
|
||||
): DecompiledText {
|
||||
val directory = builtInFile.parent!!
|
||||
val nameResolver = readStringTable(directory, KotlinBuiltInDecompiler.LOG)!!
|
||||
val content = builtInFile.contentsToByteArray()
|
||||
return when (builtInFile.fileType) {
|
||||
KotlinBuiltInPackageFileType -> {
|
||||
val packageFqName = content.toPackageProto(BuiltInsSerializedResourcePaths.extensionRegistry).packageFqName(nameResolver)
|
||||
val resolver = KotlinBuiltInDeserializerForDecompiler(directory, packageFqName, nameResolver)
|
||||
buildDecompiledText(packageFqName, resolver.resolveDeclarationsInFacade(packageFqName), decompilerRendererForBuiltIns)
|
||||
}
|
||||
KotlinBuiltInClassFileType -> {
|
||||
val classProto = content.toClassProto(BuiltInsSerializedResourcePaths.extensionRegistry)
|
||||
val classId = nameResolver.getClassId(classProto.fqName)
|
||||
val packageFqName = classId.packageFqName
|
||||
val resolver = KotlinBuiltInDeserializerForDecompiler(directory, packageFqName, nameResolver)
|
||||
buildDecompiledText(
|
||||
packageFqName,
|
||||
listOfNotNull(resolver.resolveTopLevelClass(classId)),
|
||||
decompilerRendererForBuiltIns
|
||||
)
|
||||
}
|
||||
else -> error("Unexpected filetype ${builtInFile.fileType}")
|
||||
}
|
||||
}
|
||||
|
||||
fun ProtoBuf.Package.packageFqName(nameResolver: NameResolverImpl): FqName {
|
||||
return nameResolver.getPackageFqName(getExtension(BuiltInsProtoBuf.packageFqName))
|
||||
}
|
||||
|
||||
fun isInternalBuiltInFile(virtualFile: VirtualFile): Boolean {
|
||||
when (virtualFile.fileType) {
|
||||
KotlinBuiltInPackageFileType -> {
|
||||
// do not accept kotlin_package files without packageFqName extension to avoid failing on older runtimes
|
||||
// this check may be costly but there are few kotlin_package files
|
||||
val packageProto = virtualFile.contentsToByteArray().toPackageProto(BuiltInsSerializedResourcePaths.extensionRegistry)
|
||||
return !packageProto.hasExtension(BuiltInsProtoBuf.packageFqName)
|
||||
}
|
||||
KotlinBuiltInClassFileType -> {
|
||||
val correspondsToInnerClass = virtualFile.nameWithoutExtension.contains('.')
|
||||
if (correspondsToInnerClass) {
|
||||
return true
|
||||
}
|
||||
val classFileName = virtualFile.nameWithoutExtension + "." + JavaClassFileType.INSTANCE.defaultExtension
|
||||
val classFileForTheSameClassIsPresent = virtualFile.parent!!.findChild(classFileName) != null
|
||||
return classFileForTheSameClassIsPresent
|
||||
}
|
||||
else -> error("Unexpected filetype ${virtualFile.fileType}")
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.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.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.deserialization.*
|
||||
|
||||
public class KotlinBuiltInDeserializerForDecompiler(
|
||||
packageDirectory: VirtualFile,
|
||||
packageFqName: FqName,
|
||||
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),
|
||||
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.ThrowException, ClassDescriptorFactory.EMPTY
|
||||
)
|
||||
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
|
||||
return getDescriptorsFromPackageFile(facadeFqName, BuiltInsSerializedResourcePaths, LOG, nameResolver)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinBuiltInDeserializerForDecompiler::class.java)
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.builtIns
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
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.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
|
||||
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.stubs.impl.KotlinFileStubImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
public class KotlinBuiltInStubBuilder : ClsStubBuilder() {
|
||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1
|
||||
|
||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||
|
||||
if (isInternalBuiltInFile(content.file)) return null
|
||||
|
||||
return doBuildFileStub(content)
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun doBuildFileStub(content: FileContent): KotlinFileStubImpl? {
|
||||
val file = content.file
|
||||
val directory = file.parent!!
|
||||
val nameResolver = readStringTable(directory, LOG) ?: return null
|
||||
val contentAsBytes = content.content
|
||||
|
||||
return when (file.fileType) {
|
||||
KotlinBuiltInPackageFileType -> {
|
||||
val packageProto = contentAsBytes.toPackageProto(BuiltInsSerializedResourcePaths.extensionRegistry)
|
||||
val packageFqName = packageProto.packageFqName(nameResolver)
|
||||
val components = createStubBuilderComponents(file, packageFqName, nameResolver)
|
||||
val context = components.createContext(
|
||||
nameResolver, packageFqName, TypeTable(packageProto.typeTable)
|
||||
)
|
||||
createPackageFacadeStub(packageProto, packageFqName, context)
|
||||
}
|
||||
KotlinBuiltInClassFileType -> {
|
||||
val classProto = contentAsBytes.toClassProto(BuiltInsSerializedResourcePaths.extensionRegistry)
|
||||
val classId = nameResolver.getClassId(classProto.fqName)
|
||||
val packageFqName = classId.packageFqName
|
||||
val components = createStubBuilderComponents(file, packageFqName, nameResolver)
|
||||
val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable))
|
||||
createTopLevelClassStub(classId, classProto, context)
|
||||
}
|
||||
else -> error("Unexpected filetype ${file.fileType}")
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LOG = Logger.getInstance(KotlinBuiltInStubBuilder::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun readStringTable(directory: VirtualFile, log: Logger): NameResolverImpl? {
|
||||
val stringsFileName = "${directory.name}.${BuiltInsSerializedResourcePaths.STRING_TABLE_FILE_EXTENSION}"
|
||||
val stringTableFile = directory.findFileByRelativePath(stringsFileName) ?: return run {
|
||||
log.error("$stringsFileName not found in $directory")
|
||||
null
|
||||
}
|
||||
val nameResolver = try {
|
||||
NameResolverImpl.read(ByteArrayInputStream(stringTableFile.contentsToByteArray(false)))
|
||||
}
|
||||
catch (e: Exception) {
|
||||
log.error("Error reading data from $stringTableFile ", e)
|
||||
null
|
||||
}
|
||||
return nameResolver
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.builtIns
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsSerializedResourcePaths
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
|
||||
public object KotlinBuiltInClassFileType : FileType {
|
||||
override fun getName() = "kotlin_class"
|
||||
|
||||
override fun getDescription() = "Kotlin builtin class"
|
||||
|
||||
override fun getDefaultExtension() = BuiltInsSerializedResourcePaths.CLASS_METADATA_FILE_EXTENSION
|
||||
|
||||
override fun getIcon() = KotlinIcons.CLASS
|
||||
|
||||
override fun isBinary() = true
|
||||
|
||||
override fun isReadOnly() = true
|
||||
|
||||
override fun getCharset(file: VirtualFile, content: ByteArray) = null
|
||||
}
|
||||
|
||||
public object KotlinBuiltInPackageFileType : FileType {
|
||||
override fun getName() = "kotlin_package"
|
||||
|
||||
override fun getDescription() = "Kotlin builtin package"
|
||||
|
||||
override fun getDefaultExtension() = BuiltInsSerializedResourcePaths.PACKAGE_FILE_EXTENSION
|
||||
|
||||
override fun getIcon() = KotlinIcons.FILE
|
||||
|
||||
override fun isBinary() = true
|
||||
|
||||
override fun isReadOnly() = true
|
||||
|
||||
override fun getCharset(file: VirtualFile, content: ByteArray) = null
|
||||
}
|
||||
+2
-2
@@ -64,7 +64,7 @@ public class DeserializerForClassfileDecompiler(
|
||||
LookupTracker.DO_NOTHING, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
|
||||
)
|
||||
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
|
||||
val packageFqName = facadeFqName.parent()
|
||||
assert(packageFqName == directoryPackageFqName) {
|
||||
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||
@@ -81,7 +81,7 @@ public class DeserializerForClassfileDecompiler(
|
||||
val membersScope = DeserializedPackageMemberScope(
|
||||
createDummyPackageFragment(packageFqName), packageProto, nameResolver, deserializationComponents
|
||||
) { emptyList() }
|
||||
return membersScope.getContributedDescriptors()
|
||||
return membersScope.getContributedDescriptors().toList()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+10
-19
@@ -26,14 +26,13 @@ import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolverForDecompiler
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassKind
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
||||
import org.jetbrains.kotlin.renderer.ExcludedTypeAnnotations
|
||||
import org.jetbrains.kotlin.types.flexibility
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import java.util.*
|
||||
@@ -50,14 +49,10 @@ public class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
|
||||
return KotlinDecompiledFileViewProvider(manager, file, physical) { provider ->
|
||||
val virtualFile = provider.virtualFile
|
||||
val fileIndex = ServiceManager.getService(project, FileIndexFacade::class.java)
|
||||
if (!fileIndex.isInLibraryClasses(virtualFile) && fileIndex.isInSource(virtualFile)) {
|
||||
null
|
||||
}
|
||||
else if (isKotlinInternalCompiledFile(virtualFile)) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
KtClsFile(provider)
|
||||
when {
|
||||
!fileIndex.isInLibraryClasses(virtualFile) && fileIndex.isInSource(virtualFile) -> null
|
||||
isKotlinInternalCompiledFile(virtualFile) -> null
|
||||
else -> KtClsFile(provider)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,13 +60,9 @@ public class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
|
||||
|
||||
class KtClsFile(provider: KotlinDecompiledFileViewProvider) : KtDecompiledFile(provider, { file -> buildDecompiledTextForClassFile(file) })
|
||||
|
||||
private val descriptorRendererForClassFileDecompiler = DescriptorRenderer.withOptions {
|
||||
withDefinedIn = false
|
||||
classWithPrimaryConstructor = true
|
||||
private val decompilerRendererForClassFiles = DescriptorRenderer.withOptions {
|
||||
defaultDecompilerRendererOptions()
|
||||
typeNormalizer = { type -> if (type.isFlexible()) type.flexibility().lowerBound else type }
|
||||
secondaryConstructorsAsPrimary = false
|
||||
modifiers = DescriptorRendererModifier.ALL
|
||||
excludedTypeAnnotationClasses = ExcludedTypeAnnotations.annotationsForNullabilityAndMutability
|
||||
}
|
||||
|
||||
private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI"
|
||||
@@ -103,13 +94,13 @@ public fun buildDecompiledTextForClassFile(
|
||||
mapOf())
|
||||
}
|
||||
classHeader.isCompatibleFileFacadeKind() ->
|
||||
buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())), descriptorRendererForClassFileDecompiler)
|
||||
buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())), decompilerRendererForClassFiles)
|
||||
classHeader.isCompatibleClassKind() ->
|
||||
buildDecompiledText(packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), descriptorRendererForClassFileDecompiler)
|
||||
buildDecompiledText(packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), decompilerRendererForClassFiles)
|
||||
classHeader.isCompatibleMultifileClassKind() -> {
|
||||
val partClasses = findMultifileClassParts(classFile, kotlinClass)
|
||||
val partMembers = partClasses.flatMap { partClass -> resolver.resolveDeclarationsInFacade(partClass.classId.asSingleFqName()) }
|
||||
buildDecompiledText(packageFqName, partMembers, descriptorRendererForClassFileDecompiler)
|
||||
buildDecompiledText(packageFqName, partMembers, decompilerRendererForClassFiles)
|
||||
}
|
||||
else ->
|
||||
throw UnsupportedOperationException("Unknown header kind: ${classHeader.kind} ${classHeader.isCompatibleAbiVersion}")
|
||||
|
||||
+12
-10
@@ -14,25 +14,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.decompiler.js
|
||||
package org.jetbrains.kotlin.idea.decompiler.common
|
||||
|
||||
import com.google.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.ClassIdWithTarget
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.js.JsProtoBuf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
public class AnnotationLoaderForKotlinJavaScriptStubBuilder() : AnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget> {
|
||||
public class AnnotationLoaderForStubBuilderImpl(
|
||||
private val protocol: SerializerExtensionProtocol
|
||||
) : AnnotationAndConstantLoader<ClassId, Unit, ClassIdWithTarget> {
|
||||
|
||||
override fun loadClassAnnotations(
|
||||
classProto: ProtoBuf.Class, nameResolver: NameResolver
|
||||
): List<ClassId> =
|
||||
classProto.getExtension(JsProtoBuf.classAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
classProto.getExtension(protocol.classAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
|
||||
override fun loadCallableAnnotations(
|
||||
container: ProtoContainer,
|
||||
@@ -40,9 +42,9 @@ public class AnnotationLoaderForKotlinJavaScriptStubBuilder() : AnnotationAndCon
|
||||
kind: AnnotatedCallableKind
|
||||
): List<ClassIdWithTarget> {
|
||||
val annotations = when (proto) {
|
||||
is ProtoBuf.Constructor -> proto.getExtension(JsProtoBuf.constructorAnnotation)
|
||||
is ProtoBuf.Function -> proto.getExtension(JsProtoBuf.functionAnnotation)
|
||||
is ProtoBuf.Property -> proto.getExtension(JsProtoBuf.propertyAnnotation)
|
||||
is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation)
|
||||
is ProtoBuf.Function -> proto.getExtension(protocol.functionAnnotation)
|
||||
is ProtoBuf.Property -> proto.getExtension(protocol.propertyAnnotation)
|
||||
else -> error("Unknown message: $proto")
|
||||
}.orEmpty()
|
||||
return annotations.map {
|
||||
@@ -57,7 +59,7 @@ public class AnnotationLoaderForKotlinJavaScriptStubBuilder() : AnnotationAndCon
|
||||
parameterIndex: Int,
|
||||
proto: ProtoBuf.ValueParameter
|
||||
): List<ClassId> =
|
||||
proto.getExtension(JsProtoBuf.parameterAnnotation).orEmpty().map {
|
||||
proto.getExtension(protocol.parameterAnnotation).orEmpty().map {
|
||||
container.nameResolver.getClassId(it.id)
|
||||
}
|
||||
|
||||
@@ -71,10 +73,10 @@ public class AnnotationLoaderForKotlinJavaScriptStubBuilder() : AnnotationAndCon
|
||||
proto: ProtoBuf.Type,
|
||||
nameResolver: NameResolver
|
||||
): List<ClassId> =
|
||||
proto.getExtension(JsProtoBuf.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
proto.getExtension(protocol.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
|
||||
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<ClassId> =
|
||||
proto.getExtension(JsProtoBuf.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||
|
||||
override fun loadPropertyConstant(
|
||||
container: ProtoContainer,
|
||||
+7
-9
@@ -14,18 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.serialization.js
|
||||
package org.jetbrains.kotlin.idea.decompiler.common
|
||||
|
||||
import com.google.protobuf.ExtensionRegistryLite
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
public fun ByteArray.toPackageProto(): ProtoBuf.Package {
|
||||
val registry = KotlinJavascriptSerializedResourcePaths.extensionRegistry
|
||||
return ProtoBuf.Package.parseFrom(ByteArrayInputStream(this), registry)!!
|
||||
}
|
||||
|
||||
public fun ByteArray.toClassProto(): ProtoBuf.Class {
|
||||
val registry = KotlinJavascriptSerializedResourcePaths.extensionRegistry
|
||||
return ProtoBuf.Class.parseFrom(ByteArrayInputStream(this), registry)
|
||||
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)
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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))
|
||||
}
|
||||
}
|
||||
|
||||
+7
-49
@@ -19,19 +19,17 @@ 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
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.serialization.ClassData
|
||||
import org.jetbrains.kotlin.serialization.ClassDataWithSource
|
||||
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||
import org.jetbrains.kotlin.serialization.js.*
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
public class KotlinJavaScriptDeserializerForDecompiler(
|
||||
@@ -48,62 +46,22 @@ public class KotlinJavaScriptDeserializerForDecompiler(
|
||||
|
||||
override val targetPlatform: TargetPlatform get() = JsPlatform
|
||||
|
||||
private val metaFileFinder = DirectoryBasedKotlinJavaScriptMetaFileFinder(packageDirectory, directoryPackageFqName, nameResolver)
|
||||
|
||||
private val classDataFinder = DirectoryBasedKotlinJavaScriptDataFinder(metaFileFinder, LOG)
|
||||
private val finder = DirectoryBasedClassDataFinder(packageDirectory, directoryPackageFqName, nameResolver, KotlinJavascriptSerializedResourcePaths)
|
||||
|
||||
private val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(moduleDescriptor, JsSerializerProtocol)
|
||||
|
||||
override val deserializationComponents = DeserializationComponents(
|
||||
storageManager, moduleDescriptor, classDataFinder, annotationAndConstantLoader, packageFragmentProvider,
|
||||
storageManager, moduleDescriptor, finder, annotationAndConstantLoader, packageFragmentProvider,
|
||||
ResolveEverythingToKotlinAnyLocalClassResolver(targetPlatform.builtIns), LoggingErrorReporter(LOG),
|
||||
LookupTracker.DO_NOTHING, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
|
||||
)
|
||||
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> {
|
||||
val packageFqName = facadeFqName.parent()
|
||||
assert(packageFqName == directoryPackageFqName) {
|
||||
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||
}
|
||||
val file = metaFileFinder.findKotlinJavascriptMetaFile(ClassId.topLevel(facadeFqName))
|
||||
if (file == null) {
|
||||
LOG.error("Could not read data for $facadeFqName")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val content = file.contentsToByteArray(false)
|
||||
val membersScope = DeserializedPackageMemberScope(
|
||||
createDummyPackageFragment(packageFqName), content.toPackageProto(), nameResolver, deserializationComponents
|
||||
) { emptyList() }
|
||||
return membersScope.getContributedDescriptors()
|
||||
return getDescriptorsFromPackageFile(packageFqName, KotlinJavascriptSerializedResourcePaths, LOG, nameResolver)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinJavaScriptDeserializerForDecompiler::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
class DirectoryBasedKotlinJavaScriptMetaFileFinder(
|
||||
val packageDirectory: VirtualFile,
|
||||
val directoryPackageFqName: FqName,
|
||||
val nameResolver: NameResolver
|
||||
) {
|
||||
fun findKotlinJavascriptMetaFile(classId: ClassId): VirtualFile? {
|
||||
if (classId.getPackageFqName() != directoryPackageFqName) return null
|
||||
|
||||
val targetName = classId.getRelativeClassName().pathSegments().joinToString(".", postfix = "." + KotlinJavascriptSerializationUtil.CLASS_METADATA_FILE_EXTENSION)
|
||||
return packageDirectory.findChild(targetName)
|
||||
}
|
||||
}
|
||||
|
||||
class DirectoryBasedKotlinJavaScriptDataFinder(
|
||||
val classFinder: DirectoryBasedKotlinJavaScriptMetaFileFinder,
|
||||
val log: Logger
|
||||
) : ClassDataFinder {
|
||||
override fun findClassData(classId: ClassId): ClassDataWithSource? {
|
||||
val file = classFinder.findKotlinJavascriptMetaFile(classId) ?: return null
|
||||
|
||||
val content = file.contentsToByteArray(false)
|
||||
return ClassDataWithSource(ClassData(classFinder.nameResolver, content.toClassProto()))
|
||||
}
|
||||
}
|
||||
|
||||
+4
-11
@@ -26,11 +26,10 @@ import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolverForDecompiler
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
|
||||
import org.jetbrains.kotlin.load.kotlin.OldPackageFacadeClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
||||
import org.jetbrains.kotlin.renderer.ExcludedTypeAnnotations
|
||||
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||
import java.util.*
|
||||
|
||||
@@ -57,13 +56,7 @@ class KotlinJavaScriptMetaFileDecompiler : ClassFileDecompilers.Full() {
|
||||
}
|
||||
}
|
||||
|
||||
private val descriptorRendererForKotlinJavascriptDecompiler = DescriptorRenderer.withOptions {
|
||||
withDefinedIn = false
|
||||
classWithPrimaryConstructor = true
|
||||
secondaryConstructorsAsPrimary = false
|
||||
modifiers = DescriptorRendererModifier.ALL
|
||||
excludedTypeAnnotationClasses = ExcludedTypeAnnotations.annotationsForNullabilityAndMutability
|
||||
}
|
||||
private val decompilerRendererForJS = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||
|
||||
public fun buildDecompiledTextFromJsMetadata(
|
||||
classFile: VirtualFile,
|
||||
@@ -75,11 +68,11 @@ public fun buildDecompiledTextFromJsMetadata(
|
||||
if (isPackageHeader) {
|
||||
return buildDecompiledText(packageFqName,
|
||||
resolveDeclarationsInPackage(packageFqName, resolver),
|
||||
descriptorRendererForKotlinJavascriptDecompiler)
|
||||
decompilerRendererForJS)
|
||||
}
|
||||
else {
|
||||
val classId = JsMetaFileUtils.getClassId(classFile)
|
||||
return buildDecompiledText(packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), descriptorRendererForKotlinJavascriptDecompiler)
|
||||
return buildDecompiledText(packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), decompilerRendererForJS)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-12
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.decompiler.js
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
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.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
|
||||
@@ -30,9 +33,8 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
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.KotlinJavascriptSerializedResourcePaths
|
||||
import org.jetbrains.kotlin.serialization.js.toClassProto
|
||||
import org.jetbrains.kotlin.serialization.js.toPackageProto
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
public class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
||||
@@ -61,14 +63,14 @@ public class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
||||
val components = createStubBuilderComponents(file, packageFqName, nameResolver)
|
||||
|
||||
if (isPackageHeader) {
|
||||
val packageProto = content.toPackageProto()
|
||||
val packageProto = content.toPackageProto(KotlinJavascriptSerializedResourcePaths.extensionRegistry)
|
||||
val context = components.createContext(
|
||||
nameResolver, packageFqName, TypeTable(packageProto.typeTable)
|
||||
)
|
||||
return createPackageFacadeStub(packageProto, packageFqName, context)
|
||||
}
|
||||
else {
|
||||
val classProto = content.toClassProto()
|
||||
val classProto = content.toClassProto(KotlinJavascriptSerializedResourcePaths.extensionRegistry)
|
||||
val context = components.createContext(nameResolver, packageFqName, TypeTable(classProto.typeTable))
|
||||
val classId = JsMetaFileUtils.getClassId(file)
|
||||
return createTopLevelClassStub(classId, classProto, context)
|
||||
@@ -76,13 +78,10 @@ public class KotlinJavaScriptStubBuilder : ClsStubBuilder() {
|
||||
}
|
||||
|
||||
private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, nameResolver: NameResolver): ClsStubBuilderComponents {
|
||||
val metaFileFinder = DirectoryBasedKotlinJavaScriptMetaFileFinder(file.parent!!, packageFqName, nameResolver)
|
||||
val classDataFinder = DirectoryBasedKotlinJavaScriptDataFinder(metaFileFinder, LOG)
|
||||
val annotationLoader = AnnotationLoaderForKotlinJavaScriptStubBuilder()
|
||||
val classDataFinder = DirectoryBasedClassDataFinder(
|
||||
file.parent!!, packageFqName, nameResolver, KotlinJavascriptSerializedResourcePaths
|
||||
)
|
||||
val annotationLoader = AnnotationLoaderForStubBuilderImpl(JsSerializerProtocol)
|
||||
return ClsStubBuilderComponents(classDataFinder, annotationLoader)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LOG = Logger.getInstance(KotlinJavaScriptStubBuilder::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
|
||||
import org.jetbrains.kotlin.renderer.ExcludedTypeAnnotations
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
|
||||
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
|
||||
@@ -42,6 +44,14 @@ public fun descriptorToKey(descriptor: DeclarationDescriptor): String {
|
||||
|
||||
public data class DecompiledText(public val text: String, public val renderedDescriptorsToRange: Map<String, TextRange>)
|
||||
|
||||
fun DescriptorRendererOptions.defaultDecompilerRendererOptions() {
|
||||
withDefinedIn = false
|
||||
classWithPrimaryConstructor = true
|
||||
secondaryConstructorsAsPrimary = false
|
||||
modifiers = DescriptorRendererModifier.ALL
|
||||
excludedTypeAnnotationClasses = ExcludedTypeAnnotations.annotationsForNullabilityAndMutability
|
||||
}
|
||||
|
||||
public fun buildDecompiledText(
|
||||
packageFqName: FqName,
|
||||
descriptors: List<DeclarationDescriptor>,
|
||||
|
||||
+31
-10
@@ -16,25 +16,22 @@
|
||||
|
||||
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.ClassDescriptor
|
||||
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.annotations.AnnotationWithTarget
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
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.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
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
|
||||
|
||||
@@ -63,7 +60,31 @@ public abstract class DeserializerForDecompilerBase(
|
||||
override fun resolveTopLevelClass(classId: ClassId) = deserializationComponents.deserializeClass(classId)
|
||||
|
||||
protected fun createDummyPackageFragment(fqName: FqName): MutablePackageFragmentDescriptor =
|
||||
MutablePackageFragmentDescriptor(moduleDescriptor, fqName)
|
||||
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, deserializationComponents
|
||||
) { emptyList() }
|
||||
return membersScope.getContributedDescriptors().toList()
|
||||
}
|
||||
|
||||
private fun createDummyModule(name: String) = ModuleDescriptorImpl(Name.special("<$name>"), storageManager, ModuleParameters.Empty, targetPlatform.builtIns)
|
||||
|
||||
|
||||
+1
-1
@@ -24,5 +24,5 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
public interface ResolverForDecompiler {
|
||||
public fun resolveTopLevelClass(classId: ClassId): ClassDescriptor?
|
||||
|
||||
public fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor>
|
||||
public fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor>
|
||||
}
|
||||
|
||||
@@ -16,14 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.ide.highlighter.JavaClassFileType
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.JsProjectDetector
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInClassFileType
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInPackageFileType
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
|
||||
private val classFileLike = setOf(JavaClassFileType.INSTANCE, KotlinBuiltInClassFileType, KotlinBuiltInPackageFileType)
|
||||
|
||||
public object ProjectRootsUtil {
|
||||
@JvmStatic
|
||||
@@ -42,7 +46,7 @@ public object ProjectRootsUtil {
|
||||
|| (includeLibraryClasses && fileIndex.isLibraryClassFile(file))
|
||||
}
|
||||
// NOTE: the following is a workaround for cases when class files are under library source roots and source files are under class roots
|
||||
val isClassFile = file.getFileType() == JavaClassFileType.INSTANCE
|
||||
val isClassFile = file.fileType in classFileLike
|
||||
return (includeLibraryClasses && isClassFile && fileIndex.isInLibraryClasses(file))
|
||||
|| (includeLibrarySource && !isClassFile && fileIndex.isInLibrarySource(file))
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
|
||||
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
|
||||
import org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.*
|
||||
@@ -106,7 +106,7 @@ public fun unInvalidateBuiltinsAndStdLib(project: Project, runnable: RunnableWit
|
||||
|
||||
builtInsSources.forEach { unInvalidateFile(it) }
|
||||
stdLibViewProviders.forEach {
|
||||
it.allFiles.forEach { unInvalidateFile(it as KtClsFile) }
|
||||
it.allFiles.forEach { unInvalidateFile(it as KtDecompiledFile) }
|
||||
vFileToViewProviderMap.set(it.virtualFile, it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.caches.resolve.ClsJavaStubByVirtualFileCache"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.ClsJavaStubByVirtualFileCache"/>
|
||||
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.console.KotlinConsoleKeeper"
|
||||
serviceImplementation="org.jetbrains.kotlin.console.KotlinConsoleKeeper"/>
|
||||
|
||||
@@ -293,6 +293,7 @@
|
||||
|
||||
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinFileTypeFactory"/>
|
||||
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinJavaScriptMetaFileTypeFactory"/>
|
||||
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinBuiltInFileTypeFactory"/>
|
||||
<fileTypeFactory implementation="org.jetbrains.kotlin.idea.KotlinModuleFileFactory"/>
|
||||
|
||||
<compileServer.plugin classpath="jps/kotlin-jps-plugin.jar;kotlin-runtime.jar;kotlin-reflect.jar;kotlin-plugin.jar;kotlin-android-extensions-plugin.jar;kotlin-android-extensions-compiler-plugin.jar"/>
|
||||
@@ -560,6 +561,7 @@
|
||||
|
||||
<psi.classFileDecompiler implementation="org.jetbrains.kotlin.idea.decompiler.classFile.KotlinClassFileDecompiler"/>
|
||||
<psi.classFileDecompiler implementation="org.jetbrains.kotlin.idea.decompiler.js.KotlinJavaScriptMetaFileDecompiler"/>
|
||||
<psi.classFileDecompiler implementation="org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInDecompiler"/>
|
||||
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.versions.KotlinAbiVersionIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.versions.KotlinJavaScriptAbiVersionIndex"/>
|
||||
@@ -1300,11 +1302,17 @@
|
||||
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
|
||||
|
||||
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||
|
||||
<filetype.stubBuilder filetype="KJSM" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
|
||||
|
||||
<filetype.decompiler filetype="KJSM" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
|
||||
|
||||
<fileType.fileViewProviderFactory filetype="kotlin_class" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||
<filetype.stubBuilder filetype="kotlin_class" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
|
||||
<filetype.decompiler filetype="kotlin_class" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
|
||||
|
||||
<fileType.fileViewProviderFactory filetype="kotlin_package" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||
<filetype.stubBuilder filetype="kotlin_package" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
|
||||
<filetype.decompiler filetype="kotlin_package" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
|
||||
|
||||
<pathMacroExpandableProtocol protocol="kotlin-js-meta"/>
|
||||
</extensions>
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileTypeConsumer
|
||||
import com.intellij.openapi.fileTypes.FileTypeFactory
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInClassFileType
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInPackageFileType
|
||||
|
||||
class KotlinBuiltInFileTypeFactory : FileTypeFactory() {
|
||||
override fun createFileTypes(consumer: FileTypeConsumer) {
|
||||
consumer.consume(KotlinBuiltInClassFileType, KotlinBuiltInClassFileType.defaultExtension)
|
||||
consumer.consume(KotlinBuiltInPackageFileType, KotlinBuiltInPackageFileType.defaultExtension)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -77,7 +77,7 @@ public abstract class TextConsistencyBaseTest : KotlinLightCodeInsightFixtureTes
|
||||
override fun resolveTopLevelClass(classId: ClassId): ClassDescriptor? =
|
||||
module.resolveTopLevelClass(classId.asSingleFqName(), NoLookupLocation.FROM_TEST)
|
||||
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> =
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): List<DeclarationDescriptor> =
|
||||
module.getPackage(facadeFqName.parent()).memberScope.getContributedDescriptors().filter {
|
||||
it is CallableMemberDescriptor &&
|
||||
it.module != module.builtIns.builtInsModule &&
|
||||
|
||||
Reference in New Issue
Block a user