blob: 76d63383ea64d67de45143f924a0890da155d1b2 [file] [log] [blame]
package org.jetbrains.dokka.javadoc
import com.sun.javadoc.*
import org.jetbrains.dokka.*
import java.lang.reflect.Modifier
import java.util.*
import kotlin.reflect.KClass
private interface HasModule {
val module: ModuleNodeAdapter
}
private interface HasDocumentationNode {
val node: DocumentationNode
}
open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode {
private var rawCommentText_: String? = null
override fun name(): String = node.name
override fun position(): SourcePosition? = SourcePositionAdapter(node)
override fun inlineTags(): Array<out Tag>? = emptyArray()
override fun firstSentenceTags(): Array<out Tag>? = emptyArray()
override fun tags(): Array<out Tag> = emptyArray()
override fun tags(tagname: String?): Array<out Tag>? = tags().filter { it.kind() == tagname || it.kind() == "@$tagname" }.toTypedArray()
override fun seeTags(): Array<out SeeTag>? = tags().filterIsInstance<SeeTag>().toTypedArray()
override fun commentText(): String = ""
override fun setRawCommentText(rawDocumentation: String?) {
rawCommentText_ = rawDocumentation ?: ""
}
override fun getRawCommentText(): String = rawCommentText_ ?: ""
override fun isError(): Boolean = false
override fun isException(): Boolean = node.kind == NodeKind.Exception
override fun isEnumConstant(): Boolean = node.kind == NodeKind.EnumItem
override fun isEnum(): Boolean = node.kind == NodeKind.Enum
override fun isMethod(): Boolean = node.kind == NodeKind.Function
override fun isInterface(): Boolean = node.kind == NodeKind.Interface
override fun isField(): Boolean = node.kind == NodeKind.Field
override fun isClass(): Boolean = node.kind == NodeKind.Class
override fun isAnnotationType(): Boolean = node.kind == NodeKind.AnnotationClass
override fun isConstructor(): Boolean = node.kind == NodeKind.Constructor
override fun isOrdinaryClass(): Boolean = node.kind == NodeKind.Class
override fun isAnnotationTypeElement(): Boolean = node.kind == NodeKind.Annotation
override fun compareTo(other: Any?): Int = when (other) {
!is DocumentationNodeAdapter -> 1
else -> node.name.compareTo(other.node.name)
}
override fun equals(other: Any?): Boolean = node.qualifiedName() == (other as? DocumentationNodeAdapter)?.node?.qualifiedName()
override fun hashCode(): Int = node.name.hashCode()
override fun isIncluded(): Boolean = node.kind != NodeKind.ExternalClass
}
// TODO think of source position instead of null
// TODO tags
open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeBareAdapter(node), HasModule {
override fun inlineTags(): Array<out Tag> = buildInlineTags(module, this, node.content).toTypedArray()
override fun firstSentenceTags(): Array<out Tag> = buildInlineTags(module, this, node.summary).toTypedArray()
override fun tags(): Array<out Tag> {
val result = ArrayList<Tag>(buildInlineTags(module, this, node.content))
node.content.sections.flatMapTo(result) {
when (it.tag) {
ContentTags.SeeAlso -> buildInlineTags(module, this, it)
else -> emptyList<Tag>()
}
}
node.deprecation?.let {
val content = it.content.asText()
result.add(TagImpl(this, "deprecated", content ?: ""))
}
return result.toTypedArray()
}
}
// should be extension property but can't because of KT-8745
private fun <T> nodeAnnotations(self: T): List<AnnotationDescAdapter> where T : HasModule, T : HasDocumentationNode
= self.node.annotations.map { AnnotationDescAdapter(self.module, it) }
private fun DocumentationNode.hasAnnotation(klass: KClass<*>) = klass.qualifiedName in annotations.map { it.qualifiedName() }
private fun DocumentationNode.hasModifier(name: String) = details(NodeKind.Modifier).any { it.name == name }
class PackageAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc {
private val allClasses = listOf(node).collectAllTypesRecursively()
override fun findClass(className: String?): ClassDoc? =
allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) }
override fun annotationTypes(): Array<out AnnotationTypeDoc> = emptyArray()
override fun annotations(): Array<out AnnotationDesc> = node.members(NodeKind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray()
override fun exceptions(): Array<out ClassDoc> = node.members(NodeKind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun ordinaryClasses(): Array<out ClassDoc> = node.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun interfaces(): Array<out ClassDoc> = node.members(NodeKind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun errors(): Array<out ClassDoc> = emptyArray()
override fun enums(): Array<out ClassDoc> = node.members(NodeKind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun allClasses(filter: Boolean): Array<out ClassDoc> = allClasses.values.map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun allClasses(): Array<out ClassDoc> = allClasses(true)
override fun isIncluded(): Boolean = node.name in module.allPackages
}
class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ClassDocumentationNodeAdapter(module, node), AnnotationTypeDoc {
override fun elements(): Array<out AnnotationTypeElementDoc>? = emptyArray() // TODO
}
class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc {
override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node) // TODO ?????
override fun isSynthesized(): Boolean = false
override fun elementValues(): Array<out AnnotationDesc.ElementValuePair>? = emptyArray() // TODO
}
open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc {
override fun isPublic(): Boolean = true
override fun isPackagePrivate(): Boolean = false
override fun isStatic(): Boolean = node.hasModifier("static")
override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0
override fun qualifiedName(): String? = node.qualifiedName()
override fun annotations(): Array<out AnnotationDesc>? = nodeAnnotations(this).toTypedArray()
override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim()
override fun isProtected(): Boolean = false
override fun isFinal(): Boolean = node.hasModifier("final")
override fun containingPackage(): PackageDoc? {
if (node.kind == NodeKind.Type) {
return null
}
var owner: DocumentationNode? = node
while (owner != null) {
if (owner.kind == NodeKind.Package) {
return PackageAdapter(module, owner)
}
owner = owner.owner
}
return null
}
override fun containingClass(): ClassDoc? {
if (node.kind == NodeKind.Type) {
return null
}
var owner = node.owner
while (owner != null) {
if (owner.kind in NodeKind.classLike) {
return ClassDocumentationNodeAdapter(module, owner)
}
owner = owner.owner
}
return null
}
override fun isPrivate(): Boolean = false
override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true
}
open class TypeAdapter(override val module: ModuleNodeAdapter, override val node: DocumentationNode) : Type, HasDocumentationNode, HasModule {
private val javaLanguageService = JavaLanguageService()
override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedNameFromType() ?: node.qualifiedNameFromType()
override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.simpleName() ?: node.simpleName()
override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName()
override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("")
override fun isPrimitive(): Boolean = simpleTypeName() in setOf("int", "long", "short", "byte", "char", "double", "float", "boolean", "void")
override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else
elementType?.asClassDoc() ?:
when (node.kind) {
in NodeKind.classLike,
NodeKind.ExternalClass,
NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node)
else -> when {
node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc()
else -> ClassDocumentationNodeAdapter(module, node) // TODO ?
}
}
override fun asTypeVariable(): TypeVariable? = if (node.kind == NodeKind.TypeParameter) TypeVariableAdapter(module, node) else null
override fun asParameterizedType(): ParameterizedType? =
if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null)
ParameterizedTypeAdapter(module, node)
else
null
override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == NodeKind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null
override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null
override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) }
override fun asWildcardType(): WildcardType? = null
override fun toString(): String = qualifiedTypeName() + dimension()
override fun hashCode(): Int = node.name.hashCode()
override fun equals(other: Any?): Boolean = other is TypeAdapter && toString() == other.toString()
}
class NotAnnotatedTypeAdapter(typeAdapter: AnnotatedTypeAdapter) : Type by typeAdapter {
override fun asAnnotatedType() = null
}
class AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType {
override fun underlyingType(): Type? = NotAnnotatedTypeAdapter(this)
override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
}
class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType {
override fun extendsBounds(): Array<out Type> = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
override fun superBounds(): Array<out Type> = node.details(NodeKind.LowerBound).map { TypeAdapter(module, it) }.toTypedArray()
}
class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), TypeVariable {
override fun owner(): ProgramElementDoc = node.owner!!.let<DocumentationNode, ProgramElementDoc> { owner ->
when (owner.kind) {
NodeKind.Function,
NodeKind.Constructor -> ExecutableMemberAdapter(module, owner)
NodeKind.Class,
NodeKind.Interface,
NodeKind.Enum -> ClassDocumentationNodeAdapter(module, owner)
else -> ProgramElementAdapter(module, node.owner!!)
}
}
override fun bounds(): Array<out Type>? = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
override fun annotations(): Array<out AnnotationDesc>? = node.members(NodeKind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray()
override fun qualifiedTypeName(): String = node.name
override fun simpleTypeName(): String = node.name
override fun typeName(): String = node.name
override fun hashCode(): Int = node.name.hashCode()
override fun equals(other: Any?): Boolean = other is Type && other.typeName() == typeName() && other.asTypeVariable()?.owner() == owner()
override fun asTypeVariable(): TypeVariableAdapter = this
}
class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType {
override fun typeArguments(): Array<out Type> = node.details(NodeKind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray()
override fun superclassType(): Type? =
node.lookupSuperClasses(module)
.firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass }
?.let { ClassDocumentationNodeAdapter(module, it) }
override fun interfaceTypes(): Array<out Type> =
node.lookupSuperClasses(module)
.filter { it.kind == NodeKind.Interface }
.map { ClassDocumentationNodeAdapter(module, it) }
.toTypedArray()
override fun containingType(): Type? = when (node.owner?.kind) {
NodeKind.Package -> null
NodeKind.Class,
NodeKind.Interface,
NodeKind.Object,
NodeKind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!)
else -> null
}
}
class ParameterAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter {
override fun typeName(): String? = JavaLanguageService().renderType(node.detail(NodeKind.Type))
override fun type(): Type? = TypeAdapter(module, node.detail(NodeKind.Type))
override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
}
class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode, val parent: ExecutableMemberAdapter) : DocumentationNodeAdapter(module, receiverType), Parameter {
override fun typeName(): String? = receiverType.name
override fun type(): Type? = TypeAdapter(module, receiverType)
override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
override fun name(): String = tryName("receiver")
private tailrec fun tryName(name: String): String = when (name) {
in parent.parameters().drop(1).map { it.name() } -> tryName("$$name")
else -> name
}
}
fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node ->
val pkg = fqName.substringBeforeLast(".", "")
if (pkg.isNotEmpty()) {
node.append(DocumentationNode(pkg, Content.Empty, NodeKind.Package), RefKind.Owner)
}
node
}
private fun DocumentationNode.hasNonEmptyContent() =
this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), ExecutableMemberDoc {
override fun isSynthetic(): Boolean = false
override fun isNative(): Boolean = node.annotations.any { it.name == "native" }
override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO
override fun throwsTags(): Array<out ThrowsTag> =
node.content.sections
.filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
.map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }
.toTypedArray()
override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).any { false } // TODO
override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }
override fun paramTags(): Array<out ParamTag> =
collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })
override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
override fun flatSignature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")")
override fun signature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types
override fun parameters(): Array<out Parameter> =
((receiverNode()?.let { receiver -> listOf<Parameter>(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList())
+ node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) }
).toTypedArray()
override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
override fun typeParamTags(): Array<out ParamTag> =
collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
when {
receivers.isNotEmpty() -> receivers.single().detail(NodeKind.Type)
else -> null
}
}
}
class ConstructorAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), ConstructorDoc {
override fun name(): String = node.owner?.name ?: throw IllegalStateException("No owner for $node")
override fun containingClass(): ClassDoc? {
return super.containingClass()
}
}
class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), MethodDoc {
override fun overrides(meth: MethodDoc?): Boolean = false // TODO
override fun overriddenType(): Type? = node.overrides.firstOrNull()?.owner?.let { owner -> TypeAdapter(module, owner) }
override fun overriddenMethod(): MethodDoc? = node.overrides.map { MethodAdapter(module, it) }.firstOrNull()
override fun overriddenClass(): ClassDoc? = overriddenMethod()?.containingClass()
override fun isAbstract(): Boolean = false // TODO
override fun isDefault(): Boolean = false
override fun returnType(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
override fun tags(tagname: String?) = super.tags(tagname)
override fun tags(): Array<out Tag> {
val tags = super.tags().toMutableList()
node.content.findSectionByTag(ContentTags.Return)?.let {
tags += ReturnTagAdapter(module, this, it.children)
}
return tags.toTypedArray()
}
}
class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), FieldDoc {
override fun isSynthetic(): Boolean = false
override fun constantValueExpression(): String? = node.detailOrNull(NodeKind.Value)?.let { it.name }
override fun constantValue(): Any? = constantValueExpression()
override fun type(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
override fun isTransient(): Boolean = node.hasAnnotation(Transient::class)
override fun serialFieldTags(): Array<out SerialFieldTag> = emptyArray()
override fun isVolatile(): Boolean = node.hasAnnotation(Volatile::class)
}
open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode)
: ProgramElementAdapter(module, classNode),
Type by TypeAdapter(module, classNode),
ClassDoc {
override fun name(): String {
val parent = classNode.owner
if (parent?.kind in NodeKind.classLike) {
return parent!!.name + "." + classNode.name
}
return classNode.simpleName()
}
override fun constructors(filter: Boolean): Array<out ConstructorDoc> = classNode.members(NodeKind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray()
override fun constructors(): Array<out ConstructorDoc> = constructors(true)
override fun importedPackages(): Array<out PackageDoc> = emptyArray()
override fun importedClasses(): Array<out ClassDoc>? = emptyArray()
override fun typeParameters(): Array<out TypeVariable> = classNode.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
override fun asTypeVariable(): TypeVariable? = if (classNode.kind == NodeKind.Class) TypeVariableAdapter(module, classNode) else null
override fun isExternalizable(): Boolean = interfaces().any { it.qualifiedName() == "java.io.Externalizable" }
override fun definesSerializableFields(): Boolean = false
override fun methods(filter: Boolean): Array<out MethodDoc> = classNode.members(NodeKind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods
override fun methods(): Array<out MethodDoc> = methods(true)
override fun enumConstants(): Array<out FieldDoc>? = classNode.members(NodeKind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray()
override fun isAbstract(): Boolean = classNode.details(NodeKind.Modifier).any { it.name == "abstract" }
override fun interfaceTypes(): Array<out Type> = classNode.lookupSuperClasses(module)
.filter { it.kind == NodeKind.Interface }
.map { ClassDocumentationNodeAdapter(module, it) }
.toTypedArray()
override fun interfaces(): Array<out ClassDoc> = classNode.lookupSuperClasses(module)
.filter { it.kind == NodeKind.Interface }
.map { ClassDocumentationNodeAdapter(module, it) }
.toTypedArray()
override fun typeParamTags(): Array<out ParamTag> =
collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
override fun fields(): Array<out FieldDoc> = fields(true)
override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()
override fun findClass(className: String?): ClassDoc? = null // TODO !!!
override fun serializableFields(): Array<out FieldDoc> = emptyArray()
override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
override fun serializationMethods(): Array<out MethodDoc> = emptyArray() // TODO
override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
override fun isSerializable(): Boolean = false // TODO
override fun subclassOf(cd: ClassDoc?): Boolean {
if (cd == null) {
return false
}
val expectedFQName = cd.qualifiedName()
val types = arrayListOf(classNode)
val visitedTypes = HashSet<String>()
while (types.isNotEmpty()) {
val type = types.removeAt(types.lastIndex)
val fqName = type.qualifiedName()
if (expectedFQName == fqName) {
return true
}
visitedTypes.add(fqName)
types.addAll(type.details(NodeKind.Supertype).filter { it.qualifiedName() !in visitedTypes })
}
return false
}
override fun innerClasses(): Array<out ClassDoc> = classNode.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
override fun innerClasses(filter: Boolean): Array<out ClassDoc> = innerClasses()
}
fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) =
details(NodeKind.Supertype)
.map { it.links.firstOrNull() }
.map { module.allTypes[it?.qualifiedName()] }
.filterNotNull()
fun List<DocumentationNode>.collectAllTypesRecursively(): Map<String, DocumentationNode> {
val result = hashMapOf<String, DocumentationNode>()
fun DocumentationNode.collectTypesRecursively() {
val classLikeMembers = NodeKind.classLike.flatMap { members(it) }
classLikeMembers.forEach {
result.put(it.qualifiedName(), it)
it.collectTypesRecursively()
}
}
forEach { it.collectTypesRecursively() }
return result
}
class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc {
val allPackages = module.members(NodeKind.Package).associateBy { it.name }
val allTypes = module.members(NodeKind.Package).collectAllTypesRecursively()
override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) }
override fun classes(): Array<out ClassDoc> =
allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray()
override fun options(): Array<out Array<String>> = arrayOf(
arrayOf("-d", outputPath),
arrayOf("-docencoding", "UTF-8"),
arrayOf("-charset", "UTF-8"),
arrayOf("-keywords")
)
override fun specifiedPackages(): Array<out PackageDoc>? = module.members(NodeKind.Package).map { PackageAdapter(this, it) }.toTypedArray()
override fun classNamed(qualifiedName: String?): ClassDoc? =
allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) }
override fun specifiedClasses(): Array<out ClassDoc> = classes()
}
private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFilter: (ContentSection) -> Boolean) =
(node.details(kind)
.filter(DocumentationNode::hasNonEmptyContent)
.map { ParamTagAdapter(module, this, it.name, true, it.content.children) }
+ node.content.sections
.filter(sectionFilter)
.map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) })
.toTypedArray()