Skip to content

Commit

Permalink
Merge branch 'master' into prbprbprb-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
prbprbprb authored Oct 7, 2024
2 parents d3cc0bc + d8be94d commit 420d001
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 101 deletions.
42 changes: 28 additions & 14 deletions api-doclet/src/main/kotlin/org/conscrypt/doclet/ClassIndex.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package org.conscrypt.doclet

import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import kotlin.streams.toList

class ClassIndex {
private val index = mutableMapOf<String, ClassInfo>()
Expand All @@ -31,27 +30,27 @@ class ClassIndex {
put(ClassInfo(element as TypeElement))
}

fun get(qualifiedName: String) = index[qualifiedName]
fun get(qualifiedName: String) = index[qualifiedName]!!
fun get(typeElement: TypeElement) = get(typeElement.qualifiedName.toString())
fun getParent(typeElement: TypeElement) = get(typeElement.enclosingElement as TypeElement)
fun contains(qualifiedName: String) = index.containsKey(qualifiedName)
fun find(name: String) = if (contains(name)) get(name) else findSimple(name)
private fun findSimple(name: String) = classes().firstOrNull { it.simpleName == name } // XXX dups

fun classes(): Collection<ClassInfo> = index.values

fun addVisible(elements: Set<Element>) {
elements
.filterIsInstance<TypeElement>()
.filter(Element::isVisibleType)
.forEach(::put)
}
fun addVisible(elements: Set<Element>) = elements
.filterIsInstance<TypeElement>()
.filter(Element::isVisibleType)
.forEach(::put)

private fun packages(): List<String> = index.values.stream()
private fun packages(): List<String> = index.values
.map { it.packageName }
.distinct()
.sorted()
.toList()

private fun classesForPackage(packageName: String) = index.values.stream()
private fun classesForPackage(packageName: String) = index.values
.filter { it.packageName == packageName }
.sorted()
.toList()
Expand All @@ -62,15 +61,30 @@ class ClassIndex {
h2("Package $packageName", "package-name")
ul("class-list") {
classesForPackage(packageName)
.forEach { c ->
li {
a(c.fileName, c.simpleName)
.filter { !it.isInnerClass }
.forEach {
compose {
classAndInners(it)
}
}
}
}
}
}

private fun classAndInners(classInfo: ClassInfo): String = html {
li {
a(classInfo.fileName, classInfo.simpleName)
}
val inners = classInfo.innerClasses()
inners.takeIf { it.isNotEmpty() }.let {
ul("class-list") {
inners.forEach {
compose {
classAndInners(it)
}
}
}
}
}
}

22 changes: 20 additions & 2 deletions api-doclet/src/main/kotlin/org/conscrypt/doclet/ClassInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.conscrypt.doclet

