1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava 18 19 import com.android.tools.metalava.model.ClassItem 20 import com.android.tools.metalava.model.ConstructorItem 21 import com.android.tools.metalava.model.FieldItem 22 import com.android.tools.metalava.model.Item 23 import com.android.tools.metalava.model.MethodItem 24 import com.android.tools.metalava.model.ParameterItem 25 import com.android.tools.metalava.model.TypeItem 26 import com.android.tools.metalava.model.visitors.ApiVisitor 27 import java.io.PrintWriter 28 import java.util.function.Predicate 29 30 class ProguardWriter( 31 private val writer: PrintWriter, 32 filterEmit: Predicate<Item>, 33 filterReference: Predicate<Item> 34 ) : ApiVisitor( 35 visitConstructorsAsMethods = false, 36 nestInnerClasses = false, 37 inlineInheritedFields = true, 38 filterEmit = filterEmit, 39 filterReference = filterReference 40 ) { 41 visitClassnull42 override fun visitClass(cls: ClassItem) { 43 writer.print("-keep class ") 44 writer.print(cls.qualifiedNameWithDollarInnerClasses()) 45 writer.print(" {\n") 46 } 47 afterVisitClassnull48 override fun afterVisitClass(cls: ClassItem) { 49 writer.print("}\n") 50 } 51 visitConstructornull52 override fun visitConstructor(constructor: ConstructorItem) { 53 writer.print(" ") 54 writer.print("<init>") 55 56 writeParametersKeepList(constructor.parameters()) 57 writer.print(";\n") 58 } 59 visitMethodnull60 override fun visitMethod(method: MethodItem) { 61 writer.print(" ") 62 val modifiers = method.modifiers 63 when { 64 modifiers.isPublic() -> writer.write("public ") 65 modifiers.isProtected() -> writer.write("protected ") 66 modifiers.isPrivate() -> writer.write("private ") 67 } 68 69 if (modifiers.isStatic()) { 70 writer.print("static ") 71 } 72 if (modifiers.isAbstract()) { 73 writer.print("abstract ") 74 } 75 if (modifiers.isSynchronized()) { 76 writer.print("synchronized ") 77 } 78 79 writer.print(getCleanTypeName(method.returnType())) 80 writer.print(" ") 81 writer.print(method.name()) 82 83 writeParametersKeepList(method.parameters()) 84 85 writer.print(";\n") 86 } 87 writeParametersKeepListnull88 private fun writeParametersKeepList(params: List<ParameterItem>) { 89 writer.print("(") 90 91 for (pi in params) { 92 if (pi !== params[0]) { 93 writer.print(", ") 94 } 95 writer.print(getCleanTypeName(pi.type())) 96 } 97 98 writer.print(")") 99 } 100 visitFieldnull101 override fun visitField(field: FieldItem) { 102 writer.print(" ") 103 104 val modifiers = field.modifiers 105 when { 106 modifiers.isPublic() -> writer.write("public ") 107 modifiers.isProtected() -> writer.write("protected ") 108 modifiers.isPrivate() -> writer.write("private ") 109 } 110 111 if (modifiers.isStatic()) { 112 writer.print("static ") 113 } 114 if (modifiers.isTransient()) { 115 writer.print("transient ") 116 } 117 if (modifiers.isVolatile()) { 118 writer.print("volatile ") 119 } 120 121 writer.print(getCleanTypeName(field.type())) 122 123 writer.print(" ") 124 writer.print(field.name()) 125 126 writer.print(";\n") 127 } 128 getCleanTypeNamenull129 private fun getCleanTypeName(t: TypeItem?): String { 130 t ?: return "" 131 val cls = t.asClass() ?: return t.toSimpleType() 132 return cls.qualifiedNameWithDollarInnerClasses() 133 } 134 }