blob: 77db33fff25119bcdfd5e49a71472f11b89b614a [file] [log] [blame]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conscrypt.doclet
import com.sun.source.util.DocTrees
import jdk.javadoc.doclet.Doclet
import jdk.javadoc.doclet.DocletEnvironment
import jdk.javadoc.doclet.Reporter
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.Locale
import javax.lang.model.SourceVersion
import javax.lang.model.util.Elements
import javax.lang.model.util.Types
class FilterDoclet : Doclet {
companion object {
lateinit var docTrees: DocTrees
lateinit var elementUtils: Elements
lateinit var typeUtils: Types
lateinit var outputPath: Path
var baseUrl: String = "https://docs.oracle.com/javase/8/docs/api/"
val CSS_FILENAME = "styles.css"
var outputDir = "."
var docTitle = "DTITLE"
var windowTitle = "WTITLE"
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 run(environment: DocletEnvironment): Boolean {
docTrees = environment.docTrees
elementUtils = environment.elementUtils
typeUtils = environment.typeUtils
outputPath = Paths.get(outputDir)
Files.createDirectories(outputPath)
classIndex.addVisible(environment.includedElements)
try {
generateClassFiles()
generateIndex()
return true
} catch (e: Exception) {
System.err.println("Error generating documentation: " + e.message)
e.printStackTrace()
return false
}
}
private fun generateClassFiles() = classIndex.classes().forEach(::generateClassFile)
private fun generateIndex() {
val indexPath = outputPath.resolve("index.html")
html {
body(
title = docTitle,
stylesheet = relativePath(indexPath, CSS_FILENAME),
) {
div("index-container") {
h1(docTitle, "index-title")
compose {
classIndex.generateHtml()
}
}
}
}.let {
Files.newBufferedWriter(indexPath).use { writer ->
writer.write(it)
}
}
}
private fun generateClassFile(classInfo: ClassInfo) {
val classFilePath = outputPath.resolve(classInfo.fileName)
Files.createDirectories(classFilePath.parent)
val simpleName = classInfo.simpleName
html {
body(
title = "$simpleName - conscrypt-openjdk API",
stylesheet = relativePath(classFilePath, CSS_FILENAME),
) {
compose {
classInfo.generateHtml()
}
}
}.let {
Files.newBufferedWriter(classFilePath).use { writer ->
writer.write(it)
}
}
}
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('\\', '/')
}
override fun getSupportedOptions(): Set<Doclet.Option> {
return setOf<Doclet.Option>(
StringOption(
"-d",
"<directory>",
"Destination directory for output files"
) { d: String -> outputDir = d },
StringOption(
"-doctitle",
"<title>",
"Document title"
) { t: String -> docTitle = t },
StringOption(
"-windowtitle",
"<title>",
"Window title"
) { w: String -> windowTitle = w },
StringOption(
"-link",
"<link>",
"Link"
) { l: String -> baseUrl = l },
BooleanOption(
"-notimestamp",
"Something"
) { noTimestamp = true })
}
}