xref: /aosp_15_r20/tools/metalava/metalava-model/src/main/java/com/android/tools/metalava/model/item/DefaultValue.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
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.Codebase
20 import com.android.tools.metalava.model.FixedDefaultValue
21 import com.android.tools.metalava.model.ParameterItem
22 
23 /**
24  * A lamda that given a [ParameterItem] will create a [DefaultValue] for it.
25  *
26  * This is called from within the constructor of the [ParameterItem] and should not access any
27  * properties of [ParameterItem] as they may not have been initialized. This should just store a
28  * reference for later use.
29  */
30 typealias DefaultValueFactory = (ParameterItem) -> DefaultValue
31 
32 /**
33  * Represents a parameter's default value.
34  *
35  * TODO: Investigate this abstraction to see if it matches what we need. It is a little confusing as
36  *   [hasDefaultValue] and [isDefaultValueKnown] seem like they should be different but are
37  *   implemented in Psi and Turbine to be identical.
38  */
39 interface DefaultValue {
40 
41     /** A [DefaultValue] to use for a parameter that has no default value. */
42     @Suppress("ConvertObjectToDataObject") // Requires language level 1.9
43     object NONE : DefaultValue {
hasDefaultValuenull44         override fun hasDefaultValue() = false
45 
46         override fun isDefaultValueKnown() = false
47 
48         override fun value() = error("cannot call on NONE DefaultValue")
49 
50         /** This is suitable for use by [parameter] as it has no model or codebase dependencies. */
51         override fun duplicate(parameter: ParameterItem) = this
52 
53         /** This is suitable for use in the snapshot as it has no model or codebase dependencies. */
54         override fun snapshot(parameter: ParameterItem) = this
55 
56         override fun toString() = "NONE"
57     }
58 
59     /**
60      * A [DefaultValue] to use for a parameter that has a default value but its actual value is not
61      * known.
62      */
63     @Suppress("ConvertObjectToDataObject") // Requires language level 1.9
64     object UNKNOWN : DefaultValue {
65         override fun hasDefaultValue() = true
66 
67         override fun isDefaultValueKnown() = false
68 
69         override fun value() = error("cannot call on UNKNOWN DefaultValue")
70 
71         /** This is suitable for use by [parameter] as it has no model or codebase dependencies. */
72         override fun duplicate(parameter: ParameterItem) = this
73 
74         /** This is suitable for use in the snapshot as it has no model or codebase dependencies. */
75         override fun snapshot(parameter: ParameterItem) = this
76 
77         override fun toString() = "UNKNOWN"
78     }
79 
80     companion object {
81         /** Get a [DefaultValue] wrapper around a fixed [String] value. */
fixedDefaultValuenull82         fun fixedDefaultValue(value: String?): DefaultValue {
83             return FixedDefaultValue(value)
84         }
85     }
86 
87     /**
88      * Returns whether this parameter has a default value. In Kotlin, this is supported directly; in
89      * Java, it's supported via a special annotation, {@literal @DefaultValue("source"). This does
90      * not necessarily imply that the default value is accessible, and we know the body of the
91      * default value.
92      *
93      * @see isDefaultValueKnown
94      */
hasDefaultValuenull95     fun hasDefaultValue(): Boolean
96 
97     /**
98      * Returns whether this parameter has an accessible default value that we plan to keep. This is
99      * a superset of [hasDefaultValue] - if we are not writing the default values to the signature
100      * file, then the default value might not be available, even though the parameter does have a
101      * default.
102      *
103      * @see hasDefaultValue
104      */
105     fun isDefaultValueKnown(): Boolean
106 
107     /**
108      * Returns the default value.
109      *
110      * **This method should only be called if [isDefaultValueKnown] returned true!** (This is
111      * necessary since the null return value is a valid default value separate from no default value
112      * specified.)
113      *
114      * The default value is the source string literal representation of the value, e.g. strings
115      * would be surrounded by quotes, Booleans are the strings "true" or "false", and so on.
116      */
117     fun value(): String?
118 
119     /**
120      * Return a duplicate of this instance to use by [parameter] which will be in the same type of
121      * [Codebase] as this.
122      */
123     fun duplicate(parameter: ParameterItem): DefaultValue
124 
125     /**
126      * Creates a snapshot of this.
127      *
128      * The default implementation assumes that this is either dependent on a model or the codebase
129      * and so creates a new [DefaultValue] based on the functions above.
130      */
131     fun snapshot(parameter: ParameterItem) =
132         when {
133             !hasDefaultValue() -> NONE
134             !isDefaultValueKnown() -> UNKNOWN
135             else -> fixedDefaultValue(value())
136         }
137 }
138