1 /*
2  * Copyright (C) 2018 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 @MetalavaApi
20 interface TypeParameterItem : Item {
21 
22     /** The name of the type parameter. */
namenull23     fun name(): String
24 
25     /** The [VariableTypeItem] representing the type of this type parameter. */
26     override fun type(): VariableTypeItem
27 
28     fun typeBounds(): List<BoundsTypeItem>
29 
30     /**
31      * Get the erased type of this, i.e. the type that would be used at runtime to represent
32      * something of this type. That is either the first bound (the super class) or
33      * `java.lang.Object` if there are no bounds.
34      */
35     fun asErasedType(): BoundsTypeItem? =
36         typeBounds().firstOrNull() ?: codebase.resolveClass(JAVA_LANG_OBJECT)?.type()
37 
38     fun isReified(): Boolean
39 
40     fun toSource(): String {
41         return buildString {
42             if (isReified()) {
43                 append("reified ")
44             }
45             append(name())
46             // If the only bound is Object, omit it because it is implied.
47             if (
48                 typeBounds().isNotEmpty() && typeBounds().singleOrNull()?.isJavaLangObject() != true
49             ) {
50                 append(" extends ")
51                 var first = true
52                 for (bound in typeBounds()) {
53                     if (!first) {
54                         append(" ")
55                         append("&")
56                         append(" ")
57                     }
58                     first = false
59                     append(bound.toTypeString(spaceBetweenParameters = true))
60                 }
61             }
62         }
63     }
64 
toStringForItemnull65     override fun toStringForItem(): String =
66         if (typeBounds().isEmpty() && !isReified()) name()
67         else
68             buildString {
69                 if (isReified()) append("reified ")
70                 append(name())
71                 if (typeBounds().isNotEmpty()) {
72                     append(" extends ")
73                     typeBounds().joinTo(this, " & ")
74                 }
75             }
76 
77     // Methods from [Item] that are not needed. They will be removed in a follow-up change.
parentnull78     override fun parent() = error("Not needed for TypeParameterItem")
79 
80     override val effectivelyDeprecated: Boolean
81         get() = error("Not needed for TypeParameterItem")
82 
83     override fun baselineElementId() = error("Not needed for TypeParameterItem")
84 
85     override fun accept(visitor: ItemVisitor) = error("Not needed for TypeParameterItem")
86 
87     override fun containingPackage() = error("Not needed for TypeParameterItem")
88 
89     override fun containingClass() = error("Not needed for TypeParameterItem")
90 
91     override fun findCorrespondingItemIn(
92         codebase: Codebase,
93         superMethods: Boolean,
94         duplicate: Boolean,
95     ) = error("Not needed for TypeParameterItem")
96 }
97