aboutsummaryrefslogtreecommitdiff
path: root/runners/gradle-plugin/src/main
diff options
context:
space:
mode:
authorsebastian.sellmair <sebastian.sellmair@jetbrains.com>2020-07-18 12:18:59 +0200
committerSebastian Sellmair <34319766+sellmair@users.noreply.github.com>2020-08-14 17:51:11 +0200
commiteae1ce49d18c2978b49166ea502bf2c109a85504 (patch)
tree477f39e33f14c71042f06eecc938d6efaa95e66c /runners/gradle-plugin/src/main
parent6c635551ed3ea0cfe5f04b54a98cb28225061d26 (diff)
downloaddokka-eae1ce49d18c2978b49166ea502bf2c109a85504.tar.gz
dokka-eae1ce49d18c2978b49166ea502bf2c109a85504.tar.bz2
dokka-eae1ce49d18c2978b49166ea502bf2c109a85504.zip
Simplify Dokka Gradle Plugin
Diffstat (limited to 'runners/gradle-plugin/src/main')
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt73
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt55
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt185
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt73
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt78
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt315
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt298
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt22
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt36
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt25
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt15
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt105
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt72
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt20
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt)9
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt259
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt7
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt)11
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt (renamed from runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt)0
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt1
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt21
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt12
24 files changed, 751 insertions, 941 deletions
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt
new file mode 100644
index 00000000..bf8308bf
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt
@@ -0,0 +1,73 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.Nested
+import org.jetbrains.dokka.DokkaBootstrap
+import org.jetbrains.dokka.DokkaBootstrapImpl
+import kotlin.reflect.KClass
+
+// TODO NOW: Test UP-TO-DATE behaviour
+abstract class AbstractDokkaParentTask(
+ bootstrapClass: KClass<out DokkaBootstrap> = DokkaBootstrapImpl::class
+) : AbstractDokkaTask(bootstrapClass) {
+
+ @Input
+ open var dokkaTaskNames: Set<String> = setOf()
+
+ @Input
+ var subprojectPaths: Set<String> = project.subprojects.map { project -> project.path }.toSet()
+
+ @get:Internal
+ val subprojects: List<Project>
+ get() = subprojectPaths.map { path -> project.project(path) }.distinct()
+
+ @get:Nested
+ internal val dokkaTasks: List<AbstractDokkaTask>
+ get() = dokkaTaskNames.flatMap { dokkaTaskName -> findSubprojectDokkaTasks(dokkaTaskName) }
+
+
+ /**
+ * Will remove a single project from participating in this parent task.
+ * Note: This will not remove the [project]s subprojects.
+ *
+ * @see removeAllProjects
+ */
+ fun removeSubproject(project: Project) {
+ subprojectPaths = subprojectPaths - project.path
+ }
+
+ /**
+ * Will remove the [project] and all its subprojects from participating in this parent task.
+ * @see removeSubproject
+ */
+ fun removeAllProjects(project: Project) {
+ project.allprojects.forEach(::removeSubproject)
+ }
+
+ /**
+ * Includes the [project] to participate in this parent task.
+ * Note: This will not include any of the [project]s subprojects.
+ * @see addAllProjects
+ */
+ fun addSubproject(project: Project) {
+ subprojectPaths = (subprojectPaths + project.path)
+ }
+
+ /**
+ * Includes the [project] and all its subprojects to participate in this parent task.
+ * @see addSubproject
+ */
+ fun addAllProjects(project: Project) {
+ project.allprojects.forEach(::addSubproject)
+ }
+
+ protected fun findSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<AbstractDokkaTask> {
+ return dokkaTaskNames.flatMap { dokkaTaskName -> findSubprojectDokkaTasks(dokkaTaskName) }
+ }
+
+ private fun findSubprojectDokkaTasks(dokkaTaskName: String): List<AbstractDokkaTask> {
+ return subprojects.mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
index 1269b305..6413d788 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt
@@ -1,21 +1,33 @@
package org.jetbrains.dokka.gradle
import org.gradle.api.DefaultTask
-import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
-import org.gradle.api.attributes.Usage
-import org.gradle.api.tasks.Classpath
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.TaskAction
-import org.gradle.kotlin.dsl.dependencies
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaBootstrap
+import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.plugability.Configurable
+import org.jetbrains.dokka.toJsonString
+import java.io.File
+import java.util.function.BiConsumer
+import kotlin.reflect.KClass
+abstract class AbstractDokkaTask(
+ private val bootstrapClass: KClass<out DokkaBootstrap> = DokkaBootstrap::class
+) : DefaultTask(), Configurable {
+
+ @OutputDirectory
+ var outputDirectory: File = defaultDokkaOutputDirectory()
+
+ @Optional
+ @InputDirectory
+ var cacheRoot: File? = null
+
+ @Input
+ var failOnWarning: Boolean = false
-abstract class AbstractDokkaTask : DefaultTask(), Configurable {
@Input
- var outputDirectory: String = defaultDokkaOutputDirectory().absolutePath
+ var offlineMode: Boolean = false
@Input
override val pluginsConfiguration: MutableMap<String, String> = mutableMapOf()
@@ -27,19 +39,26 @@ abstract class AbstractDokkaTask : DefaultTask(), Configurable {
val runtime: Configuration = project.maybeCreateDokkaRuntimeConfiguration(name)
@TaskAction
- protected fun run() {
- val kotlinColorsEnabledBefore = System.getProperty(DokkaTask.COLORS_ENABLED_PROPERTY) ?: "false"
- System.setProperty(DokkaTask.COLORS_ENABLED_PROPERTY, "false")
- try {
+ protected open fun generateDocumentation() {
+ DokkaBootstrap(runtime, bootstrapClass).apply {
+ configure(buildDokkaConfiguration().toJsonString(), createProxyLogger())
generate()
- } finally {
- System.setProperty(DokkaTask.COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
}
}
- protected abstract fun generate()
+ internal abstract fun buildDokkaConfiguration(): DokkaConfigurationImpl
+
+ private fun createProxyLogger(): BiConsumer<String, String> = BiConsumer { level, message ->
+ when (level) {
+ "debug" -> logger.debug(message)
+ "info" -> logger.info(message)
+ "progress" -> logger.lifecycle(message)
+ "warn" -> logger.warn(message)
+ "error" -> logger.error(message)
+ }
+ }
- protected fun DokkaBootstrap(bootstrapClassFQName: String): DokkaBootstrap {
- return DokkaBootstrap(runtime, bootstrapClassFQName)
+ init {
+ group = JavaBasePlugin.DOCUMENTATION_GROUP
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
deleted file mode 100644
index 6217703f..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.UnknownDomainObjectException
-import org.gradle.api.artifacts.ResolveException
-import org.gradle.api.file.FileCollection
-import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.SourceSet
-import org.gradle.api.tasks.compile.AbstractCompile
-import org.jetbrains.dokka.ReflectDsl
-import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
-import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
-import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
-import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
-import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import java.io.File
-import java.io.Serializable
-
-class ConfigurationExtractor(private val project: Project) {
- fun extractConfiguration(sourceSetName: String): PlatformData? {
- val projectExtension = project.extensions.findByType(KotlinProjectExtension::class.java) ?: run {
- project.logger.error("Missing kotlin project extension")
- return null
- }
-
- val sourceSet = projectExtension.sourceSets.findByName(sourceSetName) ?: run {
- project.logger.error("No source set with name '$sourceSetName' found")
- return null
- }
-
- val compilation = try {
- when (projectExtension) {
- is KotlinMultiplatformExtension -> {
- val targets = projectExtension.targets.flatMap { it.compilations }
- targets.find { it.name == sourceSetName }
- ?: targets.find { it.kotlinSourceSets.contains(sourceSet) }
- }
- is KotlinSingleTargetExtension -> projectExtension.target.compilations.find {
- it.kotlinSourceSets.contains(sourceSet)
- }
- else -> null
- }
- } catch (e: NoClassDefFoundError) { // Old Kotlin plugin versions
- null
- }
-
- val sourceRoots = sourceSet.sourceFiles
- val classpath = compilation?.classpath
- ?: sourceRoots + sourceSet.allParentSourceFiles()
-
- return PlatformData(
- sourceSetName,
- classpath.filter { it.exists() },
- sourceRoots,
- sourceSet.dependsOn.map { it.name },
- compilation?.target?.platformType?.name ?: "common"
- )
- }
-
- private fun KotlinSourceSet.allParentSourceFiles(): List<File> =
- sourceFiles + dependsOn.flatMap { it.allParentSourceFiles() }
-
- fun extractFromJavaPlugin(): PlatformData? =
- project.convention.findPlugin(JavaPluginConvention::class.java)
- ?.run { sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)?.allSource?.srcDirs }
- ?.let { PlatformData(null, emptyList(), it.toList(), emptyList(), "") }
-
- fun extractFromKotlinTasks(kotlinTasks: List<Task>): List<PlatformData> =
- try {
- kotlinTasks.map { extractFromKotlinTask(it) }
- } catch (e: Throwable) {
- when (e) {
- is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
- listOfNotNull(extractFromKotlinTasksTheHardWay(kotlinTasks))
- else -> throw e
- }
- }
-
- private fun extractFromKotlinTask(task: Task): PlatformData =
- try {
- project.extensions.getByType(KotlinSingleTargetExtension::class.java).target
- .compilations
- .find { it.compileKotlinTask == task }
- } catch (e: Throwable) {
- when (e) {
- is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
- project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets
- .flatMap { it.compilations }.firstOrNull { it.compileKotlinTask == task }
- else -> throw e
- }
- }.let { compilation ->
- PlatformData(
- task.name,
- compilation?.classpath.orEmpty(),
- compilation?.sourceFiles.orEmpty(),
- compilation?.dependentSourceSets?.map { it.name }.orEmpty(),
- compilation?.platformType?.toString() ?: ""
- )
- }
-
- private fun extractFromKotlinTasksTheHardWay(kotlinTasks: List<Task>): PlatformData? {
- val allClasspath = mutableSetOf<File>()
- var allClasspathFileCollection: FileCollection = project.files()
- val allSourceRoots = mutableSetOf<File>()
-
- kotlinTasks.forEach {
- with(ReflectDsl) {
- val taskSourceRoots: List<File>
- val abstractKotlinCompileClz: Class<out Any>
- try {
- taskSourceRoots = it["sourceRootsContainer"]["sourceRoots"].v()
- abstractKotlinCompileClz = DokkaTask.getAbstractKotlinCompileFor(it)!!
- } catch (e: NullPointerException) {
- println("Error during extraction of sources from kotlinTasks. This may be a result of outdated Kotlin Gradle Plugin")
- return null
- }
-
- val taskClasspath: Iterable<File> =
- (it["getClasspath", AbstractCompile::class].takeIfIsFunc()?.invoke()
- ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v()
- ?: it["getClasspath", abstractKotlinCompileClz]())
-
- if (taskClasspath is FileCollection) {
- allClasspathFileCollection += taskClasspath
- } else {
- allClasspath += taskClasspath
- }
- allSourceRoots += taskSourceRoots.filter { it.exists() }
- }
- }
- val classpath: MutableList<File> = try {
- allClasspathFileCollection.toMutableList()
- } catch (e: ResolveException) {
- mutableListOf()
- }
- classpath.addAll(project.files(allClasspath).toList())
-
- return PlatformData(null, classpath, allSourceRoots.toList(), emptyList(), "")
- }
-
- private val KotlinCompilation<*>.sourceFiles: List<File>
- get() = kotlinSourceSets.flatMap { it.sourceFiles }
-
- private val KotlinSourceSet.sourceFiles: List<File>
- get() = kotlin.sourceDirectories.filter { it.exists() }.toList()
-
- private val KotlinCompilation<*>.dependentSourceSets: Set<KotlinSourceSet>
- get() = (allKotlinSourceSets - kotlinSourceSets)
-
- private val KotlinCompilation<*>.classpath: List<File>
- get() = if (target.isAndroidTarget()) {
- getClasspathFromAndroidTask(this)
- } else {
- getClasspathFromRegularTask(this)
- }
-
- // This is a workaround for KT-33893
- private fun getClasspathFromAndroidTask(compilation: KotlinCompilation<*>): List<File> = (compilation
- .compileKotlinTask as? KotlinCompile)
- ?.classpath?.files?.toList() ?: getClasspathFromRegularTask(compilation)
-
- private fun getClasspathFromRegularTask(compilation: KotlinCompilation<*>): List<File> {
- // explicit dependencies of the compilation
- val ownDependencyFiles: Set<File> = compilation.compileDependencyFiles.files
-
- // the dependencies provided by the platform (e.g. Kotlin/Native platform libs)
- val platformDependencyFiles: Set<File> = (compilation as? KotlinNativeCompilation)
- ?.target?.project?.configurations
- ?.findByName(compilation.defaultSourceSet.implementationMetadataConfigurationName)?.files
- ?: emptySet()
-
- return (ownDependencyFiles + platformDependencyFiles).toList().filter { it.exists() }
- }
-
- data class PlatformData(
- val name: String?,
- val classpath: List<File>,
- val sourceRoots: List<File>,
- val dependentSourceSets: List<String>,
- val platform: String
- ) : Serializable
-}
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
index 8d337795..7a73d633 100644
--- 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
@@ -1,59 +1,24 @@
package org.jetbrains.dokka.gradle
-import com.google.gson.GsonBuilder
-import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP
-import org.gradle.api.tasks.Input
-import org.jetbrains.dokka.toJsonString
-
-open class DokkaCollectorTask : AbstractDokkaTask() {
-
- @Input
- var modules: List<String> = emptyList()
-
- @Input
- var dokkaTaskNames: Set<String> = setOf()
-
- override fun generate() {
- val configurations = getSubprojectDokkaTasks(dokkaTaskNames)
- .mapNotNull { dokkaTask -> dokkaTask.getConfigurationOrNull() }
-
- val initial = GradleDokkaConfigurationImpl().apply {
- outputDir = outputDirectory
- cacheRoot = configurations.first().cacheRoot
- }
-
- val configuration = configurations.fold(initial) { acc, it: GradleDokkaConfigurationImpl ->
- if (acc.cacheRoot != it.cacheRoot)
- throw IllegalStateException("Dokka task configurations differ on core argument cacheRoot")
- acc.sourceSets = acc.sourceSets + it.sourceSets
- acc.pluginsClasspath = (acc.pluginsClasspath + it.pluginsClasspath).distinct()
- acc
+import org.jetbrains.dokka.DokkaConfigurationImpl
+
+open class DokkaCollectorTask : AbstractDokkaParentTask() {
+
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ val initialDokkaConfiguration = DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ failOnWarning = failOnWarning,
+ offlineMode = offlineMode,
+ pluginsClasspath = plugins.resolve().toList(),
+ )
+
+ val subprojectDokkaConfigurations = dokkaTasks.map { dokkaTask -> dokkaTask.buildDokkaConfiguration() }
+ return subprojectDokkaConfigurations.fold(initialDokkaConfiguration) { acc, it: DokkaConfigurationImpl ->
+ acc.copy(
+ sourceSets = acc.sourceSets + it.sourceSets,
+ pluginsClasspath = acc.pluginsClasspath + it.pluginsClasspath
+ )
}
-
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaBootstrapImpl")
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskName: String): List<DokkaTask> {
- return project.subprojects
- .filter { subproject -> subproject.name in modules }
- .mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<DokkaTask> {
- return dokkaTaskNames.flatMap { dokkaTaskName -> getSubprojectDokkaTasks(dokkaTaskName) }
- }
-
- init {
- group = DOCUMENTATION_GROUP
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
index 986b883a..8369954b 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
@@ -1,66 +1,40 @@
package org.jetbrains.dokka.gradle
-import org.gradle.api.plugins.JavaBasePlugin.DOCUMENTATION_GROUP
+import org.gradle.api.internal.tasks.TaskDependencyInternal
import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaModuleDescriptionImpl
+import org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl
import org.jetbrains.dokka.plugability.Configurable
-import org.jetbrains.dokka.toJsonString
-open class DokkaMultimoduleTask : AbstractDokkaTask(), Configurable {
+open class DokkaMultimoduleTask : AbstractDokkaParentTask(DokkaMultimoduleBootstrapImpl::class), Configurable {
+ /**
+ * Name of the file containing all necessary module information.
+ * This file has to be placed inside the subrpojects root directory.
+ */
@Input
var documentationFileName: String = "README.md"
-
- @Input
- var dokkaTaskNames: Set<String> = setOf()
- set(value) {
- field = value.toSet()
- setDependsOn(getSubprojectDokkaTasks(value))
- }
-
-
- override fun generate() {
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl")
- val configuration = getConfiguration()
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
+ override fun getTaskDependencies(): TaskDependencyInternal {
+ return super.getTaskDependencies() + dokkaTasks
}
- @Internal
- internal fun getConfiguration(): GradleDokkaConfigurationImpl =
- GradleDokkaConfigurationImpl().apply {
- outputDir = project.file(outputDirectory).absolutePath
- pluginsClasspath = plugins.resolve().toList()
- pluginsConfiguration = this@DokkaMultimoduleTask.pluginsConfiguration
- modules = getSubprojectDokkaTasks(dokkaTaskNames).map { dokkaTask ->
- GradleDokkaModuleDescription().apply {
- name = dokkaTask.project.name
- path = dokkaTask.project.projectDir.resolve(dokkaTask.outputDirectory)
- .toRelativeString(project.file(outputDirectory))
- docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absolutePath
- }
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ return DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ pluginsConfiguration = pluginsConfiguration,
+ failOnWarning = failOnWarning,
+ offlineMode = offlineMode,
+ pluginsClasspath = plugins.resolve().toList(),
+ modules = dokkaTasks.map { dokkaTask ->
+ DokkaModuleDescriptionImpl(
+ name = dokkaTask.project.name,
+ path = dokkaTask.outputDirectory.relativeTo(outputDirectory),
+ docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absoluteFile
+ )
}
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskName: String): List<DokkaTask> {
- return project.subprojects
- .mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
- }
-
- private fun getSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<DokkaTask> {
- return dokkaTaskNames.flatMap { dokkaTaskName -> getSubprojectDokkaTasks(dokkaTaskName) }
- }
-
- init {
- group = DOCUMENTATION_GROUP
+ )
}
}
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 b4601acf..a74068ae 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
@@ -1,306 +1,35 @@
package org.jetbrains.dokka.gradle
import org.gradle.api.NamedDomainObjectContainer
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.file.FileCollection
import org.gradle.api.internal.plugins.DslObject
-import org.gradle.api.plugins.JavaBasePlugin
-import org.gradle.api.tasks.*
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
-import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
-import org.jetbrains.dokka.DokkaException
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.ReflectDsl
-import org.jetbrains.dokka.ReflectDsl.isNotInstance
-import org.jetbrains.dokka.gradle.ConfigurationExtractor.PlatformData
-import org.jetbrains.dokka.toJsonString
-import java.io.File
-import java.net.URL
-import java.util.concurrent.Callable
+import org.gradle.api.tasks.Nested
+import org.jetbrains.dokka.DokkaBootstrapImpl
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.build
-open class DokkaTask : AbstractDokkaTask() {
- private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
-
- private val ANDROIDX_REFERENCE_URL = Builder(
- url = URL("https://developer.android.com/reference/kotlin/"),
- packageListUrl = URL("https://developer.android.com/reference/androidx/package-list")
- ).build()
-
- private val configExtractor = ConfigurationExtractor(project)
-
- @Suppress("MemberVisibilityCanBePrivate")
- fun defaultKotlinTasks(): List<Task> = with(ReflectDsl) {
- val abstractKotlinCompileClz = try {
- project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (cnfe: ClassNotFoundException) {
- logger.warn("$ABSTRACT_KOTLIN_COMPILE class not found, default kotlin tasks ignored")
- return@with emptyList<Task>()
- }
-
- return@with project.tasks.filter { it isInstance abstractKotlinCompileClz }.filter { "Test" !in it.name }
- }
-
- init {
- group = JavaBasePlugin.DOCUMENTATION_GROUP
- description = "Generates dokka documentation for Kotlin"
-
- @Suppress("LeakingThis")
- dependsOn(Callable { kotlinTasks.map { it.taskDependencies } })
- }
-
- @Optional
- @Input
- var cacheRoot: String? = null
-
-
- /**
- * Hack used by DokkaCollector to enforce a different configuration to be used.
- */
- @get:Internal
- internal var enforcedConfiguration: GradleDokkaConfigurationImpl? = null
+open class DokkaTask : AbstractDokkaTask(DokkaBootstrapImpl::class) {
@get:Nested
- val dokkaSourceSets: NamedDomainObjectContainer<GradleDokkaSourceSet> =
- project.container(GradleDokkaSourceSet::class.java) { name -> GradleDokkaSourceSet(name, project) }
- .also { container -> DslObject(this).extensions.add("dokkaSourceSets", container) }
-
-
- private val kotlinTasks: List<Task> by lazy {
- extractKotlinCompileTasks(
- dokkaSourceSets.mapNotNull {
- it.collectKotlinTasks?.invoke()
- }.takeIf { it.isNotEmpty() }?.flatten() ?: defaultKotlinTasks()
- )
- }
-
- @Input
- var disableAutoconfiguration: Boolean = false
-
- @Input
- var failOnWarning: Boolean = false
-
- @Input
- var offlineMode: Boolean = false
-
- private var outputDiagnosticInfo: Boolean =
- false // Workaround for Gradle, which fires some methods (like collectConfigurations()) multiple times in its lifecycle
-
- protected fun extractKotlinCompileTasks(collectTasks: List<Any?>?): List<Task> {
- val inputList = (collectTasks ?: emptyList()).filterNotNull()
- val (paths, other) = inputList.partition { it is String }
-
- val tasksByPath = paths.map {
- project.tasks.findByPath(it as String) ?: throw IllegalArgumentException("Task with path '$it' not found")
- }
-
- other
- .filter { it !is Task || it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal entry in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE or String, but was $it") }
-
- tasksByPath
- .filter { it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") }
-
- @Suppress("UNCHECKED_CAST")
- return (tasksByPath + other) as List<Task>
- }
-
- private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootImpl> =
- this.filter { it.exists() }.map { GradleSourceRootImpl().apply { path = it.path } }
-
- private fun Iterable<String>.toProjects(): List<Project> =
- project.subprojects.toList().filter { this.contains(it.name) }
-
- protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) =
- if (project.isAndroidProject()) {
- val generatedRoot = project.buildDir.resolve("generated").absoluteFile
- sourceRoots
- .map { File(it.path) }
- .filter { it.startsWith(generatedRoot) }
- .flatMap { it.walk().toList() }
- .map { it.absolutePath }
- } else {
- emptyList()
- }
-
- override fun generate() = enforcedConfiguration?.let { generate(it) } ?: generate(getConfigurationOrThrow())
-
- protected open fun generate(configuration: GradleDokkaConfigurationImpl) {
- outputDiagnosticInfo = true
- val bootstrap = DokkaBootstrap("org.jetbrains.dokka.DokkaBootstrapImpl")
-
- bootstrap.configure(configuration.toJsonString()) { level, message ->
- when (level) {
- "debug" -> logger.debug(message)
- "info" -> logger.info(message)
- "progress" -> logger.lifecycle(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- }
- bootstrap.generate()
- }
-
-
- @Internal
- internal fun getConfigurationOrNull(): GradleDokkaConfigurationImpl? {
- val defaultModulesConfiguration = configuredDokkaSourceSets
- .map { configureDefault(it) }.takeIf { it.isNotEmpty() }
- ?: listOf(
- configureDefault(configureDokkaSourceSet(dokkaSourceSets.create("main")))
- ).takeIf { project.isNotMultiplatformProject() } ?: emptyList()
-
- if (defaultModulesConfiguration.isEmpty()) {
- return null
- }
-
- return GradleDokkaConfigurationImpl().apply {
- outputDir = project.file(outputDirectory).absolutePath
- cacheRoot = this@DokkaTask.cacheRoot
- offlineMode = this@DokkaTask.offlineMode
- sourceSets = defaultModulesConfiguration
- pluginsClasspath = plugins.resolve().toList()
- pluginsConfiguration = this@DokkaTask.pluginsConfiguration
- failOnWarning = this@DokkaTask.failOnWarning
- }
- }
-
- @Internal
- internal fun getConfigurationOrThrow(): GradleDokkaConfigurationImpl {
- return getConfigurationOrNull() ?: throw DokkaException(
- """
- No source sets to document found.
- Make source to configure at least one source set e.g.
-
- tasks {
- dokkaHtml {
- dokkaSourceSets {
- register("commonMain") {
- displayName = "common"
- platform = "common"
- }
- }
+ val dokkaSourceSets: NamedDomainObjectContainer<GradleDokkaSourceSetBuilder> =
+ project.container(GradleDokkaSourceSetBuilder::class.java, GradleDokkaSourceSetBuilderFactory())
+ .also { container ->
+ DslObject(this).extensions.add("dokkaSourceSets", container)
+ project.findKotlinSourceSets().orEmpty().forEach { kotlinSourceSet ->
+ container.register(kotlinSourceSet.name) { dokkaSourceSet ->
+ dokkaSourceSet.configureWithKotlinSourceSetGist(kotlinSourceSet)
}
}
- """
- )
- }
-
- @get:Internal
- protected val configuredDokkaSourceSets: List<GradleDokkaSourceSet>
- get() = dokkaSourceSets.map { configureDokkaSourceSet(it) }
-
- private fun configureDokkaSourceSet(config: GradleDokkaSourceSet): GradleDokkaSourceSet {
- val userConfig = config
- .apply {
- collectKotlinTasks?.let {
- configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it()))
- .fold(this) { config, platformData ->
- mergeUserConfigurationAndPlatformData(config, platformData)
- }
- }
- }
-
- if (disableAutoconfiguration) return userConfig
-
- return configExtractor.extractConfiguration(userConfig.name)
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: if (this.dokkaSourceSets.isNotEmpty()) {
- if (outputDiagnosticInfo)
- logger.warn(
- "Could not find source set with name: ${userConfig.name} in Kotlin Gradle Plugin, " +
- "using only user provided configuration for this source set"
- )
- userConfig
- } else {
- if (outputDiagnosticInfo)
- logger.warn("Could not find source set with name: ${userConfig.name} in Kotlin Gradle Plugin")
- collectFromSinglePlatformOldPlugin(userConfig.name, userConfig)
}
- }
-
- private fun collectFromSinglePlatformOldPlugin(name: String, userConfig: GradleDokkaSourceSet) =
- kotlinTasks.find { it.name == name }
- ?.let { configExtractor.extractFromKotlinTasks(listOf(it)) }
- ?.singleOrNull()
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: configExtractor.extractFromJavaPlugin()
- ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) }
- ?: userConfig
-
- private fun mergeUserConfigurationAndPlatformData(
- userConfig: GradleDokkaSourceSet,
- autoConfig: PlatformData
- ) = userConfig.copy().apply {
- sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct())
- dependentSourceSets.addAll(userConfig.dependentSourceSets)
- dependentSourceSets.addAll(autoConfig.dependentSourceSets.map { DokkaSourceSetID(project, it) })
- classpath = userConfig.classpath.union(autoConfig.classpath.map { it.absolutePath }).distinct()
- if (userConfig.platform == null && autoConfig.platform != "")
- platform = autoConfig.platform
- }
-
- private fun configureDefault(config: GradleDokkaSourceSet): GradleDokkaSourceSet {
- if (config.moduleDisplayName.isBlank()) {
- config.moduleDisplayName = project.name
- }
-
- if (config.displayName.isBlank()) {
- config.displayName = config.name.substringBeforeLast("Main", config.platform.toString())
- }
-
- if (project.isAndroidProject() && !config.noAndroidSdkLink) {
- config.externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
- config.externalDocumentationLinks.add(ANDROIDX_REFERENCE_URL)
- }
-
- if (config.platform?.isNotBlank() == true) {
- config.analysisPlatform = dokkaPlatformFromString(config.platform.toString())
- }
- // Workaround for Groovy's GStringImpl
- config.classpath = (config.classpath as List<Any>).map { it.toString() }.distinct()
- config.sourceRoots = config.sourceRoots.distinct().toMutableList()
- config.samples = config.samples.map { project.file(it).absolutePath }
- config.includes = config.includes.map { project.file(it).absolutePath }
- config.suppressedFiles += collectSuppressedFiles(config.sourceRoots)
- config.suppressedFiles = config.suppressedFiles.map { project.file(it).absolutePath }
-
- return config
- }
-
- private fun dokkaPlatformFromString(platform: String) = when (platform.toLowerCase()) {
- "androidjvm", "android" -> Platform.jvm
- "metadata" -> Platform.common
- else -> Platform.fromString(platform)
- }
-
- // Needed for Gradle incremental build
- @OutputDirectory
- fun getOutputDirectoryAsFile(): File = project.file(outputDirectory)
-
- // Needed for Gradle incremental build
- @InputFiles
- fun getInputFiles(): FileCollection = configuredDokkaSourceSets.let { config ->
- project.files(config.flatMap { it.sourceRoots }.map { project.fileTree(File(it.path)) }) +
- project.files(config.flatMap { it.includes }) +
- project.files(config.flatMap { it.samples }.map { project.fileTree(File(it)) })
- }
-
- @Classpath
- fun getInputClasspath(): FileCollection =
- project.files((configuredDokkaSourceSets.flatMap { it.classpath } as List<Any>)
- .map { project.fileTree(File(it.toString())) })
-
- companion object {
- const val COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"
- const val ABSTRACT_KOTLIN_COMPILE = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
-
- internal fun getAbstractKotlinCompileFor(task: Task) = try {
- task.project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (e: ClassNotFoundException) {
- null
- }
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ return DokkaConfigurationImpl(
+ outputDir = outputDirectory,
+ cacheRoot = cacheRoot,
+ offlineMode = offlineMode,
+ failOnWarning = failOnWarning,
+ sourceSets = dokkaSourceSets.build(),
+ pluginsConfiguration = pluginsConfiguration,
+ pluginsClasspath = plugins.resolve().toList()
+ )
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt
new file mode 100644
index 00000000..e420e1a5
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleDokkaSourceSetBuilder.kt
@@ -0,0 +1,298 @@
+@file:Suppress("FunctionName")
+
+package org.jetbrains.dokka.gradle
+
+import com.android.build.gradle.api.AndroidSourceSet
+import com.fasterxml.jackson.annotation.JsonIgnore
+import groovy.lang.Closure
+import org.gradle.api.Action
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.tasks.*
+import org.gradle.util.ConfigureUtil
+import org.jetbrains.dokka.*
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import java.io.File
+import java.net.URL
+import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinModelSourceSet
+
+
+internal fun Task.GradleDokkaSourceSetBuilderFactory(): (name: String) -> GradleDokkaSourceSetBuilder =
+ { name -> GradleDokkaSourceSetBuilder(name, project) }
+
+open class GradleDokkaSourceSetBuilder constructor(
+ @get:JsonIgnore @Transient @get:Input val name: String,
+ @get:JsonIgnore @Transient @get:Internal internal val project: Project
+) : DokkaConfigurationBuilder<DokkaSourceSetImpl> {
+
+ @Classpath
+ @Optional
+ var classpath: List<File> = emptyList()
+
+ @Input
+ @Optional
+ var moduleDisplayName: String? = null
+
+ @Input
+ @Optional
+ var displayName: String? = null
+
+ @get:Internal
+ val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name)
+
+ @Nested
+ var sourceRoots: MutableList<GradleSourceRootBuilder> = mutableListOf()
+
+ @Input
+ var dependentSourceSets: MutableSet<DokkaSourceSetID> = mutableSetOf()
+
+ @InputFiles
+ @Optional
+ var samples: List<File> = emptyList()
+
+ @InputFiles
+ @Optional
+ var includes: List<File> = emptyList()
+
+ @Input
+ var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+
+ @Input
+ var includeRootPackage: Boolean = DokkaDefaults.includeRootPackage
+
+ @Input
+ var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ @Input
+ var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages
+
+ @Input
+ var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ @Input
+ var jdkVersion: Int = DokkaDefaults.jdkVersion
+
+ @Nested
+ var sourceLinks: MutableList<GradleSourceLinkBuilder> = mutableListOf()
+
+ @Nested
+ var perPackageOptions: MutableList<GradlePackageOptionsBuilder> = mutableListOf()
+
+ @Nested
+ var externalDocumentationLinks: MutableList<GradleExternalDocumentationLinkBuilder> = mutableListOf()
+
+ @Input
+ @Optional
+ var languageVersion: String? = null
+
+ @Input
+ @Optional
+ var apiVersion: String? = null
+
+ @Input
+ var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink
+
+ @Input
+ var noJdkLink: Boolean = DokkaDefaults.noJdkLink
+
+ @Input
+ var noAndroidSdkLink: Boolean = false
+
+ @Input
+ var suppressedFiles: List<File> = emptyList()
+
+ @Input
+ @Optional
+ var analysisPlatform: Platform? = null
+
+ @Input
+ @Optional
+ var platform: String? = null
+
+ fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID {
+ return DokkaSourceSetID(project, sourceSetName)
+ }
+
+ fun dependsOn(sourceSet: SourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+ }
+
+ fun dependsOn(sourceSet: GradleDokkaSourceSetBuilder) {
+ dependsOn(sourceSet.sourceSetID)
+ }
+
+ fun dependsOn(sourceSet: DokkaConfiguration.DokkaSourceSet) {
+ dependsOn(sourceSet.sourceSetID)
+ }
+
+ fun dependsOn(sourceSetName: String) {
+ dependsOn(DokkaSourceSetID(sourceSetName))
+ }
+
+ fun dependsOn(sourceSetID: DokkaSourceSetID) {
+ dependentSourceSets.add(sourceSetID)
+ }
+
+ // TODO NOW: Cover with tests
+ fun sourceRoot(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceRootBuilder())
+ sourceRoots.add(configured)
+ }
+
+ fun sourceRoot(action: Action<in GradleSourceRootBuilder>) {
+ val sourceRoot = GradleSourceRootBuilder()
+ action.execute(sourceRoot)
+ sourceRoots.add(sourceRoot)
+ }
+
+ fun sourceLink(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceLinkBuilder())
+ sourceLinks.add(configured)
+ }
+
+ fun sourceLink(action: Action<in GradleSourceLinkBuilder>) {
+ val sourceLink = GradleSourceLinkBuilder()
+ action.execute(sourceLink)
+ sourceLinks.add(sourceLink)
+ }
+
+ fun perPackageOption(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradlePackageOptionsBuilder())
+ perPackageOptions.add(configured)
+ }
+
+ fun perPackageOption(action: Action<in GradlePackageOptionsBuilder>) {
+ val option = GradlePackageOptionsBuilder()
+ action.execute(option)
+ perPackageOptions.add(option)
+ }
+
+ fun externalDocumentationLink(c: Closure<Unit>) {
+ val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkBuilder())
+ externalDocumentationLinks.add(link)
+ }
+
+ fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkBuilder>) {
+ val link = GradleExternalDocumentationLinkBuilder()
+ action.execute(link)
+ externalDocumentationLinks.add(link)
+ }
+
+ fun externalDocumentationLink(url: String, packageListUrl: String? = null) {
+ externalDocumentationLinks.add(
+ GradleExternalDocumentationLinkBuilder().apply {
+ this.url = URL(url)
+ this.packageListUrl = URL(packageListUrl)
+ }
+ )
+ }
+
+ fun externalDocumentationLink(url: URL, packageListUrl: URL? = null) {
+ externalDocumentationLinks.add(
+ GradleExternalDocumentationLinkBuilder().apply {
+ this.url = url
+ if (packageListUrl != null) {
+ this.packageListUrl = packageListUrl
+ }
+ }
+ )
+ }
+
+ override fun build(): DokkaSourceSetImpl {
+ val moduleDisplayName = moduleDisplayName ?: project.name
+
+ val displayName = displayName ?: name.substringBeforeLast("Main", platform.toString())
+
+ val externalDocumentationLinks = externalDocumentationLinks.map { it.build() }
+ .run {
+ if (noJdkLink) this
+ else this + ExternalDocumentationLink(
+ url =
+ if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/"
+ else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/java.base/",
+ packageListUrl =
+ if (jdkVersion < 11) "https://docs.oracle.com/javase/${jdkVersion}/docs/api/package-list"
+ else "https://docs.oracle.com/en/java/javase/${jdkVersion}/docs/api/element-list"
+ )
+ }
+ .run {
+ if (noStdlibLink) this
+ else this + ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ }
+ .run {
+ if (noAndroidSdkLink || !project.isAndroidProject()) this
+ else this +
+ ExternalDocumentationLink("https://developer.android.com/reference/") +
+ ExternalDocumentationLink(
+ url = URL("https://developer.android.com/reference/kotlin/"),
+ packageListUrl = URL("https://developer.android.com/reference/androidx/package-list")
+ )
+ }
+
+ val analysisPlatform = when {
+ analysisPlatform != null -> checkNotNull(analysisPlatform)
+
+ platform?.isNotBlank() == true -> when (val platform = platform.toString().toLowerCase()) {
+ "androidjvm", "android" -> Platform.jvm
+ "metadata" -> Platform.common
+ else -> Platform.fromString(platform)
+ }
+
+ else -> Platform.DEFAULT
+ }
+
+ val sourceRoots = sourceRoots.build().distinct()
+
+ val suppressedFiles = suppressedFiles + project.collectSuppressedFiles(sourceRoots)
+
+ return DokkaSourceSetImpl(
+ classpath = classpath.distinct().toList(),
+ moduleDisplayName = moduleDisplayName,
+ displayName = displayName,
+ sourceSetID = sourceSetID,
+ sourceRoots = sourceRoots,
+ dependentSourceSets = dependentSourceSets.toSet(),
+ samples = samples.toList(),
+ includes = includes.toList(),
+ includeNonPublic = includeNonPublic,
+ includeRootPackage = includeRootPackage,
+ reportUndocumented = reportUndocumented,
+ skipEmptyPackages = skipEmptyPackages,
+ skipDeprecated = skipDeprecated,
+ jdkVersion = jdkVersion,
+ sourceLinks = sourceLinks.build(),
+ perPackageOptions = perPackageOptions.build(),
+ externalDocumentationLinks = externalDocumentationLinks,
+ languageVersion = languageVersion,
+ apiVersion = apiVersion,
+ noStdlibLink = noStdlibLink,
+ noJdkLink = noJdkLink,
+ suppressedFiles = suppressedFiles,
+ analysisPlatform = analysisPlatform
+ )
+ }
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinModelSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: KotlinSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+fun GradleDokkaSourceSetBuilder.dependsOn(sourceSet: AndroidSourceSet) {
+ dependsOn(DokkaSourceSetID(sourceSet.name))
+}
+
+// TODO NOW: Test
+private fun Project.collectSuppressedFiles(sourceRoots: List<DokkaConfiguration.SourceRoot>): List<File> =
+ if (project.isAndroidProject()) {
+ val generatedRoot = project.buildDir.resolve("generated").absoluteFile
+ sourceRoots
+ .map { it.directory }
+ .filter { it.startsWith(generatedRoot) }
+ .flatMap { it.walk().toList() }
+ } else {
+ emptyList()
+ }
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt
new file mode 100644
index 00000000..84ad6c1e
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleExternalDocumentationLinkBuilder.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.ExternalDocumentationLink
+import org.jetbrains.dokka.ExternalDocumentationLinkImpl
+import java.net.URL
+
+class GradleExternalDocumentationLinkBuilder : DokkaConfigurationBuilder<ExternalDocumentationLinkImpl> {
+ @Input
+ var url: URL? = null
+
+ @Input
+ var packageListUrl: URL? = null
+
+ override fun build(): ExternalDocumentationLinkImpl {
+ return ExternalDocumentationLink(
+ url = checkNotNull(url) { "url not specified " },
+ packageListUrl = packageListUrl
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt
new file mode 100644
index 00000000..fdc0275e
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradlePackageOptionsBuilder.kt
@@ -0,0 +1,36 @@
+@file:Suppress("FunctionName")
+
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.DokkaDefaults
+import org.jetbrains.dokka.PackageOptionsImpl
+
+
+class GradlePackageOptionsBuilder : DokkaConfigurationBuilder<PackageOptionsImpl> {
+ @Input
+ var prefix: String = ""
+
+ @Input
+ var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
+
+ @Input
+ var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
+
+ @Input
+ var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
+
+ @Input
+ var suppress: Boolean = DokkaDefaults.suppress
+
+ override fun build(): PackageOptionsImpl {
+ return PackageOptionsImpl(
+ prefix = prefix,
+ includeNonPublic = includeNonPublic,
+ reportUndocumented = reportUndocumented,
+ skipDeprecated = skipDeprecated,
+ suppress = suppress
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt
new file mode 100644
index 00000000..007575ec
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceLinkBuilder.kt
@@ -0,0 +1,25 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.Input
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.SourceLinkDefinitionImpl
+
+class GradleSourceLinkBuilder : DokkaConfigurationBuilder<SourceLinkDefinitionImpl> {
+ // TODO NOW: CHECK UP TO DATE
+ @Input
+ var path: String = ""
+
+ @Input
+ var url: String = ""
+
+ @Input
+ var lineSuffix: String? = null
+
+ override fun build(): SourceLinkDefinitionImpl {
+ return SourceLinkDefinitionImpl(
+ path = path,
+ url = url,
+ lineSuffix = lineSuffix
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt
new file mode 100644
index 00000000..687dec9c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/GradleSourceRootBuilder.kt
@@ -0,0 +1,15 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.tasks.InputDirectory
+import org.jetbrains.dokka.DokkaConfigurationBuilder
+import org.jetbrains.dokka.SourceRootImpl
+import java.io.File
+
+class GradleSourceRootBuilder : DokkaConfigurationBuilder<SourceRootImpl> {
+ @InputDirectory
+ var directory: File? = null
+
+ override fun build(): SourceRootImpl {
+ return SourceRootImpl(checkNotNull(directory) { "directory not set" })
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt
new file mode 100644
index 00000000..334aae15
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/KotlinSourceSetGist.kt
@@ -0,0 +1,105 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.jetbrains.dokka.utilities.cast
+import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import java.io.File
+
+private typealias KotlinCompilation =
+ org.jetbrains.kotlin.gradle.plugin.KotlinCompilation<KotlinCommonOptions>
+
+internal data class KotlinSourceSetGist(
+ val name: String,
+ val platform: String,
+ val classpath: List<File>,
+ val sourceRoots: List<File>,
+ val dependentSourceSets: List<String>,
+)
+
+/**
+ * @return null if the kotlin extension cannot be found,
+ * A list of [KotlinSourceSetGist] for every currently registered kotlin source set
+ */
+internal fun Project.findKotlinSourceSets(): List<KotlinSourceSetGist>? {
+ val kotlin = kotlinExtensionOrNull ?: return null
+ return kotlin.sourceSets.map { sourceSet -> kotlin.gistOf(sourceSet) }
+}
+
+internal fun KotlinProjectExtension.gistOf(sourceSet: KotlinSourceSet): KotlinSourceSetGist {
+ return KotlinSourceSetGist(
+ name = sourceSet.name,
+ platform = platformOf(sourceSet),
+ classpath = classpathOf(sourceSet).filter(File::exists),
+ sourceRoots = sourceSet.kotlin.sourceDirectories.toList().filter(File::exists),
+ dependentSourceSets = sourceSet.dependsOn.map { dependentSourceSet -> dependentSourceSet.name },
+ )
+}
+
+private fun KotlinProjectExtension.classpathOf(sourceSet: KotlinSourceSet): List<File> {
+ val compilations = compilationsOf(sourceSet)
+ if (compilations.isNotEmpty()) {
+ return compilations
+ .flatMap { compilation -> compileClasspathOf(compilation) }
+ .distinct()
+ }
+
+ return sourceSet.withAllDependentSourceSets()
+ .toList()
+ .flatMap { it.kotlin.sourceDirectories }
+}
+
+private fun KotlinProjectExtension.platformOf(sourceSet: KotlinSourceSet): String {
+ val targetNames = compilationsOf(sourceSet).map { compilation -> compilation.target.platformType.name }.distinct()
+ return when (targetNames.size) {
+ 0 -> KotlinPlatformType.common.name
+ 1 -> targetNames.single()
+ else -> throw IllegalArgumentException(
+ "Source set ${sourceSet.name} is expected to have only one target. Found $targetNames"
+ )
+ }
+}
+
+private fun KotlinProjectExtension.compilationsOf(
+ sourceSet: KotlinSourceSet
+): List<KotlinCompilation> {
+ return when (this) {
+ is KotlinMultiplatformExtension -> compilationsOf(sourceSet)
+ is KotlinSingleTargetExtension -> compilationsOf(sourceSet)
+ else -> emptyList()
+ }
+}
+
+private fun KotlinMultiplatformExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> {
+ val allCompilations = targets.flatMap { target -> target.compilations }
+ return allCompilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets }
+}
+
+private fun KotlinSingleTargetExtension.compilationsOf(sourceSet: KotlinSourceSet): List<KotlinCompilation> {
+ return target.compilations.filter { compilation -> sourceSet in compilation.kotlinSourceSets }
+}
+
+private fun compileClasspathOf(compilation: KotlinCompilation): List<File> {
+ if (compilation.target.isAndroidTarget()) {
+ // This is a workaround for https://youtrack.jetbrains.com/issue/KT-33893
+ return compilation.compileKotlinTask.cast<KotlinCompile>().classpath.files.toList()
+ }
+ return compilation.compileDependencyFiles.files.toList()
+}
+
+private fun KotlinSourceSet.withAllDependentSourceSets(): Sequence<KotlinSourceSet> {
+ return sequence {
+ yield(this@withAllDependentSourceSets)
+ for (dependentSourceSet in dependsOn) {
+ yieldAll(dependentSourceSet.withAllDependentSourceSets())
+ }
+ }
+}
+
+
+
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt
deleted file mode 100644
index 4b511022..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ReflectDsl.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.jetbrains.dokka
-
-import kotlin.reflect.*
-import kotlin.reflect.full.memberFunctions
-import kotlin.reflect.full.memberProperties
-import kotlin.reflect.jvm.isAccessible
-
-internal object ReflectDsl {
-
- class CallOrPropAccess(private val receiver: Any?,
- private val clz: KClass<*>,
- private val selector: String) {
-
- @Suppress("UNCHECKED_CAST")
- operator fun <T : Any?> invoke(vararg a: Any?): T {
- return func!!.call(receiver, *a) as T
- }
-
- operator fun get(s: String): CallOrPropAccess {
- return v<Any?>()!![s]
- }
-
- val func: KFunction<*>? by lazy { clz.memberFunctions.find { it.name == selector } }
- val prop: KProperty<*>? by lazy { clz.memberProperties.find { it.name == selector } }
-
- fun takeIfIsFunc(): CallOrPropAccess? = if (func != null) this else null
-
- fun takeIfIsProp(): CallOrPropAccess? = if (prop != null) this else null
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Any?> v(): T {
- val prop = prop!!
- return try {
- prop.getter.apply { isAccessible = true }.call(receiver) as T
- } catch (e: KotlinNullPointerException) {
- // Hack around kotlin-reflect bug KT-18480
- val jclass = clz.java
- val customGetterName = prop.getter.name
- val getterName = if (customGetterName.startsWith("<")) "get" + prop.name.capitalize() else customGetterName
- val getter = jclass.getDeclaredMethod(getterName)
- getter.isAccessible = true
-
- getter.invoke(receiver) as T
-
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- fun v(x: Any?) {
- (prop as KMutableProperty).setter.apply { isAccessible = true }.call(receiver, x)
- }
-
-
- }
-
- operator fun Any.get(s: String): CallOrPropAccess {
- val clz = this.javaClass.kotlin
- return CallOrPropAccess(this, clz, s)
- }
-
- operator fun Any.get(s: String, clz: Class<*>): CallOrPropAccess {
- val kclz = clz.kotlin
- return CallOrPropAccess(this, kclz, s)
- }
-
- operator fun Any.get(s: String, clz: KClass<*>): CallOrPropAccess {
- return CallOrPropAccess(this, clz, s)
- }
-
- inline infix fun Any.isInstance(clz: Class<*>?): Boolean = clz != null && clz.isAssignableFrom(this.javaClass)
- inline infix fun Any.isNotInstance(clz: Class<*>?): Boolean = !(this isInstance clz)
-} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt
new file mode 100644
index 00000000..fb648c02
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt
@@ -0,0 +1,20 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Task
+import org.gradle.api.internal.tasks.AbstractTaskDependency
+import org.gradle.api.internal.tasks.TaskDependencyInternal
+import org.gradle.api.internal.tasks.TaskDependencyResolveContext
+
+operator fun TaskDependencyInternal.plus(tasks: Iterable<Task>): TaskDependencyInternal {
+ return TaskDependencyInternalWithAdditions(this, tasks.toSet())
+}
+
+private class TaskDependencyInternalWithAdditions(
+ private val dependency: TaskDependencyInternal,
+ private val additionalTaskDependencies: Set<Task>
+) : AbstractTaskDependency() {
+ override fun visitDependencies(context: TaskDependencyResolveContext) {
+ dependency.visitDependencies(context)
+ additionalTaskDependencies.forEach(context::add)
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt
index 468f597f..13f9c2ff 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/automagicTypedProxy.kt
@@ -1,6 +1,9 @@
package org.jetbrains.dokka.gradle
-import java.lang.reflect.*
+import java.lang.reflect.InvocationHandler
+import java.lang.reflect.InvocationTargetException
+import java.lang.reflect.Method
+import java.lang.reflect.Proxy
/**
@@ -21,14 +24,14 @@ internal inline fun <reified T : Any> automagicTypedProxy(targetClassLoader: Cla
* to create access proxy for [delegate] into [targetClassLoader].
*
*/
-internal fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
+private fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
Proxy.newProxyInstance(
targetClassLoader,
arrayOf(targetType),
DelegatedInvocationHandler(delegate)
)
-internal class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
+private class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
@Throws(Throwable::class)
override fun invoke(proxy: Any, method: Method, args: Array<Any?>?): Any? {
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
deleted file mode 100644
index bed73d6d..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
+++ /dev/null
@@ -1,259 +0,0 @@
-@file:Suppress("FunctionName")
-
-package org.jetbrains.dokka.gradle
-
-import com.android.build.gradle.api.AndroidSourceSet
-import com.fasterxml.jackson.annotation.JsonIgnore
-import groovy.lang.Closure
-import org.gradle.api.Action
-import org.gradle.api.Project
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.Optional
-import org.gradle.util.ConfigureUtil
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.*
-import org.jetbrains.dokka.DokkaDefaults
-import org.jetbrains.dokka.DokkaSourceSetID
-import org.jetbrains.dokka.Platform
-import java.io.File
-import java.net.URL
-import java.util.concurrent.Callable
-import kotlin.reflect.KMutableProperty
-import kotlin.reflect.full.memberProperties
-import org.gradle.api.tasks.SourceSet as GradleSourceSet
-import org.jetbrains.kotlin.gradle.model.SourceSet as KotlinSourceSet
-
-class GradleSourceRootImpl : SourceRoot {
- override var path: String = ""
- set(value) {
- field = File(value).absolutePath
- }
-
- override fun toString(): String = path
-}
-
-open class GradleDokkaSourceSet constructor(
- @get:JsonIgnore @Transient @get:Input val name: String,
- @get:JsonIgnore @Transient @get:Internal internal val project: Project
-) : DokkaSourceSet {
-
- @Input
- @Optional
- override var classpath: List<String> = emptyList()
-
- @Input
- override var moduleDisplayName: String = ""
-
- @Input
- override var displayName: String = ""
-
- @get:Internal
- override val sourceSetID: DokkaSourceSetID = DokkaSourceSetID(project, name)
-
- @Input
- override var sourceRoots: MutableList<SourceRoot> = mutableListOf()
-
- @Input
- override var dependentSourceSets: MutableSet<DokkaSourceSetID> = mutableSetOf()
-
- @Input
- override var samples: List<String> = emptyList()
-
- @Input
- override var includes: List<String> = emptyList()
-
- @Input
- override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
-
- @Input
- override var includeRootPackage: Boolean = DokkaDefaults.includeRootPackage
-
- @Input
- override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
-
- @Input
- override var skipEmptyPackages: Boolean = DokkaDefaults.skipEmptyPackages
-
- @Input
- override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
-
- @Input
- override var jdkVersion: Int = DokkaDefaults.jdkVersion
-
- @Input
- override var sourceLinks: MutableList<SourceLinkDefinition> = mutableListOf()
-
- @Input
- override var perPackageOptions: MutableList<PackageOptions> = mutableListOf()
-
- @Input
- override var externalDocumentationLinks: MutableList<ExternalDocumentationLink> = mutableListOf()
-
- @Input
- @Optional
- override var languageVersion: String? = null
-
- @Input
- @Optional
- override var apiVersion: String? = null
-
- @Input
- override var noStdlibLink: Boolean = DokkaDefaults.noStdlibLink
-
- @Input
- override var noJdkLink: Boolean = DokkaDefaults.noJdkLink
-
- @Input
- var noAndroidSdkLink: Boolean = false
-
- @Input
- override var suppressedFiles: List<String> = emptyList()
-
- @Input
- override var analysisPlatform: Platform = DokkaDefaults.analysisPlatform
-
- @Input
- @Optional
- var platform: String? = null
-
- @JsonIgnore
- @Internal
- @Transient
- var collectKotlinTasks: (() -> List<Any?>?)? = null
-
- fun DokkaSourceSetID(sourceSetName: String): DokkaSourceSetID {
- return DokkaSourceSetID(project, sourceSetName)
- }
-
- fun dependsOn(sourceSet: GradleSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
- }
-
- fun dependsOn(sourceSet: DokkaSourceSet) {
- dependsOn(sourceSet.sourceSetID)
- }
-
- fun dependsOn(sourceSetName: String) {
- dependsOn(DokkaSourceSetID(sourceSetName))
- }
-
- fun dependsOn(sourceSetID: DokkaSourceSetID) {
- dependentSourceSets.add(sourceSetID)
- }
-
- fun kotlinTasks(taskSupplier: Callable<List<Any>>) {
- collectKotlinTasks = { taskSupplier.call() }
- }
-
- fun kotlinTasks(closure: Closure<Any?>) {
- collectKotlinTasks = { closure.call() as? List<Any?> }
- }
-
- fun sourceRoot(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradleSourceRootImpl())
- sourceRoots.add(configured)
- }
-
- fun sourceRoot(action: Action<in GradleSourceRootImpl>) {
- val sourceRoot = GradleSourceRootImpl()
- action.execute(sourceRoot)
- sourceRoots.add(sourceRoot)
- }
-
- fun sourceLink(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradleSourceLinkDefinitionImpl())
- sourceLinks.add(configured)
- }
-
- fun sourceLink(action: Action<in GradleSourceLinkDefinitionImpl>) {
- val sourceLink = GradleSourceLinkDefinitionImpl()
- action.execute(sourceLink)
- sourceLinks.add(sourceLink)
- }
-
- fun perPackageOption(c: Closure<Unit>) {
- val configured = ConfigureUtil.configure(c, GradlePackageOptionsImpl())
- perPackageOptions.add(configured)
- }
-
- fun perPackageOption(action: Action<in GradlePackageOptionsImpl>) {
- val option = GradlePackageOptionsImpl()
- action.execute(option)
- perPackageOptions.add(option)
- }
-
- fun externalDocumentationLink(c: Closure<Unit>) {
- val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkImpl())
- externalDocumentationLinks.add(ExternalDocumentationLink.Builder(link.url, link.packageListUrl).build())
- }
-
- fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl>) {
- val link = GradleExternalDocumentationLinkImpl()
- action.execute(link)
- externalDocumentationLinks.add(ExternalDocumentationLink.Builder(link.url, link.packageListUrl).build())
- }
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: KotlinSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-fun GradleDokkaSourceSet.dependsOn(sourceSet: AndroidSourceSet) {
- dependsOn(DokkaSourceSetID(sourceSet.name))
-}
-
-class GradleSourceLinkDefinitionImpl : SourceLinkDefinition {
- override var path: String = ""
- override var url: String = ""
- override var lineSuffix: String? = null
-}
-
-class GradleExternalDocumentationLinkImpl : ExternalDocumentationLink {
- override var url: URL = URL("http://")
- override var packageListUrl: URL = URL("http://")
-}
-
-class GradleDokkaModuleDescription : DokkaModuleDescription {
- override var name: String = ""
- override var path: String = ""
- override var docFile: String = ""
-}
-
-class GradleDokkaConfigurationImpl : DokkaConfiguration {
- override var outputDir: String = ""
- override var cacheRoot: String? = DokkaDefaults.cacheRoot
- override var offlineMode: Boolean = DokkaDefaults.offlineMode
- override var failOnWarning: Boolean = DokkaDefaults.failOnWarning
- override var sourceSets: List<GradleDokkaSourceSet> = emptyList()
- override var pluginsClasspath: List<File> = emptyList()
- override var pluginsConfiguration: Map<String, String> = mutableMapOf()
- override var modules: List<GradleDokkaModuleDescription> = emptyList()
-}
-
-class GradlePackageOptionsImpl : PackageOptions {
- override var prefix: String = ""
- override var includeNonPublic: Boolean = DokkaDefaults.includeNonPublic
- override var reportUndocumented: Boolean = DokkaDefaults.reportUndocumented
- override var skipDeprecated: Boolean = DokkaDefaults.skipDeprecated
- override var suppress: Boolean = DokkaDefaults.suppress
-}
-
-internal fun GradleDokkaSourceSet.copy(): GradleDokkaSourceSet {
- val newObj = GradleDokkaSourceSet(this.name, this.project)
- this::class.memberProperties.forEach { field ->
- if (field is KMutableProperty<*>) {
- when (val value = field.getter.call(this)) {
- is List<*> -> field.setter.call(newObj, value.toMutableList())
- is Set<*> -> field.setter.call(newObj, value.toMutableSet())
- else -> field.setter.call(newObj, field.getter.call(this))
- }
-
- }
- }
- return newObj
-}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt
new file mode 100644
index 00000000..2625f64c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt
@@ -0,0 +1,7 @@
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.withType
+import org.jetbrains.dokka.gradle.DokkaTask
+
+fun Project.dokka(configuration: DokkaTask.() -> Unit) {
+ tasks.withType<DokkaTask>().configureEach(configuration)
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt
index df29c19b..8a40ac89 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaBootstrapFactory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaBootstrapFactory.kt
@@ -1,18 +1,21 @@
+@file:Suppress("FunctionName")
+
package org.jetbrains.dokka.gradle
import org.gradle.api.artifacts.Configuration
import org.jetbrains.dokka.DokkaBootstrap
import java.net.URLClassLoader
+import kotlin.reflect.KClass
-fun DokkaBootstrap(configuration: Configuration, bootstrapClassFQName: String): DokkaBootstrap {
+fun DokkaBootstrap(configuration: Configuration, bootstrapClass: KClass<out DokkaBootstrap>): DokkaBootstrap {
val runtimeJars = configuration.resolve()
val runtimeClassLoader = URLClassLoader(
runtimeJars.map { it.toURI().toURL() }.toTypedArray(),
ClassLoader.getSystemClassLoader().parent
)
- val bootstrapClass = runtimeClassLoader.loadClass(bootstrapClassFQName)
- val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
- return automagicTypedProxy(DokkaPlugin::class.java.classLoader, bootstrapInstance)
+ val runtimeClassloaderBootstrapClass = runtimeClassLoader.loadClass(bootstrapClass.qualifiedName)
+ val runtimeClassloaderBootstrapInstance = runtimeClassloaderBootstrapClass.constructors.first().newInstance()
+ return automagicTypedProxy(DokkaPlugin::class.java.classLoader, runtimeClassloaderBootstrapInstance)
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt
index 0a7ab534..0a7ab534 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/defaultDokkaOutputDirectory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaDefaultOutputDirectory.kt
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt
index 3fadb4fd..3fadb4fd 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaSourceSetIDFactory.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaSourceSetIDFactory.kt
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt
index 20f54cc5..20f54cc5 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokkaConfigurations.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/gradleConfigurations.kt
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 51356703..71fad405 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
@@ -53,7 +53,6 @@ open class DokkaPlugin : Plugin<Project> {
}
if (collectorTaskSupported) {
project.tasks.register<DokkaCollectorTask>("${name}Collector") {
- modules = project.subprojects.map(Project::getName)
dokkaTaskNames = dokkaTaskNames + name
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt
new file mode 100644
index 00000000..9bb11f36
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/sourceSetKotlinGistConfiguration.kt
@@ -0,0 +1,21 @@
+package org.jetbrains.dokka.gradle
+
+import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
+import java.io.File
+
+// TODO NOW: Test
+fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSet(sourceSet: KotlinSourceSet) {
+ configureWithKotlinSourceSetGist(project.kotlinExtension.gistOf(sourceSet))
+}
+
+internal fun GradleDokkaSourceSetBuilder.configureWithKotlinSourceSetGist(sourceSet: KotlinSourceSetGist) {
+ sourceRoots.addAll(sourceRoots.union(sourceSet.sourceRoots.toSourceRoots()).distinct())
+ dependentSourceSets.addAll(dependentSourceSets)
+ dependentSourceSets.addAll(sourceSet.dependentSourceSets.map { DokkaSourceSetID(project, it) })
+ classpath = classpath.union(sourceSet.classpath).distinct()
+ if (platform == null && sourceSet.platform != "")
+ platform = sourceSet.platform
+}
+
+private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootBuilder> =
+ this.filter { it.exists() }.map { GradleSourceRootBuilder().apply { directory = it } }
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
index b6c5cbd8..12e22f5d 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
@@ -4,9 +4,20 @@ import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+internal val Project.kotlinExtensionOrNull: KotlinProjectExtension?
+ get() = try {
+ project.extensions.findByType(KotlinProjectExtension::class.java)
+ } catch (e: NoClassDefFoundError) {
+ null
+ }
+
+internal val Project.kotlinExtension: KotlinProjectExtension
+ get() = project.extensions.getByType(KotlinProjectExtension::class.java)
+
internal fun Project.isAndroidProject() = try {
project.extensions.getByName("android")
@@ -35,3 +46,4 @@ internal fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatfor
internal fun <T : Any> NamedDomainObjectContainer<T>.maybeCreate(name: String, configuration: T.() -> Unit): T {
return findByName(name) ?: create(name, configuration)
}
+