<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()