• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.DefaultModifierList
20 import com.android.tools.metalava.model.TypeItem
21 import com.android.tools.metalava.model.TypeParameterItem
22 import com.android.tools.metalava.model.TypeParameterListOwner
23 
24 class TextTypeParameterItem(
25     codebase: TextCodebase,
26     private val owner: TypeParameterListOwner?,
27     private val typeParameterString: String,
28     name: String,
29     private var bounds: List<TypeItem>? = null
30 ) :
31     TextClassItem(
32         codebase = codebase,
33         modifiers = TextModifiers(codebase, DefaultModifierList.PUBLIC),
34         name = name,
35         qualifiedName = name
36     ),
37     TypeParameterItem {
38 
typeBoundsnull39     override fun typeBounds(): List<TypeItem> {
40         if (bounds == null) {
41             val boundsString = bounds(typeParameterString, owner)
42             bounds = if (boundsString.isEmpty()) {
43                 emptyList()
44             } else {
45                 boundsString.mapNotNull {
46                     codebase.obtainTypeFromString(it)
47                 }.filter {
48                     !it.isJavaLangObject()
49                 }
50             }
51         }
52         return bounds!!
53     }
54 
isReifiednull55     override fun isReified(): Boolean {
56         return typeParameterString.startsWith("reified")
57     }
58 
59     companion object {
createnull60         fun create(
61             codebase: TextCodebase,
62             owner: TypeParameterListOwner?,
63             typeParameterString: String,
64             bounds: List<TypeItem>? = null
65         ): TextTypeParameterItem {
66             val length = typeParameterString.length
67             var nameEnd = length
68             for (i in 0 until length) {
69                 val c = typeParameterString[i]
70                 if (!Character.isJavaIdentifierPart(c)) {
71                     nameEnd = i
72                     break
73                 }
74             }
75             val name = typeParameterString.substring(0, nameEnd)
76             return TextTypeParameterItem(
77                 codebase = codebase,
78                 owner = owner,
79                 typeParameterString = typeParameterString,
80                 name = name,
81                 bounds = bounds
82             )
83         }
84 
boundsnull85         fun bounds(typeString: String?, owner: TypeParameterListOwner? = null): List<String> {
86             val s = typeString ?: return emptyList()
87             val index = s.indexOf("extends ")
88             if (index == -1) {
89                 // See if this is a type variable that has bounds in the parent
90                 val parameters = (owner as? TextMemberItem)?.containingClass()?.typeParameterList()?.typeParameters()
91                     ?: return emptyList()
92                 for (p in parameters) {
93                     if (p.simpleName() == s) {
94                         return p.typeBounds().filter { !it.isJavaLangObject() }.map { it.toTypeString() }
95                     }
96                 }
97 
98                 return emptyList()
99             }
100             val list = mutableListOf<String>()
101             var angleBracketBalance = 0
102             var start = index + "extends ".length
103             val length = s.length
104             for (i in start until length) {
105                 val c = s[i]
106                 if (c == '&' && angleBracketBalance == 0) {
107                     add(list, typeString, start, i)
108                     start = i + 1
109                 } else if (c == '<') {
110                     angleBracketBalance++
111                 } else if (c == '>') {
112                     angleBracketBalance--
113                     if (angleBracketBalance == 0) {
114                         add(list, typeString, start, i + 1)
115                         start = i + 1
116                     }
117                 }
118             }
119             if (start < length) {
120                 add(list, typeString, start, length)
121             }
122             return list
123         }
124 
addnull125         private fun add(list: MutableList<String>, s: String, from: Int, to: Int) {
126             for (i in from until to) {
127                 if (!Character.isWhitespace(s[i])) {
128                     var end = to
129                     while (end > i && s[end - 1].isWhitespace()) {
130                         end--
131                     }
132                     var begin = i
133                     while (begin < end && s[begin].isWhitespace()) {
134                         begin++
135                     }
136                     if (begin == end) {
137                         return
138                     }
139                     val element = s.substring(begin, end)
140                     list.add(element)
141                     return
142                 }
143             }
144         }
145     }
146 }
147