xref: /aosp_15_r20/external/conscrypt/api-doclet/src/main/kotlin/org/conscrypt/doclet/ClassIndex.kt (revision cd0cc2e34ba52cdf454361820a14d744e4bd531d)
1 /*
<lambda>null2  * 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 org.conscrypt.doclet
18 
19 import javax.lang.model.element.Element
20 import javax.lang.model.element.TypeElement
21 
22 class ClassIndex {
23     private val index = mutableMapOf<String, ClassInfo>()
24 
25     private fun put(classInfo: ClassInfo) {
26         index[classInfo.qualifiedName] = classInfo
27     }
28 
29     fun put(element: Element) {
30         put(ClassInfo(element as TypeElement))
31     }
32 
33     fun get(qualifiedName: String) = index[qualifiedName]!!
34     fun get(typeElement: TypeElement) = get(typeElement.qualifiedName.toString())
35     fun getParent(typeElement: TypeElement) = get(typeElement.enclosingElement as TypeElement)
36     fun contains(qualifiedName: String) = index.containsKey(qualifiedName)
37     fun find(name: String) = if (contains(name)) get(name) else findSimple(name)
38     private fun findSimple(name: String) = classes().firstOrNull { it.simpleName == name } // XXX dups
39 
40     fun classes(): Collection<ClassInfo> = index.values
41 
42     fun addVisible(elements: Set<Element>) = elements
43         .filterIsInstance<TypeElement>()
44         .filter(Element::isVisibleType)
45         .forEach(::put)
46 
47     private fun packages(): List<String> = index.values
48         .map { it.packageName }
49         .distinct()
50         .sorted()
51         .toList()
52 
53     private fun classesForPackage(packageName: String) = index.values
54         .filter { it.packageName == packageName }
55         .sorted()
56         .toList()
57 
58     fun generateHtml():String = html {
59         packages().forEach { packageName ->
60             div("package-section") {
61                 h2("Package $packageName", "package-name")
62                 ul("class-list") {
63                     classesForPackage(packageName)
64                         .filter { !it.isInnerClass }
65                         .forEach {
66                             compose {
67                                 classAndInners(it)
68                             }
69                         }
70                 }
71             }
72         }
73     }
74 
75     private fun classAndInners(classInfo: ClassInfo): String = html {
76         li {
77             a(classInfo.fileName, classInfo.simpleName)
78         }
79         val inners = classInfo.innerClasses()
80         inners.takeIf { it.isNotEmpty() }.let {
81             ul("class-list") {
82                 inners.forEach {
83                     compose {
84                         classAndInners(it)
85                     }
86                 }
87             }
88         }
89     }
90 }
91