Proper light classes generation in presence of the new file facades.
This commit is contained in:
committed by
Michael Bogdanov
parent
5fdfe8df3c
commit
b1b845d44d
+12
-15
@@ -49,6 +49,7 @@ import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil;
|
|||||||
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil;
|
import org.jetbrains.kotlin.idea.stubindex.StaticFacadeIndexUtil;
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil;
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil;
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
@@ -306,10 +307,9 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PsiClass clsClass = getLightClassForDecompiledFacade(packageFqName, files);
|
FqName packageFacadeFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||||
if (clsClass != null) {
|
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(packageFacadeFqName, files);
|
||||||
result.add(clsClass);
|
result.addAll(clsClasses);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -339,10 +339,8 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PsiClass clsClass = getLightClassForDecompiledFacade(facadeFqName, files);
|
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(facadeFqName, files);
|
||||||
if (clsClass != null) {
|
result.addAll(clsClasses);
|
||||||
result.add(clsClass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -377,15 +375,14 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static PsiClass getLightClassForDecompiledFacade(@NotNull FqName facadeFqName, @NotNull List<JetFile> filesWithCallables) {
|
private static List<PsiClass> getLightClassesForDecompiledFacadeFiles(@NotNull FqName facadeFqName, @NotNull List<JetFile> filesWithCallables) {
|
||||||
JetFile firstFile = filesWithCallables.iterator().next();
|
List<PsiClass> lightClasses = new ArrayList<PsiClass>();
|
||||||
if (firstFile.isCompiled()) {
|
for (JetFile file : filesWithCallables) {
|
||||||
if (filesWithCallables.size() > 1) {
|
if (file.isCompiled()) {
|
||||||
LOG.error("Several files with callables for facade: " + facadeFqName);
|
lightClasses.add(createLightClassForDecompiledKotlinFile(file));
|
||||||
}
|
}
|
||||||
return createLightClassForDecompiledKotlinFile(firstFile);
|
|
||||||
}
|
}
|
||||||
return null;
|
return lightClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+13
-2
@@ -22,7 +22,9 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
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.header.isCompatibleClassKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
@@ -64,7 +66,11 @@ public fun buildDecompiledText(
|
|||||||
mapOf())
|
mapOf())
|
||||||
}
|
}
|
||||||
classHeader.isCompatiblePackageFacadeKind() ->
|
classHeader.isCompatiblePackageFacadeKind() ->
|
||||||
buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInPackage(packageFqName)))
|
buildDecompiledText(packageFqName,
|
||||||
|
ArrayList(resolver.resolveDeclarationsInFacade(PackageClassUtils.getPackageClassFqName(packageFqName))))
|
||||||
|
classHeader.isCompatibleFileFacadeKind() ->
|
||||||
|
buildDecompiledText(packageFqName,
|
||||||
|
ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())))
|
||||||
classHeader.isCompatibleClassKind() ->
|
classHeader.isCompatibleClassKind() ->
|
||||||
buildDecompiledText(packageFqName, listOf(resolver.resolveTopLevelClass(classId)).filterNotNull())
|
buildDecompiledText(packageFqName, listOf(resolver.resolveTopLevelClass(classId)).filterNotNull())
|
||||||
else ->
|
else ->
|
||||||
@@ -80,7 +86,9 @@ public fun buildDecompiledTextFromJsMetadata(
|
|||||||
val isPackageHeader = JsMetaFileUtils.isPackageHeader(classFile)
|
val isPackageHeader = JsMetaFileUtils.isPackageHeader(classFile)
|
||||||
|
|
||||||
if (isPackageHeader) {
|
if (isPackageHeader) {
|
||||||
return buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInPackage(packageFqName)), descriptorRendererForKotlinJavascriptDecompiler)
|
return buildDecompiledText(packageFqName,
|
||||||
|
resolveDeclarationsInPackage(packageFqName, resolver),
|
||||||
|
descriptorRendererForKotlinJavascriptDecompiler)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val classId = JsMetaFileUtils.getClassId(classFile)
|
val classId = JsMetaFileUtils.getClassId(classFile)
|
||||||
@@ -88,6 +96,9 @@ public fun buildDecompiledTextFromJsMetadata(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun resolveDeclarationsInPackage(packageFqName: FqName, resolver: ResolverForDecompiler) =
|
||||||
|
ArrayList(resolver.resolveDeclarationsInFacade(PackageClassUtils.getPackageClassFqName(packageFqName)))
|
||||||
|
|
||||||
private val DECOMPILED_CODE_COMMENT = "/* compiled code */"
|
private val DECOMPILED_CODE_COMMENT = "/* compiled code */"
|
||||||
private val DECOMPILED_COMMENT_FOR_PARAMETER = "/* = compiled code */"
|
private val DECOMPILED_COMMENT_FOR_PARAMETER = "/* = compiled code */"
|
||||||
private val FLEXIBLE_TYPE_COMMENT = "/* platform type */"
|
private val FLEXIBLE_TYPE_COMMENT = "/* platform type */"
|
||||||
|
|||||||
+8
-4
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.load.kotlin.BinaryClassAnnotationAndConstantLoaderIm
|
|||||||
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.serialization.deserialization.ClassDescriptorFactory
|
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||||
@@ -53,12 +54,15 @@ public class DeserializerForDecompiler(
|
|||||||
ResolveEverythingToKotlinAnyLocalClassResolver, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
|
ResolveEverythingToKotlinAnyLocalClassResolver, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
assert(packageFqName == directoryPackageFqName) { "Was called for $packageFqName but only $directoryPackageFqName is expected" }
|
val packageFqName = facadeFqName.parent()
|
||||||
val binaryClassForPackageClass = classFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFqName))
|
assert(packageFqName == directoryPackageFqName) {
|
||||||
|
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||||
|
}
|
||||||
|
val binaryClassForPackageClass = classFinder.findKotlinClass(ClassId.topLevel(facadeFqName))
|
||||||
val annotationData = binaryClassForPackageClass?.getClassHeader()?.annotationData
|
val annotationData = binaryClassForPackageClass?.getClassHeader()?.annotationData
|
||||||
if (annotationData == null) {
|
if (annotationData == null) {
|
||||||
LOG.error("Could not read annotation data for $packageFqName from ${binaryClassForPackageClass?.getClassId()}")
|
LOG.error("Could not read annotation data for $facadeFqName from ${binaryClassForPackageClass?.getClassId()}")
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
|
||||||
|
|||||||
+8
-4
@@ -21,6 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
||||||
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.serialization.deserialization.ClassDescriptorFactory
|
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||||
@@ -55,11 +56,14 @@ public class KotlinJavaScriptDeserializerForDecompiler(
|
|||||||
ResolveEverythingToKotlinAnyLocalClassResolver, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
|
ResolveEverythingToKotlinAnyLocalClassResolver, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
assert(packageFqName == directoryPackageFqName, "Was called for $packageFqName but only $directoryPackageFqName is expected.")
|
val packageFqName = facadeFqName.parent()
|
||||||
val file = metaFileFinder.findKotlinJavascriptMetaFile(PackageClassUtils.getPackageClassId(packageFqName))
|
assert(packageFqName == directoryPackageFqName) {
|
||||||
|
"Was called for $facadeFqName; only members of $directoryPackageFqName package are expected."
|
||||||
|
}
|
||||||
|
val file = metaFileFinder.findKotlinJavascriptMetaFile(ClassId.topLevel(facadeFqName))
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
LOG.error("Could not read data for $packageFqName")
|
LOG.error("Could not read data for $facadeFqName")
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,5 +24,5 @@ import org.jetbrains.kotlin.name.ClassId
|
|||||||
public interface ResolverForDecompiler {
|
public interface ResolverForDecompiler {
|
||||||
public fun resolveTopLevelClass(classId: ClassId): ClassDescriptor?
|
public fun resolveTopLevelClass(classId: ClassId): ClassDescriptor?
|
||||||
|
|
||||||
public fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor>
|
public fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ LineBreakpoint created at stepIntoStdlibFacadeClass.kt:6
|
|||||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stepIntoStdlibFacadeClass.StepIntoStdlibFacadeClassPackage
|
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stepIntoStdlibFacadeClass.StepIntoStdlibFacadeClassPackage
|
||||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
stepIntoStdlibFacadeClass.kt:6
|
stepIntoStdlibFacadeClass.kt:6
|
||||||
KotlinPackage.!EXT!
|
SequenceKt.!EXT!
|
||||||
_Mapping.!EXT!
|
_Mapping.!EXT!
|
||||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -67,8 +67,9 @@ private class ResolverForDecompilerImpl(val module: ModuleDescriptor) : Resolver
|
|||||||
return module.resolveTopLevelClass(classId.asSingleFqName(), NoLookupLocation.FROM_TEST)
|
return module.resolveTopLevelClass(classId.asSingleFqName(), NoLookupLocation.FROM_TEST)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||||
return module.getPackage(packageFqName).memberScope.getAllDescriptors() filter {
|
// TODO how to handle non-package facades properly here?
|
||||||
|
return module.getPackage(facadeFqName.parent()).memberScope.getAllDescriptors() filter {
|
||||||
it is CallableMemberDescriptor && it.module != KotlinBuiltIns.getInstance().getBuiltInsModule()
|
it is CallableMemberDescriptor && it.module != KotlinBuiltIns.getInstance().getBuiltInsModule()
|
||||||
} sortBy MemberComparator.INSTANCE
|
} sortBy MemberComparator.INSTANCE
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.serialization.DebugProtoBuf
|
|||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
import org.jetbrains.kotlin.jps.incremental.LocalFileKotlinClass
|
import org.jetbrains.kotlin.jps.incremental.LocalFileKotlinClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
||||||
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
||||||
|
|
||||||
// Set this to true if you want to dump all bytecode (test will fail in this case)
|
// Set this to true if you want to dump all bytecode (test will fail in this case)
|
||||||
@@ -144,7 +145,8 @@ fun classFileToString(classFile: File): String {
|
|||||||
when {
|
when {
|
||||||
classHeader!!.isCompatiblePackageFacadeKind() ->
|
classHeader!!.isCompatiblePackageFacadeKind() ->
|
||||||
out.write("\n------ package proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
out.write("\n------ package proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||||
|
classHeader.isCompatibleFileFacadeKind() ->
|
||||||
|
out.write("\n------ file facade proto -----\n${DebugProtoBuf.Package.parseFrom(input, getExtensionRegistry())}")
|
||||||
classHeader.isCompatibleClassKind() ->
|
classHeader.isCompatibleClassKind() ->
|
||||||
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
|
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user