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.text
18 
19 import com.android.tools.metalava.model.BoundsTypeItem
20 import com.android.tools.metalava.model.DefaultModifierList
21 import com.android.tools.metalava.model.TypeNullability
22 import com.android.tools.metalava.model.TypeParameterItem
23 import com.android.tools.metalava.model.VariableTypeItem
24 import com.android.tools.metalava.model.type.DefaultTypeModifiers
25 import com.android.tools.metalava.model.type.DefaultVariableTypeItem
26 import com.android.tools.metalava.reporter.FileLocation
27 
28 internal class TextTypeParameterItem(
29     codebase: TextCodebase,
30     private val name: String,
31     private val isReified: Boolean,
32 ) :
33     TextItem(
34         codebase = codebase,
35         fileLocation = FileLocation.UNKNOWN,
36         modifiers = DefaultModifierList(codebase, DefaultModifierList.PUBLIC),
37     ),
38     TypeParameterItem {
39 
40     lateinit var bounds: List<BoundsTypeItem>
41 
namenull42     override fun name(): String {
43         return name
44     }
45 
typenull46     override fun type(): VariableTypeItem {
47         return DefaultVariableTypeItem(
48             DefaultTypeModifiers.create(emptyList(), TypeNullability.UNDEFINED),
49             this
50         )
51     }
52 
typeBoundsnull53     override fun typeBounds(): List<BoundsTypeItem> = bounds
54 
55     override fun isReified(): Boolean = isReified
56 
57     override fun equals(other: Any?): Boolean {
58         if (this === other) return true
59         if (other !is TypeParameterItem) return false
60 
61         return name == other.name()
62     }
63 
hashCodenull64     override fun hashCode(): Int {
65         return name.hashCode()
66     }
67 
68     companion object {
69 
70         /**
71          * Create a partially initialized [TextTypeParameterItem].
72          *
73          * This extracts the [isReified] and [name] from the [typeParameterString] and creates a
74          * [TextTypeParameterItem] with those properties initialized but the [bounds] is not.
75          *
76          * This must ONLY be used by [ApiFile.createTypeParameterList] as that will complete the
77          * initialization of the [bounds] property.
78          */
createnull79         fun create(
80             codebase: TextCodebase,
81             typeParameterString: String,
82         ): TextTypeParameterItem {
83             val length = typeParameterString.length
84             var nameEnd = length
85 
86             val isReified = typeParameterString.startsWith("reified ")
87             val nameStart =
88                 if (isReified) {
89                     8 // "reified ".length
90                 } else {
91                     0
92                 }
93 
94             for (i in nameStart until length) {
95                 val c = typeParameterString[i]
96                 if (!Character.isJavaIdentifierPart(c)) {
97                     nameEnd = i
98                     break
99                 }
100             }
101             val name = typeParameterString.substring(nameStart, nameEnd)
102 
103             return TextTypeParameterItem(
104                 codebase = codebase,
105                 name = name,
106                 isReified = isReified,
107             )
108         }
109     }
110 }
111