Refactor and fix buildDecompiledText#appendDescriptor

Make it clear that first we render all enum entries, then the companion if it
exists, then anything else. Previously the companion wasn't rendered in the
case when the scope did not contain anything else (which was the case for the
scope of a class not found in the decompiler)
This commit is contained in:
Alexander Udalov
2015-09-01 14:24:02 +03:00
parent be2324031d
commit c90bcb41f3
@@ -28,14 +28,12 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.DescriptorRendererModifier import org.jetbrains.kotlin.renderer.DescriptorRendererModifier
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumClass
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.types.error.MissingDependencyErrorClass import org.jetbrains.kotlin.types.error.MissingDependencyErrorClass
import org.jetbrains.kotlin.types.flexibility import org.jetbrains.kotlin.types.flexibility
import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.types.isFlexible
import java.util.ArrayList import java.util.*
import java.util.HashMap
private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI" private val FILE_ABI_VERSION_MARKER: String = "FILE_ABI"
private val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI" private val CURRENT_ABI_VERSION_MARKER: String = "CURRENT_ABI"
@@ -139,13 +137,13 @@ public fun buildDecompiledText(
renderedDescriptorsToRange[descriptorToKey(descriptor)] = TextRange(startOffset, endOffset) renderedDescriptorsToRange[descriptorToKey(descriptor)] = TextRange(startOffset, endOffset)
} }
fun appendDescriptor(descriptor: DeclarationDescriptor, indent: String, lastEnumEntry: Boolean = false) { fun appendDescriptor(descriptor: DeclarationDescriptor, indent: String, lastEnumEntry: Boolean? = null) {
if (descriptor is MissingDependencyErrorClass) { if (descriptor is MissingDependencyErrorClass) {
throw IllegalStateException("${descriptor.javaClass.getSimpleName()} cannot be rendered. FqName: ${descriptor.fullFqName}") throw IllegalStateException("${descriptor.javaClass.getSimpleName()} cannot be rendered. FqName: ${descriptor.fullFqName}")
} }
val startOffset = builder.length() val startOffset = builder.length()
val header = if (isEnumEntry(descriptor)) val header = if (isEnumEntry(descriptor))
descriptor.name.asString() + if (lastEnumEntry) ";" else "," descriptor.name.asString() + if (lastEnumEntry!!) ";" else ","
else else
descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER) descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER)
builder.append(header) builder.append(header)
@@ -170,58 +168,64 @@ public fun buildDecompiledText(
endOffset = builder.length() endOffset = builder.length()
} }
} }
else if (descriptor is ClassDescriptor) { else if (descriptor is ClassDescriptor && !isEnumEntry(descriptor)) {
if (!isEnumEntry(descriptor)) { builder.append(" {\n")
builder.append(" {\n")
var firstPassed = false val subindent = indent + " "
val subindent = indent + " "
val allDescriptors = descriptor.secondaryConstructors + descriptor.getDefaultType().getMemberScope().getDescriptors() var firstPassed = false
val companionObject = descriptor.getCompanionObjectDescriptor() fun newlineExceptFirst() {
var companionNeeded = (companionObject != null) if (firstPassed) {
fun newlineExceptFirst() { builder.append("\n")
if (firstPassed) {
builder.append("\n")
}
else {
firstPassed = true
}
} }
val enumEntryCount = if (isEnumClass(descriptor)) allDescriptors.count { isEnumEntry(it) } else 0 else {
var enumEntryIndex = 0 firstPassed = true
for (member in allDescriptors) {
if (member.containingDeclaration != descriptor) {
continue
}
if (member == companionObject) {
continue
}
val isEnumEntry = isEnumEntry(member)
if (companionNeeded && !isEnumEntry) {
companionNeeded = false
newlineExceptFirst()
builder.append(subindent)
appendDescriptor(companionObject!!, subindent)
}
if (member is CallableMemberDescriptor
&& member.kind != CallableMemberDescriptor.Kind.DECLARATION
//TODO: not synthesized and component like
&& !isComponentLike(member.name)) {
continue
}
newlineExceptFirst()
builder.append(subindent)
appendDescriptor(member, subindent, isEnumEntry && ++enumEntryIndex == enumEntryCount)
} }
builder.append(indent).append("}")
endOffset = builder.length()
} }
val allDescriptors = descriptor.secondaryConstructors + descriptor.defaultType.memberScope.getDescriptors()
val (enumEntries, members) = allDescriptors.partition(::isEnumEntry)
for ((index, enumEntry) in enumEntries.withIndex()) {
newlineExceptFirst()
builder.append(subindent)
appendDescriptor(enumEntry, subindent, index == enumEntries.lastIndex)
}
val companionObject = descriptor.companionObjectDescriptor
if (companionObject != null) {
newlineExceptFirst()
builder.append(subindent)
appendDescriptor(companionObject, subindent)
}
for (member in members) {
if (member.containingDeclaration != descriptor) {
continue
}
if (member == companionObject) {
continue
}
if (member is CallableMemberDescriptor
&& member.kind != CallableMemberDescriptor.Kind.DECLARATION
//TODO: not synthesized and component like
&& !isComponentLike(member.name)) {
continue
}
newlineExceptFirst()
builder.append(subindent)
appendDescriptor(member, subindent)
}
builder.append(indent).append("}")
endOffset = builder.length()
} }
builder.append("\n") builder.append("\n")
saveDescriptorToRange(descriptor, startOffset, endOffset) saveDescriptorToRange(descriptor, startOffset, endOffset)
if (descriptor is ClassDescriptor) { if (descriptor is ClassDescriptor) {
val primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor() val primaryConstructor = descriptor.unsubstitutedPrimaryConstructor
if (primaryConstructor != null) { if (primaryConstructor != null) {
saveDescriptorToRange(primaryConstructor, startOffset, endOffset) saveDescriptorToRange(primaryConstructor, startOffset, endOffset)
} }