in scrooge-adaptive/src/main/scala/com/twitter/scrooge/adapt/AdaptASMPruner.scala [45:105]
def pruneAdapt(templateFqdn: String, useMap: Map[String, Boolean]): Array[Byte] = {
// Using ASM prune Adapt first and then decoder
val classReader = new ClassReader(classBytesStream(templateFqdn))
val classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES)
val classNode = new ClassNode()
classReader.accept(classNode, ClassReader.EXPAND_FRAMES)
def isUnusedField(fieldName: String): Boolean =
useMap.get(fieldName) match {
case Some(used) => !used
case None => false
}
// Get rid of unused field members
val fieldIter = classNode.fields.iterator()
while (fieldIter.hasNext) {
val fieldNode = fieldIter.next().asInstanceOf[FieldNode]
val prefixedFieldName = fieldNode.name
if (prefixedFieldName.startsWith(MemberPrefix)) {
val fieldName = prefixedFieldName.substring(MemberPrefix.size)
if (isUnusedField(fieldName)) {
fieldIter.remove()
}
}
}
val methodIter = classNode.methods.iterator()
while (methodIter.hasNext) {
val methodNode = methodIter.next().asInstanceOf[MethodNode]
val name = methodNode.name
// Remove accessor method for unused field, we replace it with renamed
// delegate method below
if (isUnusedField(name)) {
methodIter.remove()
}
// Rename or remove delegate methods
if (name.startsWith(DelegatePrefix)) {
val fieldName = name.substring(DelegatePrefix.size)
if (useMap.contains(fieldName)) {
if (useMap(fieldName)) { // used field, remove delegate function
methodIter.remove()
} else { // unused field, rename delegate
methodNode.name = fieldName
}
}
}
// Remove setter methods for unused fields
if (name.startsWith(SetterPrefix)) {
val fieldName = name.substring(SetterPrefix.size)
if (isUnusedField(fieldName)) {
methodIter.remove()
}
}
}
classNode.accept(classWriter)
classWriter.toByteArray
}