aboutsummaryrefslogtreecommitdiff
path: root/dokka-runners/runner-maven-plugin/src/main
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-runners/runner-maven-plugin/src/main
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-runners/runner-maven-plugin/src/main')
-rw-r--r--dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/DokkaMojo.kt615
-rw-r--r--dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/ExternalDocumentationLinkBuilder.kt68
-rw-r--r--dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/MavenDokkaLogger.kt44
-rw-r--r--dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/PackageOptions.kt89
-rw-r--r--dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/SourceLinkMapItem.kt69
5 files changed, 885 insertions, 0 deletions
diff --git a/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/DokkaMojo.kt b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/DokkaMojo.kt
new file mode 100644
index 00000000..d14fea9c
--- /dev/null
+++ b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/DokkaMojo.kt
@@ -0,0 +1,615 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.maven
+
+import org.apache.maven.archiver.MavenArchiveConfiguration
+import org.apache.maven.archiver.MavenArchiver
+import org.apache.maven.artifact.DefaultArtifact
+import org.apache.maven.artifact.handler.DefaultArtifactHandler
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult
+import org.apache.maven.artifact.resolver.ResolutionErrorHandler
+import org.apache.maven.execution.MavenSession
+import org.apache.maven.model.Dependency
+import org.apache.maven.plugin.AbstractMojo
+import org.apache.maven.plugin.MojoExecutionException
+import org.apache.maven.plugins.annotations.*
+import org.apache.maven.project.MavenProject
+import org.apache.maven.project.MavenProjectHelper
+import org.apache.maven.repository.RepositorySystem
+import org.codehaus.plexus.archiver.Archiver
+import org.codehaus.plexus.archiver.jar.JarArchiver
+import org.codehaus.plexus.archiver.util.DefaultFileSet
+import org.codehaus.plexus.util.xml.Xpp3Dom
+import org.jetbrains.dokka.*
+import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
+import java.io.File
+import java.net.URL
+
+public abstract class AbstractDokkaMojo(
+ private val defaultDokkaPlugins: List<Dependency>
+) : AbstractMojo() {
+
+ @Parameter(defaultValue = "\${project}", readonly = true, required = true)
+ protected var mavenProject: MavenProject? = null
+
+ /**
+ * The current build session instance. This is used for
+ * dependency resolver API calls via repositorySystem.
+ */
+ @Parameter(defaultValue = "\${session}", required = true, readonly = true)
+ protected var session: MavenSession? = null
+
+ @Component
+ private var repositorySystem: RepositorySystem? = null
+
+ @Component
+ private var resolutionErrorHandler: ResolutionErrorHandler? = null
+
+ @Parameter(defaultValue = "JVM")
+ public var displayName: String = "JVM"
+
+ @Parameter
+ public var sourceSetName: String = "JVM"
+
+ /**
+ * Source code roots to be analyzed and documented.
+ * Accepts directories and individual `.kt` / `.java` files.
+ *
+ * Default is `{project.compileSourceRoots}`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.compileSourceRoots}")
+ public var sourceDirectories: List<String> = emptyList()
+
+ /**
+ * List of directories or files that contain sample functions which are referenced via
+ * [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier) KDoc tag.
+ */
+ @Parameter
+ public var samples: List<String> = emptyList()
+
+ /**
+ * List of Markdown files that contain
+ * [module and package documentation](https://kotlinlang.org/docs/dokka-module-and-package-docs.html).
+ *
+ * Contents of specified files will be parsed and embedded into documentation as module and package descriptions.
+ *
+ * Example of such a file:
+ *
+ * ```markdown
+ * # Module kotlin-demo
+ *
+ * The module shows the Dokka usage.
+ *
+ * # Package org.jetbrains.kotlin.demo
+ *
+ * Contains assorted useful stuff.
+ *
+ * ## Level 2 heading
+ *
+ * Text after this heading is also part of documentation for `org.jetbrains.kotlin.demo`
+ *
+ * # Package org.jetbrains.kotlin.demo2
+ *
+ * Useful stuff in another package.
+ * ```
+ */
+ @Parameter
+ public var includes: List<String> = emptyList()
+
+ /**
+ * Classpath for analysis and interactive samples.
+ *
+ * Useful if some types that come from dependencies are not resolved/picked up automatically.
+ * Property accepts both `.jar` and `.klib` files.
+ *
+ * Default is `{project.compileClasspathElements}`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.compileClasspathElements}")
+ public var classpath: List<String> = emptyList()
+
+ /**
+ * Specifies the location of the project source code on the Web. If provided, Dokka generates
+ * "source" links for each declaration. See [SourceLinkMapItem] for more details.
+ */
+ @Parameter
+ public var sourceLinks: List<SourceLinkMapItem> = emptyList()
+
+ /**
+ * Display name used to refer to the project/module. Used for ToC, navigation, logging, etc.
+ *
+ * Default is `{project.artifactId}`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.artifactId}")
+ public var moduleName: String = ""
+
+ /**
+ * Whether to skip documentation generation.
+ *
+ * Default is `false`.
+ */
+ @Parameter(required = false, defaultValue = "false")
+ public var skip: Boolean = false
+
+ /**
+ * JDK version to use when generating external documentation links for Java types.
+ *
+ * For instance, if you use [java.util.UUID] from JDK in some public declaration signature,
+ * and this property is set to `8`, Dokka will generate an external documentation link
+ * to [JDK 8 Javadocs](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) for it.
+ *
+ * Default is JDK 8.
+ */
+ @Parameter(required = false, defaultValue = "${DokkaDefaults.jdkVersion}")
+ public var jdkVersion: Int = DokkaDefaults.jdkVersion
+
+ /**
+ * Whether to document declarations annotated with [Deprecated].
+ *
+ * Can be overridden on package level by setting [PackageOptions.skipDeprecated].
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ public var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ /**
+ * Whether to skip packages that contain no visible declarations after
+ * various filters have been applied.
+ *
+ * For instance, if [skipDeprecated] is set to `true` and your package contains only
+ * deprecated declarations, it will be considered to be empty.
+ *
+ * Default is `true`.
+ */
+ @Parameter
+ public var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages
+
+ /**
+ * Whether to emit warnings about visible undocumented declarations, that is declarations without KDocs
+ * after they have been filtered by [documentedVisibilities].
+ *
+ * This setting works well with [failOnWarning].
+ *
+ * Can be overridden for a specific package by setting [PackageOptions.reportUndocumented].
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ public var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ /**
+ * Allows to customize documentation generation options on a per-package basis.
+ *
+ * @see PackageOptions for details
+ */
+ @Parameter
+ public var perPackageOptions: List<PackageOptions> = emptyList()
+
+ /**
+ * Allows linking to Dokka/Javadoc documentation of the project's dependencies.
+ *
+ * @see ExternalDocumentationLinkBuilder for details
+ */
+ @Parameter
+ public var externalDocumentationLinks: List<ExternalDocumentationLinkBuilder> = emptyList()
+
+ /**
+ * Whether to generate external documentation links that lead to API reference
+ * documentation for Kotlin's standard library when declarations from it are used.
+ *
+ * Default is `false`, meaning links will be generated.
+ */
+ @Parameter(defaultValue = "${DokkaDefaults.noStdlibLink}")
+ public var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink
+
+ /**
+ * Whether to generate external documentation links to JDK's Javadocs
+ * when declarations from it are used.
+ *
+ * The version of JDK Javadocs is determined by [jdkVersion] property.
+ *
+ * Default is `false`, meaning links will be generated.
+ */
+ @Parameter(defaultValue = "${DokkaDefaults.noJdkLink}")
+ public var noJdkLink: Boolean = DokkaDefaults.noJdkLink
+
+ /**
+ * Whether to resolve remote files/links over network.
+ *
+ * This includes package-lists used for generating external documentation links:
+ * for instance, to make classes from standard library clickable.
+ *
+ * Setting this to `true` can significantly speed up build times in certain cases,
+ * but can also worsen documentation quality and user experience, for instance by
+ * not resolving some dependency's class/member links.
+ *
+ * When using offline mode, you can cache fetched files locally and provide them to
+ * Dokka as local paths. For instance, see [ExternalDocumentationLinkBuilder].
+ *
+ * Default is `false`.
+ */
+ @Parameter(defaultValue = "${DokkaDefaults.offlineMode}")
+ public var offlineMode: Boolean = DokkaDefaults.offlineMode
+
+ /**
+ * [Kotlin language version](https://kotlinlang.org/docs/compatibility-modes.html)
+ * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier)
+ * environment.
+ *
+ * By default, the latest language version available to Dokka's embedded compiler will be used.
+ */
+ @Parameter
+ public var languageVersion: String? = null
+
+ /**
+ * [Kotlin API version](https://kotlinlang.org/docs/compatibility-modes.html)
+ * used for setting up analysis and [@sample](https://kotlinlang.org/docs/kotlin-doc.html#sample-identifier)
+ * environment.
+ *
+ * By default, it will be deduced from [languageVersion].
+ */
+ @Parameter
+ public var apiVersion: String? = null
+
+ /**
+ * Directories or individual files that should be suppressed, meaning declarations from them
+ * will be not documented.
+ */
+ @Parameter
+ public var suppressedFiles: List<String> = emptyList()
+
+ /**
+ * Set of visibility modifiers that should be documented.
+ *
+ * This can be used if you want to document protected/internal/private declarations,
+ * as well as if you want to exclude public declarations and only document internal API.
+ *
+ * Can be configured on per-package basis, see [PackageOptions.documentedVisibilities].
+ *
+ * Default is [DokkaConfiguration.Visibility.PUBLIC].
+ */
+ @Parameter(property = "visibility")
+ public var documentedVisibilities: Set<DokkaConfiguration.Visibility> = DokkaDefaults.documentedVisibilities
+ // hack to set the default value for lists, didn't find any other safe way
+ // maven seems to overwrite Kotlin's default initialization value, so it doesn't matter what you put there
+ get() = field.ifEmpty { DokkaDefaults.documentedVisibilities }
+
+ /**
+ * Whether to fail documentation generation if Dokka has emitted a warning or an error.
+ * Will wait until all errors and warnings have been emitted first.
+ *
+ * This setting works well with [reportUndocumented]
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ public var failOnWarning: Boolean = DokkaDefaults.failOnWarning
+
+ /**
+ * Whether to suppress obvious functions.
+ *
+ * A function is considered to be obvious if it is:
+ * - Inherited from `kotlin.Any`, `Kotlin.Enum`, `java.lang.Object` or `java.lang.Enum`,
+ * such as `equals`, `hashCode`, `toString`.
+ * - Synthetic (generated by the compiler) and does not have any documentation, such as
+ * `dataClass.componentN` or `dataClass.copy`.
+ *
+ * Default is `true`
+ */
+ @Parameter(defaultValue = "${DokkaDefaults.suppressObviousFunctions}")
+ public var suppressObviousFunctions: Boolean = DokkaDefaults.suppressObviousFunctions
+
+ /**
+ * Whether to suppress inherited members that aren't explicitly overridden in a given class.
+ *
+ * Note: this can suppress functions such as `equals`/`hashCode`/`toString`, but cannot suppress
+ * synthetic functions such as `dataClass.componentN` and `dataClass.copy`. Use [suppressObviousFunctions]
+ * for that.
+ *
+ * Default is `false`.
+ */
+ @Parameter(defaultValue = "${DokkaDefaults.suppressInheritedMembers}")
+ public var suppressInheritedMembers: Boolean = DokkaDefaults.suppressInheritedMembers
+
+ /**
+ * Dokka plugins to be using during documentation generation.
+ *
+ * Example:
+ *
+ * ```xml
+ * <dokkaPlugins>
+ * <plugin>
+ * <groupId>org.jetbrains.dokka</groupId>
+ * <artifactId>gfm-plugin</artifactId>
+ * <version>1.7.20</version>
+ * </plugin>
+ * </dokkaPlugins>
+ * ```
+ */
+ @Parameter
+ public var dokkaPlugins: List<Dependency> = emptyList()
+ get() = field + defaultDokkaPlugins
+
+ @Parameter
+ public var cacheRoot: String? = null
+
+ @Parameter
+ public var platform: String = ""
+
+ /**
+ * Deprecated. Use [documentedVisibilities] instead.
+ */
+ @Parameter
+ public var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+
+ protected abstract fun getOutDir(): String
+
+ override fun execute() {
+ if (skip) {
+ log.info("Dokka skip parameter is true so no dokka output will be produced")
+ return
+ }
+
+ sourceLinks.forEach {
+ if (it.path.contains("\\")) {
+ throw MojoExecutionException("Incorrect path property, only Unix based path allowed.")
+ }
+ }
+
+ if (moduleName.contains(',')) {
+ // To figure out why this is needed and if it is still relevant, see the comment here:
+ // https://github.com/Kotlin/dokka/issues/3011#issuecomment-1568620493
+ throw IllegalArgumentException("Module name cannot contain commas as it is used internally as a delimiter.")
+ }
+
+ fun defaultLinks(config: DokkaSourceSetImpl): Set<ExternalDocumentationLinkImpl> {
+ val links = mutableSetOf<ExternalDocumentationLinkImpl>()
+ if (!config.noJdkLink)
+ links += ExternalDocumentationLink.jdk(jdkVersion)
+
+ if (!config.noStdlibLink)
+ links += ExternalDocumentationLink.kotlinStdlib()
+ return links
+ }
+
+ val sourceSet = DokkaSourceSetImpl(
+ displayName = displayName,
+ sourceSetID = DokkaSourceSetID(moduleName, sourceSetName),
+ classpath = classpath.map(::File),
+ sourceRoots = sourceDirectories.map(::File).toSet(),
+ dependentSourceSets = emptySet(),
+ samples = samples.map(::File).toSet(),
+ includes = includes.map(::File).toSet(),
+ includeNonPublic = includeNonPublic,
+ documentedVisibilities = documentedVisibilities,
+ reportUndocumented = reportUndocumented,
+ skipEmptyPackages = skipEmptyPackages,
+ skipDeprecated = skipDeprecated,
+ jdkVersion = jdkVersion,
+ sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(File(it.path).canonicalPath, URL(it.url), it.lineSuffix) }.toSet(),
+ perPackageOptions = perPackageOptions.map {
+ @Suppress("DEPRECATION") // for includeNonPublic, preserve backwards compatibility
+ PackageOptionsImpl(
+ matchingRegex = it.matchingRegex,
+ includeNonPublic = it.includeNonPublic,
+ documentedVisibilities = it.documentedVisibilities,
+ reportUndocumented = it.reportUndocumented,
+ skipDeprecated = it.skipDeprecated,
+ suppress = it.suppress
+ )
+ },
+ externalDocumentationLinks = externalDocumentationLinks.map { it.build() }.toSet(),
+ languageVersion = languageVersion,
+ apiVersion = apiVersion,
+ noStdlibLink = noStdlibLink,
+ noJdkLink = noJdkLink,
+ suppressedFiles = suppressedFiles.map(::File).toSet(),
+ analysisPlatform = if (platform.isNotEmpty()) Platform.fromString(platform) else Platform.DEFAULT,
+ ).let {
+ it.copy(
+ externalDocumentationLinks = defaultLinks(it) + it.externalDocumentationLinks
+ )
+ }
+
+ val logger = MavenDokkaLogger(log)
+
+ val pluginsConfiguration =
+ (mavenProject?.getPlugin("org.jetbrains.dokka:dokka-maven-plugin")?.configuration as? Xpp3Dom)
+ ?.getChild("pluginsConfiguration")?.children?.map {
+ PluginConfigurationImpl(
+ it.name,
+ DokkaConfiguration.SerializationFormat.XML,
+ it.toString()
+ )
+ }.orEmpty()
+
+ val configuration = DokkaConfigurationImpl(
+ moduleName = moduleName,
+ outputDir = File(getOutDir()),
+ offlineMode = offlineMode,
+ cacheRoot = cacheRoot?.let(::File),
+ sourceSets = listOf(sourceSet),
+ // TODO [beresnev] analysis switcher
+ pluginsClasspath = getArtifactByMaven("org.jetbrains.dokka", "analysis-kotlin-descriptors", dokkaVersion) +
+ getArtifactByMaven("org.jetbrains.dokka", "dokka-base", dokkaVersion) +
+ dokkaPlugins.map { getArtifactByMaven(it.groupId, it.artifactId, it.version ?: dokkaVersion) }
+ .flatten(),
+ pluginsConfiguration = pluginsConfiguration.toMutableList(),
+ modules = emptyList(),
+ failOnWarning = failOnWarning,
+ suppressObviousFunctions = suppressObviousFunctions,
+ suppressInheritedMembers = suppressInheritedMembers,
+ // looks like maven has different life cycle compared to gradle,
+ // so finalizing coroutines after each module pass causes an error.
+ // see https://github.com/Kotlin/dokka/issues/2457
+ finalizeCoroutines = false,
+ )
+
+ val gen = DokkaGenerator(configuration, logger)
+
+ gen.generate()
+ }
+
+ private fun getArtifactByMaven(
+ groupId: String,
+ artifactId: String,
+ version: String
+ ): List<File> {
+
+ val request = ArtifactResolutionRequest().apply {
+ isResolveRoot = true
+ isResolveTransitively = true
+ localRepository = session!!.localRepository
+ remoteRepositories = mavenProject!!.pluginArtifactRepositories
+ isOffline = session!!.isOffline
+ isForceUpdate = session!!.request.isUpdateSnapshots
+ servers = session!!.request.servers
+ mirrors = session!!.request.mirrors
+ proxies = session!!.request.proxies
+ artifact = DefaultArtifact(
+ groupId, artifactId, version, "compile", "jar", null,
+ DefaultArtifactHandler("jar")
+ )
+ }
+
+ log.debug("Resolving $groupId:$artifactId:$version ...")
+
+ val result: ArtifactResolutionResult = repositorySystem!!.resolve(request)
+ resolutionErrorHandler!!.throwErrors(request, result)
+ return result.artifacts.map { it.file }
+ }
+
+ private val dokkaVersion: String by lazy {
+ mavenProject?.pluginArtifacts?.firstOrNull { it.groupId == "org.jetbrains.dokka" && it.artifactId == "dokka-maven-plugin" }?.version
+ ?: throw IllegalStateException("Not found dokka plugin")
+ }
+}
+
+@Mojo(
+ name = "dokka",
+ defaultPhase = LifecyclePhase.PRE_SITE,
+ threadSafe = true,
+ requiresDependencyResolution = ResolutionScope.COMPILE,
+ requiresProject = true
+)
+public class DokkaMojo : AbstractDokkaMojo(emptyList()) {
+
+ /**
+ * Directory to which documentation will be generated.
+ *
+ * Default is `{project.basedir}/target/dokka`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.basedir}/target/dokka")
+ public var outputDir: String = ""
+
+ override fun getOutDir(): String = outputDir
+}
+
+@Mojo(
+ name = "javadoc",
+ defaultPhase = LifecyclePhase.PRE_SITE,
+ threadSafe = true,
+ requiresDependencyResolution = ResolutionScope.COMPILE,
+ requiresProject = true
+)
+public class DokkaJavadocMojo : AbstractDokkaMojo(listOf(javadocDependency)) {
+
+ /**
+ * Directory to which documentation will be generated.
+ *
+ * Default is `{project.basedir}/target/dokkaJavadoc`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.basedir}/target/dokkaJavadoc")
+ public var outputDir: String = ""
+
+ override fun getOutDir(): String = outputDir
+}
+
+@Mojo(
+ name = "javadocJar",
+ defaultPhase = LifecyclePhase.PRE_SITE,
+ threadSafe = true,
+ requiresDependencyResolution = ResolutionScope.COMPILE,
+ requiresProject = true
+)
+public class DokkaJavadocJarMojo : AbstractDokkaMojo(listOf(javadocDependency)) {
+
+ /**
+ * Directory to which documentation jar will be generated.
+ *
+ * Default is `{project.basedir}/target/dokkaJavadocJar`.
+ */
+ @Parameter(required = true, defaultValue = "\${project.basedir}/target/dokkaJavadocJar")
+ public var outputDir: String = ""
+
+ /**
+ * Specifies the directory where the generated jar file will be put.
+ */
+ @Parameter(property = "project.build.directory")
+ private var jarOutputDirectory: String? = null
+
+ /**
+ * Specifies the filename that will be used for the generated jar file. Please note that `-javadoc`
+ * or `-test-javadoc` will be appended to the file name.
+ */
+ @Parameter(property = "project.build.finalName")
+ private var finalName: String? = null
+
+ /**
+ * Specifies whether to attach the generated artifact to the project helper.
+ */
+ @Parameter(property = "attach", defaultValue = "true")
+ private val attach: Boolean = false
+
+ /**
+ * The archive configuration to use.
+ * See [Maven Archiver Reference](https://maven.apache.org/shared/maven-archiver/index.html)
+ */
+ @Parameter
+ private val archive = MavenArchiveConfiguration()
+
+ @Parameter(property = "maven.javadoc.classifier", defaultValue = "javadoc", required = true)
+ private var classifier: String? = null
+
+ @Component
+ private var projectHelper: MavenProjectHelper? = null
+
+ @Component(role = Archiver::class, hint = "jar")
+ private var jarArchiver: JarArchiver? = null
+
+ override fun getOutDir(): String = outputDir
+
+ override fun execute() {
+ super.execute()
+ if (!File(outputDir).exists()) {
+ log.warn("No javadoc generated so no javadoc jar will be generated")
+ return
+ }
+ val outputFile = generateArchive("$finalName-$classifier.jar")
+ if (attach) {
+ projectHelper?.attachArtifact(mavenProject, "javadoc", classifier, outputFile)
+ }
+ }
+
+ private fun generateArchive(jarFileName: String): File {
+ val javadocJar = File(jarOutputDirectory, jarFileName)
+
+ val archiver = MavenArchiver()
+ archiver.archiver = jarArchiver
+ archiver.setOutputFile(javadocJar)
+ archiver.archiver.addFileSet(DefaultFileSet().apply { directory = File(outputDir) })
+
+ archive.isAddMavenDescriptor = false
+ archiver.createArchive(session, mavenProject, archive)
+
+ return javadocJar
+ }
+}
+
+private val javadocDependency = Dependency().apply {
+ groupId = "org.jetbrains.dokka"
+ artifactId = "javadoc-plugin"
+}
diff --git a/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/ExternalDocumentationLinkBuilder.kt b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/ExternalDocumentationLinkBuilder.kt
new file mode 100644
index 00000000..5eb4f269
--- /dev/null
+++ b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/ExternalDocumentationLinkBuilder.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.maven
+
+import org.apache.maven.plugins.annotations.Parameter
+import org.jetbrains.dokka.ExternalDocumentationLink
+import org.jetbrains.dokka.ExternalDocumentationLinkImpl
+import java.net.URL
+
+/**
+ * Configuration block that allows creating links leading to externally hosted
+ * documentation of your dependencies.
+ *
+ * For instance, if you are using types from `kotlinx.serialization`, by default
+ * they will be unclickable in your documentation, as if unresolved. However,
+ * since API reference for `kotlinx.serialization` is also built by Dokka and is
+ * [published on kotlinlang.org](https://kotlinlang.org/api/kotlinx.serialization/),
+ * you can configure external documentation links for it, allowing Dokka to generate
+ * documentation links for used types, making them clickable and appear resolved.
+ *
+ * Example:
+ *
+ * ```xml
+ * <externalDocumentationLinks>
+ * <link>
+ * <url>https://kotlinlang.org/api/latest/jvm/stdlib/</url>
+ * <packageListUrl>file:/${project.basedir}/stdlib.package.list</packageListUrl>
+ * </link>
+ * </externalDocumentationLinks>
+ * ```
+ */
+public class ExternalDocumentationLinkBuilder {
+
+ /**
+ * Root URL of documentation to link with. **Must** contain a trailing slash.
+ *
+ * Dokka will do its best to automatically find `package-list` for the given URL, and link
+ * declarations together.
+ *
+ * It automatic resolution fails or if you want to use locally cached files instead,
+ * consider providing [packageListUrl].
+ *
+ * Example:
+ *
+ * ```xml
+ * <url>https://kotlinlang.org/api/latest/jvm/stdlib/</url>
+ * ```
+ */
+ @Parameter(name = "url", required = true)
+ public var url: URL? = null
+
+ /**
+ * Specifies the exact location of a `package-list` instead of relying on Dokka
+ * automatically resolving it. Can also be a locally cached file to avoid network calls.
+ *
+ * Example:
+ *
+ * ```xml
+ * <packageListUrl>file:/${project.basedir}/stdlib.package.list</packageListUrl>
+ * ```
+ */
+ @Parameter(name = "packageListUrl", required = true)
+ public var packageListUrl: URL? = null
+
+ public fun build(): ExternalDocumentationLinkImpl = ExternalDocumentationLink(url, packageListUrl)
+}
diff --git a/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/MavenDokkaLogger.kt b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/MavenDokkaLogger.kt
new file mode 100644
index 00000000..1bc39d10
--- /dev/null
+++ b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/MavenDokkaLogger.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.maven
+
+import org.apache.maven.plugin.logging.Log
+import org.jetbrains.dokka.utilities.DokkaLogger
+import java.util.concurrent.atomic.AtomicInteger
+
+public class MavenDokkaLogger(
+ public val log: Log
+) : DokkaLogger {
+ private val warningsCounter = AtomicInteger()
+ private val errorsCounter = AtomicInteger()
+
+ override var warningsCount: Int
+ get() = warningsCounter.get()
+ set(value) = warningsCounter.set(value)
+
+ override var errorsCount: Int
+ get() = errorsCounter.get()
+ set(value) = errorsCounter.set(value)
+
+ override fun debug(message: String) {
+ log.debug(message)
+ }
+
+ override fun info(message: String) {
+ log.info(message)
+ }
+
+ override fun progress(message: String) {
+ log.info(message)
+ }
+
+ override fun warn(message: String) {
+ this.log.warn(message).also { warningsCounter.incrementAndGet() }
+ }
+
+ override fun error(message: String) {
+ log.error(message).also { errorsCounter.incrementAndGet() }
+ }
+}
diff --git a/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/PackageOptions.kt b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/PackageOptions.kt
new file mode 100644
index 00000000..875fb047
--- /dev/null
+++ b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/PackageOptions.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.maven
+
+import org.apache.maven.plugins.annotations.Parameter
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaDefaults
+
+/**
+ * Configuration block that allows setting some options for specific packages
+ * matched by [matchingRegex].
+ *
+ * Example:
+ *
+ * ```xml
+ * <configuration>
+ * <perPackageOptions>
+ * <packageOptions>
+ * <matchingRegex>.*api.*</matchingRegex>
+ * <suppress>false</suppress>
+ * <reportUndocumented>false</reportUndocumented>
+ * <skipDeprecated>false</skipDeprecated>
+ * <documentedVisibilities>
+ * <visibility>PUBLIC</visibility>
+ * <visibility>PROTECTED</visibility>
+ * </documentedVisibilities>
+ * </packageOptions>
+ * </perPackageOptions>
+ * </configuration>
+ * ```
+ */
+public class PackageOptions : DokkaConfiguration.PackageOptions {
+
+ /**
+ * Regular expression that is used to match the package.
+ *
+ * If multiple packages match the same `matchingRegex`, the longest `matchingRegex` will be used.
+ *
+ * Default is any string: `.*`.
+ */
+ @Parameter
+ override var matchingRegex: String = ".*"
+
+ /**
+ * Whether this package should be skipped when generating documentation.
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ override var suppress: Boolean = DokkaDefaults.suppress
+
+ /**
+ * List of visibility modifiers that should be documented.
+ *
+ * This can be used if you want to document protected/internal/private declarations within a
+ * specific package, as well as if you want to exclude public declarations and only document internal API.
+ *
+ * Default is [DokkaConfiguration.Visibility.PUBLIC].
+ */
+ @Parameter(property = "visibility")
+ override var documentedVisibilities: Set<DokkaConfiguration.Visibility> = DokkaDefaults.documentedVisibilities
+
+ /**
+ * Whether to document declarations annotated with [Deprecated].
+ *
+ * Can be set on project level with [AbstractDokkaMojo.skipDeprecated].
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ /**
+ * Whether to emit warnings about visible undocumented declarations, that is declarations from
+ * this package and without KDocs, after they have been filtered by [documentedVisibilities].
+ *
+ * This setting works well with [AbstractDokkaMojo.failOnWarning].
+ *
+ * Default is `false`.
+ */
+ @Parameter
+ override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ @Parameter
+ @Deprecated("Use [documentedVisibilities] property for a more flexible control over documented visibilities")
+ override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+}
diff --git a/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/SourceLinkMapItem.kt b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/SourceLinkMapItem.kt
new file mode 100644
index 00000000..ee2354aa
--- /dev/null
+++ b/dokka-runners/runner-maven-plugin/src/main/kotlin/org/jetbrains/dokka/maven/SourceLinkMapItem.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.maven
+
+import org.apache.maven.plugins.annotations.Parameter
+
+/**
+ * Configuration block that allows adding a `source` link to each signature
+ * which leads to [path] with a specific line number (configurable by setting [lineSuffix]),
+ * letting documentation readers find source code for each declaration.
+ *
+ * Example:
+ *
+ * ```xml
+ * <sourceLinks>
+ * <link>
+ * <path>${project.basedir}/src</path>
+ * <url>https://github.com/kotlin/dokka/tree/master/src</url>
+ * <lineSuffix>#L</lineSuffix>
+ * </link>
+ * </sourceLinks>
+ * ```
+ */
+public class SourceLinkMapItem {
+
+ /**
+ * Path to the local source directory. The path must be relative to the root of current project.
+ *
+ * Example:
+ *
+ * ```xml
+ * <path>${project.basedir}/src</path>
+ * ```
+ */
+ @Parameter(name = "path", required = true)
+ public var path: String = ""
+
+ /**
+ * URL of source code hosting service that can be accessed by documentation readers,
+ * like GitHub, GitLab, Bitbucket, etc. This URL will be used to generate
+ * source code links of declarations.
+ *
+ * Example:
+ *
+ * ```xml
+ * <url>https://github.com/username/projectname/tree/master/src</url>
+ * ```
+ */
+ @Parameter(name = "url", required = true)
+ public var url: String = ""
+
+ /**
+ * Suffix used to append source code line number to the URL. This will help readers navigate
+ * not only to the file, but to the specific line number of the declaration.
+ *
+ * The number itself will be appended to the specified suffix. For instance,
+ * if this property is set to `#L` and the line number is 10, resulting URL suffix
+ * will be `#L10`
+ *
+ * Suffixes used by popular services:
+ * - GitHub: `#L`
+ * - GitLab: `#L`
+ * - Bitbucket: `#lines-`
+ */
+ @Parameter(name = "lineSuffix")
+ public var lineSuffix: String? = null
+}