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.VisibilityLevel 27 import com.android.tools.metalava.model.visitors.ApiVisitor 28 import java.io.PrintWriter 29 import java.util.function.Predicate 30 31 class ProguardWriter( 32 private val writer: PrintWriter, 33 filterEmit: Predicate<Item>, 34 filterReference: Predicate<Item> 35 ) : ApiVisitor( 36 visitConstructorsAsMethods = false, 37 nestInnerClasses = false, 38 inlineInheritedFields = true, 39 filterEmit = filterEmit, 40 filterReference = filterReference 41 ) { 42 visitClassnull43 override fun visitClass(cls: ClassItem) { 44 writer.print("-keep class ") 45 writer.print(cls.qualifiedNameWithDollarInnerClasses()) 46 writer.print(" {\n") 47 } 48 afterVisitClassnull49 override fun afterVisitClass(cls: ClassItem) { 50 writer.print("}\n") 51 } 52 visitConstructornull53 override fun visitConstructor(constructor: ConstructorItem) { 54 writer.print(" ") 55 writer.print("<init>") 56 57 writeParametersKeepList(constructor.parameters()) 58 writer.print(";\n") 59 } 60 visitMethodnull61 override fun visitMethod(method: MethodItem) { 62 writer.print(" ") 63 val modifiers = method.modifiers 64 val visibilityLevel = modifiers.getVisibilityLevel() 65 if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) { 66 writer.write(visibilityLevel.sourceCodeModifier + " ") 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 val visibilityLevel = modifiers.getVisibilityLevel() 106 if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) { 107 writer.write(visibilityLevel.sourceCodeModifier + " ") 108 } 109 110 if (modifiers.isStatic()) { 111 writer.print("static ") 112 } 113 if (modifiers.isTransient()) { 114 writer.print("transient ") 115 } 116 if (modifiers.isVolatile()) { 117 writer.print("volatile ") 118 } 119 120 writer.print(getCleanTypeName(field.type())) 121 122 writer.print(" ") 123 writer.print(field.name()) 124 125 writer.print(";\n") 126 } 127 getCleanTypeNamenull128 private fun getCleanTypeName(t: TypeItem?): String { 129 t ?: return "" 130 val cls = t.asClass() ?: return t.toCanonicalType() 131 var qualifiedName = cls.qualifiedNameWithDollarInnerClasses() 132 133 for (i in 0 until t.arrayDimensions()) { 134 qualifiedName += "[]" 135 } 136 return qualifiedName 137 } 138 }