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.util.ProjectRootsUtil;
|
||||
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.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -306,10 +307,9 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiClass clsClass = getLightClassForDecompiledFacade(packageFqName, files);
|
||||
if (clsClass != null) {
|
||||
result.add(clsClass);
|
||||
}
|
||||
FqName packageFacadeFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
|
||||
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(packageFacadeFqName, files);
|
||||
result.addAll(clsClasses);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -339,10 +339,8 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiClass clsClass = getLightClassForDecompiledFacade(facadeFqName, files);
|
||||
if (clsClass != null) {
|
||||
result.add(clsClass);
|
||||
}
|
||||
List<PsiClass> clsClasses = getLightClassesForDecompiledFacadeFiles(facadeFqName, files);
|
||||
result.addAll(clsClasses);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -377,15 +375,14 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiClass getLightClassForDecompiledFacade(@NotNull FqName facadeFqName, @NotNull List<JetFile> filesWithCallables) {
|
||||
JetFile firstFile = filesWithCallables.iterator().next();
|
||||
if (firstFile.isCompiled()) {
|
||||
if (filesWithCallables.size() > 1) {
|
||||
LOG.error("Several files with callables for facade: " + facadeFqName);
|
||||
private static List<PsiClass> getLightClassesForDecompiledFacadeFiles(@NotNull FqName facadeFqName, @NotNull List<JetFile> filesWithCallables) {
|
||||
List<PsiClass> lightClasses = new ArrayList<PsiClass>();
|
||||
for (JetFile file : filesWithCallables) {
|
||||
if (file.isCompiled()) {
|
||||
lightClasses.add(createLightClassForDecompiledKotlinFile(file));
|
||||
}
|
||||
return createLightClassForDecompiledKotlinFile(firstFile);
|
||||
}
|
||||
return null;
|
||||
return lightClasses;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+13
-2
@@ -22,7 +22,9 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
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.isCompatibleFileFacadeKind
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
@@ -64,7 +66,11 @@ public fun buildDecompiledText(
|
||||
mapOf())
|
||||
}
|
||||
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() ->
|
||||
buildDecompiledText(packageFqName, listOf(resolver.resolveTopLevelClass(classId)).filterNotNull())
|
||||
else ->
|
||||
@@ -80,7 +86,9 @@ public fun buildDecompiledTextFromJsMetadata(
|
||||
val isPackageHeader = JsMetaFileUtils.isPackageHeader(classFile)
|
||||
|
||||
if (isPackageHeader) {
|
||||
return buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInPackage(packageFqName)), descriptorRendererForKotlinJavascriptDecompiler)
|
||||
return buildDecompiledText(packageFqName,
|
||||
resolveDeclarationsInPackage(packageFqName, resolver),
|
||||
descriptorRendererForKotlinJavascriptDecompiler)
|
||||
}
|
||||
else {
|
||||
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_COMMENT_FOR_PARAMETER = "/* = compiled code */"
|
||||
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.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||
@@ -53,12 +54,15 @@ public class DeserializerForDecompiler(
|
||||
ResolveEverythingToKotlinAnyLocalClassResolver, JavaFlexibleTypeCapabilitiesDeserializer, ClassDescriptorFactory.EMPTY
|
||||
)
|
||||
|
||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
assert(packageFqName == directoryPackageFqName) { "Was called for $packageFqName but only $directoryPackageFqName is expected" }
|
||||
val binaryClassForPackageClass = classFinder.findKotlinClass(PackageClassUtils.getPackageClassId(packageFqName))
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
val packageFqName = facadeFqName.parent()
|
||||
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
|
||||
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()
|
||||
}
|
||||
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.idea.decompiler.navigation.JsMetaFileUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||
@@ -55,11 +56,14 @@ public class KotlinJavaScriptDeserializerForDecompiler(
|
||||
ResolveEverythingToKotlinAnyLocalClassResolver, FlexibleTypeCapabilitiesDeserializer.Dynamic, ClassDescriptorFactory.EMPTY
|
||||
)
|
||||
|
||||
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))
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<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 $packageFqName")
|
||||
LOG.error("Could not read data for $facadeFqName")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,5 +24,5 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
public interface ResolverForDecompiler {
|
||||
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
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
stepIntoStdlibFacadeClass.kt:6
|
||||
KotlinPackage.!EXT!
|
||||
SequenceKt.!EXT!
|
||||
_Mapping.!EXT!
|
||||
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)
|
||||
}
|
||||
|
||||
override fun resolveDeclarationsInPackage(packageFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
return module.getPackage(packageFqName).memberScope.getAllDescriptors() filter {
|
||||
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> {
|
||||
// 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()
|
||||
} sortBy MemberComparator.INSTANCE
|
||||
}
|
||||
|
||||
+3
-1
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.serialization.DebugProtoBuf
|
||||
import java.util.Arrays
|
||||
import org.jetbrains.kotlin.jps.incremental.LocalFileKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
|
||||
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
|
||||
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)
|
||||
@@ -144,7 +145,8 @@ fun classFileToString(classFile: File): String {
|
||||
when {
|
||||
classHeader!!.isCompatiblePackageFacadeKind() ->
|
||||
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() ->
|
||||
out.write("\n------ class proto -----\n${DebugProtoBuf.Class.parseFrom(input, getExtensionRegistry())}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user