xref: /aosp_15_r20/tools/metalava/metalava-model/src/main/java/com/android/tools/metalava/model/ParameterItem.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
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
18 
19 import com.android.tools.metalava.model.item.DefaultValue
20 
21 @MetalavaApi
22 interface ParameterItem : ClassContentItem, Item {
23     /** The name of this field */
namenull24     fun name(): String
25 
26     /** The type of this field */
27     @MetalavaApi override fun type(): TypeItem
28 
29     override fun findCorrespondingItemIn(
30         codebase: Codebase,
31         superMethods: Boolean,
32         duplicate: Boolean,
33     ) =
34         containingCallable()
35             .findCorrespondingItemIn(codebase, superMethods = superMethods, duplicate = duplicate)
36             ?.parameters()
37             ?.getOrNull(parameterIndex)
38 
39     /** The containing callable. */
40     fun containingCallable(): CallableItem
41 
42     /** The possible containing method, returns null if this is a constructor parameter. */
43     fun possibleContainingMethod(): MethodItem? = containingCallable().let { it as? MethodItem }
44 
45     /** Index of this parameter in the parameter list (0-based) */
46     val parameterIndex: Int
47 
48     /**
49      * The public name of this parameter. In Kotlin, names are part of the public API; in Java they
50      * are not. In Java, you can annotate a parameter with {@literal @ParameterName("foo")} to name
51      * the parameter something (potentially different from the actual code parameter name).
52      */
publicNamenull53     fun publicName(): String?
54 
55     /**
56      * Returns whether this parameter has a default value. In Kotlin, this is supported directly; in
57      * Java, it's supported via a special annotation, {@literal @DefaultValue("source"). This does
58      * not necessarily imply that the default value is accessible, and we know the body of the
59      * default value.
60      *
61      * @see isDefaultValueKnown
62      */
63     fun hasDefaultValue(): Boolean
64 
65     /**
66      * Returns whether this parameter has an accessible default value that we plan to keep. This is
67      * a superset of [hasDefaultValue] - if we are not writing the default values to the signature
68      * file, then the default value might not be available, even though the parameter does have a
69      * default.
70      *
71      * @see hasDefaultValue
72      */
73     fun isDefaultValueKnown(): Boolean
74 
75     /**
76      * Returns the default value.
77      *
78      * **This method should only be called if [isDefaultValueKnown] returned true!** (This is
79      * necessary since the null return value is a valid default value separate from no default value
80      * specified.)
81      *
82      * The default value is the source string literal representation of the value, e.g. strings
83      * would be surrounded by quotes, Booleans are the strings "true" or "false", and so on.
84      */
85     fun defaultValueAsString(): String?
86 
87     /** The default value of this [ParameterItem]. */
88     val defaultValue: DefaultValue
89 
90     /** Whether this is a varargs parameter */
91     fun isVarArgs(): Boolean = modifiers.isVarArg()
92 
93     /** The property declared by this parameter; inverse of [PropertyItem.constructorParameter] */
94     val property: PropertyItem?
95         get() = null
96 
97     override fun parent(): CallableItem? = containingCallable()
98 
99     override val effectivelyDeprecated: Boolean
100         get() = originallyDeprecated || containingCallable().effectivelyDeprecated
101 
102     override fun baselineElementId() =
103         containingCallable().baselineElementId() + " parameter #" + parameterIndex
104 
105     override fun accept(visitor: ItemVisitor) {
106         visitor.visit(this)
107     }
108 
109     /**
110      * Returns whether this parameter is SAM convertible or a Kotlin lambda. If this parameter is
111      * the last parameter, it also means that it could be called in Kotlin using the trailing lambda
112      * syntax.
113      *
114      * Specifically this will attempt to handle the follow cases:
115      * - Java SAM interface = true
116      * - Kotlin SAM interface = false // Kotlin (non-fun) interfaces are not SAM convertible
117      * - Kotlin fun interface = true
118      * - Kotlin lambda = true
119      * - Any other type = false
120      */
isSamCompatibleOrKotlinLambdanull121     fun isSamCompatibleOrKotlinLambda(): Boolean =
122         // TODO(b/354889186): Implement correctly
123         false
124 
125     /**
126      * Create a duplicate of this for [containingCallable].
127      *
128      * The duplicate's [type] must have applied the [typeVariableMap] substitutions by using
129      * [TypeItem.convertType].
130      *
131      * This is called from within the constructor of the [containingCallable] so must only access
132      * its `name` and its reference. In particularly it must not access its
133      * [CallableItem.parameters] property as this is called during its initialization.
134      */
135     fun duplicate(
136         containingCallable: CallableItem,
137         typeVariableMap: TypeParameterBindings,
138     ): ParameterItem
139 
140     override fun equalsToItem(other: Any?): Boolean {
141         if (this === other) return true
142         if (other !is ParameterItem) return false
143 
144         return parameterIndex == other.parameterIndex &&
145             containingCallable() == other.containingCallable()
146     }
147 
hashCodeForItemnull148     override fun hashCodeForItem(): Int {
149         return name().hashCode()
150     }
151 
toStringForItemnull152     override fun toStringForItem() = "parameter ${name()}"
153 
154     override fun containingClass(): ClassItem = containingCallable().containingClass()
155 
156     override fun containingPackage(): PackageItem? = containingCallable().containingPackage()
157 
158     // TODO: modifier list
159 }
160