• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

<lambda>null1 package org.jetbrains.dokka.javadoc
2 
3 import com.sun.javadoc.*
4 import org.jetbrains.dokka.*
5 import java.lang.reflect.Modifier
6 import java.util.*
7 import kotlin.reflect.KClass
8 
9 private interface HasModule {
10     val module: ModuleNodeAdapter
11 }
12 
13 private interface HasDocumentationNode {
14     val node: DocumentationNode
15 }
16 
17 open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode {
18     private var rawCommentText_: String? = null
19 
namenull20     override fun name(): String = node.name
21     override fun position(): SourcePosition? = SourcePositionAdapter(node)
22 
23     override fun inlineTags(): Array<out Tag>? = emptyArray()
24     override fun firstSentenceTags(): Array<out Tag>? = emptyArray()
25     override fun tags(): Array<out Tag> = emptyArray()
26     override fun tags(tagname: String?): Array<out Tag>? = tags().filter { it.kind() == tagname || it.kind() == "@$tagname" }.toTypedArray()
seeTagsnull27     override fun seeTags(): Array<out SeeTag>? = tags().filterIsInstance<SeeTag>().toTypedArray()
28     override fun commentText(): String = ""
29 
30     override fun setRawCommentText(rawDocumentation: String?) {
31         rawCommentText_ = rawDocumentation ?: ""
32     }
33 
getRawCommentTextnull34     override fun getRawCommentText(): String = rawCommentText_ ?: ""
35 
36     override fun isError(): Boolean = false
37     override fun isException(): Boolean = node.kind == NodeKind.Exception
38     override fun isEnumConstant(): Boolean = node.kind == NodeKind.EnumItem
39     override fun isEnum(): Boolean = node.kind == NodeKind.Enum
40     override fun isMethod(): Boolean = node.kind == NodeKind.Function
41     override fun isInterface(): Boolean = node.kind == NodeKind.Interface
42     override fun isField(): Boolean = node.kind == NodeKind.Field
43     override fun isClass(): Boolean = node.kind == NodeKind.Class
44     override fun isAnnotationType(): Boolean = node.kind == NodeKind.AnnotationClass
45     override fun isConstructor(): Boolean = node.kind == NodeKind.Constructor
46     override fun isOrdinaryClass(): Boolean = node.kind == NodeKind.Class
47     override fun isAnnotationTypeElement(): Boolean = node.kind == NodeKind.Annotation
48 
49     override fun compareTo(other: Any?): Int = when (other) {
50         !is DocumentationNodeAdapter -> 1
51         else -> node.name.compareTo(other.node.name)
52     }
53 
equalsnull54     override fun equals(other: Any?): Boolean = node.qualifiedName() == (other as? DocumentationNodeAdapter)?.node?.qualifiedName()
55     override fun hashCode(): Int = node.name.hashCode()
56 
57     override fun isIncluded(): Boolean = node.kind != NodeKind.ExternalClass
58 }
59 
60 
61 // TODO think of source position instead of null
62 // TODO tags
63 open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeBareAdapter(node), HasModule {
64     override fun inlineTags(): Array<out Tag> = buildInlineTags(module, this, node.content).toTypedArray()
65     override fun firstSentenceTags(): Array<out Tag> = buildInlineTags(module, this, node.summary).toTypedArray()
66 
67     override fun tags(): Array<out Tag> {
68         val result = ArrayList<Tag>(buildInlineTags(module, this, node.content))
69         node.content.sections.flatMapTo(result) {
70             when (it.tag) {
71                 ContentTags.SeeAlso -> buildInlineTags(module, this, it)
72                 else -> emptyList<Tag>()
73             }
74         }
75 
76         node.deprecation?.let {
77             val content = it.content.asText()
78             result.add(TagImpl(this, "deprecated", content ?: ""))
79         }
80 
81         return result.toTypedArray()
82     }
83 }
84 
85 // should be extension property but can't because of KT-8745
nodeAnnotationsnull86 private fun <T> nodeAnnotations(self: T): List<AnnotationDescAdapter> where T : HasModule, T : HasDocumentationNode
87     = self.node.annotations.map { AnnotationDescAdapter(self.module, it) }
88 
<lambda>null89 private fun DocumentationNode.hasAnnotation(klass: KClass<*>) = klass.qualifiedName in annotations.map { it.qualifiedName() }
<lambda>null90 private fun DocumentationNode.hasModifier(name: String) = details(NodeKind.Modifier).any { it.name == name }
91 
92 
93 class PackageAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc {
94     private val allClasses = listOf(node).collectAllTypesRecursively()
95 
findClassnull96     override fun findClass(className: String?): ClassDoc? =
97             allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) }
98 
annotationTypesnull99     override fun annotationTypes(): Array<out AnnotationTypeDoc> = emptyArray()
100     override fun annotations(): Array<out AnnotationDesc> = node.members(NodeKind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray()
<lambda>null101     override fun exceptions(): Array<out ClassDoc> = node.members(NodeKind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
<lambda>null102     override fun ordinaryClasses(): Array<out ClassDoc> = node.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
<lambda>null103     override fun interfaces(): Array<out ClassDoc> = node.members(NodeKind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
errorsnull104     override fun errors(): Array<out ClassDoc> = emptyArray()
105     override fun enums(): Array<out ClassDoc> = node.members(NodeKind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
<lambda>null106     override fun allClasses(filter: Boolean): Array<out ClassDoc> = allClasses.values.map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
allClassesnull107     override fun allClasses(): Array<out ClassDoc> = allClasses(true)
108 
109     override fun isIncluded(): Boolean = node.name in module.allPackages
110 }
111 
112 class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ClassDocumentationNodeAdapter(module, node), AnnotationTypeDoc {
113     override fun elements(): Array<out AnnotationTypeElementDoc>? = emptyArray() // TODO
114 }
115 
116 class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc {
annotationTypenull117     override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node) // TODO ?????
118     override fun isSynthesized(): Boolean = false
119     override fun elementValues(): Array<out AnnotationDesc.ElementValuePair>? = emptyArray() // TODO
120 }
121 
122 open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc {
123     override fun isPublic(): Boolean = true
124     override fun isPackagePrivate(): Boolean = false
125     override fun isStatic(): Boolean = node.hasModifier("static")
126     override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0
127     override fun qualifiedName(): String? = node.qualifiedName()
128     override fun annotations(): Array<out AnnotationDesc>? = nodeAnnotations(this).toTypedArray()
129     override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim()
130     override fun isProtected(): Boolean = false
131 
132     override fun isFinal(): Boolean = node.hasModifier("final")
133 
134     override fun containingPackage(): PackageDoc? {
135         if (node.kind == NodeKind.Type) {
136             return null
137         }
138 
139         var owner: DocumentationNode? = node
140         while (owner != null) {
141             if (owner.kind == NodeKind.Package) {
142                 return PackageAdapter(module, owner)
143             }
144             owner = owner.owner
145         }
146 
147         return null
148     }
149 
150     override fun containingClass(): ClassDoc? {
151         if (node.kind == NodeKind.Type) {
152             return null
153         }
154 
155         var owner = node.owner
156         while (owner != null) {
157             if (owner.kind in NodeKind.classLike) {
158                 return ClassDocumentationNodeAdapter(module, owner)
159             }
160             owner = owner.owner
161         }
162 
163         return null
164     }
165 
166     override fun isPrivate(): Boolean = false
167     override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true
168 }
169 
170 open class TypeAdapter(override val module: ModuleNodeAdapter, override val node: DocumentationNode) : Type, HasDocumentationNode, HasModule {
171     private val javaLanguageService = JavaLanguageService()
172 
qualifiedTypeNamenull173     override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedNameFromType() ?: node.qualifiedNameFromType()
174     override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.simpleName() ?: node.simpleName()
175     override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName()
176 
177     override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("")
178     override fun isPrimitive(): Boolean = simpleTypeName() in setOf("int", "long", "short", "byte", "char", "double", "float", "boolean", "void")
179 
180     override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else
181             elementType?.asClassDoc() ?:
182             when (node.kind) {
183                 in NodeKind.classLike,
184                 NodeKind.ExternalClass,
185                 NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node)
186 
187                 else -> when {
188                     node.links.firstOrNull { it.kind != NodeKind.ExternalLink } != null -> {
189                         TypeAdapter(module, node.links.firstOrNull { it.kind != NodeKind.ExternalLink }!!).asClassDoc()
190                     }
191                     else -> ClassDocumentationNodeAdapter(module, node) // TODO ?
192                 }
193             }
194 
asTypeVariablenull195     override fun asTypeVariable(): TypeVariable? = if (node.kind == NodeKind.TypeParameter) TypeVariableAdapter(module, node) else null
196     override fun asParameterizedType(): ParameterizedType? =
197             if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null)
198                 ParameterizedTypeAdapter(module, node)
199             else
200                 null
201 
202     override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == NodeKind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null
203     override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null
204     override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) }
asWildcardTypenull205     override fun asWildcardType(): WildcardType? = null
206 
207     override fun toString(): String = qualifiedTypeName() + dimension()
208     override fun hashCode(): Int = node.name.hashCode()
209     override fun equals(other: Any?): Boolean = other is TypeAdapter && toString() == other.toString()
210 }
211 
212 class NotAnnotatedTypeAdapter(typeAdapter: AnnotatedTypeAdapter) : Type by typeAdapter {
213     override fun asAnnotatedType() = null
214 }
215 
216 class AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType {
underlyingTypenull217     override fun underlyingType(): Type? = NotAnnotatedTypeAdapter(this)
218     override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
219 }
220 
221 class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType {
222     override fun extendsBounds(): Array<out Type> = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
223     override fun superBounds(): Array<out Type> = node.details(NodeKind.LowerBound).map { TypeAdapter(module, it) }.toTypedArray()
224 }
225 
226 class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), TypeVariable {
ownernull227     override fun owner(): ProgramElementDoc = node.owner!!.let<DocumentationNode, ProgramElementDoc> { owner ->
228         when (owner.kind) {
229             NodeKind.Function,
230             NodeKind.Constructor -> ExecutableMemberAdapter(module, owner)
231 
232             NodeKind.Class,
233             NodeKind.Interface,
234             NodeKind.Enum -> ClassDocumentationNodeAdapter(module, owner)
235 
236             else -> ProgramElementAdapter(module, node.owner!!)
237         }
238     }
239 
<lambda>null240     override fun bounds(): Array<out Type>? = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
<lambda>null241     override fun annotations(): Array<out AnnotationDesc>? = node.members(NodeKind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray()
242 
qualifiedTypeNamenull243     override fun qualifiedTypeName(): String = node.name
244     override fun simpleTypeName(): String = node.name
245     override fun typeName(): String = node.name
246 
247     override fun hashCode(): Int = node.name.hashCode()
248     override fun equals(other: Any?): Boolean = other is Type && other.typeName() == typeName() && other.asTypeVariable()?.owner() == owner()
249 
250     override fun asTypeVariable(): TypeVariableAdapter = this
251 }
252 
253 class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType {
254     override fun typeArguments(): Array<out Type> = node.details(NodeKind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray()
255     override fun superclassType(): Type? =
256             node.lookupSuperClasses(module)
257                     .firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass }
258                     ?.let { ClassDocumentationNodeAdapter(module, it) }
259 
260     override fun interfaceTypes(): Array<out Type> =
261             node.lookupSuperClasses(module)
262                     .filter { it.kind == NodeKind.Interface }
263                     .map { ClassDocumentationNodeAdapter(module, it) }
264                     .toTypedArray()
265 
266     override fun containingType(): Type? = when (node.owner?.kind) {
267         NodeKind.Package -> null
268         NodeKind.Class,
269         NodeKind.Interface,
270         NodeKind.Object,
271         NodeKind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!)
272 
273         else -> null
274     }
275 }
276 
277 class ParameterAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter {
typeNamenull278     override fun typeName(): String? = JavaLanguageService().renderType(node.detail(NodeKind.Type))
279     override fun type(): Type? = TypeAdapter(module, node.detail(NodeKind.Type))
280     override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
281 }
282 
283 class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode, val parent: ExecutableMemberAdapter) : DocumentationNodeAdapter(module, receiverType), Parameter {
284     override fun typeName(): String? = receiverType.name
285     override fun type(): Type? = TypeAdapter(module, receiverType)
286     override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
287     override fun name(): String = tryName("receiver")
288 
289     private tailrec fun tryName(name: String): String = when (name) {
290         in parent.parameters().drop(1).map { it.name() } -> tryName("$$name")
291         else -> name
292     }
293 }
294 
nodenull295 fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node ->
296     val pkg = fqName.substringBeforeLast(".", "")
297     if (pkg.isNotEmpty()) {
298         node.append(DocumentationNode(pkg, Content.Empty, NodeKind.Package), RefKind.Owner)
299     }
300 
301     node
302 }
303 
hasNonEmptyContentnull304 private fun DocumentationNode.hasNonEmptyContent() =
305         this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
306 
307 
308 open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), ExecutableMemberDoc {
309 
310     override fun isSynthetic(): Boolean = false
311     override fun isNative(): Boolean = node.annotations.any { it.name == "native" }
312 
313     override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO
314     override fun throwsTags(): Array<out ThrowsTag> =
315             node.content.sections
316                     .filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
317                     .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }
318                     .toTypedArray()
319 
320     override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).any { false } // TODO
321 
322     override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }
323 
324     override fun paramTags(): Array<out ParamTag> =
325             collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })
326 
327     override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
328     override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
329     override fun flatSignature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")")
330     override fun signature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types
331 
332     override fun parameters(): Array<out Parameter> =
333             ((receiverNode()?.let { receiver -> listOf<Parameter>(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList())
334                     + node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) }
335                     ).toTypedArray()
336 
337     override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
338 
339     override fun typeParamTags(): Array<out ParamTag> =
340             collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
341 
342     private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
343         when {
344             receivers.isNotEmpty() -> receivers.single().detail(NodeKind.Type)
345             else -> null
346         }
347     }
348 }
349 
350 class ConstructorAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), ConstructorDoc {
namenull351     override fun name(): String = node.owner?.name ?: throw IllegalStateException("No owner for $node")
352 
353     override fun containingClass(): ClassDoc? {
354         return super.containingClass()
355     }
356 }
357 
358 class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), MethodDoc {
overridesnull359     override fun overrides(meth: MethodDoc?): Boolean = false // TODO
360 
361     override fun overriddenType(): Type? = node.overrides.firstOrNull()?.owner?.let { owner -> TypeAdapter(module, owner) }
362 
<lambda>null363     override fun overriddenMethod(): MethodDoc? = node.overrides.map { MethodAdapter(module, it) }.firstOrNull()
overriddenClassnull364     override fun overriddenClass(): ClassDoc? = overriddenMethod()?.containingClass()
365 
366     override fun isAbstract(): Boolean = false // TODO
367 
368     override fun isDefault(): Boolean = false
369 
370     override fun returnType(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
371 
372     override fun tags(tagname: String?) = super.tags(tagname)
373 
374     override fun tags(): Array<out Tag> {
375         val tags = super.tags().toMutableList()
376         node.content.findSectionByTag(ContentTags.Return)?.let {
377             tags += ReturnTagAdapter(module, this, it.children)
378         }
379 
380         return tags.toTypedArray()
381     }
382 }
383 
384 class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), FieldDoc {
isSyntheticnull385     override fun isSynthetic(): Boolean = false
386 
387     override fun constantValueExpression(): String? = node.detailOrNull(NodeKind.Value)?.let { it.name }
constantValuenull388     override fun constantValue(): Any? = constantValueExpression()
389 
390     override fun type(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
391     override fun isTransient(): Boolean = node.hasAnnotation(Transient::class)
392     override fun serialFieldTags(): Array<out SerialFieldTag> = emptyArray()
393 
394     override fun isVolatile(): Boolean = node.hasAnnotation(Volatile::class)
395 }
396 open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode)
397     : ProgramElementAdapter(module, classNode),
398       Type by TypeAdapter(module, classNode),
399         ClassDoc {
400 
401     override fun name(): String {
402         val parent = classNode.owner
403         if (parent?.kind in NodeKind.classLike) {
404             return parent!!.name + "." + classNode.name
405         }
406         return classNode.simpleName()
407     }
408 
409     override fun constructors(filter: Boolean): Array<out ConstructorDoc> = classNode.members(NodeKind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray()
410     override fun constructors(): Array<out ConstructorDoc> = constructors(true)
411     override fun importedPackages(): Array<out PackageDoc> = emptyArray()
412     override fun importedClasses(): Array<out ClassDoc>? = emptyArray()
413     override fun typeParameters(): Array<out TypeVariable> = classNode.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
414     override fun asTypeVariable(): TypeVariable? = if (classNode.kind == NodeKind.Class) TypeVariableAdapter(module, classNode) else null
415     override fun isExternalizable(): Boolean = interfaces().any { it.qualifiedName() == "java.io.Externalizable" }
416     override fun definesSerializableFields(): Boolean = false
417     override fun methods(filter: Boolean): Array<out MethodDoc> = classNode.members(NodeKind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods
418     override fun methods(): Array<out MethodDoc> = methods(true)
419     override fun enumConstants(): Array<out FieldDoc>? = classNode.members(NodeKind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray()
420     override fun isAbstract(): Boolean = classNode.details(NodeKind.Modifier).any { it.name == "abstract" }
421     override fun interfaceTypes(): Array<out Type> = classNode.lookupSuperClasses(module)
422             .filter { it.kind == NodeKind.Interface }
423             .map { ClassDocumentationNodeAdapter(module, it) }
424             .toTypedArray()
425 
426     override fun interfaces(): Array<out ClassDoc> = classNode.lookupSuperClasses(module)
427             .filter { it.kind == NodeKind.Interface }
428             .map { ClassDocumentationNodeAdapter(module, it) }
429             .toTypedArray()
430 
431     override fun typeParamTags(): Array<out ParamTag> =
432             collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
433 
434     override fun fields(): Array<out FieldDoc> = fields(true)
435     override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()
436 
437     override fun findClass(className: String?): ClassDoc? = null // TODO !!!
438     override fun serializableFields(): Array<out FieldDoc> = emptyArray()
439     override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
440     override fun serializationMethods(): Array<out MethodDoc> = emptyArray() // TODO
441     override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
442     override fun isSerializable(): Boolean = false // TODO
443     override fun subclassOf(cd: ClassDoc?): Boolean {
444         if (cd == null) {
445             return false
446         }
447 
448         val expectedFQName = cd.qualifiedName()
449         val types = arrayListOf(classNode)
450         val visitedTypes = HashSet<String>()
451 
452         while (types.isNotEmpty()) {
453             val type = types.removeAt(types.lastIndex)
454             val fqName = type.qualifiedName()
455 
456             if (expectedFQName == fqName) {
457                 return true
458             }
459 
460             visitedTypes.add(fqName)
461             types.addAll(type.details(NodeKind.Supertype).filter { it.qualifiedName() !in visitedTypes })
462         }
463 
464         return false
465     }
466 
467     override fun innerClasses(): Array<out ClassDoc> = classNode.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
468     override fun innerClasses(filter: Boolean): Array<out ClassDoc> = innerClasses()
469 }
470 
lookupSuperClassesnull471 fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) =
472         details(NodeKind.Supertype)
473                 .map { it.links.firstOrNull() }
<lambda>null474                 .map { module.allTypes[it?.qualifiedName()] }
475                 .filterNotNull()
476 
collectAllTypesRecursivelynull477 fun List<DocumentationNode>.collectAllTypesRecursively(): Map<String, DocumentationNode> {
478     val result = hashMapOf<String, DocumentationNode>()
479 
480     fun DocumentationNode.collectTypesRecursively() {
481         val classLikeMembers = NodeKind.classLike.flatMap { members(it) }
482         classLikeMembers.forEach {
483             result.put(it.qualifiedName(), it)
484             it.collectTypesRecursively()
485         }
486     }
487 
488     forEach { it.collectTypesRecursively() }
489     return result
490 }
491 
492 class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc {
<lambda>null493     val allPackages = module.members(NodeKind.Package).associateBy { it.name }
494     val allTypes = module.members(NodeKind.Package).collectAllTypesRecursively()
495 
<lambda>null496     override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) }
497 
classesnull498     override fun classes(): Array<out ClassDoc> =
499             allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray()
500 
optionsnull501     override fun options(): Array<out Array<String>> = arrayOf(
502             arrayOf("-d", outputPath),
503             arrayOf("-docencoding", "UTF-8"),
504             arrayOf("-charset", "UTF-8"),
505             arrayOf("-keywords")
506     )
507 
508     override fun specifiedPackages(): Array<out PackageDoc>? = module.members(NodeKind.Package).map { PackageAdapter(this, it) }.toTypedArray()
509 
classNamednull510     override fun classNamed(qualifiedName: String?): ClassDoc? =
511             allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) }
512 
specifiedClassesnull513     override fun specifiedClasses(): Array<out ClassDoc> = classes()
514 }
515 
516 private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFilter: (ContentSection) -> Boolean) =
517         (node.details(kind)
518                 .filter(DocumentationNode::hasNonEmptyContent)
519                 .map { ParamTagAdapter(module, this, it.name, true, it.content.children) }
520 
521                 + node.content.sections
522                 .filter(sectionFilter)
<lambda>null523                 .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) })
524 
525                 .toTypedArray()