aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBłażej Kardyś <bkardys@virtuslab.com>2020-06-25 20:41:28 +0200
committerPaweł Marks <pmarks@virtuslab.com>2020-06-26 00:40:47 +0200
commit0e35a9d3b2a24b50d6016e82e9889d9fdc3dbbf0 (patch)
treeb0ce1d6307aeb8fc4d6117d5421aa4c17bbe66a4
parenta1c316e829827ddb0e3e288e684ac287e8fd28ff (diff)
downloaddokka-0e35a9d3b2a24b50d6016e82e9889d9fdc3dbbf0.tar.gz
dokka-0e35a9d3b2a24b50d6016e82e9889d9fdc3dbbf0.tar.bz2
dokka-0e35a9d3b2a24b50d6016e82e9889d9fdc3dbbf0.zip
Adding external url handling
-rw-r--r--.idea/compiler.xml16
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt141
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt20
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt67
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt16
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProvider.kt (renamed from plugins/javadoc/src/main/kotlin/javadoc/JavadocLocationProvider.kt)45
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProviderFactory.kt11
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt25
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt34
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt22
-rw-r--r--plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt55
-rw-r--r--plugins/javadoc/src/main/resources/views/components/indexTable.korte2
-rw-r--r--plugins/javadoc/src/main/resources/views/listPage.korte2
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt24
14 files changed, 293 insertions, 187 deletions
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 8144c3cf..00000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="CompilerConfiguration">
- <wildcardResourcePatterns>
- <entry name="!?*.java" />
- <entry name="!?*.form" />
- <entry name="!?*.class" />
- <entry name="!?*.groovy" />
- <entry name="!?*.scala" />
- <entry name="!?*.flex" />
- <entry name="!?*.kt" />
- <entry name="!?*.clj" />
- </wildcardResourcePatterns>
- <bytecodeTargetLevel target="1.8" />
- </component>
-</project> \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt
new file mode 100644
index 00000000..ab633fdc
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/BaseLocationProvider.kt
@@ -0,0 +1,141 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.query
+import java.lang.IllegalStateException
+import java.net.HttpURLConnection
+import java.net.URL
+import java.net.URLConnection
+
+abstract class BaseLocationProvider(protected val dokkaContext: DokkaContext) : LocationProvider {
+
+ protected val externalLocationProviderFactories =
+ dokkaContext.plugin<DokkaBase>().query { externalLocationProviderFactory }
+
+ protected fun getExternalLocation(
+ dri: DRI,
+ sourceSets: Set<DokkaSourceSet>
+ ): String {
+ val jdkToExternalDocumentationLinks = dokkaContext.configuration.sourceSets
+ .filter { sourceSet ->
+ sourceSets.contains(sourceSet)
+ }
+ .groupBy({ it.jdkVersion }, { it.externalDocumentationLinks })
+ .map { it.key to it.value.flatten().distinct() }.toMap()
+
+ val toResolve: MutableMap<Int, MutableList<DokkaConfiguration.ExternalDocumentationLink>> = mutableMapOf()
+ for ((jdk, links) in jdkToExternalDocumentationLinks) {
+ for (link in links) {
+ val info = cache[link.packageListUrl]
+ if (info == null) {
+ toResolve.getOrPut(jdk) { mutableListOf() }.add(link)
+ } else if (info.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, info)
+ }
+ }
+ }
+ // Not in cache, resolve packageLists
+ for ((jdk, links) in toResolve) {
+ for (link in links) {
+ if (dokkaContext.configuration.offlineMode && link.packageListUrl.protocol.toLowerCase() != "file")
+ continue
+ val locationInfo =
+ loadPackageList(jdk, link.packageListUrl)
+ if (locationInfo.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(dri, locationInfo)
+ }
+ }
+ toResolve.remove(jdk)
+ }
+ return ""
+ }
+
+ private val cache: MutableMap<URL, DefaultLocationProvider.LocationInfo> = mutableMapOf()
+
+
+ private fun getLink(dri: DRI, locationInfo: DefaultLocationProvider.LocationInfo): String =
+ locationInfo.locations[dri.packageName + "." + dri.classNames]
+ ?: // Not sure if it can be here, previously it shadowed only kotlin/dokka related sources, here it shadows both dokka/javadoc, cause I cannot distinguish what LocationProvider has been hypothetically chosen
+ if (locationInfo.externalLocationProvider != null)
+ with(locationInfo.externalLocationProvider) {
+ dri.toLocation()
+ }
+ else
+ throw IllegalStateException("Have not found any convenient ExternalLocationProvider for $dri DRI!")
+
+ private fun loadPackageList(jdk: Int, url: URL): DefaultLocationProvider.LocationInfo {
+ val packageListStream = url.doOpenConnectionToReadContent().getInputStream()
+ val (params, packages) =
+ packageListStream
+ .bufferedReader()
+ .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } }
+
+ val paramsMap = params.asSequence()
+ .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) }
+ .groupBy({ (key, _) -> key }, { (_, value) -> value })
+
+ val format = paramsMap["format"]?.singleOrNull() ?: when {
+ jdk < 8 -> "javadoc1" // Covers JDK 1 - 7
+ jdk < 10 -> "javadoc8" // Covers JDK 8 - 9
+ else -> "javadoc10" // Covers JDK 10+
+ }
+
+ val locations = paramsMap["location"].orEmpty()
+ .map { it.split("\u001f", limit = 2) }
+ .map { (key, value) -> key to value }
+ .toMap()
+
+ val externalLocationProvider =
+ externalLocationProviderFactories.asSequence().map { it.getExternalLocationProvider(format) }
+ .filterNotNull().take(1).firstOrNull()
+
+ val info = DefaultLocationProvider.LocationInfo(
+ externalLocationProvider,
+ packages.toSet(),
+ locations
+ )
+ cache[url] = info
+ return info
+ }
+
+ private fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection {
+ val connection = this.openConnection().apply {
+ connectTimeout = timeout
+ readTimeout = timeout
+ }
+
+ when (connection) {
+ is HttpURLConnection -> {
+ return when (connection.responseCode) {
+ in 200..299 -> {
+ connection
+ }
+ HttpURLConnection.HTTP_MOVED_PERM,
+ HttpURLConnection.HTTP_MOVED_TEMP,
+ HttpURLConnection.HTTP_SEE_OTHER -> {
+ if (redirectsAllowed > 0) {
+ val newUrl = connection.getHeaderField("Location")
+ URL(newUrl).doOpenConnectionToReadContent(timeout, redirectsAllowed - 1)
+ } else {
+ throw RuntimeException("Too many redirects")
+ }
+ }
+ else -> {
+ throw RuntimeException("Unhandled http code: ${connection.responseCode}")
+ }
+ }
+ }
+ else -> return connection
+ }
+ }
+
+ companion object {
+ const val DOKKA_PARAM_PREFIX = "\$dokka."
+ }
+
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
index 6c4869d8..e48aa926 100644
--- a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
@@ -2,30 +2,23 @@ package org.jetbrains.dokka.base.resolvers.local
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProvider
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLConnection
import java.util.*
private const val PAGE_WITH_CHILDREN_SUFFIX = "index"
-private const val DOKKA_PARAM_PREFIX = "\$dokka."
open class DefaultLocationProvider(
protected val pageGraphRoot: RootPageNode,
- protected val dokkaContext: DokkaContext
-) : LocationProvider {
+ dokkaContext: DokkaContext
+) : BaseLocationProvider(dokkaContext) {
protected open val extension = ".html"
- protected val externalLocationProviderFactories =
- dokkaContext.plugin<DokkaBase>().query { externalLocationProviderFactory }
-
protected val pagesIndex: Map<DRI, ContentPage> = pageGraphRoot.asSequence().filterIsInstance<ContentPage>()
.map { it.dri.map { dri -> dri to it } }.flatten()
.groupingBy { it.first }
@@ -49,12 +42,7 @@ open class DefaultLocationProvider(
override fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode?): String =
pagesIndex[dri]?.let { resolve(it, context) } ?:
// Not found in PageGraph, that means it's an external link
- getLocation(
- dri,
- sourceSets
- .groupBy({ it.jdkVersion }, { it.externalDocumentationLinks })
- .map { it.key to it.value.flatten().distinct() }.toMap()
- )
+ getExternalLocation(dri, sourceSets)
override fun resolveRoot(node: PageNode): String =
pathTo(pageGraphRoot, node).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
@@ -105,7 +93,7 @@ open class DefaultLocationProvider(
// Not in cache, resolve packageLists
for ((jdk, links) in toResolve) {
for (link in links) {
- if (dokkaContext.configuration.offlineMode && link.packageListUrl.protocol.toLowerCase() != "file")
+ if(dokkaContext.configuration.offlineMode && link.packageListUrl.protocol.toLowerCase() != "file")
continue
val locationInfo =
loadPackageList(jdk, link.packageListUrl)
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
index 12c53ab7..767e0c68 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPageCreator.kt
@@ -17,7 +17,6 @@ import org.jetbrains.dokka.pages.ContentNode
import org.jetbrains.dokka.pages.ContentText
import org.jetbrains.dokka.pages.DCI
import org.jetbrains.dokka.utilities.DokkaLogger
-import org.jetbrains.kotlin.utils.addToStdlib.safeAs
open class JavadocPageCreator(
commentsToContentConverter: CommentsToContentConverter,
@@ -47,13 +46,22 @@ open class JavadocPageCreator(
modifiers = listOfNotNull(c.visibility[jvm]?.name),
signature = signatureProvider.signature(c).nodeForJvm(jvm),
description = c.descriptionToContentNodes(),
- constructors = c.safeAs<WithConstructors>()?.constructors?.map { it.toJavadocFunction(jvm) }.orEmpty(),
- methods = c.functions.map { it.toJavadocFunction(jvm) },
- entries = c.safeAs<DEnum>()?.entries?.map { JavadocEntryNode(signatureProvider.signature(it).nodeForJvm(jvm), it.descriptionToContentNodes(jvm)) }.orEmpty(),
+ constructors = (c as? WithConstructors)?.constructors?.mapNotNull { it.toJavadocFunction() }.orEmpty(),
+ methods = c.functions.mapNotNull { it.toJavadocFunction() },
+ entries = (c as? DEnum)?.entries?.map {
+ JavadocEntryNode(
+ signatureProvider.signature(it).nodeForJvm(jvm), it.descriptionToContentNodes(jvm)
+ )
+ }.orEmpty(),
classlikes = c.classlikes.mapNotNull { pageForClasslike(it) },
- properties = c.properties.map { JavadocPropertyNode(signatureProvider.signature(it).nodeForJvm(jvm), it.descriptionToContentNodes(jvm)) },
+ properties = c.properties.map {
+ JavadocPropertyNode(
+ signatureProvider.signature(it).nodeForJvm(jvm),
+ it.descriptionToContentNodes(jvm)
+ )
+ },
documentable = c,
- extras = c.safeAs<WithExtraProperties<Documentable>>()?.extra ?: PropertyContainer.empty()
+ extras = (c as? WithExtraProperties<Documentable>)?.extra ?: PropertyContainer.empty()
)
}
@@ -61,7 +69,7 @@ open class JavadocPageCreator(
JavadocContentGroup(
setOf(m.dri),
JavadocContentKind.OverviewSummary,
- m.jvmSource.toSet()
+ m.jvmSourceSets.toSet()
) {
title(m.name, m.brief(),"0.0.1", dri = setOf(m.dri), kind = ContentKind.Main)
list("Packages", "Package", setOf(m.dri), ContentKind.Packages, m.packages.sortedBy { it.name }.map { p ->
@@ -76,9 +84,9 @@ open class JavadocPageCreator(
JavadocContentGroup(
setOf(p.dri),
JavadocContentKind.PackageSummary,
- p.jvmSource.toSet()
+ p.jvmSourceSets.toSet()
) {
- title(p.name, p.brief(),"0.0.1", dri = setOf(p.dri), kind = ContentKind.Packages)
+ title(p.name, p.brief(), "0.0.1", dri = setOf(p.dri), kind = ContentKind.Packages)
list("Packages", "Package", setOf(p.dri), ContentKind.Packages, p.classlikes.sortedBy { it.name }.map { c ->
RowJavadocListEntry(
LinkJavadocListEntry(c.name.orEmpty(), setOf(c.dri), JavadocContentKind.Class, sourceSets),
@@ -91,7 +99,7 @@ open class JavadocPageCreator(
JavadocContentGroup(
setOf(c.dri),
JavadocContentKind.Class,
- c.jvmSource.toSet()
+ c.jvmSourceSets.toSet()
) {
title(
c.name.orEmpty(),
@@ -127,31 +135,34 @@ open class JavadocPageCreator(
is UnresolvedBound -> p.name
}
- private fun DFunction.toJavadocFunction(sourceSetData: DokkaSourceSet) = JavadocFunctionNode(
- name = name,
- signature = signatureProvider.signature(this).nodeForJvm(sourceSetData),
- brief = brief(sourceSetData),
- parameters = parameters.map {
- JavadocParameterNode(
- name = it.name.orEmpty(),
- type = signatureForProjection(it.type),
- description = it.brief()
- )
- },
- extras = extra
- )
+ private fun DFunction.toJavadocFunction() = highestJvmSourceSet?.let { jvm ->
+ JavadocFunctionNode(
+ name = name,
+ dri = dri,
+ signature = signatureProvider.signature(this).nodeForJvm(jvm),
+ brief = brief(jvm),
+ parameters = parameters.map {
+ JavadocParameterNode(
+ name = it.name.orEmpty(),
+ type = signatureForProjection(it.type),
+ description = it.brief()
+ )
+ },
+ extras = extra
+ )
+ }
- private val Documentable.jvmSource
+ private val Documentable.jvmSourceSets
get() = sourceSets.filter { it.analysisPlatform == Platform.jvm }
private val Documentable.highestJvmSourceSet
- get() = jvmSource.let { sources ->
- sources.firstOrNull { it != expectPresentInSet } ?: sources.firstOrNull()
+ get() = jvmSourceSets.let { sources ->
+ sources.firstOrNull { it != expectPresentInSet } ?: sources.firstOrNull()
}
private val firstSentenceRegex = Regex("^((?:[^.?!]|[.!?](?!\\s))*[.!?])")
- private inline fun <reified T: TagWrapper> Documentable.findNodeInDocumentation(sourceSetData: DokkaSourceSet?): T? =
+ private inline fun <reified T : TagWrapper> Documentable.findNodeInDocumentation(sourceSetData: DokkaSourceSet?): T? =
documentation[sourceSetData]?.firstChildOfType<T>()
private fun Documentable.descriptionToContentNodes(sourceSet: DokkaSourceSet? = highestJvmSourceSet) = findNodeInDocumentation<Description>(sourceSet)?.let {
@@ -169,7 +180,7 @@ open class JavadocPageCreator(
val description = descriptionToContentNodes(sourceSet)
val contents = mutableListOf<ContentNode>()
for (node in description) {
- if ( node is ContentText && firstSentenceRegex.containsMatchIn(node.text) ) {
+ if (node is ContentText && firstSentenceRegex.containsMatchIn(node.text)) {
contents.add(node.copy(text = firstSentenceRegex.find(node.text)?.value.orEmpty()))
break
} else {
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
index 504eecfd..2d24bbf1 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/JavadocPlugin.kt
@@ -1,16 +1,21 @@
package org.jetbrains.dokka.javadoc
import javadoc.JavadocDocumentableToPageTranslator
+import javadoc.location.JavadocLocationProviderFactory
import javadoc.renderer.KorteJavadocRenderer
import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.base.DokkaBase
+import org.jetbrains.dokka.base.resolvers.external.JavadocExternalLocationProviderFactory
import org.jetbrains.dokka.plugability.DokkaPlugin
import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.kotlinAsJava.signatures.JavaSignatureProvider
class JavadocPlugin : DokkaPlugin() {
+
+ val dokkaBasePlugin by lazy { plugin<DokkaBase>() }
+
+ val locationProviderFactory by extensionPoint<JavadocLocationProviderFactory>()
+
val dokkaJavadocPlugin by extending {
- val dokkaBasePlugin = plugin<DokkaBase>()
CoreExtensions.renderer providing { ctx ->
KorteJavadocRenderer(
dokkaBasePlugin.querySingle { outputWriter },
@@ -21,7 +26,6 @@ class JavadocPlugin : DokkaPlugin() {
}
val pageTranslator by extending {
- val dokkaBasePlugin = plugin<DokkaBase>()
CoreExtensions.documentableToPageTranslator providing { context ->
JavadocDocumentableToPageTranslator(
dokkaBasePlugin.querySingle { commentsToContentConverter },
@@ -30,5 +34,11 @@ class JavadocPlugin : DokkaPlugin() {
)
}
}
+
+ val javadocLocationProviderFactory by extending {
+ locationProviderFactory providing { context ->
+ JavadocLocationProviderFactory(context)
+ }
+ }
}
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/JavadocLocationProvider.kt b/plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProvider.kt
index d731ec5f..56a9015a 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/JavadocLocationProvider.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProvider.kt
@@ -1,32 +1,19 @@
-package javadoc
+package javadoc.location
import javadoc.pages.*
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.resolvers.local.LocationProvider
+import org.jetbrains.dokka.base.resolvers.local.BaseLocationProvider
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.ContentPage
import org.jetbrains.dokka.pages.PageNode
import org.jetbrains.dokka.pages.RootPageNode
import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-import java.nio.file.Paths
import java.util.*
-class JavadocLocationProvider(pageRoot: RootPageNode, private val context: DokkaContext) : LocationProvider {
- private val externalLocationProviderFactories =
- context.plugin<DokkaBase>().query { externalLocationProviderFactory }
- private val externalLocationProvider =
- externalLocationProviderFactories.asSequence().map { it.getExternalLocationProvider("javadoc10") }
- .filterNotNull().take(1).firstOrNull()
- private val externalDocumentationLinks by lazy {
- context.configuration.sourceSets
- .filter { sourceSet -> sourceSet.analysisPlatform == Platform.jvm }
- .flatMap { it.externalDocumentationLinks }
- .distinct()
- }
+class JavadocLocationProvider(pageRoot: RootPageNode, private val context: DokkaContext) : BaseLocationProvider(context) {
private val pathIndex = IdentityHashMap<PageNode, List<String>>().apply {
fun registerPath(page: PageNode, prefix: List<String> = emptyList()) {
@@ -54,10 +41,9 @@ class JavadocLocationProvider(pageRoot: RootPageNode, private val context: Dokka
pageRoot.children.forEach { registerPath(it) }
}
- private val nodeIndex = IdentityHashMap<DRI, PageNode>().apply {
+ private val nodeIndex = HashMap<DRI, PageNode>().apply {
fun registerNode(node: PageNode) {
if (node is ContentPage) put(node.dri.first(), node)
-
node.children.forEach(::registerNode)
}
registerNode(pageRoot)
@@ -65,24 +51,27 @@ class JavadocLocationProvider(pageRoot: RootPageNode, private val context: Dokka
private operator fun IdentityHashMap<PageNode, List<String>>.get(dri: DRI) = this[nodeIndex[dri]]
+ private fun List<String>.relativeTo(context: List<String>): String {
+ val contextPath = context.dropLast(1)
+ val commonPathElements = zip(contextPath).takeWhile { (a,b) -> a == b }.count()
+ return (List(contextPath.size - commonPathElements ) { ".." } + this.drop(commonPathElements)).joinToString("/")
+ }
+
override fun resolve(dri: DRI, sourceSets: Set<DokkaSourceSet>, context: PageNode?): String =
- context?.let { resolve(it, skipExtension = false) } ?: nodeIndex[dri]?.let {
- resolve(it, skipExtension = true)
- } ?: with(externalLocationProvider!!) {
- dri.toLocation()
- }
+ nodeIndex[dri]?.let { resolve(it, context) }
+ ?: getExternalLocation(dri, sourceSets)
override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
- pathIndex[node]?.joinToString("/")?.let {
+ pathIndex[node]?.relativeTo(pathIndex[context].orEmpty())?.let {
if (skipExtension) it.removeSuffix(".html") else it
} ?: run {
throw IllegalStateException("Path for ${node::class.java.canonicalName}:${node.name} not found")
}
- fun resolve(link: LinkJavadocListEntry, dir: String = "", skipExtension: Boolean = true) =
+ fun resolve(link: LinkJavadocListEntry, contextRoot: PageNode? = null, skipExtension: Boolean = true) =
pathIndex[link.dri.first()]?.let {
when (link.kind) {
- JavadocContentKind.Class -> it
+ JavadocContentKind.Class -> it
JavadocContentKind.OverviewSummary -> it.dropLast(1) + "index"
JavadocContentKind.PackageSummary -> it.dropLast(1) + "package-summary"
JavadocContentKind.AllClasses -> it.dropLast(1) + "allclasses"
@@ -90,9 +79,7 @@ class JavadocLocationProvider(pageRoot: RootPageNode, private val context: Dokka
JavadocContentKind.PackageTree -> it.dropLast(1) + "package-tree"
else -> it
}
- }?.joinToString("/")?.let { if (skipExtension) "$it.html" else it }?.let {
- Paths.get(dir).relativize(Paths.get(it)).toString()
- } ?: run { "" } //TODO just a glue to compile it on HMPP
+ }?.relativeTo(pathIndex[contextRoot].orEmpty())?.let { if (skipExtension) "$it.html" else it }.orEmpty()
override fun resolveRoot(node: PageNode): String {
TODO("Not yet implemented")
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProviderFactory.kt b/plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProviderFactory.kt
new file mode 100644
index 00000000..b6bfb48d
--- /dev/null
+++ b/plugins/javadoc/src/main/kotlin/javadoc/location/JavadocLocationProviderFactory.kt
@@ -0,0 +1,11 @@
+package javadoc.location
+
+import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory
+import org.jetbrains.dokka.pages.RootPageNode
+import org.jetbrains.dokka.plugability.DokkaContext
+
+class JavadocLocationProviderFactory(private val context: DokkaContext) : LocationProviderFactory {
+
+ override fun getLocationProvider(pageNode: RootPageNode) =
+ JavadocLocationProvider(pageNode, context)
+} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
index 5ac232d4..24e481e8 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/pages/JavadocPageNodes.kt
@@ -104,28 +104,10 @@ data class JavadocFunctionNode(
val signature: ContentNode,
val brief: List<ContentNode>,
val parameters: List<JavadocParameterNode>,
- override val name: String,
- override val dri: Set<DRI> = emptySet(),
- override val children: List<PageNode> = emptyList(),
- override val documentable: Documentable? = null,
- override val embeddedResources: List<String> = emptyList(),
+ val name: String,
+ val dri: DRI,
val extras: PropertyContainer<DFunction> = PropertyContainer.empty()
-) : JavadocPageNode {
-
- override val content: ContentNode = EmptyNode(DRI.topLevel, ContentKind.Classlikes, emptySet())
-
- override fun modified(
- name: String,
- children: List<PageNode>
- ): PageNode = TODO()
-
- override fun modified(
- name: String,
- content: ContentNode,
- dri: Set<DRI>,
- embeddedResources: List<String>,
- children: List<PageNode>
- ): ContentPage = TODO()
+) {
val modifiersAndSignature: Pair<ContentNode, ContentNode>
get() = (signature as ContentGroup).splitSignatureIntoModifiersAndName()
@@ -340,7 +322,6 @@ class TreeViewPage(
listOf(psi to l) + l.flatMap { gatherPsiClasses(it) }
}
-
val psiInheritanceTree = documentables.flatMap { (_, v) -> (v as? WithExpectActual)?.sources?.values.orEmpty() }
.filterIsInstance<PsiDocumentableSource>().mapNotNull { it.psi as? PsiClass }.flatMap(::gatherPsiClasses)
.flatMap { entry -> entry.second.map { it to entry.first } }
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
index 5f628626..7d6f37c0 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToHtmlTranslator.kt
@@ -1,41 +1,31 @@
package javadoc.renderer
import javadoc.pages.TextNode
-import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.base.resolvers.local.LocationProvider
-import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
-import java.nio.file.Path
-import java.nio.file.Paths
internal class JavadocContentToHtmlTranslator(
private val locationProvider: LocationProvider,
private val context: DokkaContext
) {
- fun <T> htmlForContentNode(node: ContentNode, relative: T?, locate: ContentDRILink.(T?) -> String): String =
+ fun htmlForContentNode(node: ContentNode, relative: PageNode?): String =
when (node) {
- is ContentGroup -> htmlForContentNodes(node.children, relative, locate)
+ is ContentGroup -> htmlForContentNodes(node.children, relative)
is ContentText -> node.text
is TextNode -> node.text
is ContentDRILink -> buildLink(
- node.locate(relative),
- htmlForContentNodes(node.children, relative, locate)
+ locationProvider.resolve(node.address, node.sourceSets, relative),
+ htmlForContentNodes(node.children, relative)
)
- is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, relative, locate))
+ is ContentResolvedLink -> buildLink(node.address, htmlForContentNodes(node.children, relative))
is ContentCode -> htmlForCode(node.children)
else -> ""
}
- fun <T> htmlForContentNodes(list: List<ContentNode>, relative: T?, locate: ContentDRILink.(T?) -> String) =
- list.joinToString(separator = "") { htmlForContentNode(it, relative, locate) }
-
- private fun locate(link: ContentDRILink, relativePath: String?) =
- resolveLink(link.address, link.sourceSets, relativePath)
-
- fun htmlForContentNodes(list: List<ContentNode>, relative: String?) =
- htmlForContentNodes(list, relative, ::locate)
+ fun htmlForContentNodes(list: List<ContentNode>, relative: PageNode?) =
+ list.joinToString(separator = "") { htmlForContentNode(it, relative) }
private fun htmlForCode(code: List<ContentNode>): String = code.map { element ->
when (element) {
@@ -45,16 +35,6 @@ internal class JavadocContentToHtmlTranslator(
}
}.joinToString("<br>", """<span class="code">""", "</span>") { it }
- private fun resolveLink(address: DRI, sourceSets: Set<DokkaConfiguration.DokkaSourceSet>, relativePath: String?) =
- locationProvider.resolve(address, sourceSets).let {
- val afterFormattingToHtml = it.formatToEndWithHtml()
- if (relativePath != null) afterFormattingToHtml.relativizePath(relativePath)
- else afterFormattingToHtml
- }
-
- private fun String.relativizePath(parent: String) =
- Paths.get(parent).relativize(Paths.get(this)).normalize().toFile().toString()
-
companion object {
fun buildLink(address: String, content: String) =
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
index 4d1ccca5..50a971ea 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/JavadocContentToTemplateMapTranslator.kt
@@ -19,6 +19,7 @@ internal class JavadocContentToTemplateMapTranslator(
mapOf<String, Any?>(
"docName" to "docName", // todo docname
"pathToRoot" to pathToRoot,
+ "contextRoot" to node,
"kind" to "main",
) + templateMapForNode(node)
@@ -27,7 +28,6 @@ internal class JavadocContentToTemplateMapTranslator(
when (node) {
is JavadocModulePageNode -> InnerTranslator(node).templateMapForJavadocContentNode(node.content)
is JavadocClasslikePageNode -> InnerTranslator(node).templateMapForClasslikeNode(node)
- is JavadocFunctionNode -> InnerTranslator(node).templateMapForFunctionNode(node)
is JavadocPackagePageNode -> InnerTranslator(node).templateMapForPackagePageNode(node)
is TreeViewPage -> InnerTranslator(node).templateMapForTreeViewPage(node)
is AllClassesPage -> InnerTranslator(node).templateMapForAllClassesPage(node)
@@ -65,19 +65,19 @@ internal class JavadocContentToTemplateMapTranslator(
internal fun templateMapForFunctionNode(node: JavadocFunctionNode): TemplateMap {
val (modifiers, signature) = node.modifiersAndSignature
return mapOf(
- "signature" to htmlForContentNode(node.signature, node),
- "brief" to htmlForContentNodes(node.brief, node),
+ "signature" to htmlForContentNode(node.signature, contextNode),
+ "brief" to htmlForContentNodes(node.brief, contextNode),
"parameters" to node.parameters.map { templateMapForParameterNode(it) },
"inlineParameters" to node.parameters.joinToString { "${it.type} ${it.name}" },
- "modifiers" to htmlForContentNode(modifiers, node),
- "signatureWithoutModifiers" to htmlForContentNode(signature, node),
+ "modifiers" to htmlForContentNode(modifiers, contextNode),
+ "signatureWithoutModifiers" to htmlForContentNode(signature, contextNode),
"name" to node.name
)
}
internal fun templateMapForClasslikeNode(node: JavadocClasslikePageNode): TemplateMap =
mapOf(
- "constructors" to node.constructors.map { templateMapForNode(it) },
+ "constructors" to node.constructors.map { templateMapForFunctionNode(it) },
"signature" to htmlForContentNode(node.signature, node),
"methods" to templateMapForClasslikeMethods(node.methods),
"classlikeDocumentation" to htmlForContentNodes(node.description, node),
@@ -113,12 +113,12 @@ internal class JavadocContentToTemplateMapTranslator(
private fun templateMapForClasslikeMethods(nodes: List<JavadocFunctionNode>): TemplateMap {
val (inherited, own) = nodes.partition {
val extra = it.extras[InheritedFunction]
- extra?.inheritedFrom?.keys?.first { it.analysisPlatform == Platform.jvm }?.let { jvm ->
+ extra?.inheritedFrom?.keys?.firstOrNull { it.analysisPlatform == Platform.jvm }?.let { jvm ->
extra.isInherited(jvm)
} ?: false
}
return mapOf(
- "own" to own.map { templateMapForNode(it) },
+ "own" to own.map { templateMapForFunctionNode(it) },
"inherited" to inherited.map { templateMapForInheritedMethod(it) }
.groupBy { it["inheritedFrom"] as String }.entries.map {
mapOf(
@@ -188,14 +188,12 @@ internal class JavadocContentToTemplateMapTranslator(
"list" to node.children
)
}
- fun locate(link: ContentDRILink, relativeNode: PageNode?) =
- locationProvider.resolve(link.address, link.sourceSets, relativeNode)
private fun htmlForContentNode(node: ContentNode, relativeNode: PageNode) =
- htmlTranslator.htmlForContentNode(node, relativeNode, ::locate)
+ htmlTranslator.htmlForContentNode(node, relativeNode)
private fun htmlForContentNodes(nodes: List<ContentNode>, relativeNode: PageNode) =
- htmlTranslator.htmlForContentNodes(nodes, relativeNode, ::locate)
+ htmlTranslator.htmlForContentNodes(nodes, relativeNode)
}
private fun DRI.displayable(): String = "${packageName}.${sureClassNames}"
diff --git a/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt b/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt
index 7b122b7d..a7d18100 100644
--- a/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt
+++ b/plugins/javadoc/src/main/kotlin/javadoc/renderer/KorteJavadocRenderer.kt
@@ -1,7 +1,7 @@
package javadoc.renderer
import com.soywiz.korte.*
-import javadoc.JavadocLocationProvider
+import javadoc.location.JavadocLocationProvider
import javadoc.pages.*
import javadoc.renderer.JavadocContentToHtmlTranslator.Companion.buildLink
import kotlinx.coroutines.CoroutineScope
@@ -9,9 +9,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.jetbrains.dokka.base.renderers.OutputWriter
+import org.jetbrains.dokka.javadoc.JavadocPlugin
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.renderers.Renderer
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.nio.file.Path
@@ -20,14 +23,22 @@ import java.time.LocalDate
typealias TemplateMap = Map<String, Any?>
-class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaContext, val resourceDir: String) :
+class KorteJavadocRenderer(private val outputWriter: OutputWriter, val context: DokkaContext, resourceDir: String) :
Renderer {
private lateinit var locationProvider: JavadocLocationProvider
- override fun render(root: RootPageNode) = root.let { preprocessors.fold(root) { r, t -> t.invoke(r) } }.let { r ->
- locationProvider = JavadocLocationProvider(r, context)
+ private val contentToHtmlTranslator by lazy {
+ JavadocContentToHtmlTranslator(locationProvider, context)
+ }
+
+ private val contentToTemplateMapTranslator by lazy {
+ JavadocContentToTemplateMapTranslator(locationProvider, context)
+ }
+
+ override fun render(root: RootPageNode) = root.let { preprocessors.fold(root) { r, t -> t.invoke(r) } }.let { newRoot ->
+ locationProvider = context.plugin<JavadocPlugin>().querySingle { locationProviderFactory }.getLocationProvider(newRoot)
runBlocking(Dispatchers.IO) {
- renderModulePageNode(r as JavadocModulePageNode)
+ renderModulePageNode(newRoot as JavadocModulePageNode)
}
}
@@ -53,7 +64,7 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
val name = "index"
val pathToRoot = ""
- val contentMap = JavadocContentToTemplateMapTranslator(locationProvider, context).templateMapForPageNode(node, pathToRoot)
+ val contentMap = contentToTemplateMapTranslator.templateMapForPageNode(node, pathToRoot)
writeFromTemplate(outputWriter, "$link/$name".toNormalized(), "tabPage.korte", contentMap.toList())
node.children.forEach { renderNode(it, link) }
@@ -66,12 +77,12 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
if (it.isNotEmpty()) "$it/" else it
}
- val contentMap = JavadocContentToTemplateMapTranslator(locationProvider, context).templateMapForPageNode(node, pathToRoot)
+ val contentMap = contentToTemplateMapTranslator.templateMapForPageNode(node, pathToRoot)
writeFromTemplate(outputWriter, link, templateForNode(node), contentMap.toList())
node.children.forEach { renderNode(it, link.toNormalized()) }
}
- fun CoroutineScope.renderSpecificPage(node: RendererSpecificPage, path: String) = launch {
+ private fun CoroutineScope.renderSpecificPage(node: RendererSpecificPage, path: String) = launch {
when (val strategy = node.strategy) {
is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, "")
is RenderingStrategy.Write -> outputWriter.writeHtml(path, strategy.text)
@@ -83,10 +94,10 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
}
}
- fun Pair<String, String>.pairToTag() =
- """<th class="colFirst" scope="row">${first}</th>\n<td class="colLast">${second}</td>"""
+ private fun Pair<String, String>.pairToTag() =
+ """<th class="colFirst" scope="row">${first}</th><td class="colLast">${second}</td>"""
- fun DRI.toLink(context: PageNode? = null) = locationProvider.resolve(this, emptySet(), context)
+ private fun DRI.toLink(context: PageNode? = null) = locationProvider.resolve(this, emptySet(), context)
private fun Path.toNormalized() = this.normalize().toFile().toString()
private fun String.toNormalized() = Paths.get(this).toNormalized()
@@ -102,7 +113,7 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
writer.writeHtml(path, tmp)
}
- fun getTemplateConfig() = TemplateConfig().also { config ->
+ private fun getTemplateConfig() = TemplateConfig().also { config ->
listOf(
TeFunction("curDate") { LocalDate.now() },
TeFunction("jQueryVersion") { "3.1" },
@@ -111,18 +122,17 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
TeFunction("h1Title") { args -> if ((args.first() as? String) == "package") "title=\"Package\" " else "" },
TeFunction("createTabRow") { args ->
val (link, doc) = args.first() as RowJavadocListEntry
- val dir = args[1] as String?
- val translator = JavadocContentToHtmlTranslator(locationProvider, context)
+ val contextRoot = args[1] as PageNode?
(buildLink(
- locationProvider.resolve(link, dir.orEmpty()),
+ locationProvider.resolve(link, contextRoot),
link.name
- ) to translator.htmlForContentNodes(doc, dir)).pairToTag().trim()
+ ) to contentToHtmlTranslator.htmlForContentNodes(doc, contextRoot)).pairToTag().trim()
},
TeFunction("createListRow") { args ->
val link = args.first() as LinkJavadocListEntry
- val dir = args[1] as String?
+ val contextRoot = args[1] as PageNode?
buildLink(
- locationProvider.resolve(link, dir.orEmpty()),
+ locationProvider.resolve(link, contextRoot),
link.name
)
},
@@ -171,13 +181,14 @@ class KorteJavadocRenderer(val outputWriter: OutputWriter, val context: DokkaCon
}
}
- val config = getTemplateConfig()
- val templateRenderer = Templates(
+ private val config = getTemplateConfig()
+ private val templateRenderer = Templates(
ResourceTemplateProvider(
resourceDir
- ), config = config, cache = true)
+ ), config = config, cache = true
+ )
- class ResourceTemplateProvider(val basePath: String) : TemplateProvider {
+ private class ResourceTemplateProvider(val basePath: String) : TemplateProvider {
override suspend fun get(template: String): String =
javaClass.classLoader.getResourceAsStream("$basePath/$template")?.bufferedReader()?.lines()?.toArray()
?.joinToString("\n") ?: throw IllegalStateException("Template not found: $basePath/$template")
diff --git a/plugins/javadoc/src/main/resources/views/components/indexTable.korte b/plugins/javadoc/src/main/resources/views/components/indexTable.korte
index 8595a728..9ee387e1 100644
--- a/plugins/javadoc/src/main/resources/views/components/indexTable.korte
+++ b/plugins/javadoc/src/main/resources/views/components/indexTable.korte
@@ -6,7 +6,7 @@
</tr>
<tbody>
{% for item in list %}
- <tr class="{{ rowColor(loop.index0) }}">{{ createTabRow(item, dir)|raw }}</tr>
+ <tr class="{{ rowColor(loop.index0) }}">{{ createTabRow(item, contextRoot)|raw }}</tr>
{% end -%}
</tbody>
</table> \ No newline at end of file
diff --git a/plugins/javadoc/src/main/resources/views/listPage.korte b/plugins/javadoc/src/main/resources/views/listPage.korte
index 981ceeb9..985f1d4d 100644
--- a/plugins/javadoc/src/main/resources/views/listPage.korte
+++ b/plugins/javadoc/src/main/resources/views/listPage.korte
@@ -5,7 +5,7 @@
<main role="main" class="indexContainer">
<ul>
{% for item in list %}
- <li>{{ createListRow(item, dir)|raw }}</li>
+ <li>{{ createListRow(item, contextRoot)|raw }}</li>
{% end -%}
</ul>
</main>
diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
index c6fcb9b0..ca817219 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
@@ -117,16 +117,20 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge
val returnType = f.type
signatureForProjection(returnType)
text(nbsp.toString())
- link(f.name, f.dri)
- list(f.generics, prefix = "<", suffix = ">") {
- +buildSignature(it)
- }
- list(f.parameters, "(", ")") {
- annotationsInline(it)
- text(it.modifiers()[it]?.toSignatureString() ?: "")
- signatureForProjection(it.type)
- text(nbsp.toString())
- link(it.name!!, it.dri)
+ group {
+ link(f.name, f.dri)
+ list(f.generics, prefix = "<", suffix = ">") {
+ +buildSignature(it)
+ }
+ text("(")
+ list(f.parameters) {
+ annotationsInline(it)
+ text(it.modifiers()[it]?.toSignatureString() ?: "")
+ signatureForProjection(it.type)
+ text(nbsp.toString())
+ link(it.name!!, it.dri)
+ }
+ text(")")
}
}