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.DelegatedVisitor 22 import com.android.tools.metalava.model.FieldItem 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.TypeStringConfiguration 27 import com.android.tools.metalava.model.VisibilityLevel 28 import java.io.PrintWriter 29 30 class ProguardWriter( 31 private val writer: PrintWriter, 32 ) : DelegatedVisitor { 33 visitClassnull34 override fun visitClass(cls: ClassItem) { 35 writer.print("-keep class ") 36 writer.print(getCleanTypeName(cls.type())) 37 writer.print(" {\n") 38 } 39 afterVisitClassnull40 override fun afterVisitClass(cls: ClassItem) { 41 writer.print("}\n") 42 } 43 visitConstructornull44 override fun visitConstructor(constructor: ConstructorItem) { 45 writer.print(" ") 46 writer.print("<init>") 47 48 writeParametersKeepList(constructor.parameters()) 49 writer.print(";\n") 50 } 51 visitMethodnull52 override fun visitMethod(method: MethodItem) { 53 writer.print(" ") 54 val modifiers = method.modifiers 55 val visibilityLevel = modifiers.getVisibilityLevel() 56 if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) { 57 writer.write(visibilityLevel.javaSourceCodeModifier + " ") 58 } 59 60 if (modifiers.isStatic()) { 61 writer.print("static ") 62 } 63 if (modifiers.isAbstract()) { 64 writer.print("abstract ") 65 } 66 if (modifiers.isSynchronized()) { 67 writer.print("synchronized ") 68 } 69 70 writer.print(getCleanTypeName(method.returnType())) 71 writer.print(" ") 72 writer.print(method.name()) 73 74 writeParametersKeepList(method.parameters()) 75 76 writer.print(";\n") 77 } 78 writeParametersKeepListnull79 private fun writeParametersKeepList(params: List<ParameterItem>) { 80 writer.print("(") 81 82 for (pi in params) { 83 if (pi !== params[0]) { 84 writer.print(", ") 85 } 86 writer.print(getCleanTypeName(pi.type())) 87 } 88 89 writer.print(")") 90 } 91 visitFieldnull92 override fun visitField(field: FieldItem) { 93 writer.print(" ") 94 95 val modifiers = field.modifiers 96 val visibilityLevel = modifiers.getVisibilityLevel() 97 if (visibilityLevel != VisibilityLevel.PACKAGE_PRIVATE) { 98 writer.write(visibilityLevel.javaSourceCodeModifier + " ") 99 } 100 101 if (modifiers.isStatic()) { 102 writer.print("static ") 103 } 104 if (modifiers.isTransient()) { 105 writer.print("transient ") 106 } 107 if (modifiers.isVolatile()) { 108 writer.print("volatile ") 109 } 110 111 writer.print(getCleanTypeName(field.type())) 112 113 writer.print(" ") 114 writer.print(field.name()) 115 116 writer.print(";\n") 117 } 118 getCleanTypeNamenull119 private fun getCleanTypeName(t: TypeItem?): String { 120 return t?.toTypeString(PROGUARD_TYPE_STRING_CONFIGURATION) ?: "" 121 } 122 123 companion object { 124 private val PROGUARD_TYPE_STRING_CONFIGURATION = 125 TypeStringConfiguration( 126 eraseGenerics = true, 127 nestedClassSeparator = '$', 128 treatVarargsAsArray = true, 129 ) 130 } 131 } 132