Do not generate DefaultImpls if empty

This commit is contained in:
Yan Zhulanow
2015-10-26 16:03:58 +03:00
parent 2a28baa154
commit 3475b4796f
14 changed files with 271 additions and 64 deletions
@@ -334,7 +334,7 @@ public class ClassFileFactory implements OutputFileCollection {
public abstract String asText(ClassBuilderFactory factory);
}
public void removeInlinedClasses(Set<String> classNamesToRemove) {
public void removeClasses(Set<String> classNamesToRemove) {
for (String classInternalName : classNamesToRemove) {
generators.remove(classInternalName + ".class");
}
@@ -32,8 +32,12 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.DelegationToTraitImpl
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.KtScope
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
import org.jetbrains.org.objectweb.asm.FieldVisitor
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_FINAL
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
import org.jetbrains.org.objectweb.asm.Opcodes.V1_6
@@ -45,7 +49,9 @@ public class InterfaceImplBodyCodegen(
v: ClassBuilder,
state: GenerationState,
parentCodegen: MemberCodegen<*>?
) : ClassBodyCodegen(aClass, context, v, state, parentCodegen) {
) : ClassBodyCodegen(aClass, context, InterfaceImplBodyCodegen.InterfaceImplClassBuilder(v), state, parentCodegen) {
private var isAnythingGenerated: Boolean = false
get() = (v as InterfaceImplClassBuilder).isAnythingGenerated
override fun generateDeclaration() {
v.defineClass(
@@ -57,6 +63,7 @@ public class InterfaceImplBodyCodegen(
}
override fun classForInnerClassRecord(): ClassDescriptor? {
if (!isAnythingGenerated) return null
if (DescriptorUtils.isLocal(descriptor)) return null
val classDescriptorImpl = ClassDescriptorImpl(
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
@@ -144,9 +151,59 @@ public class InterfaceImplBodyCodegen(
}
override fun generateKotlinAnnotation() {
(v as InterfaceImplClassBuilder).stopCounting()
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(KOTLIN_INTERFACE_DEFAULT_IMPLS), true)
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmAbi.VERSION.toArray())
av.visitEnd()
AsmUtil.writeKotlinSyntheticClassAnnotation(v, state)
}
override fun done() {
super.done()
if (!isAnythingGenerated) {
state.factory.removeClasses(setOf(typeMapper.mapDefaultImpls(descriptor).internalName))
}
}
private class InterfaceImplClassBuilder(private val v: ClassBuilder) : DelegatingClassBuilder() {
private var shouldCount: Boolean = true
var isAnythingGenerated: Boolean = false
private set
fun stopCounting() {
shouldCount = false
}
override fun getDelegate() = v
override fun newField(
origin: JvmDeclarationOrigin,
access: Int,
name: String,
desc: String,
signature: String?,
value: Any?
): FieldVisitor {
if (shouldCount) isAnythingGenerated = true
return super.newField(origin, access, name, desc, signature, value)
}
override fun newMethod(
origin: JvmDeclarationOrigin,
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
if (shouldCount) isAnythingGenerated = true
return super.newMethod(origin, access, name, desc, signature, exceptions)
}
override fun newAnnotation(desc: String, visible: Boolean): AnnotationVisitor {
if (shouldCount) isAnythingGenerated = true
return super.newAnnotation(desc, visible)
}
}
}
@@ -170,7 +170,7 @@ public class InlineCodegen extends CallGenerator {
codegen.propagateChildReifiedTypeParametersUsages(result.getReifiedTypeParametersUsages());
state.getFactory().removeInlinedClasses(result.getClassesToRemove());
state.getFactory().removeClasses(result.getClassesToRemove());
codegen.markLineNumberAfterInlineIfNeeded();
}