1 package org.jetbrains.dokka.Formats
2
3 import com.google.inject.Binder
4 import kotlinx.html.*
5 import org.jetbrains.dokka.*
6 import org.jetbrains.dokka.Utilities.bind
7 import org.jetbrains.dokka.Utilities.lazyBind
8 import org.jetbrains.dokka.Utilities.toOptional
9 import org.jetbrains.dokka.Utilities.toType
10 import java.net.URI
11 import kotlin.reflect.KClass
12
13
14 abstract class JavaLayoutHtmlFormatDescriptorBase : FormatDescriptor, DefaultAnalysisComponent {
15
<lambda>null16 override fun configureOutput(binder: Binder): Unit = with(binder) {
17 bind<Generator>() toType generatorServiceClass
18 bind<LanguageService>() toType languageServiceClass
19 bind<JavaLayoutHtmlTemplateService>() toType templateServiceClass
20 bind<JavaLayoutHtmlUriProvider>() toType generatorServiceClass
21 lazyBind<JavaLayoutHtmlFormatOutlineFactoryService>() toOptional outlineFactoryClass
22 bind<PackageListService>() toType packageListServiceClass
23 bind<JavaLayoutHtmlFormatOutputBuilderFactory>() toType outputBuilderFactoryClass
24 }
25
26 val generatorServiceClass = JavaLayoutHtmlFormatGenerator::class
27 abstract val languageServiceClass: KClass<out LanguageService>
28 abstract val templateServiceClass: KClass<out JavaLayoutHtmlTemplateService>
29 abstract val outlineFactoryClass: KClass<out JavaLayoutHtmlFormatOutlineFactoryService>?
30 abstract val packageListServiceClass: KClass<out PackageListService>
31 abstract val outputBuilderFactoryClass: KClass<out JavaLayoutHtmlFormatOutputBuilderFactory>
32 }
33
<lambda>null34 class JavaLayoutHtmlFormatDescriptor : JavaLayoutHtmlFormatDescriptorBase(), DefaultAnalysisComponentServices by KotlinAsKotlin {
35 override val outputBuilderFactoryClass: KClass<out JavaLayoutHtmlFormatOutputBuilderFactory> = JavaLayoutHtmlFormatOutputBuilderFactoryImpl::class
36 override val packageListServiceClass: KClass<out PackageListService> = JavaLayoutHtmlPackageListService::class
37 override val languageServiceClass = KotlinLanguageService::class
38 override val templateServiceClass = JavaLayoutHtmlTemplateService.Default::class
39 override val outlineFactoryClass = null
40 }
41
<lambda>null42 class JavaLayoutHtmlAsJavaFormatDescriptor : JavaLayoutHtmlFormatDescriptorBase(), DefaultAnalysisComponentServices by KotlinAsJava {
43 override val outputBuilderFactoryClass: KClass<out JavaLayoutHtmlFormatOutputBuilderFactory> = JavaLayoutHtmlFormatOutputBuilderFactoryImpl::class
44 override val packageListServiceClass: KClass<out PackageListService> = JavaLayoutHtmlPackageListService::class
45 override val languageServiceClass = NewJavaLanguageService::class
46 override val templateServiceClass = JavaLayoutHtmlTemplateService.Default::class
47 override val outlineFactoryClass = null
48 }
49
50 interface JavaLayoutHtmlFormatOutlineFactoryService {
generateOutlinesnull51 fun generateOutlines(outputProvider: (URI) -> Appendable, nodes: Iterable<DocumentationNode>)
52 }
53
54
55 interface JavaLayoutHtmlUriProvider {
56 fun tryGetContainerUri(node: DocumentationNode): URI?
57 fun tryGetMainUri(node: DocumentationNode): URI?
58 fun tryGetOutlineRootUri(node: DocumentationNode): URI?
59 fun containerUri(node: DocumentationNode): URI = tryGetContainerUri(node) ?: error("Unsupported ${node.kind}")
60 fun mainUri(node: DocumentationNode): URI = tryGetMainUri(node) ?: error("Unsupported ${node.kind}")
61 fun outlineRootUri(node: DocumentationNode): URI = tryGetOutlineRootUri(node) ?: error("Unsupported ${node.kind}")
62
63
64 fun linkTo(to: DocumentationNode, from: URI): String {
65 return mainUri(to).relativeTo(from).toString()
66 }
67
68 fun linkToFromOutline(to: DocumentationNode, from: URI): String {
69 return outlineRootUri(to).relativeTo(from).toString()
70 }
71
72 fun mainUriOrWarn(node: DocumentationNode): URI? = tryGetMainUri(node) ?: (null).also {
73 AssertionError("Not implemented mainUri for ${node.kind} (${node})").printStackTrace()
74 }
75 }
76
77
78 interface JavaLayoutHtmlTemplateService {
composePagenull79 fun composePage(
80 page: JavaLayoutHtmlFormatOutputBuilder.Page,
81 tagConsumer: TagConsumer<Appendable>,
82 headContent: HEAD.() -> Unit,
83 bodyContent: BODY.() -> Unit
84 )
85
86 class Default : JavaLayoutHtmlTemplateService {
87 override fun composePage(
88 page: JavaLayoutHtmlFormatOutputBuilder.Page,
89 tagConsumer: TagConsumer<Appendable>,
90 headContent: HEAD.() -> Unit,
91 bodyContent: BODY.() -> Unit
92 ) {
93 tagConsumer.html {
94 head {
95 meta(charset = "UTF-8")
96 headContent()
97 }
98 body(block = bodyContent)
99 }
100 }
101 }
102 }
103
<lambda>null104 val DocumentationNode.companion get() = members(NodeKind.Object).find { it.details(NodeKind.Modifier).any { it.name == "companion" } }
105
signatureForAnchornull106 fun DocumentationNode.signatureForAnchor(logger: DokkaLogger): String {
107
108 fun StringBuilder.appendReceiverIfSo() {
109 detailOrNull(NodeKind.Receiver)?.let {
110 append("(")
111 append(it.detail(NodeKind.Type).qualifiedNameFromType())
112 append(").")
113 }
114 }
115
116 return when (kind) {
117 NodeKind.Function, NodeKind.Constructor, NodeKind.CompanionObjectFunction -> buildString {
118 if (kind == NodeKind.CompanionObjectFunction) {
119 append("Companion.")
120 }
121 appendReceiverIfSo()
122 append(prettyName)
123 details(NodeKind.Parameter).joinTo(this, prefix = "(", postfix = ")") { it.detail(NodeKind.Type).qualifiedNameFromType() }
124 }
125 NodeKind.Property, NodeKind.CompanionObjectProperty -> buildString {
126 if (kind == NodeKind.CompanionObjectProperty) {
127 append("Companion.")
128 }
129 appendReceiverIfSo()
130 append(name)
131 append(":")
132 append(detail(NodeKind.Type).qualifiedNameFromType())
133 }
134 NodeKind.TypeParameter, NodeKind.Parameter -> this.detail(NodeKind.Signature).name // Todo Why not signatureForAnchor
135 NodeKind.Field -> name
136 NodeKind.EnumItem -> "ENUM_VALUE:$name"
137 NodeKind.Attribute -> "attr_$name"
138 else -> "Not implemented signatureForAnchor $this".also { logger.warn(it) }
139 }
140 }
141
142