aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrzej Ratajczak <andrzej.ratajczak98@gmail.com>2020-03-13 10:46:33 +0100
committerBłażej Kardyś <bkardys@virtuslab.com>2020-03-23 13:57:07 +0100
commitc09bde34ff729ef9b1f3bea602fb53cd4e6dca42 (patch)
tree3a744a16c133b813ab1849761aef1ec3544f401f
parentcedf8b7594deef2cd26e981865daa8aae0155520 (diff)
downloaddokka-c09bde34ff729ef9b1f3bea602fb53cd4e6dca42.tar.gz
dokka-c09bde34ff729ef9b1f3bea602fb53cd4e6dca42.tar.bz2
dokka-c09bde34ff729ef9b1f3bea602fb53cd4e6dca42.zip
Gradle Task supporting multimodular projects
-rw-r--r--core/src/main/kotlin/DokkaBootstrapImpl.kt32
-rw-r--r--core/src/main/kotlin/defaultConfiguration.kt2
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt15
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt2
-rw-r--r--plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt116
-rw-r--r--plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt99
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt35
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt23
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt37
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt222
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt (renamed from plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt)5
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt (renamed from plugins/base/src/main/kotlin/resolvers/LocationProvider.kt)3
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt12
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt1
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt7
-rw-r--r--plugins/base/src/test/kotlin/renderers/RenderingOnlyTestBase.kt12
-rw-r--r--plugins/gfm/build.gradle.kts8
-rw-r--r--plugins/gfm/src/main/kotlin/GfmPlugin.kt196
-rw-r--r--plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
-rw-r--r--plugins/jekyll/build.gradle.kts8
-rw-r--r--plugins/jekyll/src/main/kotlin/JekyllPlugin.kt182
-rw-r--r--plugins/jekyll/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt16
-rw-r--r--runners/gradle-plugin/build.gradle.kts1
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt56
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt37
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt36
-rw-r--r--runners/maven-plugin/src/main/kotlin/DokkaMojo.kt9
-rw-r--r--testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt6
29 files changed, 898 insertions, 282 deletions
diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt
index fc1b6926..f164a3c1 100644
--- a/core/src/main/kotlin/DokkaBootstrapImpl.kt
+++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt
@@ -20,7 +20,13 @@ fun parsePerPackageOptions(arg: String): List<PackageOptions> {
val reportUndocumented = args.find { it.endsWith("warnUndocumented") }?.startsWith("+") ?: true
val privateApi = args.find { it.endsWith("privateApi") }?.startsWith("+") ?: false
val suppress = args.find { it.endsWith("suppress") }?.startsWith("+") ?: false
- PackageOptionsImpl(prefix, includeNonPublic = privateApi, reportUndocumented = reportUndocumented, skipDeprecated = !deprecated, suppress = suppress)
+ PackageOptionsImpl(
+ prefix,
+ includeNonPublic = privateApi,
+ reportUndocumented = reportUndocumented,
+ skipDeprecated = !deprecated,
+ suppress = suppress
+ )
}
}
@@ -52,10 +58,11 @@ class DokkaBootstrapImpl : DokkaBootstrap {
override fun report() {
if (warningsCount > 0 || errorsCount > 0) {
- println("Generation completed with $warningsCount warning" +
- (if(DokkaConsoleLogger.warningsCount == 1) "" else "s") +
- " and $errorsCount error" +
- if(DokkaConsoleLogger.errorsCount == 1) "" else "s"
+ println(
+ "Generation completed with $warningsCount warning" +
+ (if (DokkaConsoleLogger.warningsCount == 1) "" else "s") +
+ " and $errorsCount error" +
+ if (DokkaConsoleLogger.errorsCount == 1) "" else "s"
)
} else {
println("generation completed successfully")
@@ -83,10 +90,11 @@ class DokkaBootstrapImpl : DokkaBootstrap {
}
val configurationWithLinks =
- configuration.copy(passesConfigurations =
- passesConfigurations
- .map {
- val links: List<ExternalDocumentationLinkImpl> = it.externalDocumentationLinks + defaultLinks(it)
+ configuration.copy(
+ passesConfigurations =
+ passesConfigurations.map {
+ val links: List<ExternalDocumentationLinkImpl> =
+ it.externalDocumentationLinks + defaultLinks(it)
it.copy(externalDocumentationLinks = links)
}
)
@@ -94,8 +102,10 @@ class DokkaBootstrapImpl : DokkaBootstrap {
generator = DokkaGenerator(configurationWithLinks, logger)
}
- override fun configure(logger: BiConsumer<String, String>, serializedConfigurationJSON: String)
- = configure(DokkaProxyLogger(logger), gson.fromJson(serializedConfigurationJSON, DokkaConfigurationImpl::class.java))
+ override fun configure(logger: BiConsumer<String, String>, serializedConfigurationJSON: String) = configure(
+ DokkaProxyLogger(logger),
+ gson.fromJson(serializedConfigurationJSON, DokkaConfigurationImpl::class.java)
+ )
override fun generate() = generator.generate()
}
diff --git a/core/src/main/kotlin/defaultConfiguration.kt b/core/src/main/kotlin/defaultConfiguration.kt
index 148bf830..b0c12015 100644
--- a/core/src/main/kotlin/defaultConfiguration.kt
+++ b/core/src/main/kotlin/defaultConfiguration.kt
@@ -10,7 +10,7 @@ data class DokkaConfigurationImpl(
override val cacheRoot: String?,
override val impliedPlatforms: List<String>,
override val passesConfigurations: List<PassConfigurationImpl>,
- override val pluginsClasspath: List<File>
+ override var pluginsClasspath: List<File>
) : DokkaConfiguration
data class PassConfigurationImpl (
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
index 448373ea..548bcb93 100644
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ b/plugins/base/src/main/kotlin/DokkaBase.kt
@@ -4,10 +4,12 @@ import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.base.renderers.FileWriter
import org.jetbrains.dokka.base.renderers.OutputWriter
import org.jetbrains.dokka.base.renderers.html.*
-import org.jetbrains.dokka.base.resolvers.DefaultLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.LocationProviderFactory
+import org.jetbrains.dokka.base.renderers.html.HtmlRenderer
import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
import org.jetbrains.dokka.base.signatures.SignatureProvider
+import org.jetbrains.dokka.base.resolvers.external.*
+import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory
import org.jetbrains.dokka.base.transformers.documentables.DefaultDocumentableMerger
import org.jetbrains.dokka.base.transformers.documentables.InheritorsExtractorTransformer
import org.jetbrains.dokka.base.transformers.pages.annotations.DeprecatedStrikethroughTransformer
@@ -29,6 +31,7 @@ class DokkaBase : DokkaPlugin() {
val commentsToContentConverter by extensionPoint<CommentsToContentConverter>()
val signatureProvider by extensionPoint<SignatureProvider>()
val locationProviderFactory by extensionPoint<LocationProviderFactory>()
+ val externalLocationProviderFactory by extensionPoint<ExternalLocationProviderFactory>()
val outputWriter by extensionPoint<OutputWriter>()
val htmlPreprocessors by extensionPoint<PageTransformer>()
@@ -98,6 +101,14 @@ class DokkaBase : DokkaPlugin() {
locationProviderFactory providing ::DefaultLocationProviderFactory
}
+ val javadocLocationProvider by extending {
+ externalLocationProviderFactory with JavadocExternalLocationProviderFactory()
+ }
+
+ val dokkaLocationProvider by extending {
+ externalLocationProviderFactory with DokkaExternalLocationProviderFactory()
+ }
+
val fileWriter by extending(isFallback = true) {
outputWriter providing ::FileWriter
}
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
index 0e0001b9..0ff0511a 100644
--- a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -1,7 +1,7 @@
package org.jetbrains.dokka.base.renderers
import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.resolvers.LocationProvider
+import org.jetbrains.dokka.base.resolvers.local.LocationProvider
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
diff --git a/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt
deleted file mode 100644
index 2238b0c3..00000000
--- a/plugins/base/src/main/kotlin/resolvers/DefaultLocationProvider.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-package org.jetbrains.dokka.base.resolvers
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.utilities.htmlEscape
-import java.util.*
-
-private const val PAGE_WITH_CHILDREN_SUFFIX = "index"
-
-open class DefaultLocationProvider(
- protected val pageGraphRoot: RootPageNode,
- protected val dokkaContext: DokkaContext
-) : LocationProvider {
- protected val extension = ".html"
-
- protected val pagesIndex: Map<DRI, ContentPage> = pageGraphRoot.asSequence().filterIsInstance<ContentPage>()
- .map { it.dri.map { dri -> dri to it } }.flatten()
- .groupingBy { it.first }
- .aggregate { dri, _, (_, page), first ->
- if (first) page else throw AssertionError("Multiple pages associated with dri: $dri")
- }
-
- protected val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
- fun registerPath(page: PageNode, prefix: List<String>) {
- val newPrefix = prefix + page.pathName
- put(page, newPrefix)
- page.children.forEach { registerPath(it, newPrefix) }
- }
- put(pageGraphRoot, emptyList())
- pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
- }
-
- override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
- pathTo(node, context) + if (!skipExtension) extension else ""
-
- override fun resolve(dri: DRI, platforms: List<PlatformData>, context: PageNode?): String =
- pagesIndex[dri]?.let { resolve(it, context) } ?:
- // Not found in PageGraph, that means it's an external link
- ExternalLocationProvider.getLocation(dri,
- this.dokkaContext.configuration.passesConfigurations
- .filter { passConfig ->
- platforms.toSet()
- .contains(PlatformData(passConfig.moduleName, passConfig.analysisPlatform, passConfig.targets))
- } // TODO: change targets to something better?
- .flatMap { it.externalDocumentationLinks }.distinct()
- )
-
- override fun resolveRoot(node: PageNode): String =
- pathTo(pageGraphRoot, node).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
-
- override fun ancestors(node: PageNode): List<PageNode> =
- generateSequence(node) { it.parent() }.toList()
-
- protected open fun pathTo(node: PageNode, context: PageNode?): String {
- fun pathFor(page: PageNode) = pathsIndex[page] ?: throw AssertionError(
- "${page::class.simpleName}(${page.name}) does not belong to current page graph so it is impossible to compute its path"
- )
-
- val contextNode =
- if (context?.children?.isEmpty() == true && context.parent() != null) context.parent() else context
- val nodePath = pathFor(node)
- val contextPath = contextNode?.let { pathFor(it) }.orEmpty()
-
- val commonPathElements = nodePath.asSequence().zip(contextPath.asSequence())
- .takeWhile { (a, b) -> a == b }.count()
-
- return (List(contextPath.size - commonPathElements) { ".." } + nodePath.drop(commonPathElements) +
- if (node.children.isNotEmpty()) listOf(PAGE_WITH_CHILDREN_SUFFIX) else emptyList()).joinToString("/")
- }
-
- private fun PageNode.parent() = pageGraphRoot.parentMap[this]
-}
-
-fun DRI.toJavadocLocation(jdkVersion: Int): String { // TODO: classes without packages?
- val packageLink = packageName?.replace(".", "/")
- if (classNames == null) {
- return "$packageLink/package-summary.html".htmlEscape()
- }
- val classLink = if (packageLink == null) "$classNames.html" else "$packageLink/$classNames.html"
- val callableChecked = callable ?: return classLink.htmlEscape()
-
- val callableLink = "$classLink#${callableChecked.name}" + when {
- jdkVersion < 8 -> "(${callableChecked.params.joinToString(", ")})"
- jdkVersion < 10 -> "-${callableChecked.params.joinToString("-")}-"
- else -> "(${callableChecked.params.joinToString(",")})"
- }
-
- return callableLink.htmlEscape()
-}
-
-fun DRI.toDokkaLocation(extension: String): String { // TODO: classes without packages?
- val classNamesChecked = classNames ?: return "$packageName/index$extension"
-
- val classLink = if (packageName == null) {
- ""
- } else {
- "$packageName/"
- } + classNamesChecked.split('.').joinToString("/", transform = ::identifierToFilename)
-
- val callableChecked = callable ?: return "$classLink/index$extension"
-
- return "$classLink/${identifierToFilename(callableChecked.name)}$extension"
-}
-
-private val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out")
-
-private fun identifierToFilename(name: String): String {
- if (name.isEmpty()) return "--root--"
- val escaped = name.replace('<', '-').replace('>', '-')
- val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }
- return if (lowercase in reservedFilenames) "--$lowercase--" else lowercase
-}
-
-private val PageNode.pathName: String
- get() = if (this is PackagePageNode) name else identifierToFilename(name)
diff --git a/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt
deleted file mode 100644
index 7c0e9952..00000000
--- a/plugins/base/src/main/kotlin/resolvers/ExternalLocationProvider.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.jetbrains.dokka.base.resolvers
-
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
-import org.jetbrains.dokka.links.DRI
-import java.net.HttpURLConnection
-import java.net.URL
-import java.net.URLConnection
-
-object ExternalLocationProvider { // TODO: Refactor this!!!
- private const val DOKKA_PARAM_PREFIX = "\$dokka."
-
- private val cache: MutableMap<URL, LocationInfo> = mutableMapOf()
-
- fun getLocation(dri: DRI, externalDocumentationLinks: List<ExternalDocumentationLink>): String {
- val toResolve: MutableList<ExternalDocumentationLink> = mutableListOf()
- for(link in externalDocumentationLinks){
- val info = cache[link.packageListUrl]
- if(info == null) {
- toResolve.add(link)
- } else if(info.packages.contains(dri.packageName)) {
- return link.url.toExternalForm() + getLink(dri, info)
- }
- }
- // Not in cache, resolve packageLists
- while (toResolve.isNotEmpty()){
- val link = toResolve.first().also { toResolve.remove(it) }
- val locationInfo = loadPackageList(link.packageListUrl)
- if(locationInfo.packages.contains(dri.packageName)) {
- return link.url.toExternalForm() + getLink(dri, locationInfo)
- }
- }
- return ""
- }
-
- private fun getLink(dri: DRI, locationInfo: LocationInfo): String = when(locationInfo.format) {
- "javadoc" -> dri.toJavadocLocation(8)
- "kotlin-website-html", "html" -> locationInfo.locations[dri.packageName + "." + dri.classNames] ?: dri.toDokkaLocation(".html")
- "markdown" -> locationInfo.locations[dri.packageName + "." + dri.classNames] ?: dri.toDokkaLocation(".md")
- // TODO: rework this
- else -> throw RuntimeException("Unrecognized format")
- }
-
-
- private fun loadPackageList(url: URL): 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() ?: "javadoc"
-
- val locations = paramsMap["location"].orEmpty()
- .map { it.split("\u001f", limit = 2) }
- .map { (key, value) -> key to value }
- .toMap()
-
- val info = LocationInfo(format, 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
- }
- }
- data class LocationInfo(val format: String, val packages: Set<String>, val locations: Map<String, String>)
-
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..ff9186f7
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/DokkaExternalLocationProviderFactory.kt
@@ -0,0 +1,35 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.base.resolvers.local.identifierToFilename
+import org.jetbrains.dokka.links.DRI
+
+
+class DokkaExternalLocationProviderFactory : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
+ object : ExternalLocationProviderFactory {
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ when (param) {
+ "kotlin-website-html", "html" -> DokkaExternalLocationProvider(param, ".html")
+ "markdown" -> DokkaExternalLocationProvider(param, ".md")
+ else -> null
+ }
+ }
+)
+
+class DokkaExternalLocationProvider(override val param: String, val extension: String) : ExternalLocationProvider {
+
+ override fun DRI.toLocation(): String { // TODO: classes without packages?
+
+ val classNamesChecked = classNames ?: return "${packageName ?: ""}/index$extension"
+
+ val classLink = (listOfNotNull(packageName) + classNamesChecked.split('.')).joinToString(
+ "/",
+ transform = ::identifierToFilename
+ )
+
+ val callableChecked = callable ?: return "$classLink/index$extension"
+
+ return "$classLink/${identifierToFilename(
+ callableChecked.name
+ )}$extension"
+ }
+}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..6fb05024
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
@@ -0,0 +1,23 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.links.DRI
+
+
+interface ExternalLocationProvider {
+
+ val param: String
+ fun DRI.toLocation(): String
+}
+
+interface ExternalLocationProviderFactory {
+
+ fun getExternalLocationProvider(param: String): ExternalLocationProvider?
+}
+
+class ExternalLocationProviderFactoryWithCache(val ext: ExternalLocationProviderFactory) : ExternalLocationProviderFactory {
+
+ private val locationProviders: MutableList<ExternalLocationProvider> = mutableListOf()
+
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ locationProviders.find { it.param == param } ?: ext.getExternalLocationProvider(param)?.also { locationProviders.add(it) }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt
new file mode 100644
index 00000000..c52c9bbb
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/external/JavadocExternalLocationProviderFactory.kt
@@ -0,0 +1,37 @@
+package org.jetbrains.dokka.base.resolvers.external
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.utilities.htmlEscape
+
+class JavadocExternalLocationProviderFactory : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
+ object : ExternalLocationProviderFactory {
+ override fun getExternalLocationProvider(param: String): ExternalLocationProvider? =
+ when(param) {
+ "javadoc1" -> JavadocExternalLocationProvider(param, "()", ", ") // Covers JDK 1 - 7
+ "javadoc8" -> JavadocExternalLocationProvider(param, "--", "-") // Covers JDK 8 - 9
+ "javadoc10" -> JavadocExternalLocationProvider(param, "()", ",") // Covers JDK 10
+ else -> null
+ }
+ }
+)
+
+class JavadocExternalLocationProvider(override val param: String, val brackets: String, val separator: String) : ExternalLocationProvider {
+
+ override fun DRI.toLocation(): String {
+
+ val packageLink = packageName?.replace(".", "/")
+ if (classNames == null) {
+ return "$packageLink/package-summary.html".htmlEscape()
+ }
+ val classLink = if (packageLink == null) "$classNames.html" else "$packageLink/$classNames.html"
+ val callableChecked = callable ?: return classLink.htmlEscape()
+
+ val callableLink = "$classLink#" +
+ callableChecked.name +
+ "${brackets.first()}" +
+ callableChecked.params.joinToString(separator) +
+ "${brackets.last()}"
+
+ return callableLink.htmlEscape()
+ }
+} \ 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
new file mode 100644
index 00000000..736367a9
--- /dev/null
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
@@ -0,0 +1,222 @@
+package org.jetbrains.dokka.base.resolvers.local
+
+import org.jetbrains.dokka.DokkaConfiguration
+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.lang.IllegalStateException
+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 {
+ protected 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 }
+ .aggregate { dri, _, (_, page), first ->
+ if (first) page else throw AssertionError("Multiple pages associated with dri: $dri")
+ }
+
+ protected val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
+ fun registerPath(page: PageNode, prefix: List<String>) {
+ val newPrefix = prefix + page.pathName
+ put(page, newPrefix)
+ page.children.forEach { registerPath(it, newPrefix) }
+ }
+ put(pageGraphRoot, emptyList())
+ pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
+ }
+
+ override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
+ pathTo(node, context) + if (!skipExtension) extension else ""
+
+ override fun resolve(dri: DRI, platforms: List<PlatformData>, context: PageNode?): String =
+ pagesIndex[dri]?.let { resolve(it, context) } ?:
+ // Not found in PageGraph, that means it's an external link
+ getLocation(dri,
+ this.dokkaContext.configuration.passesConfigurations
+ .filter { passConfig ->
+ platforms.toSet()
+ .contains(PlatformData(passConfig.moduleName, passConfig.analysisPlatform, passConfig.targets))
+ } // TODO: change targets to something better?
+ .groupBy({ it.jdkVersion }, { it.externalDocumentationLinks })
+ .map { it.key to it.value.flatten().distinct() }.toMap()
+ )
+
+ override fun resolveRoot(node: PageNode): String =
+ pathTo(pageGraphRoot, node).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
+
+ override fun ancestors(node: PageNode): List<PageNode> =
+ generateSequence(node) { it.parent() }.toList()
+
+ protected open fun pathTo(node: PageNode, context: PageNode?): String {
+ fun pathFor(page: PageNode) = pathsIndex[page] ?: throw AssertionError(
+ "${page::class.simpleName}(${page.name}) does not belong to current page graph so it is impossible to compute its path"
+ )
+
+ val contextNode =
+ if (context?.children?.isEmpty() == true && context.parent() != null) context.parent() else context
+ val nodePath = pathFor(node)
+ val contextPath = contextNode?.let { pathFor(it) }.orEmpty()
+
+ val commonPathElements = nodePath.asSequence().zip(contextPath.asSequence())
+ .takeWhile { (a, b) -> a == b }.count()
+
+ return (List(contextPath.size - commonPathElements) { ".." } + nodePath.drop(commonPathElements) +
+ if (node.children.isNotEmpty()) listOf(PAGE_WITH_CHILDREN_SUFFIX) else emptyList()).joinToString("/")
+ }
+
+ private fun PageNode.parent() = pageGraphRoot.parentMap[this]
+
+ private val cache: MutableMap<URL, LocationInfo> = mutableMapOf()
+
+ private fun getLocation(
+ dri: DRI,
+ jdkToExternalDocumentationLinks: Map<Int, List<DokkaConfiguration.ExternalDocumentationLink>>
+ ): String {
+ 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) {
+ val locationInfo =
+ loadPackageList(
+ jdk,
+ link.packageListUrl
+ )
+ if (locationInfo.packages.contains(dri.packageName)) {
+ return link.url.toExternalForm() + getLink(
+ dri,
+ locationInfo
+ )
+ }
+ }
+ toResolve.remove(jdk)
+ }
+ return ""
+ }
+
+ private fun getLink(dri: DRI, locationInfo: 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): 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 = 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
+ }
+ }
+
+ data class LocationInfo(
+ val externalLocationProvider: ExternalLocationProvider?,
+ val packages: Set<String>,
+ val locations: Map<String, String>
+ )
+}
+
+private val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out")
+
+internal fun identifierToFilename(name: String): String {
+ if (name.isEmpty()) return "--root--"
+ val escaped = name.replace("<|>".toRegex(), "-")
+ val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }
+ return if (lowercase in reservedFilenames) "--$lowercase--" else lowercase
+}
+
+private val PageNode.pathName: String
+ get() = if (this is PackagePageNode) name else identifierToFilename(
+ name
+ )
diff --git a/plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt
index c649e22b..57f53ba6 100644
--- a/plugins/base/src/main/kotlin/resolvers/DefaultLocationProviderFactory.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProviderFactory.kt
@@ -1,9 +1,10 @@
-package org.jetbrains.dokka.base.resolvers
+package org.jetbrains.dokka.base.resolvers.local
import org.jetbrains.dokka.pages.RootPageNode
import org.jetbrains.dokka.plugability.DokkaContext
class DefaultLocationProviderFactory(private val context: DokkaContext) : LocationProviderFactory {
- override fun getLocationProvider(pageNode: RootPageNode) = DefaultLocationProvider(pageNode, context)
+ override fun getLocationProvider(pageNode: RootPageNode) =
+ DefaultLocationProvider(pageNode, context)
} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/resolvers/LocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
index 13f4563c..0814cb3e 100644
--- a/plugins/base/src/main/kotlin/resolvers/LocationProvider.kt
+++ b/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
@@ -1,7 +1,6 @@
-package org.jetbrains.dokka.base.resolvers
+package org.jetbrains.dokka.base.resolvers.local
import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.ContentPage
import org.jetbrains.dokka.pages.PageNode
import org.jetbrains.dokka.pages.PlatformData
import org.jetbrains.dokka.pages.RootPageNode
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
index bb7dbaaf..48be8ae7 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt
@@ -12,17 +12,17 @@ import org.jetbrains.dokka.transformers.documentation.DocumentableMerger
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
internal object DefaultDocumentableMerger : DocumentableMerger {
+
override fun invoke(modules: Collection<DModule>, context: DokkaContext): DModule {
- val name = modules.map { it.name }.distinct().singleOrNull() ?: run {
- context.logger.error("All module names need to be the same")
- modules.first().name
- }
+
+ val projectName =
+ modules.fold(modules.first().name) { acc, module -> acc.commonPrefixWith(module.name) }.takeIf { it.isNotEmpty() }
+ ?: "project"
return modules.reduce { left, right ->
val list = listOf(left, right)
-
DModule(
- name = name,
+ name = projectName,
packages = merge(
list.flatMap { it.packages },
DPackage::mergeWith
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt
index 150df302..9f86c82a 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt
@@ -15,6 +15,7 @@ internal object DocumentableVisibilityFilter : PreMergeDocumentableTransformer {
val packageOptions =
context.configuration.passesConfigurations.first { original.platformData.contains(it.platformData) }
.perPackageOptions
+
DocumentableFilter(packageOptions).processModule(original)
}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
index 885fbfee..2eb63504 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
@@ -30,14 +30,15 @@ object DocTagToContentConverter : CommentsToContentConverter {
)
)
- fun buildList(ordered: Boolean) =
+ fun buildList(ordered: Boolean, start: Int = 1) =
listOf(
ContentList(
buildChildren(docTag),
ordered,
dci,
platforms,
- styles
+ styles,
+ ((PropertyContainer.empty<ContentNode>()) + SimpleAttr("start", start.toString()))
)
)
@@ -53,7 +54,7 @@ object DocTagToContentConverter : CommentsToContentConverter {
is H5 -> buildHeader(5)
is H6 -> buildHeader(6)
is Ul -> buildList(false)
- is Ol -> buildList(true)
+ is Ol -> buildList(true, docTag.params["start"]?.toInt() ?: 1)
is Li -> buildChildren(docTag)
is Br -> buildNewLine()
is B -> buildChildren(docTag, setOf(TextStyle.Strong))
diff --git a/plugins/base/src/test/kotlin/renderers/RenderingOnlyTestBase.kt b/plugins/base/src/test/kotlin/renderers/RenderingOnlyTestBase.kt
index f77ec086..852ac735 100644
--- a/plugins/base/src/test/kotlin/renderers/RenderingOnlyTestBase.kt
+++ b/plugins/base/src/test/kotlin/renderers/RenderingOnlyTestBase.kt
@@ -2,9 +2,11 @@ package renderers
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.renderers.html.RootCreator
-import org.jetbrains.dokka.base.resolvers.DefaultLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.LocationProvider
-import org.jetbrains.dokka.base.resolvers.LocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.external.DokkaExternalLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.external.JavadocExternalLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.local.DefaultLocationProviderFactory
+import org.jetbrains.dokka.base.resolvers.local.LocationProvider
+import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory
import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
@@ -26,7 +28,9 @@ abstract class RenderingOnlyTestBase {
val context = MockContext(
DokkaBase().outputWriter to { _ -> files },
DokkaBase().locationProviderFactory to ::DefaultLocationProviderFactory,
- DokkaBase().htmlPreprocessors to { _ -> RootCreator }
+ DokkaBase().htmlPreprocessors to { _ -> RootCreator },
+ DokkaBase().externalLocationProviderFactory to { _ -> ::JavadocExternalLocationProviderFactory },
+ DokkaBase().externalLocationProviderFactory to { _ -> ::DokkaExternalLocationProviderFactory }
)
protected val renderedContent: Element by lazy {
diff --git a/plugins/gfm/build.gradle.kts b/plugins/gfm/build.gradle.kts
new file mode 100644
index 00000000..c327b96c
--- /dev/null
+++ b/plugins/gfm/build.gradle.kts
@@ -0,0 +1,8 @@
+publishing {
+ publications {
+ register<MavenPublication>("gfm-plugin") {
+ artifactId = "gfm-plugin"
+ from(components["java"])
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/gfm/src/main/kotlin/GfmPlugin.kt b/plugins/gfm/src/main/kotlin/GfmPlugin.kt
new file mode 100644
index 00000000..64a2cdfc
--- /dev/null
+++ b/plugins/gfm/src/main/kotlin/GfmPlugin.kt
@@ -0,0 +1,196 @@
+package org.jetbrains.dokka.commonmarkrenderer
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import java.lang.StringBuilder
+
+
+class CommonmarkRendererPlugin : DokkaPlugin() {
+
+ val locationProviderFactory by extensionPoint<LocationProviderFactory>()
+ val outputWriter by extensionPoint<OutputWriter>()
+
+ val renderer by extending {
+ CoreExtensions.renderer providing { CommonmarkRenderer(it.single(outputWriter), it) }
+ }
+
+ val locationProvider by extending {
+ locationProviderFactory providing { MarkdownLocationProviderFactory(it) } order {
+ before(renderer)
+ }
+ }
+}
+
+class CommonmarkRenderer(
+ outputWriter: OutputWriter,
+ context: DokkaContext
+) : DefaultRenderer<StringBuilder>(outputWriter, context) {
+ override fun StringBuilder.buildHeader(level: Int, content: StringBuilder.() -> Unit) {
+ buildParagraph()
+ append("#".repeat(level) + " ")
+ content()
+ buildNewLine()
+ }
+
+ override fun StringBuilder.buildLink(address: String, content: StringBuilder.() -> Unit) {
+ append("[")
+ content()
+ append("]($address)")
+ }
+
+ override fun StringBuilder.buildList(node: ContentList, pageContext: ContentPage, platformRestriction: PlatformData?) {
+ buildParagraph()
+ buildListLevel(node, pageContext)
+ buildParagraph()
+ }
+
+ private val indent = " ".repeat(4)
+
+ private fun StringBuilder.buildListItem(items: List<ContentNode>, pageContext: ContentPage, bullet: String = "*") {
+ items.forEach {
+ if (it is ContentList) {
+ val builder = StringBuilder()
+ builder.append(indent)
+ builder.buildListLevel(it, pageContext)
+ append(builder.toString().replace(Regex(" \n(?!$)"), " \n$indent"))
+ } else {
+ append("$bullet ")
+ it.build(this, pageContext)
+ buildNewLine()
+ }
+ }
+ }
+
+ private fun StringBuilder.buildListLevel(node: ContentList, pageContext: ContentPage) {
+ if (node.ordered) {
+ buildListItem(
+ node.children,
+ pageContext,
+ "${node.extra.allOfType<SimpleAttr>().find { it.extraKey == "start" }?.extraValue
+ ?: 1.also { context.logger.error("No starting number specified for ordered list in node ${pageContext.dri.first()}!")}}."
+ )
+ } else {
+ buildListItem(node.children, pageContext, "*")
+ }
+ }
+
+ override fun StringBuilder.buildNewLine() {
+ append(" \n")
+ }
+
+ private fun StringBuilder.buildParagraph() {
+ append("\n\n")
+ }
+
+ override fun StringBuilder.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage) {
+ append("Resource")
+ }
+
+ override fun StringBuilder.buildTable(node: ContentTable, pageContext: ContentPage, platformRestriction: PlatformData?) {
+
+ val size = node.children.firstOrNull()?.children?.size ?: 0
+ buildParagraph()
+
+ if (node.header.size > 0) {
+ node.header.forEach {
+ it.children.forEach {
+ append("| ")
+ it.build(this, pageContext)
+ }
+ append("|\n")
+ }
+ } else {
+ append("| ".repeat(size))
+ if (size > 0) append("|\n")
+ }
+
+ append("|---".repeat(size))
+ if (size > 0) append("|\n")
+
+ node.children.forEach {
+ it.children.forEach {
+ append("| ")
+ it.build(this, pageContext)
+ }
+ append("|\n")
+ }
+ }
+
+ override fun StringBuilder.buildText(textNode: ContentText) {
+ val decorators = decorators(textNode.style)
+ append(decorators)
+ append(textNode.text.escapeIllegalCharacters())
+ append(decorators.reversed())
+ }
+
+ override fun StringBuilder.buildNavigation(page: PageNode) {
+ locationProvider.ancestors(page).asReversed().forEach { node ->
+ append("/")
+ if (node.isNavigable) buildLink(node, page)
+ else append(node.name)
+ }
+ buildParagraph()
+ }
+
+ override fun buildPage(page: ContentPage, content: (StringBuilder, ContentPage) -> Unit): String =
+ StringBuilder().apply {
+ content(this, page)
+ }.toString()
+
+ override fun buildError(node: ContentNode) {
+ context.logger.warn("Markdown renderer has encountered problem. The unmatched node is $node")
+ }
+
+ private fun decorators(styles: Set<Style>) = StringBuilder().apply {
+ styles.forEach {
+ when (it) {
+ TextStyle.Bold -> append("**")
+ TextStyle.Italic -> append("*")
+ TextStyle.Strong -> append("**")
+ TextStyle.Strikethrough -> append("~~")
+ else -> Unit
+ }
+ }
+ }.toString()
+
+ private val PageNode.isNavigable: Boolean
+ get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
+
+ private fun StringBuilder.buildLink(to: PageNode, from: PageNode) =
+ buildLink(locationProvider.resolve(to, from)) {
+ append(to.name)
+ }
+
+ override fun renderPage(page: PageNode) {
+ val path by lazy { locationProvider.resolve(page, skipExtension = true) }
+ when (page) {
+ is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".md")
+ is RendererSpecificPage -> when (val strategy = page.strategy) {
+ is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path)
+ is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "")
+ is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".md")
+ RenderingStrategy.DoNothing -> Unit
+ }
+ else -> throw AssertionError(
+ "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content"
+ )
+ }
+ }
+}
+
+class MarkdownLocationProviderFactory(val context: DokkaContext) : LocationProviderFactory {
+
+ override fun getLocationProvider(pageNode: RootPageNode) = MarkdownLocationProvider(pageNode, context)
+}
+
+class MarkdownLocationProvider(
+ pageGraphRoot: RootPageNode,
+ dokkaContext: DokkaContext
+) : DefaultLocationProvider(
+ pageGraphRoot,
+ dokkaContext
+) {
+ override val extension = ".md"
+} \ No newline at end of file
diff --git a/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
new file mode 100644
index 00000000..ae291d68
--- /dev/null
+++ b/plugins/gfm/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
@@ -0,0 +1 @@
+org.jetbrains.dokka.gfm.GfmPlugin
diff --git a/plugins/jekyll/build.gradle.kts b/plugins/jekyll/build.gradle.kts
new file mode 100644
index 00000000..535a0aef
--- /dev/null
+++ b/plugins/jekyll/build.gradle.kts
@@ -0,0 +1,8 @@
+publishing {
+ publications {
+ register<MavenPublication>("jekyll-plugin") {
+ artifactId = "jekyll-plugin"
+ from(components["java"])
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt b/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt
new file mode 100644
index 00000000..0a0a2cc4
--- /dev/null
+++ b/plugins/jekyll/src/main/kotlin/JekyllPlugin.kt
@@ -0,0 +1,182 @@
+package org.jetbrains.dokka.jekyll
+
+import org.jetbrains.dokka.CoreExtensions
+import org.jetbrains.dokka.pages.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.jetbrains.dokka.plugability.single
+import org.jetbrains.dokka.renderers.DefaultRenderer
+import org.jetbrains.dokka.renderers.OutputWriter
+import org.jetbrains.dokka.resolvers.DefaultLocationProvider
+import org.jetbrains.dokka.resolvers.LocationProvider
+import org.jetbrains.dokka.resolvers.LocationProviderFactory
+import java.lang.StringBuilder
+
+
+class JekyllPlugin : DokkaPlugin() {
+
+ val renderer by extending {
+ CoreExtensions.renderer providing { JekyllRenderer(it.single(CoreExtensions.outputWriter), it) }
+ }
+}
+
+class JekyllRenderer(
+ outputWriter: OutputWriter,
+ context: DokkaContext
+) : DefaultRenderer<StringBuilder>(outputWriter, context) {
+ override fun StringBuilder.buildHeader(level: Int, content: StringBuilder.() -> Unit) {
+ buildParagraph()
+ append("${"#".repeat(level)} ")
+ content()
+ buildNewLine()
+ }
+
+ override fun StringBuilder.buildLink(address: String, content: StringBuilder.() -> Unit) {
+ append("[")
+ content()
+ append("]($address)")
+ }
+
+ override fun StringBuilder.buildList(node: ContentList, pageContext: ContentPage) {
+ buildListLevel(node, pageContext)
+ buildParagraph()
+ }
+
+ private val indent = " ".repeat(4)
+
+ private fun StringBuilder.buildListItem(items: List<ContentNode>, pageContext: ContentPage, bullet: String = "*") {
+ items.forEach {
+ if(it is ContentList) {
+ val builder = StringBuilder()
+ builder.append(indent)
+ builder.buildListLevel(it, pageContext)
+ append(builder.toString().replace(Regex(" \n(?!$)"), " \n$indent"))
+ } else {
+ append("$bullet ")
+ it.build(this, pageContext)
+ buildNewLine()
+ }
+ }
+ }
+
+ private fun StringBuilder.buildListLevel(node: ContentList, pageContext: ContentPage) {
+ if(node.ordered) {
+ buildListItem(node.children, pageContext, "${node.start}.")
+ } else {
+ buildListItem(node.children, pageContext, "*")
+ }
+ }
+
+ override fun StringBuilder.buildNewLine() {
+ this.append(" \n")
+ }
+
+ fun StringBuilder.buildParagraph() {
+ this.append("\n\n")
+ }
+
+ override fun StringBuilder.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage) {
+ this.append("Resource")
+ }
+
+ override fun StringBuilder.buildTable(node: ContentTable, pageContext: ContentPage) {
+
+ buildParagraph()
+
+ val size = node.children.firstOrNull()?.children?.size ?: 0
+
+ if(node.header.size > 0) {
+ node.header.forEach {
+ it.children.forEach {
+ append("| ")
+ it.build(this, pageContext)
+ }
+ append("|\n")
+ }
+ } else {
+ append("| ".repeat(size))
+ if(size > 0) append("|\n")
+ }
+
+ append("|---".repeat(size))
+ if(size > 0) append("|\n")
+
+
+ node.children.forEach {
+ it.children.forEach {
+ append("| ")
+ it.build(this, pageContext)
+ }
+ append("|\n")
+ }
+
+ buildParagraph()
+ }
+
+ override fun StringBuilder.buildText(textNode: ContentText) {
+ val decorators = decorators(textNode.style)
+ this.append(decorators)
+ this.append(textNode.text.replace(Regex("[<>]"), ""))
+ this.append(decorators.reversed())
+ }
+
+ override fun StringBuilder.buildNavigation(page: PageNode) {
+ locationProvider.ancestors(page).asReversed().forEach { node ->
+ append("/")
+ if (node.isNavigable) buildLink(node, page)
+ else append(node.name)
+ }
+ buildParagraph()
+ }
+
+ override fun buildPage(page: ContentPage, content: (StringBuilder, ContentPage) -> Unit): String {
+ val builder = StringBuilder()
+ builder.append("---\n")
+ builder.append("title: ${page.name} -\n")
+ builder.append("---\n")
+ content(builder, page)
+ return builder.toString()
+ }
+
+ override fun buildError(node: ContentNode) {
+ println("Error")
+ }
+
+ private fun decorators(styles: Set<Style>): String {
+ val decorators = StringBuilder()
+ styles.forEach {
+ when(it) {
+ TextStyle.Bold -> decorators.append("**")
+ TextStyle.Italic -> decorators.append("*")
+ TextStyle.Strong -> decorators.append("**")
+ TextStyle.Strikethrough -> decorators.append("~~")
+ else -> Unit
+ }
+ }
+ return decorators.toString()
+ }
+
+ private val PageNode.isNavigable: Boolean
+ get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
+
+ private fun StringBuilder.buildLink(to: PageNode, from: PageNode) =
+ buildLink(locationProvider.resolve(to, from)) {
+ append(to.name)
+ }
+
+ override fun renderPage(page: PageNode) {
+ val path by lazy { locationProvider.resolve(page, skipExtension = true) }
+ when (page) {
+ is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".md")
+ is RendererSpecificPage -> when (val strategy = page.strategy) {
+ is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path)
+ is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "")
+ is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".md")
+ RenderingStrategy.DoNothing -> Unit
+ }
+ else -> throw AssertionError(
+ "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content"
+ )
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/jekyll/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/jekyll/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
new file mode 100644
index 00000000..92c75544
--- /dev/null
+++ b/plugins/jekyll/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
@@ -0,0 +1 @@
+org.jetbrains.dokka.jekyll.JekyllPlugin
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index e9329c38..644ecee4 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -52,7 +52,7 @@ open class GlobalArguments(parser: DokkaArgumentsParser) : DokkaConfiguration {
listOf("-pass"),
"Single dokka pass"
) {
- Arguments(parser)
+ Arguments(parser).also { if(it.moduleName.isEmpty()) DokkaConsoleLogger.warn("Not specified module name. It can result in unexpected behaviour while including documentation for module") }
}
}
@@ -260,14 +260,18 @@ object MainKt {
listOf("-globalPackageOptions"),
"List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" "
) { link ->
- configuration.passesConfigurations.all { it.perPackageOptions.addAll(parsePerPackageOptions(link)) }
+ configuration.passesConfigurations.all {
+ it.perPackageOptions.toMutableList().addAll(parsePerPackageOptions(link))
+ }
}
parseContext.cli.singleAction(
listOf("-globalLinks"),
"External documentation links in format url^packageListUrl^^url2..."
) { link ->
- configuration.passesConfigurations.all { it.externalDocumentationLinks.addAll(parseLinks(link)) }
+ configuration.passesConfigurations.all {
+ it.externalDocumentationLinks.toMutableList().addAll(parseLinks(link))
+ }
}
parseContext.cli.repeatingAction(
@@ -278,12 +282,14 @@ object MainKt {
listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it))
else {
if (it.isNotEmpty()) {
- println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ DokkaConsoleLogger.warn("Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
}
listOf()
}
- configuration.passesConfigurations.all { it.sourceLinks.addAll(newSourceLinks) }
+ configuration.passesConfigurations.all {
+ it.sourceLinks.toMutableList().addAll(newSourceLinks)
+ }
}
parser.parseInto(configuration)
diff --git a/runners/gradle-plugin/build.gradle.kts b/runners/gradle-plugin/build.gradle.kts
index 0d68a525..df4a8738 100644
--- a/runners/gradle-plugin/build.gradle.kts
+++ b/runners/gradle-plugin/build.gradle.kts
@@ -15,6 +15,7 @@ dependencies {
compileOnly("com.android.tools.build:gradle-core:3.0.0")
compileOnly("com.android.tools.build:builder-model:3.0.0")
compileOnly(gradleApi())
+ compileOnly(gradleKotlinDsl())
constraints {
val kotlin_version: String by project
compileOnly("org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}") {
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt
new file mode 100644
index 00000000..f4fa7aaa
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt
@@ -0,0 +1,56 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.UnknownTaskException
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.TaskAction
+import org.gradle.kotlin.dsl.getByName
+import java.lang.IllegalStateException
+
+open class DokkaCollectorTask : DefaultTask() {
+
+ @Input
+ var modules: List<String> = emptyList()
+
+ @Input
+ var outputDirectory: String = ""
+
+ private lateinit var configuration: GradleDokkaConfigurationImpl
+
+ @TaskAction
+ fun collect() {
+ val passesConfigurations = getProjects(project).filter { it.name in modules }.map {
+ val task = try {
+ it.tasks.getByName(DOKKA_TASK_NAME, DokkaTask::class)
+ } catch (e: UnknownTaskException) {
+ throw IllegalStateException("No dokka task declared in module ${it.name}")
+ }
+ task.getConfiguration()
+ }
+
+ val initial = GradleDokkaConfigurationImpl().apply {
+ outputDir = outputDirectory
+ cacheRoot = passesConfigurations.first().cacheRoot
+ format = passesConfigurations.first().format
+ generateIndexPages = passesConfigurations.first().generateIndexPages
+ }
+
+ configuration = passesConfigurations.fold(initial) { acc, it: GradleDokkaConfigurationImpl ->
+ if(acc.format != it.format || acc.generateIndexPages != it.generateIndexPages || acc.cacheRoot != it.cacheRoot)
+ throw IllegalStateException("Dokka task configurations differ on core arguments (format, generateIndexPages, cacheRoot)")
+ acc.passesConfigurations = acc.passesConfigurations + it.passesConfigurations
+ acc.pluginsClasspath = (acc.pluginsClasspath + it.pluginsClasspath).distinct()
+ acc
+ }
+ project.tasks.getByName(DOKKA_TASK_NAME).setProperty("config", configuration)
+ }
+
+ init {
+ finalizedBy(project.tasks.getByName(DOKKA_TASK_NAME))
+ }
+
+ private fun getProjects(project: Project): Set<Project> =
+ project.subprojects + project.subprojects.flatMap { getProjects(it) }
+
+} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
index 65b0f4b3..4f7b88c4 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
@@ -8,7 +8,6 @@ import org.gradle.api.internal.plugins.DslObject
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaBootstrap
-import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
import org.jetbrains.dokka.Platform
@@ -76,10 +75,11 @@ open class DokkaTask : DefaultTask() {
@Nested get() = DslObject(this).extensions.getByType(GradlePassConfigurationImpl::class.java)
internal set(value) = DslObject(this).extensions.add(CONFIGURATION_EXTENSION_NAME, value)
+ var config: GradleDokkaConfigurationImpl? = null
+
// Configure Dokka with closure in Gradle Kotlin DSL
fun configuration(action: Action<in GradlePassConfigurationImpl>) = action.execute(configuration)
-
private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks(configuration.collectKotlinTasks ?: { defaultKotlinTasks() }) }
private val configExtractor = ConfigurationExtractor(project)
@@ -133,6 +133,10 @@ open class DokkaTask : DefaultTask() {
@TaskAction
fun generate() {
+ generateForConfig(config ?: getConfiguration())
+ }
+
+ internal fun generateForConfig(configuration: GradleDokkaConfigurationImpl) {
outputDiagnosticInfo = true
val kotlinColorsEnabledBefore = System.getProperty(COLORS_ENABLED_PROPERTY) ?: "false"
System.setProperty(COLORS_ENABLED_PROPERTY, "false")
@@ -146,20 +150,6 @@ open class DokkaTask : DefaultTask() {
val gson = GsonBuilder().setPrettyPrinting().create()
- val globalConfig = multiplatform.toList().find { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
- val passConfigurationList = collectConfigurations()
- .map { defaultPassConfiguration(it, globalConfig) }
-
- val configuration = GradleDokkaConfigurationImpl().apply {
- outputDir = outputDirectory
- format = outputFormat
- generateIndexPages = true
- cacheRoot = cacheRoot
- impliedPlatforms = impliedPlatforms
- passesConfigurations = passConfigurationList
- pluginsClasspath = pluginsConfiguration.resolve().toList()
- }
-
bootstrapProxy.configure(
BiConsumer { level, message ->
when (level) {
@@ -180,6 +170,21 @@ open class DokkaTask : DefaultTask() {
}
}
+ internal fun getConfiguration(): GradleDokkaConfigurationImpl {
+ val globalConfig = multiplatform.toList().find { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
+ val defaultModulesConfiguration = collectConfigurations()
+ .map { defaultPassConfiguration(it, globalConfig) }
+ return GradleDokkaConfigurationImpl().apply {
+ outputDir = outputDirectory
+ format = outputFormat
+ generateIndexPages = true
+ cacheRoot = cacheRoot
+ impliedPlatforms = impliedPlatforms
+ passesConfigurations = defaultModulesConfiguration
+ pluginsClasspath = pluginsConfiguration.resolve().toList()
+ }
+ }
+
private fun collectConfigurations() =
if (this.isMultiplatformProject()) collectMultiplatform() else listOf(collectSinglePlatform(configuration))
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
index f4ffdab6..4efc5010 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
@@ -10,9 +10,10 @@ import java.util.*
internal const val CONFIGURATION_EXTENSION_NAME = "configuration"
internal const val MULTIPLATFORM_EXTENSION_NAME = "multiplatform"
+internal const val DOKKA_TASK_NAME = "dokka"
+internal const val DOKKA_COLLECTOR_TASK_NAME = "dokkaCollector"
open class DokkaPlugin : Plugin<Project> {
- private val taskName = "dokka"
override fun apply(project: Project) {
loadDokkaVersion()
@@ -20,33 +21,50 @@ open class DokkaPlugin : Plugin<Project> {
val pluginsConfiguration = project.configurations.create("dokkaPlugins").apply {
defaultDependencies { it.add(project.dependencies.create("org.jetbrains.dokka:dokka-base:${DokkaVersion.version}")) }
}
- addTasks(project, dokkaRuntimeConfiguration, pluginsConfiguration, DokkaTask::class.java)
+ addDokkaTasks(project, dokkaRuntimeConfiguration, pluginsConfiguration, DokkaTask::class.java)
+ addDokkaCollectorTasks(project, DokkaCollectorTask::class.java)
}
- private fun loadDokkaVersion() = DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
+ private fun loadDokkaVersion() =
+ DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
private fun addConfiguration(project: Project) =
project.configurations.create("dokkaRuntime").apply {
- defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create("org.jetbrains.dokka:dokka-core:${DokkaVersion.version}")) }
+ defaultDependencies { dependencies -> dependencies.add(project.dependencies.create("org.jetbrains.dokka:dokka-core:${DokkaVersion.version}")) }
}
- private fun addTasks(
+ private fun addDokkaTasks(
project: Project,
runtimeConfiguration: Configuration,
pluginsConfiguration: Configuration,
taskClass: Class<out DokkaTask>
) {
- if(GradleVersion.current() >= GradleVersion.version("4.10")) {
- project.tasks.register(taskName, taskClass)
+ if (GradleVersion.current() >= GradleVersion.version("4.10")) {
+ project.tasks.register(DOKKA_TASK_NAME, taskClass)
} else {
- project.tasks.create(taskName, taskClass)
+ project.tasks.create(DOKKA_TASK_NAME, taskClass)
}
project.tasks.withType(taskClass) { task ->
task.multiplatform = project.container(GradlePassConfigurationImpl::class.java)
task.configuration = GradlePassConfigurationImpl()
task.dokkaRuntime = runtimeConfiguration
task.pluginsConfiguration = pluginsConfiguration
- task.outputDirectory = File(project.buildDir, taskName).absolutePath
+ task.outputDirectory = File(project.buildDir, DOKKA_TASK_NAME).absolutePath
+ }
+ }
+
+ private fun addDokkaCollectorTasks(
+ project: Project,
+ taskClass: Class<out DokkaCollectorTask>
+ ) {
+ if (GradleVersion.current() >= GradleVersion.version("4.10")) {
+ project.tasks.register(DOKKA_COLLECTOR_TASK_NAME, taskClass)
+ } else {
+ project.tasks.create(DOKKA_COLLECTOR_TASK_NAME, taskClass)
+ }
+ project.tasks.withType(taskClass) { task ->
+ task.modules = emptyList()
+ task.outputDirectory = File(project.buildDir, DOKKA_TASK_NAME).absolutePath
}
}
}
diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
index c84b97f4..cfe278ce 100644
--- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
+++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
@@ -29,6 +29,7 @@ import org.eclipse.aether.transport.file.FileTransporterFactory
import org.eclipse.aether.transport.http.HttpTransporterFactory
import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator
import org.jetbrains.dokka.*
+import org.jetbrains.dokka.utilities.DokkaConsoleLogger
import java.io.File
import java.net.URL
@@ -219,18 +220,22 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
includeRootPackage = includeRootPackage
)
+ val logger = MavenDokkaLogger(log)
+
val configuration = DokkaConfigurationImpl(
outputDir = getOutDir(),
format = getOutFormat(),
impliedPlatforms = impliedPlatforms,
cacheRoot = cacheRoot,
- passesConfigurations = listOf(passConfiguration),
+ passesConfigurations = listOf(passConfiguration).also {
+ if(passConfiguration.moduleName.isEmpty()) logger.warn("Not specified module name. It can result in unexpected behaviour while including documentation for module")
+ },
generateIndexPages = generateIndexPages,
pluginsClasspath = getArtifactByAether("org.jetbrains.dokka", "dokka-base", dokkaVersion) +
dokkaPlugins.map { getArtifactByAether(it.groupId, it.artifactId, it.version) }.flatten()
)
- val gen = DokkaGenerator(configuration, MavenDokkaLogger(log))
+ val gen = DokkaGenerator(configuration, logger)
gen.generate()
}
diff --git a/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
index 64d16fef..d2db90b7 100644
--- a/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
+++ b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt
@@ -63,8 +63,9 @@ abstract class AbstractCoreTest {
val newConfiguration =
configuration.copy(
outputDir = testDirPath.toAbsolutePath().toString(),
- passesConfigurations = configuration.passesConfigurations
- .map { it.copy(sourceRoots = it.sourceRoots.map { it.copy(path = "${testDirPath.toAbsolutePath()}/${it.path}") }) }
+ passesConfigurations = configuration.passesConfigurations.map {
+ it.copy(sourceRoots = it.sourceRoots.map { it.copy(path = "${testDirPath.toAbsolutePath()}/${it.path}") })
+ }
)
DokkaTestGenerator(
newConfiguration,
@@ -139,7 +140,6 @@ abstract class AbstractCoreTest {
var cacheRoot: String? = null
var pluginsClasspath: List<File> = emptyList()
private val passesConfigurations = mutableListOf<PassConfigurationImpl>()
-
fun build() = DokkaConfigurationImpl(
outputDir = outputDir,
format = format,