aboutsummaryrefslogtreecommitdiff
path: root/runners/cli
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-01-10 13:14:43 +0100
committerGitHub <noreply@github.com>2023-01-10 13:14:43 +0100
commit7544a215fb580ae0c47d1f397334f150d1a1ec65 (patch)
treea30aa62c827e3ba88a498a7406ac57fa7334b270 /runners/cli
parent2161c397e1b1aadcf3d39c8518258e9bdb2b431a (diff)
downloaddokka-7544a215fb580ae0c47d1f397334f150d1a1ec65.tar.gz
dokka-7544a215fb580ae0c47d1f397334f150d1a1ec65.tar.bz2
dokka-7544a215fb580ae0c47d1f397334f150d1a1ec65.zip
Revise documentation (#2728)
Co-authored-by: Sarah Haggarty <sarahhaggarty@users.noreply.github.com>
Diffstat (limited to 'runners/cli')
-rw-r--r--runners/cli/api/cli.api10
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt91
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt164
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt37
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt34
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt155
-rw-r--r--runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt429
7 files changed, 502 insertions, 418 deletions
diff --git a/runners/cli/api/cli.api b/runners/cli/api/cli.api
index cdd051cc..74769272 100644
--- a/runners/cli/api/cli.api
+++ b/runners/cli/api/cli.api
@@ -62,7 +62,8 @@ public final class org/jetbrains/dokka/ArgTypeVisibility : kotlinx/cli/ArgType {
public final class org/jetbrains/dokka/GlobalArguments : org/jetbrains/dokka/DokkaConfiguration {
public fun <init> ([Ljava/lang/String;)V
- public fun getCacheRoot ()Ljava/io/File;
+ public synthetic fun getCacheRoot ()Ljava/io/File;
+ public fun getCacheRoot ()Ljava/lang/Void;
public fun getDelayTemplateSubstitution ()Z
public fun getFailOnWarning ()Z
public fun getFinalizeCoroutines ()Z
@@ -88,10 +89,13 @@ public final class org/jetbrains/dokka/GlobalArguments : org/jetbrains/dokka/Dok
public fun getSuppressObviousFunctions ()Z
}
-public final class org/jetbrains/dokka/MainKt {
+public final class org/jetbrains/dokka/LinkMapperKt {
public static final fun defaultLinks (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/List;
+ public static final fun parseLinks (Ljava/util/List;)Ljava/util/List;
+}
+
+public final class org/jetbrains/dokka/MainKt {
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/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt
new file mode 100644
index 00000000..f52f72fd
--- /dev/null
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/CliArgumentTypes.kt
@@ -0,0 +1,91 @@
+package org.jetbrains.dokka
+
+import kotlinx.cli.ArgParser
+import kotlinx.cli.ArgType
+import kotlinx.cli.CLIEntity
+import org.jetbrains.dokka.utilities.LoggingLevel
+import java.io.File
+import java.nio.file.Paths
+
+
+object ArgTypeFile : ArgType<File>(true) {
+ override fun convert(value: kotlin.String, name: kotlin.String): File = Paths.get(value).toRealPath().toFile()
+ override val description: kotlin.String
+ get() = "{ String that represents a directory / file path }"
+}
+
+object ArgTypePlatform : ArgType<Platform>(true) {
+ override fun convert(value: kotlin.String, name: kotlin.String): Platform = Platform.fromString(value)
+ override val description: kotlin.String
+ get() = "{ String that represents a Kotlin platform. Possible values: jvm/js/native/common/android }"
+}
+
+object ArgTypeVisibility : ArgType<DokkaConfiguration.Visibility>(true) {
+ override fun convert(value: kotlin.String, name: kotlin.String) = DokkaConfiguration.Visibility.fromString(value)
+ override val description: kotlin.String
+ get() = "{ String that represents a visibility modifier. Possible values: ${getPossibleVisibilityValues()}"
+
+ private fun getPossibleVisibilityValues(): kotlin.String =
+ DokkaConfiguration.Visibility.values().joinToString(separator = ", ")
+}
+
+object ArgTypePlugin : ArgType<DokkaConfiguration.PluginConfiguration>(true) {
+ override fun convert(
+ value: kotlin.String,
+ name: kotlin.String
+ ): DokkaConfiguration.PluginConfiguration {
+ return value.split("=").let {
+ PluginConfigurationImpl(
+ fqPluginName = it[0],
+ serializationFormat = DokkaConfiguration.SerializationFormat.JSON,
+ values = it[1]
+ )
+ }
+ }
+
+ override val description: kotlin.String
+ get() = "{ String that represents plugin configuration. " +
+ "Format is {fullyQualifiedPluginName}={jsonConfiguration}. " +
+ "Quotation marks (`\"`) inside json must be escaped. }"
+}
+
+object ArgTypeSourceLinkDefinition : ArgType<DokkaConfiguration.SourceLinkDefinition>(true) {
+ override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.SourceLinkDefinition {
+ return if (value.isNotEmpty() && value.contains("="))
+ SourceLinkDefinitionImpl.parseSourceLinkDefinition(value)
+ else {
+ throw IllegalArgumentException(
+ "Warning: Invalid -srcLink syntax. " +
+ "Expected: <path>=<url>[#lineSuffix]. No source links will be generated."
+ )
+ }
+ }
+
+ override val description: kotlin.String
+ get() = "{ String that represent source links. Format: {srcPath}={remotePath#lineSuffix} }"
+}
+
+data class ArgTypeArgument(val moduleName: CLIEntity<kotlin.String>) :
+ ArgType<DokkaConfiguration.DokkaSourceSet>(true) {
+ override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.DokkaSourceSet =
+ (if (moduleName.valueOrigin != ArgParser.ValueOrigin.UNSET && moduleName.valueOrigin != ArgParser.ValueOrigin.UNDEFINED) {
+ moduleName.value
+ } else {
+ DokkaDefaults.moduleName
+ }).let { moduleNameOrDefault ->
+ parseSourceSet(moduleNameOrDefault, value.split(" ").filter { it.isNotBlank() }.toTypedArray())
+ }
+
+ override val description: kotlin.String
+ get() = ""
+}
+
+// Workaround for printing nested parsers help
+data class ArgTypeHelpSourceSet(val moduleName: CLIEntity<kotlin.String>) : ArgType<Any>(false) {
+ override fun convert(value: kotlin.String, name: kotlin.String): Any = Any().also {
+ parseSourceSet(moduleName.value, arrayOf("-h"))
+ }
+
+ override val description: kotlin.String
+ get() = ""
+}
diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt
new file mode 100644
index 00000000..2bda8d79
--- /dev/null
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/GlobalArguments.kt
@@ -0,0 +1,164 @@
+package org.jetbrains.dokka
+
+import kotlinx.cli.*
+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 java.io.File
+
+class GlobalArguments(args: Array<String>) : DokkaConfiguration {
+
+ val parser = ArgParser("dokka-cli", prefixStyle = ArgParser.OptionPrefixStyle.JVM)
+
+ val json: String? by parser.argument(ArgType.String, description = "JSON configuration file path").optional()
+
+ private val _moduleName = parser.option(
+ ArgType.String,
+ description = "Name of the project/module",
+ fullName = "moduleName"
+ ).default(DokkaDefaults.moduleName)
+
+ override val moduleName: String by _moduleName
+
+ override val moduleVersion by parser.option(
+ ArgType.String,
+ description = "Documented version",
+ fullName = "moduleVersion"
+ )
+
+ override val outputDir by parser.option(ArgTypeFile, description = "Output directory path, ./dokka by default")
+ .default(DokkaDefaults.outputDir)
+
+ override val cacheRoot = null
+
+ override val sourceSets by parser.option(
+ ArgTypeArgument(_moduleName),
+ description = "Configuration for a Dokka source set. Contains nested configuration.",
+ fullName = "sourceSet"
+ ).multiple()
+
+ override val pluginsConfiguration by parser.option(
+ ArgTypePlugin,
+ description = "Configuration for Dokka plugins. Accepts multiple values separated by `^^`."
+ ).delimiter("^^")
+
+ override val pluginsClasspath by parser.option(
+ ArgTypeFile,
+ fullName = "pluginsClasspath",
+ description = "List of jars with Dokka plugins and their dependencies. Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ override val offlineMode by parser.option(
+ ArgType.Boolean,
+ description = "Whether to resolve remote files/links over network"
+ ).default(DokkaDefaults.offlineMode)
+
+ override val failOnWarning by parser.option(
+ ArgType.Boolean,
+ description = "Whether to fail documentation generation if Dokka has emitted a warning or an error"
+ ).default(DokkaDefaults.failOnWarning)
+
+ override val delayTemplateSubstitution by parser.option(
+ ArgType.Boolean,
+ description = "Delay substitution of some elements. Used in incremental builds of multimodule projects"
+ ).default(DokkaDefaults.delayTemplateSubstitution)
+
+ val noSuppressObviousFunctions: Boolean by parser.option(
+ ArgType.Boolean,
+ description = "Whether to suppress obvious functions such as inherited from `kotlin.Any` and `java.lang.Object`"
+ ).default(!DokkaDefaults.suppressObviousFunctions)
+
+ override val suppressObviousFunctions: Boolean by lazy { !noSuppressObviousFunctions }
+
+ private val _includes by parser.option(
+ ArgTypeFile,
+ fullName = "includes",
+ description = "Markdown files that contain module and package documentation. " +
+ "Accepts multiple values separated by semicolons"
+ ).delimiter(";")
+
+ override val includes: Set<File> by lazy { _includes.toSet() }
+
+ override val suppressInheritedMembers: Boolean by parser.option(
+ ArgType.Boolean,
+ description = "Whether to suppress inherited members that aren't explicitly overridden in a given class"
+ ).default(DokkaDefaults.suppressInheritedMembers)
+
+ override val finalizeCoroutines: Boolean = true
+
+ val globalPackageOptions by parser.option(
+ ArgType.String,
+ description = "Global list of package configurations in format " +
+ "\"matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...\". " +
+ "Accepts multiple values separated by semicolons. "
+ ).delimiter(";")
+
+ val globalLinks by parser.option(
+ ArgType.String,
+ description = "Global external documentation links in format {url}^{packageListUrl}. " +
+ "Accepts multiple values separated by `^^`"
+ ).delimiter("^^")
+
+ val globalSrcLink by parser.option(
+ ArgType.String,
+ description = "Global mapping between a source directory and a Web service for browsing the code. " +
+ "Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ val helpSourceSet by parser.option(
+ ArgTypeHelpSourceSet(_moduleName),
+ description = "Prints help for nested -sourceSet configuration"
+ )
+
+ val loggingLevel by parser.option(
+ ArgType.Choice(toVariant = {
+ when (it.toUpperCase().trim()) {
+ "DEBUG", "" -> LoggingLevel.DEBUG
+ "PROGRESS" -> LoggingLevel.PROGRESS
+ "INFO" -> LoggingLevel.INFO
+ "WARN" -> LoggingLevel.WARN
+ "ERROR" -> LoggingLevel.ERROR
+ else -> {
+ println("""Failed to deserialize logging level, got $it expected one of
+ |"DEBUG", "PROGRESS", "INFO", "WARN", "ERROR", falling back to DEBUG""".trimMargin())
+ LoggingLevel.DEBUG
+ }
+ }
+ }, toString = { it.toString() }
+ )).default(LoggingLevel.DEBUG)
+
+ override val modules: List<DokkaConfiguration.DokkaModuleDescription> = emptyList()
+
+ val logger: DokkaLogger by lazy {
+ DokkaConsoleLogger(loggingLevel)
+ }
+
+ init {
+ parser.parse(args)
+
+ sourceSets.forEach {
+ it.perPackageOptions.cast<MutableList<DokkaConfiguration.PackageOptions>>()
+ .addAll(parsePerPackageOptions(globalPackageOptions))
+ }
+
+ sourceSets.forEach {
+ it.externalDocumentationLinks.cast<MutableSet<DokkaConfiguration.ExternalDocumentationLink>>().addAll(parseLinks(globalLinks))
+ }
+
+ globalSrcLink.forEach {
+ if (it.isNotEmpty() && it.contains("="))
+ sourceSets.all { sourceSet ->
+ sourceSet.sourceLinks.cast<MutableSet<SourceLinkDefinitionImpl>>()
+ .add(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it))
+ }
+ else {
+ logger.warn("Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ }
+ }
+
+ sourceSets.forEach {
+ it.externalDocumentationLinks.cast<MutableSet<DokkaConfiguration.ExternalDocumentationLink>>().addAll(defaultLinks(it))
+ }
+ }
+}
diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt
new file mode 100644
index 00000000..191d5067
--- /dev/null
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/LinkMapper.kt
@@ -0,0 +1,37 @@
+package org.jetbrains.dokka
+
+import java.io.File
+import java.net.MalformedURLException
+import java.net.URL
+
+@OptIn(ExperimentalStdlibApi::class) // for buildList
+fun defaultLinks(config: DokkaConfiguration.DokkaSourceSet): MutableList<DokkaConfiguration.ExternalDocumentationLink> =
+ buildList<DokkaConfiguration.ExternalDocumentationLink> {
+ if (!config.noJdkLink) {
+ add(DokkaConfiguration.ExternalDocumentationLink.jdk(config.jdkVersion))
+ }
+
+ if (!config.noStdlibLink) {
+ add(DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib())
+ }
+ }.toMutableList()
+
+
+fun parseLinks(links: List<String>): List<DokkaConfiguration.ExternalDocumentationLink> {
+ val (parsedLinks, parsedOfflineLinks) = links
+ .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
+ .filter { it.isNotEmpty() }
+ .partition { it.size == 1 }
+
+ return parsedLinks.map { (root) -> ExternalDocumentationLink(root) } +
+ parsedOfflineLinks.map { (root, packageList) ->
+ val rootUrl = URL(root)
+ val packageListUrl =
+ try {
+ URL(packageList)
+ } catch (ex: MalformedURLException) {
+ File(packageList).toURI().toURL()
+ }
+ ExternalDocumentationLink(rootUrl, packageListUrl)
+ }
+}
diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt
new file mode 100644
index 00000000..1b9a3c56
--- /dev/null
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/PackageOptionsParser.kt
@@ -0,0 +1,34 @@
+package org.jetbrains.dokka
+
+internal fun parsePerPackageOptions(args: List<String>): List<DokkaConfiguration.PackageOptions> = args.map { it.split(",") }.map {
+ val matchingRegex = it.first()
+
+ val options = it.subList(1, it.size)
+
+ val deprecated = options.find { it.endsWith("skipDeprecated") }?.startsWith("+")
+ ?: DokkaDefaults.skipDeprecated
+
+ val reportUndocumented = options.find { it.endsWith("reportUndocumented") }?.startsWith("+")
+ ?: DokkaDefaults.reportUndocumented
+
+ val privateApi = options.find { it.endsWith("includeNonPublic") }?.startsWith("+")
+ ?: DokkaDefaults.includeNonPublic
+
+ val suppress = options.find { it.endsWith("suppress") }?.startsWith("+")
+ ?: DokkaDefaults.suppress
+
+ val documentedVisibilities = options
+ .filter { it.matches(Regex("\\+visibility:.+")) } // matches '+visibility:' with at least one symbol after the semicolon
+ .map { DokkaConfiguration.Visibility.fromString(it.split(":")[1]) }
+ .toSet()
+ .ifEmpty { DokkaDefaults.documentedVisibilities }
+
+ PackageOptionsImpl(
+ matchingRegex,
+ includeNonPublic = privateApi,
+ documentedVisibilities = documentedVisibilities,
+ reportUndocumented = reportUndocumented,
+ skipDeprecated = !deprecated,
+ suppress = suppress
+ )
+}
diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt
new file mode 100644
index 00000000..49e8f2ae
--- /dev/null
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/SourceSetArgumentsParser.kt
@@ -0,0 +1,155 @@
+package org.jetbrains.dokka
+
+import kotlinx.cli.ArgParser
+import kotlinx.cli.ArgType
+import kotlinx.cli.default
+import kotlinx.cli.delimiter
+
+internal fun parseSourceSet(moduleName: String, args: Array<String>): DokkaConfiguration.DokkaSourceSet {
+
+ val parser = ArgParser("sourceSet", prefixStyle = ArgParser.OptionPrefixStyle.JVM)
+
+ val sourceSetName by parser.option(
+ ArgType.String,
+ description = "Name of the source set"
+ ).default("main")
+
+ val displayName by parser.option(
+ ArgType.String,
+ description = "Display name of the source set, used both internally and externally"
+ ).default(DokkaDefaults.sourceSetDisplayName)
+
+ val classpath by parser.option(
+ ArgTypeFile,
+ description = "Classpath for analysis and interactive samples. Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ val sourceRoots by parser.option(
+ ArgTypeFile,
+ description = "Source code roots to be analyzed and documented. Accepts multiple paths separated by semicolons",
+ fullName = "src"
+ ).delimiter(";")
+
+ val dependentSourceSets by parser.option(
+ ArgType.String,
+ description = "Names of dependent source sets in format \"moduleName/sourceSetName\". " +
+ "Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ val samples by parser.option(
+ ArgTypeFile,
+ description = "List of directories or files that contain sample functions. " +
+ "Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ val includes by parser.option(
+ ArgTypeFile,
+ description = "Markdown files that contain module and package documentation. " +
+ "Accepts multiple paths separated by semicolons"
+ ).delimiter(";")
+
+ val includeNonPublic: Boolean by parser.option(
+ ArgType.Boolean,
+ description = "Deprecated, use documentedVisibilities")
+ .default(DokkaDefaults.includeNonPublic)
+
+ val documentedVisibilities by parser.option(
+ ArgTypeVisibility,
+ description = "Visibilities to be documented. Accepts multiple values separated by semicolons"
+ ).delimiter(";")
+
+ val reportUndocumented by parser.option(ArgType.Boolean, description = "Whether to report undocumented declarations")
+ .default(DokkaDefaults.reportUndocumented)
+
+ val noSkipEmptyPackages by parser.option(
+ ArgType.Boolean,
+ description = "Whether to create pages for empty packages"
+ ).default(!DokkaDefaults.skipEmptyPackages)
+
+ val skipEmptyPackages by lazy { !noSkipEmptyPackages }
+
+ val skipDeprecated by parser.option(ArgType.Boolean, description = "Whether to skip deprecated declarations")
+ .default(DokkaDefaults.skipDeprecated)
+
+ val jdkVersion by parser.option(
+ ArgType.Int,
+ description = "Version of JDK to use for linking to JDK Javadocs"
+ ).default(DokkaDefaults.jdkVersion)
+
+ val languageVersion by parser.option(
+ ArgType.String,
+ description = "Language version used for setting up analysis and samples"
+ )
+
+ val apiVersion by parser.option(
+ ArgType.String,
+ description = "Kotlin API version used for setting up analysis and samples"
+ )
+
+ val noStdlibLink by parser.option(ArgType.Boolean, description = "Whether to generate links to Standard library")
+ .default(DokkaDefaults.noStdlibLink)
+
+ val noJdkLink by parser.option(ArgType.Boolean, description = "Whether to generate links to JDK Javadocs")
+ .default(DokkaDefaults.noJdkLink)
+
+ val suppressedFiles by parser.option(
+ ArgTypeFile,
+ description = "Paths to files to be suppressed. Accepts multiple paths separated by semicolons."
+ ).delimiter(";")
+
+ val analysisPlatform: Platform by parser.option(
+ ArgTypePlatform,
+ description = "Platform used for setting up analysis"
+ ).default(DokkaDefaults.analysisPlatform)
+
+ val perPackageOptions by parser.option(
+ ArgType.String,
+ description = "List of package source set configuration in format " +
+ "\"matchingRegexp,-deprecated,-privateApi,+warnUndocumented,+suppress;...\". " +
+ "Accepts multiple values separated by semicolons. "
+ ).delimiter(";")
+
+ val externalDocumentationLinks by parser.option(
+ ArgType.String,
+ description = "External documentation links in format {url}^{packageListUrl}. " +
+ "Accepts multiple values separated by `^^`"
+ ).delimiter("^^")
+
+ val sourceLinks by parser.option(
+ ArgTypeSourceLinkDefinition,
+ description = "Mapping between a source directory and a Web service for browsing the code. " +
+ "Accepts multiple paths separated by semicolons",
+ fullName = "srcLink"
+ ).delimiter(";")
+
+ parser.parse(args)
+
+ return object : DokkaConfiguration.DokkaSourceSet {
+ override val displayName = displayName
+ override val sourceSetID = DokkaSourceSetID(moduleName, sourceSetName)
+ override val classpath = classpath.toMutableList()
+ override val sourceRoots = sourceRoots.toMutableSet()
+ override val dependentSourceSets = dependentSourceSets
+ .map { dependentSourceSetName -> dependentSourceSetName.split('/').let { DokkaSourceSetID(it[0], it[1]) } }
+ .toMutableSet()
+ override val samples = samples.toMutableSet()
+ override val includes = includes.toMutableSet()
+ @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities")
+ override val includeNonPublic = includeNonPublic
+ override val reportUndocumented = reportUndocumented
+ override val skipEmptyPackages = skipEmptyPackages
+ override val skipDeprecated = skipDeprecated
+ override val jdkVersion = jdkVersion
+ override val sourceLinks = sourceLinks.toMutableSet()
+ override val analysisPlatform = analysisPlatform
+ override val perPackageOptions = parsePerPackageOptions(perPackageOptions).toMutableList()
+ override val externalDocumentationLinks = parseLinks(externalDocumentationLinks).toMutableSet()
+ override val languageVersion = languageVersion
+ override val apiVersion = apiVersion
+ override val noStdlibLink = noStdlibLink
+ override val noJdkLink = noJdkLink
+ override val suppressedFiles = suppressedFiles.toMutableSet()
+ override val documentedVisibilities: Set<DokkaConfiguration.Visibility> = documentedVisibilities.toSet()
+ .ifEmpty { DokkaDefaults.documentedVisibilities }
+ }
+}
diff --git a/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt b/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt
index 7fe782a9..99813f62 100644
--- a/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt
+++ b/runners/cli/src/main/kotlin/org/jetbrains/dokka/main.kt
@@ -1,429 +1,28 @@
package org.jetbrains.dokka
-import kotlinx.cli.*
import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
import org.jetbrains.dokka.utilities.*
-import java.io.*
-import java.net.MalformedURLException
-import java.net.URL
import java.nio.file.Paths
-class GlobalArguments(args: Array<String>) : DokkaConfiguration {
-
- val parser = ArgParser("globalArguments", prefixStyle = ArgParser.OptionPrefixStyle.JVM)
-
- val json: String? by parser.argument(ArgType.String, description = "Json file name").optional()
-
- private val _moduleName = parser.option(
- ArgType.String,
- description = "Name of the documentation module",
- fullName = "moduleName"
- ).default(DokkaDefaults.moduleName)
-
- override val moduleName: String by _moduleName
-
- override val moduleVersion by parser.option(
- ArgType.String,
- description = "Documentation version",
- fullName = "moduleVersion"
- )
-
- override val outputDir by parser.option(ArgTypeFile, description = "Output directory path")
- .default(DokkaDefaults.outputDir)
-
- override val cacheRoot by parser.option(
- ArgTypeFile,
- description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled"
- )
-
- override val sourceSets by parser.option(
- ArgTypeArgument(_moduleName),
- description = "Single dokka source set",
- fullName = "sourceSet"
- ).multiple()
-
- override val pluginsConfiguration by parser.option(
- ArgTypePlugin,
- description = "Configuration for plugins in format fqPluginName=json^^fqPluginName=json..."
- ).delimiter("^^")
-
- override val pluginsClasspath by parser.option(
- ArgTypeFile,
- fullName = "pluginsClasspath",
- description = "List of jars with dokka plugins (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- override val offlineMode by parser.option(
- ArgType.Boolean,
- description = "Offline mode (do not download package lists from the Internet)"
- ).default(DokkaDefaults.offlineMode)
-
- override val failOnWarning by parser.option(
- ArgType.Boolean,
- description = "Throw an exception if the generation exited with warnings"
- ).default(DokkaDefaults.failOnWarning)
-
- override val delayTemplateSubstitution by parser.option(
- ArgType.Boolean,
- description = "Delay substitution of some elements (usefull for incremental builds of multimodule projects)"
- ).default(DokkaDefaults.delayTemplateSubstitution)
-
- val noSuppressObviousFunctions: Boolean by parser.option(
- ArgType.Boolean,
- description = "Document generated or obvious functions like default `toString` or `equals`"
- ).default(!DokkaDefaults.suppressObviousFunctions)
-
- override val suppressObviousFunctions: Boolean by lazy { !noSuppressObviousFunctions }
-
- 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(";")
-
- override val includes: Set<File> by lazy { _includes.toSet() }
-
- override val suppressInheritedMembers: Boolean by parser.option(
- ArgType.Boolean,
- description = "Suppress members inherited from other classes"
- ).default(DokkaDefaults.suppressInheritedMembers)
-
- override val finalizeCoroutines: Boolean = true
-
- val globalPackageOptions by parser.option(
- ArgType.String,
- description = "List of package source sets in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" "
- ).delimiter(";")
-
- val globalLinks by parser.option(
- ArgType.String,
- description = "External documentation links in format url^packageListUrl^^url2..."
- ).delimiter("^^")
-
- val globalSrcLink by parser.option(
- ArgType.String,
- description = "Mapping between a source directory and a Web site for browsing the code (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val helpSourceSet by parser.option(
- ArgTypeHelpSourceSet(_moduleName),
- description = "Prints help for single -sourceSet"
- )
-
- val loggingLevel by parser.option(
- ArgType.Choice(toVariant = {
- when (it.toUpperCase().trim()) {
- "DEBUG", "" -> LoggingLevel.DEBUG
- "PROGRESS" -> LoggingLevel.PROGRESS
- "INFO" -> LoggingLevel.INFO
- "WARN" -> LoggingLevel.WARN
- "ERROR" -> LoggingLevel.ERROR
- else -> {
- println("""Failed to deserialize logging level, got $it expected one of "DEBUG", "PROGRESS", "INFO", "WARN", "ERROR", falling back to DEBUG""")
- LoggingLevel.DEBUG
- }
- }
- }, toString = { it.toString() }
- )).default(LoggingLevel.DEBUG)
-
- override val modules: List<DokkaConfiguration.DokkaModuleDescription> = emptyList()
-
- val logger: DokkaLogger by lazy {
- DokkaConsoleLogger(loggingLevel)
- }
-
- init {
- parser.parse(args)
-
- sourceSets.forEach {
- it.perPackageOptions.cast<MutableList<DokkaConfiguration.PackageOptions>>()
- .addAll(parsePerPackageOptions(globalPackageOptions))
- }
-
- sourceSets.forEach {
- it.externalDocumentationLinks.cast<MutableSet<ExternalDocumentationLink>>().addAll(parseLinks(globalLinks))
- }
-
- globalSrcLink.forEach {
- if (it.isNotEmpty() && it.contains("="))
- sourceSets.all { sourceSet ->
- sourceSet.sourceLinks.cast<MutableSet<SourceLinkDefinitionImpl>>()
- .add(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it))
- }
- else {
- logger.warn("Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
- }
- }
-
- sourceSets.forEach {
- it.externalDocumentationLinks.cast<MutableSet<ExternalDocumentationLink>>().addAll(defaultLinks(it))
- }
- }
-}
-
-private fun parseSourceSet(moduleName: String, args: Array<String>): DokkaConfiguration.DokkaSourceSet {
-
- val parser = ArgParser("sourceSet", prefixStyle = ArgParser.OptionPrefixStyle.JVM)
-
- val sourceSetName by parser.option(
- ArgType.String,
- description = "Name of the source set"
- ).default("main")
-
- val displayName by parser.option(
- ArgType.String,
- description = "Displayed name of the source set"
- ).default(DokkaDefaults.sourceSetDisplayName)
-
- val classpath by parser.option(
- ArgTypeFile,
- description = "Classpath for symbol resolution (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val sourceRoots by parser.option(
- ArgTypeFile,
- description = "Source file or directory (allows many paths separated by the semicolon `;`)",
- fullName = "src"
- ).delimiter(";")
-
- val dependentSourceSets by parser.option(
- ArgType.String,
- description = "Names of dependent source sets in format \"moduleName/sourceSetName\" (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val samples by parser.option(
- ArgTypeFile,
- description = "Source root for samples (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val includes by parser.option(
- ArgTypeFile,
- description = "Markdown files to load (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val includeNonPublic: Boolean by parser.option(ArgType.Boolean, description = "Include non public")
- .default(DokkaDefaults.includeNonPublic)
-
- val documentedVisibilities by parser.option(
- ArgTypeVisibility,
- description = "Visibilities to be documented (allows multiple values separated by the semicolon `;`)"
- ).delimiter(";")
-
- val reportUndocumented by parser.option(ArgType.Boolean, description = "Report undocumented members")
- .default(DokkaDefaults.reportUndocumented)
-
- val noSkipEmptyPackages by parser.option(
- ArgType.Boolean,
- description = "Create index pages for empty packages"
- ).default(!DokkaDefaults.skipEmptyPackages)
-
- val skipEmptyPackages by lazy { !noSkipEmptyPackages }
-
- val skipDeprecated by parser.option(ArgType.Boolean, description = "Do not output deprecated members")
- .default(DokkaDefaults.skipDeprecated)
-
- val jdkVersion by parser.option(
- ArgType.Int,
- description = "Version of JDK to use for linking to JDK JavaDoc"
- ).default(DokkaDefaults.jdkVersion)
-
- val languageVersion by parser.option(
- ArgType.String,
- description = "Language Version to pass to Kotlin analysis"
- )
-
- val apiVersion by parser.option(
- ArgType.String,
- description = "Kotlin Api Version to pass to Kotlin analysis"
- )
-
- val noStdlibLink by parser.option(ArgType.Boolean, description = "Disable documentation link to stdlib")
- .default(DokkaDefaults.noStdlibLink)
-
- val noJdkLink by parser.option(ArgType.Boolean, description = "Disable documentation link to JDK")
- .default(DokkaDefaults.noJdkLink)
-
- val suppressedFiles by parser.option(
- ArgTypeFile,
- description = "Paths to files to be suppressed (allows many paths separated by the semicolon `;`)"
- ).delimiter(";")
-
- val analysisPlatform: Platform by parser.option(
- ArgTypePlatform,
- description = "Platform for analysis"
- ).default(DokkaDefaults.analysisPlatform)
-
- val perPackageOptions by parser.option(
- ArgType.String,
- description = "List of package source set configuration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" "
- ).delimiter(";")
-
- val externalDocumentationLinks by parser.option(
- ArgType.String,
- description = "External documentation links in format url^packageListUrl^^url2..."
- ).delimiter("^^")
-
- val sourceLinks by parser.option(
- ArgTypeSourceLinkDefinition,
- description = "Mapping between a source directory and a Web site for browsing the code (allows many paths separated by the semicolon `;`)",
- fullName = "srcLink"
- ).delimiter(";")
-
- parser.parse(args)
-
- return object : DokkaConfiguration.DokkaSourceSet {
- override val displayName = displayName
- override val sourceSetID = DokkaSourceSetID(moduleName, sourceSetName)
- override val classpath = classpath.toMutableList()
- override val sourceRoots = sourceRoots.toMutableSet()
- override val dependentSourceSets = dependentSourceSets
- .map { dependentSourceSetName -> dependentSourceSetName.split('/').let { DokkaSourceSetID(it[0], it[1]) } }
- .toMutableSet()
- override val samples = samples.toMutableSet()
- override val includes = includes.toMutableSet()
- @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities")
- override val includeNonPublic = includeNonPublic
- override val reportUndocumented = reportUndocumented
- override val skipEmptyPackages = skipEmptyPackages
- override val skipDeprecated = skipDeprecated
- override val jdkVersion = jdkVersion
- override val sourceLinks = sourceLinks.toMutableSet()
- override val analysisPlatform = analysisPlatform
- override val perPackageOptions = parsePerPackageOptions(perPackageOptions).toMutableList()
- override val externalDocumentationLinks = parseLinks(externalDocumentationLinks).toMutableSet()
- override val languageVersion = languageVersion
- override val apiVersion = apiVersion
- override val noStdlibLink = noStdlibLink
- override val noJdkLink = noJdkLink
- override val suppressedFiles = suppressedFiles.toMutableSet()
- override val documentedVisibilities: Set<DokkaConfiguration.Visibility> = documentedVisibilities.toSet()
- .ifEmpty { DokkaDefaults.documentedVisibilities }
- }
-}
-
-object ArgTypeFile : ArgType<File>(true) {
- override fun convert(value: kotlin.String, name: kotlin.String): File = Paths.get(value).toRealPath().toFile()
- override val description: kotlin.String
- get() = "{ String that points to file path }"
-}
-
-object ArgTypePlatform : ArgType<Platform>(true) {
- override fun convert(value: kotlin.String, name: kotlin.String): Platform = Platform.fromString(value)
- override val description: kotlin.String
- get() = "{ String that represents platform }"
-}
-
-object ArgTypeVisibility : ArgType<DokkaConfiguration.Visibility>(true) {
- override fun convert(value: kotlin.String, name: kotlin.String) = DokkaConfiguration.Visibility.fromString(value)
- override val description: kotlin.String
- get() = "{ String that represents a visibility modifier. " +
- "Possible values: ${DokkaConfiguration.Visibility.values().joinToString(separator = ", ")} }"
-}
-
-object ArgTypePlugin : ArgType<DokkaConfiguration.PluginConfiguration>(true) {
- override fun convert(
- value: kotlin.String,
- name: kotlin.String
- ): DokkaConfiguration.PluginConfiguration {
- return value.split("=").let {
- PluginConfigurationImpl(
- fqPluginName = it[0],
- serializationFormat = DokkaConfiguration.SerializationFormat.JSON,
- values = it[1]
- )
- }
- }
-
- override val description: kotlin.String
- get() = "{ String fqName=json, remember to escape `\"` inside json }"
-}
-
-object ArgTypeSourceLinkDefinition : ArgType<DokkaConfiguration.SourceLinkDefinition>(true) {
- override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.SourceLinkDefinition =
- if (value.isNotEmpty() && value.contains("="))
- SourceLinkDefinitionImpl.parseSourceLinkDefinition(value)
- else {
- throw IllegalArgumentException("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
- }
-
- override val description: kotlin.String
- get() = "{ String that represent source links }"
-}
-
-data class ArgTypeArgument(val moduleName: CLIEntity<kotlin.String>) :
- ArgType<DokkaConfiguration.DokkaSourceSet>(true) {
- override fun convert(value: kotlin.String, name: kotlin.String): DokkaConfiguration.DokkaSourceSet =
- (if (moduleName.valueOrigin != ArgParser.ValueOrigin.UNSET && moduleName.valueOrigin != ArgParser.ValueOrigin.UNDEFINED) {
- moduleName.value
- } else {
- DokkaDefaults.moduleName
- }).let { moduleNameOrDefault ->
- parseSourceSet(moduleNameOrDefault, value.split(" ").filter { it.isNotBlank() }.toTypedArray())
- }
-
- override val description: kotlin.String
- get() = ""
-}
-
-// Workaround for printing nested parsers help
-data class ArgTypeHelpSourceSet(val moduleName: CLIEntity<kotlin.String>) : ArgType<Any>(false) {
- override fun convert(value: kotlin.String, name: kotlin.String): Any = Any().also {
- parseSourceSet(moduleName.value, arrayOf("-h"))
- }
-
- override val description: kotlin.String
- get() = ""
+fun main(args: Array<String>) {
+ val globalArguments = GlobalArguments(args)
+ val configuration = initializeConfiguration(globalArguments)
+ DokkaGenerator(configuration, globalArguments.logger).generate()
}
-@OptIn(ExperimentalStdlibApi::class)
-fun defaultLinks(config: DokkaConfiguration.DokkaSourceSet): MutableList<ExternalDocumentationLink> =
- buildList<ExternalDocumentationLink> {
- if (!config.noJdkLink) {
- add(ExternalDocumentationLink.jdk(config.jdkVersion))
- }
+fun initializeConfiguration(globalArguments: GlobalArguments): DokkaConfiguration {
+ return if (globalArguments.json != null) {
+ val jsonContent = Paths.get(checkNotNull(globalArguments.json)).toFile().readText()
+ val globals = GlobalDokkaConfiguration(jsonContent)
+ val dokkaConfigurationImpl = DokkaConfigurationImpl(jsonContent)
- if (!config.noStdlibLink) {
- add(ExternalDocumentationLink.kotlinStdlib())
- }
- }.toMutableList()
-
-
-fun parseLinks(links: List<String>): List<ExternalDocumentationLink> {
- val (parsedLinks, parsedOfflineLinks) = links
- .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
- .filter { it.isNotEmpty() }
- .partition { it.size == 1 }
-
- return parsedLinks.map { (root) -> ExternalDocumentationLink(root) } +
- parsedOfflineLinks.map { (root, packageList) ->
- val rootUrl = URL(root)
- val packageListUrl =
- try {
- URL(packageList)
- } catch (ex: MalformedURLException) {
- File(packageList).toURI().toURL()
- }
- ExternalDocumentationLink(rootUrl, packageListUrl)
+ dokkaConfigurationImpl.apply(globals).apply {
+ sourceSets.forEach {
+ it.externalDocumentationLinks.cast<MutableSet<ExternalDocumentationLink>>().addAll(defaultLinks(it))
}
-}
-
-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
}
-} else {
- globalArguments
-}
-
-fun main(args: Array<String>) {
- val globalArguments = GlobalArguments(args)
- val configuration = initializeConfiguration(globalArguments)
- DokkaGenerator(configuration, globalArguments.logger).generate()
}