import org.conscrypt.doclet.FilterDoclet.Companion.classIndex
import java.nio.file.Paths
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.TypeElement
Expand All @@ -25,7 +27,14 @@ data class ClassInfo(val element: TypeElement) : Comparable<ClassInfo> {
val simpleName = element.simpleName.toString()
val qualifiedName = element.qualifiedName.toString()
val packageName = FilterDoclet.elementUtils.getPackageOf(element).qualifiedName.toString()
val fileName = qualifiedName.replace('.', '/') + ".html"
val fileName = element.baseFileName() + ".html"
val isInnerClass = element.enclosingElement.isType()

fun innerClasses() = element.enclosedElements
.filterIsInstance<TypeElement>()
.filter(TypeElement::isType)
.map(classIndex::get)
.sorted()

override fun compareTo(other: ClassInfo) = qualifiedName.compareTo(other.qualifiedName)

Expand Down Expand Up @@ -57,8 +66,13 @@ data class ClassInfo(val element: TypeElement) : Comparable<ClassInfo> {
nested.takeIf { it.isNotEmpty() }?.let {
h2("Nested Classes")
nested.forEach { cls ->
val typeElement = cls as TypeElement
val info = classIndex.get(typeElement)
val parent = classIndex.getParent(typeElement)
div("member") {
h4(cls.simpleName.toString())
h4 {
a(relativePath(parent.fileName, info.fileName), info.simpleName)
}
compose {
cls.commentsAndTagTrees()
}
Expand Down Expand Up @@ -132,5 +146,9 @@ data class ClassInfo(val element: TypeElement) : Comparable<ClassInfo> {
nestedClasses()
}
}

private fun relativePath(from: String, to: String) =
Paths.get(from).parent.relativize(Paths.get(to)).toString()

}

16 changes: 10 additions & 6 deletions api-doclet/src/main/kotlin/org/conscrypt/doclet/ElementUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ fun Element.isVisibleConstructor() = isExecutable() && isVisible() && kind == El
fun Element.isVisibleField() = isField() && isVisible()
fun Element.isPublic() = modifiers.contains(Modifier.PUBLIC)
fun Element.isPrivate() = !isPublic() // Ignore protected for now :)
fun Element.isHidden() = isPrivate() || hasHideMarker() || parentIsHidden()
fun Element.isVisible() = !isHidden()
fun Element.hasHideMarker() = hasAnnotation("org.conscrypt.Internal") || hasHideTag()
fun Element.isHidden() = isPrivate() || isFiltered() || parentIsHidden()
fun Element.children(filterFunction: (Element) -> Boolean) = enclosedElements
.filter(filterFunction)
.toList()
Expand All @@ -53,10 +52,9 @@ fun Element.hasAnnotation(annotationName: String): Boolean = annotationMirrors
.map { it.annotationType.toString() }
.any { it == annotationName }


fun Element.hasHideTag(): Boolean {
fun Element.hasJavadocTag(tagName: String): Boolean {
return docTree()?.blockTags?.any {
tag -> tag is UnknownBlockTagTree && tag.tagName == "hide"
tag -> tag is UnknownBlockTagTree && tag.tagName == tagName
} ?: false
}

Expand All @@ -79,7 +77,7 @@ fun ExecutableElement.methodSignature(): String {
val exceptions = thrownTypes
.joinToString(", ")
.prefixIfNotEmpty(" throws ")
return "$modifiers $typeParams$returnType${simpleName}($parameters)$exceptions"
return "$modifiers $typeParams$returnType${name()}($parameters)$exceptions"
}

fun formatType(typeMirror: TypeMirror): String {
Expand All @@ -105,6 +103,12 @@ fun TypeElement.signature(): String {
return "$modifiers $kind $simpleName$superName$interfaces"
}

fun TypeElement.baseFileName(): String =
if (enclosingElement.isType())
(enclosingElement as TypeElement).baseFileName() + "." + simpleName
else
qualifiedName.toString().replace('.', '/')

fun superDisplayName(mirror: TypeMirror): String {
return when (mirror.toString()) {
"none", "java.lang.Object" -> ""
Expand Down
39 changes: 21 additions & 18 deletions api-doclet/src/main/kotlin/org/conscrypt/doclet/FilterDoclet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,42 @@ import java.nio.file.Path
import java.nio.file.Paths
import java.util.Locale
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.util.Elements
import javax.lang.model.util.Types

/**
* A Doclet which can filter out internal APIs in various ways and then render the results
* as HTML.
*
* See also: The Element.isFiltered extension function below to see what is filtered.
*/
class FilterDoclet : Doclet {
companion object {
lateinit var docTrees: DocTrees
lateinit var elementUtils: Elements
lateinit var typeUtils: Types
lateinit var outputPath: Path
lateinit var cssPath: Path
var baseUrl: String = "https://docs.oracle.com/javase/8/docs/api/"
val CSS_FILENAME = "styles.css"
const val CSS_FILENAME = "styles.css"
var outputDir = "."
var docTitle = "DTITLE"
var windowTitle = "WTITLE"
var docTitle = "DOC TITLE"
var windowTitle = "WINDOW TITLE"
var noTimestamp: Boolean = false
val classIndex = ClassIndex()
}

override fun init(locale: Locale?, reporter: Reporter?) = Unit // TODO
override fun getName() = "FilterDoclet"
override fun getSupportedSourceVersion() = SourceVersion.latest()
override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()

override fun run(environment: DocletEnvironment): Boolean {
docTrees = environment.docTrees
elementUtils = environment.elementUtils
typeUtils = environment.typeUtils
outputPath = Paths.get(outputDir)
cssPath = outputPath.resolve(CSS_FILENAME)
Files.createDirectories(outputPath)

classIndex.addVisible(environment.includedElements)
Expand All @@ -75,7 +84,7 @@ class FilterDoclet : Doclet {
html {
body(
title = docTitle,
stylesheet = relativePath(indexPath, CSS_FILENAME),
stylesheet = relativePath(indexPath, cssPath),
) {
div("index-container") {
h1(docTitle, "index-title")
Expand All @@ -99,7 +108,7 @@ class FilterDoclet : Doclet {
html {
body(
title = "$simpleName - conscrypt-openjdk API",
stylesheet = relativePath(classFilePath, CSS_FILENAME),
stylesheet = relativePath(classFilePath, cssPath),
) {
compose {
classInfo.generateHtml()
Expand All @@ -112,17 +121,7 @@ class FilterDoclet : Doclet {
}
}

private fun relativePath(from: Path, to: String): String {
val fromDir = from.parent
val toPath = Paths.get(outputDir).resolve(to)

if (fromDir == null) {
return to
}

val relativePath = fromDir.relativize(toPath)
return relativePath.toString().replace('\\', '/')
}
private fun relativePath(from: Path, to: Path) = from.parent.relativize(to).toString()

override fun getSupportedOptions(): Set<Doclet.Option> {
return setOf<Doclet.Option>(
Expand Down Expand Up @@ -151,4 +150,8 @@ class FilterDoclet : Doclet {
"Something"
) { noTimestamp = true })
}
}
}

// Called to determine whether to filter each public API element.
fun Element.isFiltered() =
hasJavadocTag("hide") || hasAnnotation("org.conscrypt.Internal")
Loading

0 comments on commit 420d001

Please sign in to comment.