1 /*
2  * Copyright (C) 2023 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.turbine
18 
19 import com.android.tools.metalava.model.ClassItem
20 import com.android.tools.metalava.model.DefaultModifierList
21 import com.android.tools.metalava.model.ExceptionTypeItem
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.TypeParameterList
26 import com.android.tools.metalava.model.computeSuperMethods
27 import com.android.tools.metalava.model.updateCopiedMethodState
28 import com.android.tools.metalava.reporter.FileLocation
29 import com.google.turbine.binder.sym.MethodSymbol
30 
31 internal open class TurbineMethodItem(
32     codebase: TurbineBasedCodebase,
33     fileLocation: FileLocation,
34     private val methodSymbol: MethodSymbol,
35     containingClass: ClassItem,
36     private val returnType: TypeItem,
37     modifiers: DefaultModifierList,
38     override val typeParameterList: TypeParameterList,
39     documentation: String,
40     private val defaultValue: String,
41 ) :
42     TurbineMemberItem(codebase, fileLocation, modifiers, documentation, containingClass),
43     MethodItem {
44 
45     private lateinit var superMethodList: List<MethodItem>
46     internal lateinit var throwableTypes: List<ExceptionTypeItem>
47     internal lateinit var parameters: List<ParameterItem>
48 
49     override var inheritedFrom: ClassItem? = null
50 
namenull51     override fun name(): String = methodSymbol.name()
52 
53     override fun parameters(): List<ParameterItem> = parameters
54 
55     override fun returnType(): TypeItem = returnType
56 
57     override fun throwsTypes(): List<ExceptionTypeItem> = throwableTypes
58 
59     override fun isExtensionMethod(): Boolean = false // java does not support extension methods
60 
61     override fun isConstructor(): Boolean = false
62 
63     /**
64      * Super methods for a given method M with containing class C are calculated as follows:
65      * 1) Superclass Search: Traverse the class hierarchy, starting from C's direct superclass, and
66      *    add the first method that matches M's signature to the list.
67      * 2) Interface Supermethod Search: For each direct interface implemented by C, check if it
68      *    contains a method matching M's signature. If found, return that method. If not,
69      *    recursively apply this method to the direct interfaces of the current interface.
70      *
71      * Note: This method's implementation is based on MethodItem.matches method which only checks
72      * that name and parameter list types match. Parameter names, Return types and Throws list types
73      * are not matched
74      */
75     override fun superMethods(): List<MethodItem> {
76         if (!::superMethodList.isInitialized) {
77             superMethodList = computeSuperMethods()
78         }
79         return superMethodList
80     }
81 
equalsnull82     override fun equals(other: Any?): Boolean {
83         if (this === other) return true
84         if (javaClass != other?.javaClass) return false
85 
86         other as TurbineMethodItem
87 
88         if (methodSymbol != other.methodSymbol) return false
89 
90         return true
91     }
92 
hashCodenull93     override fun hashCode(): Int {
94         return methodSymbol.hashCode()
95     }
96 
97     @Deprecated("This property should not be accessed directly.")
98     override var _requiresOverride: Boolean? = null
99 
duplicatenull100     override fun duplicate(targetContainingClass: ClassItem): TurbineMethodItem {
101         val retType = returnType.duplicate()
102         val mods = modifiers.duplicate()
103         val duplicated =
104             TurbineMethodItem(
105                 codebase,
106                 fileLocation,
107                 methodSymbol,
108                 targetContainingClass,
109                 retType,
110                 mods,
111                 typeParameterList,
112                 documentation,
113                 defaultValue,
114             )
115         // Duplicate the parameters
116         val params =
117             parameters.map { TurbineParameterItem.duplicate(codebase, duplicated, it, emptyMap()) }
118         duplicated.parameters = params
119         duplicated.inheritedFrom = containingClass()
120         duplicated.throwableTypes = throwableTypes
121 
122         // Preserve flags that may have been inherited (propagated) from surrounding packages
123         if (targetContainingClass.hidden) {
124             duplicated.hidden = true
125         }
126         if (targetContainingClass.removed) {
127             duplicated.removed = true
128         }
129         if (targetContainingClass.docOnly) {
130             duplicated.docOnly = true
131         }
132 
133         duplicated.updateCopiedMethodState()
134 
135         return duplicated
136     }
137 
findMainDocumentationnull138     override fun findMainDocumentation(): String = TODO("b/295800205")
139 
140     internal fun setThrowsTypes(throwsList: List<ExceptionTypeItem>) {
141         throwableTypes = throwsList
142     }
143 
getSymbolnull144     internal fun getSymbol(): MethodSymbol = methodSymbol
145 
146     override fun defaultValue(): String = defaultValue
147 }
148