1 /*
2  * Copyright (C) 2024 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.item
18 
19 import com.android.tools.metalava.model.ApiVariantSelectorsFactory
20 import com.android.tools.metalava.model.BaseModifierList
21 import com.android.tools.metalava.model.CallableBody
22 import com.android.tools.metalava.model.CallableBodyFactory
23 import com.android.tools.metalava.model.CallableItem
24 import com.android.tools.metalava.model.ClassItem
25 import com.android.tools.metalava.model.Codebase
26 import com.android.tools.metalava.model.ExceptionTypeItem
27 import com.android.tools.metalava.model.ItemDocumentationFactory
28 import com.android.tools.metalava.model.ItemLanguage
29 import com.android.tools.metalava.model.ParameterItem
30 import com.android.tools.metalava.model.TypeItem
31 import com.android.tools.metalava.model.TypeParameterList
32 import com.android.tools.metalava.reporter.FileLocation
33 
34 /**
35  * A lamda that given a [CallableItem] will create a list of [ParameterItem]s for it.
36  *
37  * This is called from within the constructor of the [ParameterItem.containingCallable] and can only
38  * access the [CallableItem.name] (to identify callables that have special nullability rules) and
39  * store a reference to it in [ParameterItem.containingCallable]. In particularly, it must not
40  * access [CallableItem.parameters] as that will not yet have been initialized when this is called.
41  */
42 typealias ParameterItemsFactory = (CallableItem) -> List<ParameterItem>
43 
44 abstract class DefaultCallableItem(
45     codebase: Codebase,
46     fileLocation: FileLocation,
47     itemLanguage: ItemLanguage,
48     modifiers: BaseModifierList,
49     documentationFactory: ItemDocumentationFactory,
50     variantSelectorsFactory: ApiVariantSelectorsFactory,
51     name: String,
52     containingClass: ClassItem,
53     override val typeParameterList: TypeParameterList,
54     returnType: TypeItem,
55     parameterItemsFactory: ParameterItemsFactory,
56     internal val throwsTypes: List<ExceptionTypeItem>,
57     callableBodyFactory: CallableBodyFactory,
58 ) :
59     DefaultMemberItem(
60         codebase,
61         fileLocation,
62         itemLanguage,
63         modifiers,
64         documentationFactory,
65         variantSelectorsFactory,
66         name,
67         containingClass,
68     ),
69     CallableItem {
70 
71     /** Make it readable to subclasses but not writable. */
72     protected var returnType: TypeItem = returnType
73         private set
74 
75     /**
76      * Create the [ParameterItem] list during initialization of this callable to allow them to
77      * contain an immutable reference to this object.
78      *
79      * The leaking of `this` to `parameterItemsFactory` is ok as implementations follow the rules
80      * explained in the documentation of [ParameterItemsFactory].
81      */
82     @Suppress("LeakingThis") internal val parameters = parameterItemsFactory(this)
83 
returnTypenull84     override fun returnType(): TypeItem = returnType
85 
86     override fun setType(type: TypeItem) {
87         returnType = type
88     }
89 
parametersnull90     final override fun parameters(): List<ParameterItem> = parameters
91 
92     final override fun throwsTypes(): List<ExceptionTypeItem> = throwsTypes
93 
94     /**
95      * Create the [CallableBody] during initialization of this callable to allow it to contain an
96      * immutable reference to this object.
97      *
98      * The leaking of `this` to `callableBodyFactory` is ok as implementations follow the rules
99      * explained in the documentation of [CallableBodyFactory].
100      */
101     final override val body: CallableBody = callableBodyFactory(@Suppress("LeakingThis") this)
102 }
103