aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrzej Ratajczak <32793002+BarkingBad@users.noreply.github.com>2022-01-12 15:04:59 +0100
committerGitHub <noreply@github.com>2022-01-12 17:04:59 +0300
commit6b729257b89ff5a19a52045efa386349feec0bc6 (patch)
tree790ca1fc300466496dc18e045997d4818b7a50e1
parentb30db0aeafd5663dce3d3020f3dde6599ec368f3 (diff)
downloaddokka-6b729257b89ff5a19a52045efa386349feec0bc6.tar.gz
dokka-6b729257b89ff5a19a52045efa386349feec0bc6.tar.bz2
dokka-6b729257b89ff5a19a52045efa386349feec0bc6.zip
Add global settings to JSON dokka cli input (#2292)
* Add global settings to JSON dokka cli input * Apply requested changes * Move initialization of global arguments to extension function in core module
-rw-r--r--core/api/core.api17
-rw-r--r--core/src/main/kotlin/configuration.kt29
-rw-r--r--core/src/main/kotlin/utilities/json.kt1
-rw-r--r--integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt111
-rw-r--r--integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/jsonBuilder.kt52
-rw-r--r--integration-tests/cli/src/integrationTest/resources/my-file.json0
-rw-r--r--plugins/base/frontend/package-lock.json2
-rw-r--r--runners/cli/api/cli.api1
-rw-r--r--runners/cli/build.gradle.kts1
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt27
-rw-r--r--runners/cli/src/test/kotlin/cli/CliTest.kt30
-rw-r--r--runners/cli/src/test/resources/my-file.json51
12 files changed, 309 insertions, 13 deletions
diff --git a/core/api/core.api b/core/api/core.api
index 471f6314..8b9e5c7b 100644
--- a/core/api/core.api
+++ b/core/api/core.api
@@ -4,6 +4,8 @@ public final class org/jetbrains/dokka/ConfigurationKt {
public static final fun ExternalDocumentationLink (Ljava/net/URL;Ljava/net/URL;)Lorg/jetbrains/dokka/ExternalDocumentationLinkImpl;
public static synthetic fun ExternalDocumentationLink$default (Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/dokka/ExternalDocumentationLinkImpl;
public static synthetic fun ExternalDocumentationLink$default (Ljava/net/URL;Ljava/net/URL;ILjava/lang/Object;)Lorg/jetbrains/dokka/ExternalDocumentationLinkImpl;
+ public static final fun GlobalDokkaConfiguration (Ljava/lang/String;)Lorg/jetbrains/dokka/GlobalDokkaConfiguration;
+ public static final fun apply (Lorg/jetbrains/dokka/DokkaConfiguration;Lorg/jetbrains/dokka/GlobalDokkaConfiguration;)Lorg/jetbrains/dokka/DokkaConfiguration;
public static final fun build (Ljava/lang/Iterable;)Ljava/util/List;
public static final fun toJsonString (Lorg/jetbrains/dokka/DokkaConfiguration;)Ljava/lang/String;
public static final fun toJsonString (Lorg/jetbrains/dokka/plugability/ConfigurableBlock;)Ljava/lang/String;
@@ -343,6 +345,21 @@ public final class org/jetbrains/dokka/ExternalDocumentationLinkImpl : org/jetbr
public fun toString ()Ljava/lang/String;
}
+public final class org/jetbrains/dokka/GlobalDokkaConfiguration {
+ public fun <init> (Ljava/util/List;Ljava/util/List;Ljava/util/List;)V
+ public final fun component1 ()Ljava/util/List;
+ public final fun component2 ()Ljava/util/List;
+ public final fun component3 ()Ljava/util/List;
+ public final fun copy (Ljava/util/List;Ljava/util/List;Ljava/util/List;)Lorg/jetbrains/dokka/GlobalDokkaConfiguration;
+ public static synthetic fun copy$default (Lorg/jetbrains/dokka/GlobalDokkaConfiguration;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/dokka/GlobalDokkaConfiguration;
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getExternalDocumentationLinks ()Ljava/util/List;
+ public final fun getPerPackageOptions ()Ljava/util/List;
+ public final fun getSourceLinks ()Ljava/util/List;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
public final class org/jetbrains/dokka/PackageOptionsImpl : org/jetbrains/dokka/DokkaConfiguration$PackageOptions {
public fun <init> (Ljava/lang/String;ZLjava/lang/Boolean;ZZLjava/util/Set;)V
public final fun component1 ()Ljava/lang/String;
diff --git a/core/src/main/kotlin/configuration.kt b/core/src/main/kotlin/configuration.kt
index 46b338d2..038a5bb7 100644
--- a/core/src/main/kotlin/configuration.kt
+++ b/core/src/main/kotlin/configuration.kt
@@ -3,6 +3,7 @@
package org.jetbrains.dokka
import org.jetbrains.dokka.plugability.ConfigurableBlock
+import org.jetbrains.dokka.utilities.cast
import org.jetbrains.dokka.utilities.parseJson
import org.jetbrains.dokka.utilities.toJsonString
import java.io.File
@@ -86,6 +87,34 @@ data class DokkaSourceSetID(
fun DokkaConfigurationImpl(json: String): DokkaConfigurationImpl = parseJson(json)
+/**
+ * Global options are applied to all packages and modules and overwrite package configuration.
+ *
+ * These are handy if we have multiple sourcesets sharing the same global options as it reduces the size of the boilerplate.
+ * Otherwise, the user would be enforced to repeat all these options per each sourceset.
+ */
+data class GlobalDokkaConfiguration(
+ val perPackageOptions: List<PackageOptionsImpl>?,
+ val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>?,
+ val sourceLinks: List<SourceLinkDefinitionImpl>?
+)
+
+fun GlobalDokkaConfiguration(json: String): GlobalDokkaConfiguration = parseJson(json)
+
+fun DokkaConfiguration.apply(globals: GlobalDokkaConfiguration): DokkaConfiguration = this.apply {
+ sourceSets.forEach {
+ it.perPackageOptions.cast<MutableList<DokkaConfiguration.PackageOptions>>().addAll(globals.perPackageOptions ?: emptyList())
+ }
+
+ sourceSets.forEach {
+ it.externalDocumentationLinks.cast<MutableSet<DokkaConfiguration.ExternalDocumentationLink>>().addAll(globals.externalDocumentationLinks ?: emptyList())
+ }
+
+ sourceSets.forEach {
+ it.sourceLinks.cast<MutableSet<SourceLinkDefinitionImpl>>().addAll(globals.sourceLinks ?: emptyList())
+ }
+}
+
fun DokkaConfiguration.toJsonString(): String = toJsonString(this)
fun <T : ConfigurableBlock> T.toJsonString(): String = toJsonString(this)
diff --git a/core/src/main/kotlin/utilities/json.kt b/core/src/main/kotlin/utilities/json.kt
index 211037d6..d3762f6d 100644
--- a/core/src/main/kotlin/utilities/json.kt
+++ b/core/src/main/kotlin/utilities/json.kt
@@ -34,7 +34,6 @@ internal fun toJsonString(value: Any): String = objectMapper.writeValueAsString(
@PublishedApi
internal inline fun <reified T : Any> parseJson(json: String): T = parseJson(json, TypeReference())
-
@PublishedApi
internal fun <T : Any> parseJson(json: String, typeReference: TypeReference<T>): T =
objectMapper.readValue(json, typeReference.jackson)
diff --git a/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt
index b87badd7..b94df32a 100644
--- a/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt
+++ b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/CliIntegrationTest.kt
@@ -2,6 +2,8 @@ package org.jetbrains.dokka.it.cli
import org.jetbrains.dokka.it.awaitProcessResult
import java.io.File
+import java.io.PrintWriter
+import java.lang.IllegalStateException
import kotlin.test.*
class CliIntegrationTest : AbstractCliIntegrationTest() {
@@ -193,7 +195,7 @@ class CliIntegrationTest : AbstractCliIntegrationTest() {
}
@Test
- fun `logging level should be respected`(){
+ fun `logging level should be respected`() {
val dokkaOutputDir = File(projectDir, "output")
assertTrue(dokkaOutputDir.mkdirs())
val process = ProcessBuilder(
@@ -259,4 +261,111 @@ class CliIntegrationTest : AbstractCliIntegrationTest() {
)
)
}
+
+
+ @Test
+ fun `should accept json as input configuration`() {
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.mkdirs())
+ val jsonPath = javaClass.getResource("/my-file.json")?.path ?: throw IllegalStateException("No JSON found!")
+ PrintWriter(jsonPath).run {
+ write(jsonBuilder(dokkaOutputDir.path, basePluginJarFile.path, File(projectDir, "src").path, reportUndocumented = true))
+ close()
+ }
+
+ val process = ProcessBuilder(
+ "java", "-jar", cliJarFile.path, jsonPath
+ ).redirectErrorStream(true).start()
+
+ val result = process.awaitProcessResult()
+ assertEquals(0, result.exitCode, "Expected exitCode 0 (Success)")
+
+ val extensionLoadedRegex = Regex("""Extension: org\.jetbrains\.dokka\.base\.DokkaBase""")
+ val amountOfExtensionsLoaded = extensionLoadedRegex.findAll(result.output).count()
+
+ assertTrue(
+ amountOfExtensionsLoaded > 10,
+ "Expected more than 10 extensions being present (found $amountOfExtensionsLoaded)"
+ )
+
+ val undocumentedReportRegex = Regex("""Undocumented:""")
+ val amountOfUndocumentedReports = undocumentedReportRegex.findAll(result.output).count()
+ assertTrue(
+ amountOfUndocumentedReports > 0,
+ "Expected at least one report of undocumented code (found $amountOfUndocumentedReports)"
+ )
+
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+ }
+
+ /**
+ * This test disables global `reportUndocumneted` property and set `reportUndocumented` via perPackageOptions to
+ * make sure that global settings apply to dokka context.
+ */
+ @Test
+ fun `global settings should overwrite package options in configuration`() {
+ val dokkaOutputDir = File(projectDir, "output")
+ assertTrue(dokkaOutputDir.mkdirs())
+ val jsonPath = javaClass.getResource("/my-file.json")?.path ?: throw IllegalStateException("No JSON found!")
+ PrintWriter(jsonPath).run {
+ write(
+ jsonBuilder(
+ outputPath = dokkaOutputDir.path,
+ pluginsClasspath = basePluginJarFile.path,
+ projectPath = File(projectDir, "src").path,
+ globalSourceLinks = """
+ {
+ "localDirectory": "/home/Vadim.Mishenev/dokka/examples/cli/src/main/kotlin",
+ "remoteUrl": "https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-gradle-example/src/main/kotlin",
+ "remoteLineSuffix": "#L"
+ }
+ """.trimIndent(),
+ globalExternalDocumentationLinks = """
+ {
+ "url": "https://docs.oracle.com/javase/8/docs/api/",
+ "packageListUrl": "https://docs.oracle.com/javase/8/docs/api/package-list"
+ },
+ {
+ "url": "https://kotlinlang.org/api/latest/jvm/stdlib/",
+ "packageListUrl": "https://kotlinlang.org/api/latest/jvm/stdlib/package-list"
+ }
+ """.trimIndent(),
+ globalPerPackageOptions = """
+ {
+ "matchingRegex": ".*",
+ "skipDeprecated": "true",
+ "reportUndocumented": "true",
+ "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"]
+ }
+ """.trimIndent(),
+ reportUndocumented = false
+ ),
+ )
+ close()
+ }
+
+ val process = ProcessBuilder(
+ "java", "-jar", cliJarFile.path, jsonPath
+ ).redirectErrorStream(true).start()
+
+ val result = process.awaitProcessResult()
+ assertEquals(0, result.exitCode, "Expected exitCode 0 (Success)")
+
+ val extensionLoadedRegex = Regex("""Extension: org\.jetbrains\.dokka\.base\.DokkaBase""")
+ val amountOfExtensionsLoaded = extensionLoadedRegex.findAll(result.output).count()
+
+ assertTrue(
+ amountOfExtensionsLoaded > 10,
+ "Expected more than 10 extensions being present (found $amountOfExtensionsLoaded)"
+ )
+
+ val undocumentedReportRegex = Regex("""Undocumented:""")
+ val amountOfUndocumentedReports = undocumentedReportRegex.findAll(result.output).count()
+ assertTrue(
+ amountOfUndocumentedReports > 0,
+ "Expected at least one report of undocumented code (found $amountOfUndocumentedReports)"
+ )
+
+ assertTrue(dokkaOutputDir.isDirectory, "Missing dokka output directory")
+ }
}
diff --git a/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/jsonBuilder.kt b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/jsonBuilder.kt
new file mode 100644
index 00000000..d5d1df82
--- /dev/null
+++ b/integration-tests/cli/src/integrationTest/kotlin/org/jetbrains/dokka/it/cli/jsonBuilder.kt
@@ -0,0 +1,52 @@
+package org.jetbrains.dokka.it.cli
+
+fun jsonBuilder(
+ outputPath: String,
+ pluginsClasspath: String,
+ projectPath: String,
+ globalSourceLinks: String = "",
+ globalExternalDocumentationLinks: String = "",
+ globalPerPackageOptions: String = "",
+ reportUndocumented: Boolean = false
+
+): String {
+ return """{
+ "moduleName": "Dokka Example",
+ "moduleVersion": null,
+ "outputDir": "$outputPath",
+ "pluginsClasspath": ["$pluginsClasspath"],
+ "cacheRoot": null,
+ "offlineMode": false,
+ "sourceLinks": [$globalSourceLinks],
+ "externalDocumentationLinks": [$globalExternalDocumentationLinks],
+ "perPackageOptions": [$globalPerPackageOptions],
+ "sourceSets": [
+ {
+ "displayName": "jvm",
+ "sourceSetID": {
+ "scopeId": ":dokkaHtml",
+ "sourceSetName": "main"
+ },
+ "sourceRoots": [
+ "$projectPath"
+ ],
+ "dependentSourceSets": [],
+ "samples": [],
+ "includes": [],
+ "includeNonPublic": false,
+ "reportUndocumented": $reportUndocumented,
+ "skipEmptyPackages": true,
+ "skipDeprecated": false,
+ "jdkVersion": 8,
+ "sourceLinks": [],
+ "perPackageOptions": [],
+ "externalDocumentationLinks": [],
+ "noStdlibLink": false,
+ "noJdkLink": false,
+ "suppressedFiles": [],
+ "analysisPlatform": "jvm"
+ }
+ ]
+}
+"""
+}
diff --git a/integration-tests/cli/src/integrationTest/resources/my-file.json b/integration-tests/cli/src/integrationTest/resources/my-file.json
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/integration-tests/cli/src/integrationTest/resources/my-file.json
diff --git a/plugins/base/frontend/package-lock.json b/plugins/base/frontend/package-lock.json
index 997f5c03..a28d810e 100644
--- a/plugins/base/frontend/package-lock.json
+++ b/plugins/base/frontend/package-lock.json
@@ -41,7 +41,7 @@
"terser-webpack-plugin": "^5.2.5"
},
"engines": {
- "node": ">=17.0.0"
+ "node": ">=16.0.0"
}
},
"node_modules/@babel/code-frame": {
diff --git a/runners/cli/api/cli.api b/runners/cli/api/cli.api
index e1e52c05..208235ae 100644
--- a/runners/cli/api/cli.api
+++ b/runners/cli/api/cli.api
@@ -89,6 +89,7 @@ public final class org/jetbrains/dokka/GlobalArguments : org/jetbrains/dokka/Dok
public final class org/jetbrains/dokka/MainKt {
public static final fun defaultLinks (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/List;
+ public static final fun initializeConfiguration (Lorg/jetbrains/dokka/GlobalArguments;)Lorg/jetbrains/dokka/DokkaConfiguration;
public static final fun main ([Ljava/lang/String;)V
public static final fun parseLinks (Ljava/util/List;)Ljava/util/List;
}
diff --git a/runners/cli/build.gradle.kts b/runners/cli/build.gradle.kts
index 08fadec9..2785e92f 100644
--- a/runners/cli/build.gradle.kts
+++ b/runners/cli/build.gradle.kts
@@ -10,6 +10,7 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-cli-jvm:0.3.3")
implementation(project(":core"))
implementation(kotlin("stdlib"))
+ testImplementation(kotlin("test-junit"))
}
tasks {
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index 739539a9..1dc32a45 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -2,10 +2,7 @@ package org.jetbrains.dokka
import kotlinx.cli.*
import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
-import org.jetbrains.dokka.utilities.DokkaConsoleLogger
-import org.jetbrains.dokka.utilities.DokkaLogger
-import org.jetbrains.dokka.utilities.LoggingLevel
-import org.jetbrains.dokka.utilities.cast
+import org.jetbrains.dokka.utilities.*
import java.io.*
import java.net.MalformedURLException
import java.net.URL
@@ -80,6 +77,7 @@ class GlobalArguments(args: Array<String>) : DokkaConfiguration {
private val _includes by parser.option(
ArgTypeFile,
+ fullName = "includes",
description = "Markdown files that would be displayed in multi-module page separated by the semicolon `;`)"
).delimiter(";")
@@ -406,14 +404,23 @@ fun parseLinks(links: List<String>): List<ExternalDocumentationLink> {
}
}
+fun initializeConfiguration(globalArguments: GlobalArguments): DokkaConfiguration = if (globalArguments.json != null) {
+ val jsonContent = Paths.get(checkNotNull(globalArguments.json)).toFile().readText()
+ val globals = GlobalDokkaConfiguration(jsonContent)
+ val dokkaConfigurationImpl = DokkaConfigurationImpl(jsonContent)
+
+ dokkaConfigurationImpl.apply(globals).apply {
+ sourceSets.forEach {
+ it.externalDocumentationLinks.cast<MutableSet<ExternalDocumentationLink>>().addAll(defaultLinks(it))
+ }
+ }
+ } else {
+ globalArguments
+ }
+
fun main(args: Array<String>) {
val globalArguments = GlobalArguments(args)
- val configuration = if (globalArguments.json != null)
- DokkaConfigurationImpl(
- Paths.get(checkNotNull(globalArguments.json)).toFile().readText()
- )
- else
- globalArguments
+ val configuration = initializeConfiguration(globalArguments)
DokkaGenerator(configuration, globalArguments.logger).generate()
}
diff --git a/runners/cli/src/test/kotlin/cli/CliTest.kt b/runners/cli/src/test/kotlin/cli/CliTest.kt
new file mode 100644
index 00000000..5910e938
--- /dev/null
+++ b/runners/cli/src/test/kotlin/cli/CliTest.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka
+
+import junit.framework.Assert.assertTrue
+import org.junit.Test
+import java.lang.IllegalStateException
+import java.nio.file.Paths
+import kotlin.test.assertEquals
+
+class CliIntegrationTest {
+
+ @Test
+ fun `should apply global settings to all source sets`() {
+ val jsonPath = Paths.get(javaClass.getResource("/my-file.json")?.toURI() ?: throw IllegalStateException("No JSON found!")).toFile().toString()
+ val globalArguments = GlobalArguments(arrayOf(jsonPath))
+
+ val configuration = initializeConfiguration(globalArguments)
+
+ configuration.sourceSets.forEach {
+ assertTrue(it.perPackageOptions.isNotEmpty())
+ assertTrue(it.sourceLinks.isNotEmpty())
+ assertTrue(it.externalDocumentationLinks.isNotEmpty())
+
+ assertTrue(it.externalDocumentationLinks.any { it.url.toString() == "https://docs.oracle.com/javase/8/docs/api/" })
+ assertEquals(it.sourceLinks.single().localDirectory, "/home/Vadim.Mishenev/dokka/examples/cli/src/main/kotlin")
+ assertEquals(it.perPackageOptions.single().matchingRegex, "my-custom-regex")
+ }
+
+ }
+
+}
diff --git a/runners/cli/src/test/resources/my-file.json b/runners/cli/src/test/resources/my-file.json
new file mode 100644
index 00000000..49dda814
--- /dev/null
+++ b/runners/cli/src/test/resources/my-file.json
@@ -0,0 +1,51 @@
+{
+ "moduleName": "Dokka Example",
+ "moduleVersion": null,
+ "outputDir": "$outputPath",
+ "pluginsClasspath": ["$pluginsClasspath"],
+ "cacheRoot": null,
+ "offlineMode": false,
+ "sourceLinks": [{
+ "localDirectory": "/home/Vadim.Mishenev/dokka/examples/cli/src/main/kotlin",
+ "remoteUrl": "https://github.com/Kotlin/dokka/tree/master/examples/gradle/dokka-gradle-example/src/main/kotlin",
+ "remoteLineSuffix": "#L"
+ }],
+ "externalDocumentationLinks": [{
+ "url": "https://docs.oracle.com/javase/8/docs/api/",
+ "packageListUrl": "https://docs.oracle.com/javase/8/docs/api/package-list"
+ }],
+ "perPackageOptions": [{
+ "matchingRegex": "my-custom-regex",
+ "skipDeprecated": "true",
+ "reportUndocumented": "true",
+ "includeNonPublic": "true",
+ "documentedVisibilities": ["PUBLIC", "PRIVATE", "PROTECTED", "INTERNAL", "PACKAGE"]
+ }],
+ "sourceSets": [
+ {
+ "displayName": "jvm",
+ "sourceSetID": {
+ "scopeId": ":dokkaHtml",
+ "sourceSetName": "main"
+ },
+ "sourceRoots": [
+ "$projectPath"
+ ],
+ "dependentSourceSets": [],
+ "samples": [],
+ "includes": [],
+ "includeNonPublic": false,
+ "reportUndocumented": false,
+ "skipEmptyPackages": true,
+ "skipDeprecated": false,
+ "jdkVersion": 8,
+ "sourceLinks": [],
+ "perPackageOptions": [],
+ "externalDocumentationLinks": [],
+ "noStdlibLink": false,
+ "noJdkLink": false,
+ "suppressedFiles": [],
+ "analysisPlatform": "jvm"
+ }
+ ]
+}