Proper light classes generation in presence of the new file facades.

This commit is contained in:
Dmitry Petrov
2015-08-26 13:28:34 +03:00
committed by Michael Bogdanov
parent 5fdfe8df3c
commit b1b845d44d
8 changed files with 49 additions and 30 deletions
@@ -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
@@ -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 */"
@@ -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)
@@ -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()
}
@@ -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'
@@ -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
}
@@ -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())}")