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.model.text 18 19 import com.android.tools.metalava.compatibility 20 import com.android.tools.metalava.model.ClassItem 21 import com.android.tools.metalava.model.Item 22 import com.android.tools.metalava.model.MethodItem 23 import com.android.tools.metalava.model.ParameterItem 24 import com.android.tools.metalava.model.TypeItem 25 import com.android.tools.metalava.model.TypeParameterItem 26 import com.android.tools.metalava.model.TypeParameterList 27 import com.android.tools.metalava.model.TypeParameterListOwner 28 import java.util.function.Predicate 29 30 open class TextMethodItem( 31 codebase: TextCodebase, 32 name: String, 33 containingClass: TextClassItem, 34 modifiers: TextModifiers, 35 private val returnType: TextTypeItem?, 36 position: SourcePositionInfo 37 ) : TextMemberItem( 38 codebase, name, containingClass, position, 39 modifiers = modifiers 40 ), MethodItem, TypeParameterListOwner { 41 init { 42 @Suppress("LeakingThis") 43 modifiers.setOwner(this) 44 } 45 equalsnull46 override fun equals(other: Any?): Boolean { 47 if (this === other) return true 48 if (other !is MethodItem) return false 49 50 if (name() != other.name()) { 51 return false 52 } 53 54 if (containingClass() != other.containingClass()) { 55 return false 56 } 57 58 val parameters1 = parameters() 59 val parameters2 = other.parameters() 60 61 if (parameters1.size != parameters2.size) { 62 return false 63 } 64 65 for (i in parameters1.indices) { 66 val parameter1 = parameters1[i] 67 val parameter2 = parameters2[i] 68 if (parameter1.type() != parameter2.type()) { 69 return false 70 } 71 } 72 return true 73 } 74 hashCodenull75 override fun hashCode(): Int { 76 return name().hashCode() 77 } 78 isConstructornull79 override fun isConstructor(): Boolean = false 80 81 override fun returnType(): TypeItem? = returnType 82 83 override fun superMethods(): List<MethodItem> { 84 if (isConstructor()) { 85 return emptyList() 86 } 87 88 val list = mutableListOf<MethodItem>() 89 90 var curr = containingClass().superClass() 91 while (curr != null) { 92 val superMethod = curr.findMethod(this) 93 if (superMethod != null) { 94 list.add(superMethod) 95 break 96 } 97 curr = curr.superClass() 98 } 99 100 // Interfaces 101 for (itf in containingClass().allInterfaces()) { 102 val interfaceMethod = itf.findMethod(this) 103 if (interfaceMethod != null) { 104 list.add(interfaceMethod) 105 } 106 } 107 108 return list 109 } 110 findPredicateSuperMethodnull111 override fun findPredicateSuperMethod(predicate: Predicate<Item>): MethodItem? = null 112 113 private var typeParameterList: TypeParameterList = TypeParameterList.NONE 114 115 fun setTypeParameterList(typeParameterList: TypeParameterList) { 116 this.typeParameterList = typeParameterList 117 } 118 typeParameterListnull119 override fun typeParameterList(): TypeParameterList = typeParameterList 120 121 override fun typeParameterListOwnerParent(): TypeParameterListOwner? { 122 return containingClass() as TextClassItem? 123 } 124 resolveParameternull125 override fun resolveParameter(variable: String): TypeParameterItem? { 126 for (t in typeParameterList.typeParameters()) { 127 if (t.simpleName() == variable) { 128 return t 129 } 130 } 131 132 return (containingClass() as TextClassItem).resolveParameter(variable) 133 } 134 duplicatenull135 override fun duplicate(targetContainingClass: ClassItem): MethodItem { 136 val duplicated = TextMethodItem( 137 codebase, name(), targetContainingClass as TextClassItem, 138 modifiers.duplicate(), returnType, position 139 ) 140 duplicated.inheritedFrom = containingClass() 141 142 // Preserve flags that may have been inherited (propagated) from surrounding packages 143 if (targetContainingClass.hidden) { 144 duplicated.hidden = true 145 } 146 if (targetContainingClass.removed) { 147 duplicated.removed = true 148 } 149 if (targetContainingClass.docOnly) { 150 duplicated.docOnly = true 151 } 152 if (targetContainingClass.deprecated && compatibility.propagateDeprecatedMembers) { 153 duplicated.deprecated = true 154 } 155 156 duplicated.varargs = varargs 157 duplicated.deprecated = deprecated 158 duplicated.annotationDefault = annotationDefault 159 duplicated.throwsTypes.addAll(throwsTypes) 160 duplicated.throwsClasses = throwsClasses 161 duplicated.typeParameterList = typeParameterList 162 // Consider cloning these: they have back references to the parent method (though it's 163 // unlikely anyone will care about the difference in parent methods) 164 duplicated.parameters.addAll(parameters) 165 166 return duplicated 167 } 168 169 override val synthetic: Boolean get() = isEnumSyntheticMethod() 170 171 private val throwsTypes = mutableListOf<String>() 172 private val parameters = mutableListOf<TextParameterItem>() 173 private var throwsClasses: List<ClassItem>? = null 174 throwsTypeNamesnull175 fun throwsTypeNames(): List<String> { 176 return throwsTypes 177 } 178 throwsTypesnull179 override fun throwsTypes(): List<ClassItem> = if (throwsClasses == null) emptyList() else throwsClasses!! 180 181 fun setThrowsList(throwsClasses: List<TextClassItem>) { 182 this.throwsClasses = throwsClasses 183 } 184 parametersnull185 override fun parameters(): List<ParameterItem> = parameters 186 187 fun addException(throwsType: String) { 188 throwsTypes += throwsType 189 } 190 addParameternull191 fun addParameter(parameter: TextParameterItem) { 192 parameters += parameter 193 } 194 195 private var varargs: Boolean = false 196 setVarargsnull197 fun setVarargs(varargs: Boolean) { 198 this.varargs = varargs 199 } 200 isVarArgnull201 fun isVarArg(): Boolean = varargs 202 203 override fun isExtensionMethod(): Boolean = codebase.unsupported() 204 205 override var inheritedMethod: Boolean = false 206 override var inheritedFrom: ClassItem? = null 207 208 override fun toString(): String = 209 "${if (isConstructor()) "constructor" else "method"} ${containingClass().qualifiedName()}.${name()}(${parameters().joinToString { 210 it.type().toSimpleType() 211 }})" 212 213 private var annotationDefault = "" 214 215 fun setAnnotationDefault(default: String) { 216 annotationDefault = default 217 } 218 defaultValuenull219 override fun defaultValue(): String { 220 return annotationDefault 221 } 222 } 223