xref: /aosp_15_r20/external/conscrypt/api-doclet/src/main/kotlin/org/conscrypt/doclet/DocTreeUtils.kt (revision cd0cc2e34ba52cdf454361820a14d744e4bd531d)
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 org.conscrypt.doclet
18 
19 import org.conscrypt.doclet.FilterDoclet.Companion.baseUrl
20 import com.sun.source.doctree.DocCommentTree
21 import com.sun.source.doctree.DocTree
22 import com.sun.source.doctree.EndElementTree
23 import com.sun.source.doctree.LinkTree
24 import com.sun.source.doctree.LiteralTree
25 import com.sun.source.doctree.ParamTree
26 import com.sun.source.doctree.ReturnTree
27 import com.sun.source.doctree.SeeTree
28 import com.sun.source.doctree.StartElementTree
29 import com.sun.source.doctree.TextTree
30 import com.sun.source.doctree.ThrowsTree
31 import org.conscrypt.doclet.FilterDoclet.Companion.classIndex
32 import org.conscrypt.doclet.FilterDoclet.Companion.docTrees
33 import javax.lang.model.element.Element
34 import javax.lang.model.type.TypeMirror
35 
renderDocTreeListnull36 fun renderDocTreeList(treeList: List<DocTree>):String =
37     treeList.joinToString("\n", transform = ::renderDocTree)
38 
39 fun renderDocTree(docTree: DocTree): String = when (docTree) {
40     is TextTree -> docTree.body
41     is LinkTree -> {
42         val reference = docTree.reference.toString()
43         val label = if (docTree.label.isEmpty()) {
44             reference
45         } else {
46             renderDocTreeList(docTree.label)
47         }
48         createLink(reference, label)
49     }
50     is StartElementTree, is EndElementTree -> docTree.toString()
51     is LiteralTree -> "<code>${docTree.body}</code>"
52     else -> error("[${docTree.javaClass} / ${docTree.kind} --- ${docTree}]")
53 }
54 
<lambda>null55 fun createLink(reference: String, label: String) = html {
56     val parts = reference.split('#')
57     val className = parts[0]
58     val anchor = if (parts.size > 1) "#${parts[1]}" else ""
59     val classInfo = classIndex.find(className)
60     val href = if (classInfo != null)
61         "${classInfo.simpleName}.html$anchor"
62     else
63         "$baseUrl${className.replace('.', '/')}.html$anchor"
64 
65     a(href, label)
66 }
67 
renderBlockTagListnull68 fun renderBlockTagList(tagList: List<DocTree>): String =
69     tagList.joinToString("\n", transform = ::renderBlockTag)
70 
71 fun renderBlockTag(tag: DocTree) = when (tag) {
72     is ParamTree, is ReturnTree, is ThrowsTree -> error("Unexpected block tag: $tag")
73     is SeeTree -> html {
74         br()
75         p {
76             strong("See: ")
77             text(renderDocTreeList(tag.reference))
78         }
79     }
80     else -> tag.toString()
81 }
82 
filterTagsnull83 inline fun <reified T> Element.filterTags() =
84     docTree()?.blockTags?.filterIsInstance<T>() ?: emptyList()
85 
86 fun Element.paramTags() = filterTags<ParamTree>()
87     .map { it.name.toString() to renderDocTreeList(it.description) }
88     .toList()
89 
90 
Elementnull91 fun Element.returnTag(returnType: TypeMirror): List<Pair<String, String>> {
92     val list = mutableListOf<Pair<String, String>>()
93     val descriptions  = filterTags<ReturnTree>()
94         .map {  renderDocTreeList(it.description) }
95         .singleOrNull()
96 
97     if (descriptions != null) {
98         list.add(returnType.toString() to descriptions)
99     }
100     return list
101 }
102 
Elementnull103 fun Element.throwTags() = filterTags<ThrowsTree>()
104     .map { it.exceptionName.toString() to renderDocTreeList(it.description) }
105     .toList()
106 
docTreenull107 fun Element.docTree(): DocCommentTree? = docTrees.getDocCommentTree(this)
108 fun Element.commentTree() = docTree()?.let { renderDocTreeList(it.fullBody) } ?: ""
<lambda>null109 fun Element.tagTree() = docTree()?.let { renderBlockTagList(it.blockTags) } ?: ""
Elementnull110 fun Element.commentsAndTagTrees() = commentTree() + tagTree()
111