aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsebastian.sellmair <sebastian.sellmair@jetbrains.com>2020-08-05 22:56:16 +0200
committerSebastian Sellmair <34319766+sellmair@users.noreply.github.com>2020-08-14 17:51:11 +0200
commite3c1b2bdbfe20e602fbf570df946edc94266e5ff (patch)
treeccd210e61209e7540954667a34d8d4126a8a0c70
parent23827bed7b4877b15633e1924f7ee3864f8ebe2c (diff)
downloaddokka-e3c1b2bdbfe20e602fbf570df946edc94266e5ff.tar.gz
dokka-e3c1b2bdbfe20e602fbf570df946edc94266e5ff.tar.bz2
dokka-e3c1b2bdbfe20e602fbf570df946edc94266e5ff.zip
API refinement for AbstractDokkaParentTask and DokkaMultiModuleTask
-rw-r--r--core/src/main/kotlin/defaultConfiguration.kt2
-rw-r--r--integration-tests/gradle/projects/it-basic/build.gradle.kts2
-rw-r--r--integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/MultiModule0IntegrationTest.kt (renamed from integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt)17
-rw-r--r--kotlin-analysis/intellij-dependency/build.gradle.kts4
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTask.kt103
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaTask.kt35
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTask.kt15
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayout.kt52
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt69
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt42
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt10
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/TaskDependencyInternalWithAdditions.kt2
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/checkChildDokkaTasksIsNotEmpty.kt43
-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/main.kt27
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt1
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt10
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt255
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt26
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt14
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt13
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayoutTest.kt100
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt88
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaPluginApplyTest.kt (renamed from runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaTasksTest.kt)21
-rw-r--r--runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt11
25 files changed, 710 insertions, 259 deletions
diff --git a/core/src/main/kotlin/defaultConfiguration.kt b/core/src/main/kotlin/defaultConfiguration.kt
index 384fa27e..ec461ffd 100644
--- a/core/src/main/kotlin/defaultConfiguration.kt
+++ b/core/src/main/kotlin/defaultConfiguration.kt
@@ -32,7 +32,7 @@ data class DokkaSourceSetImpl(
override val jdkVersion: Int = DokkaDefaults.jdkVersion,
override val sourceLinks: Set<SourceLinkDefinitionImpl> = emptySet(),
override val perPackageOptions: List<PackageOptionsImpl> = emptyList(),
- override var externalDocumentationLinks: Set<ExternalDocumentationLinkImpl> = emptySet(),
+ override val externalDocumentationLinks: Set<ExternalDocumentationLinkImpl> = emptySet(),
override val languageVersion: String? = null,
override val apiVersion: String? = null,
override val noStdlibLink: Boolean = DokkaDefaults.noStdlibLink,
diff --git a/integration-tests/gradle/projects/it-basic/build.gradle.kts b/integration-tests/gradle/projects/it-basic/build.gradle.kts
index 1840ba94..43d3a0f3 100644
--- a/integration-tests/gradle/projects/it-basic/build.gradle.kts
+++ b/integration-tests/gradle/projects/it-basic/build.gradle.kts
@@ -28,5 +28,3 @@ tasks.withType<DokkaTask> {
}
}
}
-
-buildDir.resolve("")
diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/MultiModule0IntegrationTest.kt
index 70b5832d..0184d150 100644
--- a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/Multimodule0IntegrationTest.kt
+++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/MultiModule0IntegrationTest.kt
@@ -5,7 +5,7 @@ import org.junit.runners.Parameterized
import java.io.File
import kotlin.test.*
-class Multimodule0IntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
+class MultiModule0IntegrationTest(override val versions: BuildVersions) : AbstractGradleIntegrationTest() {
companion object {
@get:JvmStatic
@get:Parameterized.Parameters(name = "{0}")
@@ -27,15 +27,15 @@ class Multimodule0IntegrationTest(override val versions: BuildVersions) : Abstra
@Test
fun execute() {
val result = createGradleRunner(
- ":moduleA:dokkaHtmlMultimodule",
- ":moduleA:dokkaGfmMultimodule",
- ":moduleA:dokkaJekyllMultimodule",
+ ":moduleA:dokkaHtmlMultiModule",
+ ":moduleA:dokkaGfmMultiModule",
+ ":moduleA:dokkaJekyllMultiModule",
"-i", "-s"
).buildRelaxed()
- assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaHtmlMultimodule")).outcome)
- assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaGfmMultimodule")).outcome)
- assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaJekyllMultimodule")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaHtmlMultiModule")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaGfmMultiModule")).outcome)
+ assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:dokkaJekyllMultiModule")).outcome)
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleB:dokkaHtml")).outcome)
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleC:dokkaHtml")).outcome)
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleB:dokkaGfm")).outcome)
@@ -44,7 +44,7 @@ class Multimodule0IntegrationTest(override val versions: BuildVersions) : Abstra
assertEquals(TaskOutcome.SUCCESS, assertNotNull(result.task(":moduleA:moduleC:dokkaJekyll")).outcome)
- val outputDir = File(projectDir, "moduleA/build/dokka/htmlMultimodule")
+ val outputDir = File(projectDir, "moduleA/build/dokka/htmlMultiModule")
assertTrue(outputDir.isDirectory, "Missing dokka output directory")
assertTrue(
@@ -70,6 +70,5 @@ class Multimodule0IntegrationTest(override val versions: BuildVersions) : Abstra
"moduleC" in modulesFileText,
"Expected moduleC being mentioned in -modules.html"
)
-
}
}
diff --git a/kotlin-analysis/intellij-dependency/build.gradle.kts b/kotlin-analysis/intellij-dependency/build.gradle.kts
index 4ff68e4e..8e080374 100644
--- a/kotlin-analysis/intellij-dependency/build.gradle.kts
+++ b/kotlin-analysis/intellij-dependency/build.gradle.kts
@@ -30,10 +30,6 @@ dependencies {
val idea_version: String by project
intellijCore("com.jetbrains.intellij.idea:intellij-core:$idea_version")
implementation(intellijCoreAnalysis())
-
- val kotlin_version: String by project
- api("org.jetbrains.kotlin:kotlin-compiler:$kotlin_version")
-
}
tasks {
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
index bf8308bf..c782197e 100644
--- 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
@@ -1,73 +1,86 @@
package org.jetbrains.dokka.gradle
import org.gradle.api.Project
-import org.gradle.api.tasks.Input
+import org.gradle.api.Task
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()
+ internal var childDokkaTaskPaths: Set<String> = emptySet()
+ private set
@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
+ internal val childDokkaTasks: Set<AbstractDokkaTask>
+ get() = childDokkaTaskPaths
+ .mapNotNull { path -> project.tasks.findByPath(path) }
+ .map(::checkIsAbstractDokkaTask)
+ .toSet()
+
+ /* By task reference */
+ fun addChildTask(task: AbstractDokkaTask) {
+ childDokkaTaskPaths = childDokkaTaskPaths + task.path
+ }
+
+ fun removeChildTask(task: AbstractDokkaTask) {
+ childDokkaTaskPaths = childDokkaTaskPaths - task.path
+ }
+
+ /* By path */
+ fun addChildTask(path: String) {
+ childDokkaTaskPaths = childDokkaTaskPaths + project.absoluteProjectPath(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)
+ fun removeChildTask(path: String) {
+ childDokkaTaskPaths = childDokkaTaskPaths - project.absoluteProjectPath(path)
}
- /**
- * 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)
+ /* By project reference and name */
+ fun addChildTasks(projects: Iterable<Project>, childTasksName: String) {
+ projects.forEach { project ->
+ addChildTask(project.absoluteProjectPath(childTasksName))
+ }
}
- /**
- * Includes the [project] and all its subprojects to participate in this parent task.
- * @see addSubproject
- */
- fun addAllProjects(project: Project) {
- project.allprojects.forEach(::addSubproject)
+ fun removeChildTasks(projects: Iterable<Project>, childTasksName: String) {
+ projects.forEach { project ->
+ removeChildTask(project.absoluteProjectPath(childTasksName))
+ }
}
- protected fun findSubprojectDokkaTasks(dokkaTaskNames: Set<String>): List<AbstractDokkaTask> {
- return dokkaTaskNames.flatMap { dokkaTaskName -> findSubprojectDokkaTasks(dokkaTaskName) }
+ fun addSubprojectChildTasks(childTasksName: String) {
+ addChildTasks(project.subprojects, childTasksName)
}
- private fun findSubprojectDokkaTasks(dokkaTaskName: String): List<AbstractDokkaTask> {
- return subprojects.mapNotNull { subproject -> subproject.tasks.findByName(dokkaTaskName) as? DokkaTask }
+ fun removeSubprojectChildTasks(childTasksName: String) {
+ removeChildTasks(project.subprojects, childTasksName)
+ }
+
+ fun removeChildTasks(project: Project) {
+ childDokkaTaskPaths = childDokkaTaskPaths.filter { path ->
+ parsePath(path).parent != parsePath(project.path)
+ }.toSet()
+ }
+
+ fun removeChildTasks(projects: Iterable<Project>) {
+ projects.forEach { project -> removeChildTasks(project) }
+ }
+
+ private fun checkIsAbstractDokkaTask(task: Task): AbstractDokkaTask {
+ if (task is AbstractDokkaTask) {
+ return task
+ }
+ throw IllegalArgumentException(
+ "Only tasks of type ${AbstractDokkaTask::class.java.name} can be added as child for " +
+ "${AbstractDokkaParentTask::class.java.name} tasks.\n" +
+ "Found task ${task.path} of type ${task::class.java.name} added to $path"
+ )
}
}
+
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 6413d788..5deaac49 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,12 +1,20 @@
+@file:Suppress("UnstableApiUsage")
+
package org.jetbrains.dokka.gradle
+import groovy.lang.Closure
+import org.gradle.api.Action
import org.gradle.api.DefaultTask
+import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.provider.MapProperty
+import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
+import org.gradle.kotlin.dsl.mapProperty
import org.jetbrains.dokka.DokkaBootstrap
import org.jetbrains.dokka.DokkaConfigurationImpl
-import org.jetbrains.dokka.plugability.Configurable
+import org.jetbrains.dokka.DokkaDefaults
import org.jetbrains.dokka.toJsonString
import java.io.File
import java.util.function.BiConsumer
@@ -14,23 +22,26 @@ import kotlin.reflect.KClass
abstract class AbstractDokkaTask(
private val bootstrapClass: KClass<out DokkaBootstrap> = DokkaBootstrap::class
-) : DefaultTask(), Configurable {
+) : DefaultTask() {
@OutputDirectory
- var outputDirectory: File = defaultDokkaOutputDirectory()
+ val outputDirectory: Property<File> = project.objects.safeProperty<File>()
+ .safeConvention(defaultDokkaOutputDirectory())
@Optional
@InputDirectory
- var cacheRoot: File? = null
+ val cacheRoot: Property<File?> = project.objects.safeProperty()
@Input
- var failOnWarning: Boolean = false
+ val failOnWarning: Property<Boolean> = project.objects.safeProperty<Boolean>()
+ .safeConvention(DokkaDefaults.failOnWarning)
@Input
- var offlineMode: Boolean = false
+ val offlineMode: Property<Boolean> = project.objects.safeProperty<Boolean>()
+ .safeConvention(DokkaDefaults.offlineMode)
@Input
- override val pluginsConfiguration: MutableMap<String, String> = mutableMapOf()
+ val pluginsConfiguration: MapProperty<String, String> = project.objects.mapProperty()
@Classpath
val plugins: Configuration = project.maybeCreateDokkaPluginConfiguration(name)
@@ -38,8 +49,16 @@ abstract class AbstractDokkaTask(
@Classpath
val runtime: Configuration = project.maybeCreateDokkaRuntimeConfiguration(name)
+ final override fun doFirst(action: Action<in Task>): Task {
+ return super.doFirst(action)
+ }
+
+ final override fun doFirst(action: Closure<*>): Task {
+ return super.doFirst(action)
+ }
+
@TaskAction
- protected open fun generateDocumentation() {
+ internal open fun generateDocumentation() {
DokkaBootstrap(runtime, bootstrapClass).apply {
configure(buildDokkaConfiguration().toJsonString(), createProxyLogger())
generate()
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 4762c333..37571fc5 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
@@ -4,16 +4,21 @@ import org.jetbrains.dokka.DokkaConfigurationImpl
open class DokkaCollectorTask : AbstractDokkaParentTask() {
+ override fun generateDocumentation() {
+ checkChildDokkaTasksIsNotEmpty()
+ super.generateDocumentation()
+ }
+
override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
val initialDokkaConfiguration = DokkaConfigurationImpl(
- outputDir = outputDirectory,
- cacheRoot = cacheRoot,
- failOnWarning = failOnWarning,
- offlineMode = offlineMode,
+ outputDir = outputDirectory.getSafe(),
+ cacheRoot = cacheRoot.getSafe(),
+ failOnWarning = failOnWarning.getSafe(),
+ offlineMode = offlineMode.getSafe(),
pluginsClasspath = plugins.resolve().toSet(),
)
- val subprojectDokkaConfigurations = dokkaTasks.map { dokkaTask -> dokkaTask.buildDokkaConfiguration() }
+ val subprojectDokkaConfigurations = childDokkaTasks.map { dokkaTask -> dokkaTask.buildDokkaConfiguration() }
return subprojectDokkaConfigurations.fold(initialDokkaConfiguration) { acc, it: DokkaConfigurationImpl ->
acc.copy(
sourceSets = acc.sourceSets + it.sourceSets,
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayout.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayout.kt
new file mode 100644
index 00000000..8cca98d5
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayout.kt
@@ -0,0 +1,52 @@
+package org.jetbrains.dokka.gradle
+
+import java.io.File
+
+interface DokkaMultiModuleFileLayout {
+ fun targetChildOutputDirectory(parent: AbstractDokkaParentTask, child: AbstractDokkaTask): File
+
+ object NoCopy : DokkaMultiModuleFileLayout {
+ override fun targetChildOutputDirectory(parent: AbstractDokkaParentTask, child: AbstractDokkaTask): File {
+ return child.outputDirectory.getSafe()
+ }
+ }
+
+ object CompactInParent : DokkaMultiModuleFileLayout {
+ override fun targetChildOutputDirectory(parent: AbstractDokkaParentTask, child: AbstractDokkaTask): File {
+ val relativeProjectPath = parent.project.relativeProjectPath(child.project.path)
+ val relativeFilePath = relativeProjectPath.replace(":", File.separator)
+ check(!File(relativeFilePath).isAbsolute) { "Unexpected absolute path $relativeFilePath" }
+ return parent.outputDirectory.getSafe().resolve(relativeFilePath)
+ }
+ }
+}
+
+internal fun DokkaMultiModuleTask.targetChildOutputDirectory(
+ child: AbstractDokkaTask
+): File {
+ return fileLayout.targetChildOutputDirectory(this, child)
+}
+
+internal fun DokkaMultiModuleTask.copyChildOutputDirectories() {
+ childDokkaTasks.forEach { child ->
+ fileLayout.copyChildOutputDirectory(this, child)
+ }
+}
+
+internal fun DokkaMultiModuleFileLayout.copyChildOutputDirectory(
+ parent: AbstractDokkaParentTask, child: AbstractDokkaTask
+) {
+ val targetChildOutputDirectory = parent.project.file(targetChildOutputDirectory(parent, child))
+ val sourceChildOutputDirectory = child.outputDirectory.getSafe()
+
+ if (!sourceChildOutputDirectory.exists()) {
+ return
+ }
+
+ if (sourceChildOutputDirectory.absoluteFile == targetChildOutputDirectory.absoluteFile) {
+ return
+ }
+
+ sourceChildOutputDirectory.copyRecursively(targetChildOutputDirectory, overwrite = false)
+}
+
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
new file mode 100644
index 00000000..29e0d76e
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTask.kt
@@ -0,0 +1,69 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.internal.tasks.TaskDependencyInternal
+import org.gradle.api.tasks.*
+import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaModuleDescriptionImpl
+import org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl
+import java.io.File
+
+@Suppress("unused") // Shall provide source compatibility if possible
+@Deprecated("Use 'DokkaMultimoduleTask' instead", ReplaceWith("DokkaMultimoduleTask"))
+typealias DokkaMultimoduleTask = DokkaMultiModuleTask
+
+
+open class DokkaMultiModuleTask : AbstractDokkaParentTask(DokkaMultimoduleBootstrapImpl::class) {
+
+ /**
+ * Name of the file containing all necessary module information.
+ * This file has to be placed inside the subproject root directory.
+ */
+ @Internal
+ var documentationFileName: String = "README.md"
+
+ @Internal
+ var fileLayout: DokkaMultiModuleFileLayout = DokkaMultiModuleFileLayout.CompactInParent
+
+ @get:InputFiles
+ internal val childDocumentationFiles: Iterable<File>
+ get() = childDokkaTasks.map { task -> task.project.projectDir.resolve(documentationFileName) }
+
+ @get:InputFiles
+ internal val sourceChildOutputDirectories: Iterable<File>
+ get() = childDokkaTasks.map { task -> task.outputDirectory.getSafe() }
+
+ @get:OutputDirectories
+ internal val targetChildOutputDirectories: Iterable<File>
+ get() = childDokkaTasks.map { task -> targetChildOutputDirectory(task) }
+
+ @Internal
+ override fun getTaskDependencies(): TaskDependencyInternal {
+ return super.getTaskDependencies() + childDokkaTasks
+ }
+
+ override fun generateDocumentation() {
+ checkChildDokkaTasksIsNotEmpty()
+ copyChildOutputDirectories()
+ super.generateDocumentation()
+ }
+
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ return DokkaConfigurationImpl(
+ outputDir = outputDirectory.getSafe(),
+ cacheRoot = cacheRoot.getSafe(),
+ pluginsConfiguration = pluginsConfiguration.getSafe(),
+ failOnWarning = failOnWarning.getSafe(),
+ offlineMode = offlineMode.getSafe(),
+ pluginsClasspath = plugins.resolve().toSet(),
+ modules = childDokkaTasks.map { dokkaTask ->
+ DokkaModuleDescriptionImpl(
+ name = dokkaTask.project.name,
+ path = targetChildOutputDirectory(dokkaTask).relativeTo(outputDirectory.getSafe()),
+ docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absoluteFile
+ )
+ }
+ )
+ }
+}
+
+
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
deleted file mode 100644
index 48a9721f..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaMultimoduleTask.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-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
-
-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"
-
- @Internal
- override fun getTaskDependencies(): TaskDependencyInternal {
- return super.getTaskDependencies() + dokkaTasks
- }
-
- override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
- return DokkaConfigurationImpl(
- outputDir = outputDirectory,
- cacheRoot = cacheRoot,
- pluginsConfiguration = pluginsConfiguration,
- failOnWarning = failOnWarning,
- offlineMode = offlineMode,
- pluginsClasspath = plugins.resolve().toSet(),
- modules = dokkaTasks.map { dokkaTask ->
- DokkaModuleDescriptionImpl(
- name = dokkaTask.project.name,
- path = dokkaTask.outputDirectory.relativeTo(outputDirectory),
- docFile = dokkaTask.project.projectDir.resolve(documentationFileName).absoluteFile
- )
- }
- )
- }
-}
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 c5713d16..6f92abdf 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
@@ -26,12 +26,12 @@ open class DokkaTask : AbstractDokkaTask(DokkaBootstrapImpl::class) {
override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
return DokkaConfigurationImpl(
- outputDir = outputDirectory,
- cacheRoot = cacheRoot,
- offlineMode = offlineMode,
- failOnWarning = failOnWarning,
+ outputDir = outputDirectory.getSafe(),
+ cacheRoot = cacheRoot.getSafe(),
+ offlineMode = offlineMode.getSafe(),
+ failOnWarning = failOnWarning.getSafe(),
sourceSets = dokkaSourceSets.build(),
- pluginsConfiguration = pluginsConfiguration,
+ pluginsConfiguration = pluginsConfiguration.getSafe(),
pluginsClasspath = plugins.resolve()
)
}
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
index fb648c02..969b1aa1 100644
--- 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
@@ -5,7 +5,7 @@ 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 {
+internal operator fun TaskDependencyInternal.plus(tasks: Iterable<Task>): TaskDependencyInternal {
return TaskDependencyInternalWithAdditions(this, tasks.toSet())
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/checkChildDokkaTasksIsNotEmpty.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/checkChildDokkaTasksIsNotEmpty.kt
new file mode 100644
index 00000000..a47ea4cd
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/checkChildDokkaTasksIsNotEmpty.kt
@@ -0,0 +1,43 @@
+package org.jetbrains.dokka.gradle
+
+import org.jetbrains.dokka.DokkaException
+
+fun AbstractDokkaParentTask.checkChildDokkaTasksIsNotEmpty() {
+ if (childDokkaTaskPaths.isEmpty()) {
+ throw DokkaException(
+ """
+ The ${this::class.java.simpleName} $path has no configured child tasks.
+ Add some dokka tasks like e.g.:
+
+ tasks.named<AbstractDokkaParentTask>("$name") {
+ addChildTask(..)
+ addChildTasks(subprojects, "...")
+ //...
+ }
+ """.trimIndent()
+ )
+ }
+
+ if (childDokkaTasks.isEmpty()) {
+ throw DokkaException(
+ """
+ The ${this::class.java.simpleName} $path could not find any registered child task.
+ child tasks: $childDokkaTaskPaths
+
+ Please make sure to apply the dokka plugin to all included (sub)-projects individually e.g.:
+
+ // subproject build.gradle.kts
+ plugins {
+ id("org.jetbrains.dokka")
+ }
+
+ or
+
+ // parent build.gradle.kts
+ subprojects {
+ plugins.apply("org.jetbrains.dokka")
+ }
+ """
+ )
+ }
+}
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
deleted file mode 100644
index 2625f64c..00000000
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/dokka.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-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/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
index 71fad405..8ba28e83 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
@@ -1,5 +1,6 @@
package org.jetbrains.dokka.gradle
+import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.register
@@ -11,7 +12,7 @@ open class DokkaPlugin : Plugin<Project> {
project.setupDokkaTasks(
name = "dokkaJavadoc",
- multimoduleTaskSupported = false
+ multiModuleTaskSupported = false
) {
plugins.dependencies.add(project.dokkaArtifacts.javadocPlugin)
}
@@ -26,12 +27,12 @@ open class DokkaPlugin : Plugin<Project> {
}
/**
- * Creates [DokkaTask], [DokkaMultimoduleTask] for the given
+ * Creates [DokkaTask], [DokkaMultiModuleTask] for the given
* name and configuration.
*/
private fun Project.setupDokkaTasks(
name: String,
- multimoduleTaskSupported: Boolean = true,
+ multiModuleTaskSupported: Boolean = true,
collectorTaskSupported: Boolean = true,
configuration: AbstractDokkaTask.() -> Unit = {}
) {
@@ -42,18 +43,24 @@ open class DokkaPlugin : Plugin<Project> {
}
if (project.subprojects.isNotEmpty()) {
- if (multimoduleTaskSupported) {
- val multimoduleName = "${name}Multimodule"
- project.maybeCreateDokkaPluginConfiguration(multimoduleName)
- project.maybeCreateDokkaRuntimeConfiguration(multimoduleName)
- project.tasks.register<DokkaMultimoduleTask>(multimoduleName) {
- dokkaTaskNames = dokkaTaskNames + name
+ if (multiModuleTaskSupported) {
+ val multiModuleName = "${name}MultiModule"
+ project.maybeCreateDokkaPluginConfiguration(multiModuleName)
+ project.maybeCreateDokkaRuntimeConfiguration(multiModuleName)
+ project.tasks.register<DokkaMultiModuleTask>(multiModuleName) {
+ addSubprojectChildTasks(name)
configuration()
}
+ project.tasks.register<DefaultTask>("${name}Multimodule") {
+ dependsOn(multiModuleName)
+ doLast {
+ logger.warn("'Multimodule' is deprecated. Use 'MultiModule' instead")
+ }
+ }
}
if (collectorTaskSupported) {
project.tasks.register<DokkaCollectorTask>("${name}Collector") {
- dokkaTaskNames = dokkaTaskNames + name
+ addSubprojectChildTasks(name)
}
}
}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt
index 64d44157..c815a8a3 100644
--- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/toDokkaSourceSetImpl.kt
@@ -63,7 +63,6 @@ private fun GradleDokkaSourceSetBuilder.externalDocumentationLinksWithDefaults()
.toSet()
}
-
private fun GradleDokkaSourceSetBuilder.suppressedFilesWithDefaults(): Set<File> {
val suppressedFilesForAndroid = if (project.isAndroidProject()) {
val generatedRoot = project.buildDir.resolve("generated").absoluteFile
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 28c16a2a..7a69c409 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
@@ -3,8 +3,10 @@ package org.jetbrains.dokka.gradle
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.UnknownDomainObjectException
+import org.gradle.api.provider.HasMultipleValues
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
+import org.gradle.util.Path
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
@@ -18,6 +20,14 @@ internal infix fun <T> Property<T>.by(value: Provider<T>) {
this.set(value)
}
+internal infix fun <T> HasMultipleValues<in T>.by(values: Iterable<T>) {
+ this.set(values)
+}
+
+internal fun parsePath(path: String): Path {
+ return Path.path(path)
+}
+
internal val Project.kotlinOrNull: KotlinProjectExtension?
get() = try {
project.extensions.findByType(KotlinProjectExtension::class.java)
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt
index da0f3f35..f0e05637 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaParentTaskTest.kt
@@ -1,107 +1,200 @@
package org.jetbrains.dokka.gradle
-import org.gradle.kotlin.dsl.register
-import org.gradle.kotlin.dsl.withType
+import org.gradle.api.Project
+import org.gradle.api.UnknownTaskException
+import org.gradle.kotlin.dsl.create
+import org.gradle.kotlin.dsl.getByName
import org.gradle.testfixtures.ProjectBuilder
+import org.jetbrains.dokka.DokkaConfigurationImpl
import kotlin.test.Test
import kotlin.test.assertEquals
-import kotlin.test.assertTrue
+import kotlin.test.assertFailsWith
class AbstractDokkaParentTaskTest {
private val rootProject = ProjectBuilder.builder().build()
private val subproject0 = ProjectBuilder.builder().withName("subproject0").withParent(rootProject).build()
private val subproject1 = ProjectBuilder.builder().withName("subproject1").withParent(rootProject).build()
- private val subSubproject0a = ProjectBuilder.builder().withName("subSubproject0a").withParent(subproject0).build()
+ private val subSubproject0 = ProjectBuilder.builder().withName("subSubproject0").withParent(subproject0).build()
init {
- rootProject.allprojects { project -> project.plugins.apply("org.jetbrains.dokka") }
+ rootProject.subprojects { project ->
+ project.tasks.create<DokkaTask>("dokkaTask")
+ }
}
- private val parentTasks = rootProject.tasks.withType<AbstractDokkaParentTask>().toList()
+ private val parentTask = rootProject.tasks.create<TestDokkaParentTask>("parent")
+
@Test
- fun `at least one parent task is registered`() {
- assertTrue(
- parentTasks.isNotEmpty(),
- "Expected at least one ${AbstractDokkaParentTask::class.simpleName} task in rootProject"
+ fun `add and remove tasks by reference`() {
+ assertEquals(
+ emptySet(), parentTask.childDokkaTasks,
+ "Expected no childDokkaTasks by default"
+ )
+
+ parentTask.addChildTask(subproject0.dokkaTask)
+ assertEquals(
+ setOf(subproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} being registered as child task"
+ )
+
+ parentTask.addChildTask(subproject1.dokkaTask)
+ assertEquals(
+ setOf(subproject0.dokkaTask, subproject1.dokkaTask), parentTask.childDokkaTasks,
+ "Expected both dokka tasks being present"
+ )
+
+ parentTask.removeChildTask(subproject0.dokkaTask)
+ assertEquals(
+ setOf(subproject1.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} being removed from child tasks"
+ )
+
+ parentTask.addChildTask(subSubproject0.dokkaTask)
+ assertEquals(
+ setOf(subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subSubproject0.dokkaTask.path} being added as child task"
+ )
+
+ parentTask.addChildTask(subSubproject0.dokkaTask)
+ assertEquals(
+ setOf(subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected no effect for adding a task twice"
)
}
@Test
- fun `configuring subprojects`() {
- parentTasks.forEach { task ->
- assertEquals(
- setOf(":subproject0", ":subproject1", ":subproject0:subSubproject0a"), task.subprojectPaths,
- "Expected all sub projects registered by default"
- )
-
- assertEquals(
- listOf(subproject0, subproject1, subSubproject0a), task.subprojects,
- "Expected all sub projects registered by default"
- )
-
- assertEquals(3, task.dokkaTasks.size, "Expected three referenced dokka tasks")
- assertTrue(listOf(subproject0, subproject1, subSubproject0a).all { project ->
- task.dokkaTasks.any { task -> task in project.tasks }
- }, "Expected all sub projects to contribute to referenced dokka tasks")
-
- task.removeSubproject(subproject0)
- assertEquals(
- setOf(":subproject1", ":subproject0:subSubproject0a"), task.subprojectPaths,
- "Expected subproject0 to be removed (without removing its children)"
- )
-
- task.addSubproject(subproject0)
- assertEquals(
- setOf(":subproject1", ":subproject0:subSubproject0a", ":subproject0"), task.subprojectPaths,
- "Expected subproject0 being added again"
- )
-
- task.addSubproject(subproject0)
- assertEquals(
- setOf(":subproject1", ":subproject0:subSubproject0a", ":subproject0"), task.subprojectPaths,
- "Expected adding same project twice to be ignored"
- )
-
- task.removeAllProjects(subproject0)
- assertEquals(
- setOf(":subproject1"), task.subprojectPaths,
- "Expected subproject0 and subSubproject0a to be removed"
- )
-
- task.addAllProjects(subproject0)
- assertEquals(
- setOf(":subproject1", ":subproject0", ":subproject0:subSubproject0a"), task.subprojectPaths,
- "Expected subproject0 and subSubproject0a to be added again"
- )
- }
+ fun `add and remove by absolute path`() {
+ parentTask.addChildTask(":subproject0:dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} as child task"
+ )
+
+ parentTask.addChildTask(":subproject0:subSubproject0:dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subSubproject0.dokkaTask.path} being added as child task"
+ )
+
+ parentTask.removeChildTask(":subproject0:dokkaTask")
+ assertEquals(
+ setOf(subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} being removed as child task"
+ )
}
@Test
- fun `configure dokkaTaskNames`() {
- parentTasks.forEach { task ->
- assertEquals(
- 3, task.dokkaTasks.size,
- "Expected 3 tasks referenced by default"
- )
-
- val customDokkaTaskName = "custom${task.name}"
- task.dokkaTaskNames = setOf(customDokkaTaskName)
- assertTrue(task.dokkaTasks.isEmpty(), "Expected no $customDokkaTaskName. Found: ${task.dokkaTasks}")
-
- rootProject.subprojects { subproject ->
- subproject.tasks.register<DokkaTask>(customDokkaTaskName)
- }
-
- assertEquals(
- 3, task.dokkaTasks.size,
- "Expected three $customDokkaTaskName found"
- )
-
- task.dokkaTasks.forEach { dokkaTask ->
- assertEquals(customDokkaTaskName, dokkaTask.name)
- }
- }
+ fun `add and remove by relative path`() {
+ parentTask.addChildTask("subproject0:dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} as child task"
+ )
+
+ parentTask.addChildTask("subproject0:subSubproject0:dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subSubproject0.dokkaTask.path} being added as child task"
+ )
+
+ parentTask.removeChildTask("subproject0:dokkaTask")
+ assertEquals(
+ setOf(subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} being removed as child task"
+ )
+ }
+
+ @Test
+ fun `add and remove by relative path ob subproject0`() {
+ val parentTask = subproject0.tasks.create<TestDokkaParentTask>("parent")
+
+ parentTask.addChildTask("subSubproject0:dokkaTask")
+ assertEquals(
+ setOf(subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subSubproject0.dokkaTask.path} being registered as child"
+ )
+
+ parentTask.removeChildTask("subSubproject0:dokkaTask")
+ assertEquals(
+ emptySet(), parentTask.childDokkaTasks,
+ "Expected ${subSubproject0.dokkaTask.path} being removed as child"
+ )
+ }
+
+ @Test
+ fun `add and remove by project and name`() {
+ parentTask.addChildTasks(rootProject.subprojects, "dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask, subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected all subproject tasks being registered as child task"
+ )
+
+ parentTask.removeChildTasks(rootProject.subprojects, "dokkaTask")
+ assertEquals(
+ emptySet(), parentTask.childDokkaTasks,
+ "Expected all tasks being removed"
+ )
+
+ parentTask.addChildTasks(listOf(subproject0), "dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected only ${subproject0.dokkaTask.path} being registered as child"
+ )
+
+ parentTask.addSubprojectChildTasks("dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask, subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected all subproject tasks being registered as child task"
+ )
+
+ parentTask.removeSubprojectChildTasks("dokkaTask")
+ assertEquals(
+ emptySet(), parentTask.childDokkaTasks,
+ "Expected all tasks being removed"
+ )
+
+ parentTask.addSubprojectChildTasks("dokkaTask")
+ assertEquals(
+ setOf(subproject0.dokkaTask, subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected all subproject tasks being registered as child task"
+ )
+
+ parentTask.removeChildTasks(subproject0)
+ assertEquals(
+ setOf(subproject1.dokkaTask, subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected only ${subproject0.dokkaTask.path} being removed"
+ )
+
+ parentTask.addSubprojectChildTasks("dokkaTask")
+ parentTask.removeChildTasks(listOf(subproject0, subproject1))
+ assertEquals(
+ setOf(subSubproject0.dokkaTask), parentTask.childDokkaTasks,
+ "Expected ${subproject0.dokkaTask.path} and ${subproject1.dokkaTask.path} being removed"
+ )
+ }
+
+ @Test
+ fun `adding invalid path will not throw exception`() {
+ parentTask.addChildTask(":some:stupid:path")
+ parentTask.childDokkaTasks
+ }
+
+ @Test
+ fun `adding non dokka task will throw exception`() {
+ val badTask = rootProject.tasks.create("badTask")
+ parentTask.addChildTask(badTask.path)
+ assertFailsWith<IllegalArgumentException> { parentTask.childDokkaTasks }
+ }
+}
+
+internal open class TestDokkaParentTask : AbstractDokkaParentTask() {
+ override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
+ throw NotImplementedError()
}
}
+
+private val Project.dokkaTask: DokkaTask get() = tasks.getByName<DokkaTask>("dokkaTask")
+
+
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt
index 18128e34..d7f0e946 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaCollectorTaskTest.kt
@@ -1,13 +1,14 @@
package org.jetbrains.dokka.gradle
-import org.gradle.api.artifacts.Dependency
-import org.gradle.api.artifacts.FileCollectionDependency
+import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaException
import java.io.File
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
class DokkaCollectorTaskTest {
@@ -32,15 +33,15 @@ class DokkaCollectorTaskTest {
val collectorTasks = rootProject.tasks.withType<DokkaCollectorTask>()
collectorTasks.configureEach { task ->
- task.outputDirectory = File("customOutputDirectory")
- task.cacheRoot = File("customCacheRoot")
- task.failOnWarning = true
- task.offlineMode = true
+ task.outputDirectory by File("customOutputDirectory")
+ task.cacheRoot by File("customCacheRoot")
+ task.failOnWarning by true
+ task.offlineMode by true
}
assertTrue(collectorTasks.isNotEmpty(), "Expected at least one collector task")
- collectorTasks.forEach { task ->
+ collectorTasks.toList().forEach { task ->
val dokkaConfiguration = task.buildDokkaConfiguration()
assertEquals(
DokkaConfigurationImpl(
@@ -48,17 +49,24 @@ class DokkaCollectorTaskTest {
cacheRoot = File("customCacheRoot"),
failOnWarning = true,
offlineMode = true,
- sourceSets = task.dokkaTasks
+ sourceSets = task.childDokkaTasks
.map { it.buildDokkaConfiguration() }
.map { it.sourceSets }
.reduce { acc, list -> acc + list },
- pluginsClasspath = task.dokkaTasks
+ pluginsClasspath = task.childDokkaTasks
.map { it.plugins.resolve() }
.reduce { acc, mutableSet -> acc + mutableSet }
),
dokkaConfiguration
)
}
+ }
+ @Test
+ fun `with no child tasks throws DokkaException`() {
+ val project = ProjectBuilder.builder().build()
+ val collectorTask = project.tasks.create<DokkaCollectorTask>("collector")
+ project.configurations.all { configuration -> configuration.withDependencies { it.clear() } }
+ assertFailsWith<DokkaException> { collectorTask.generateDocumentation() }
}
}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
index 7a3bc2bd..29532877 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationJsonTest.kt
@@ -1,3 +1,5 @@
+@file:Suppress("UnstableApiUsage")
+
package org.jetbrains.dokka.gradle
import org.gradle.kotlin.dsl.withType
@@ -19,12 +21,12 @@ class DokkaConfigurationJsonTest {
dependencies.clear()
}
dokkaTask.apply {
- this.failOnWarning = true
- this.offlineMode = true
- this.outputDirectory = File("customOutputDir")
- this.cacheRoot = File("customCacheRoot")
- this.pluginsConfiguration["0"] = "a"
- this.pluginsConfiguration["1"] = "b"
+ this.failOnWarning by true
+ this.offlineMode by true
+ this.outputDirectory by File("customOutputDir")
+ this.cacheRoot by File("customCacheRoot")
+ this.pluginsConfiguration.put("0", "a")
+ this.pluginsConfiguration.put("1", "b")
this.dokkaSourceSets.create("main") { sourceSet ->
sourceSet.moduleDisplayName by "moduleDisplayName"
sourceSet.displayName by "customSourceSetDisplayName"
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
index e4dc5afc..f22a5b8c 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaConfigurationSerializableTest.kt
@@ -13,6 +13,7 @@ import java.net.URL
import kotlin.test.Test
import kotlin.test.assertEquals
+@Suppress("UnstableApiUsage")
class DokkaConfigurationSerializableTest {
@get:Rule
@@ -27,12 +28,12 @@ class DokkaConfigurationSerializableTest {
dependencies.clear()
}
dokkaTask.apply {
- this.failOnWarning = true
- this.offlineMode = true
- this.outputDirectory = File("customOutputDir")
- this.cacheRoot = File("customCacheRoot")
- this.pluginsConfiguration["0"] = "a"
- this.pluginsConfiguration["1"] = "b"
+ this.failOnWarning by true
+ this.offlineMode by true
+ this.outputDirectory by File("customOutputDir")
+ this.cacheRoot by File("customCacheRoot")
+ this.pluginsConfiguration.put("0", "a")
+ this.pluginsConfiguration.put("1", "b")
this.dokkaSourceSets.create("main") { sourceSet ->
sourceSet.moduleDisplayName by "moduleDisplayName"
sourceSet.displayName by "customSourceSetDisplayName"
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayoutTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayoutTest.kt
new file mode 100644
index 00000000..36abacfc
--- /dev/null
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleFileLayoutTest.kt
@@ -0,0 +1,100 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.kotlin.dsl.create
+import org.gradle.testfixtures.ProjectBuilder
+import org.jetbrains.dokka.gradle.DokkaMultiModuleFileLayout.CompactInParent
+import org.jetbrains.dokka.gradle.DokkaMultiModuleFileLayout.NoCopy
+import java.io.File
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class DokkaMultiModuleFileLayoutTest {
+
+ @Test
+ fun `no copy`() {
+ val project = ProjectBuilder.builder().build()
+ val child = project.tasks.create<DokkaTask>("child")
+ val parent = project.tasks.create<DokkaMultiModuleTask>("parent")
+ child.outputDirectory by File("some/path")
+
+ assertEquals(
+ File("some/path"), NoCopy.targetChildOutputDirectory(parent, child),
+ "Expected original file path returned"
+ )
+ }
+
+ @Test
+ fun `compact in parent`() {
+ val rootProject = ProjectBuilder.builder().build()
+ val parentProject = ProjectBuilder.builder().withName("parent").withParent(rootProject).build()
+ val intermediateProject = ProjectBuilder.builder().withName("intermediate").withParent(parentProject).build()
+ val childProject = ProjectBuilder.builder().withName("child").withParent(intermediateProject).build()
+
+ val parentTask = parentProject.tasks.create<DokkaMultiModuleTask>("parentTask")
+ val childTask = childProject.tasks.create<DokkaTask>("childTask")
+
+ val targetOutputDirectory = CompactInParent.targetChildOutputDirectory(parentTask, childTask)
+ assertEquals(
+ parentTask.outputDirectory.getSafe().resolve("intermediate/child"), targetOutputDirectory,
+ "Expected nested file structure representing project structure"
+ )
+ }
+
+ @Test
+ fun copyChildOutputDirectory() {
+ /* Prepare */
+ val project = ProjectBuilder.builder().build()
+ val childTask = project.tasks.create<DokkaTask>("child")
+ val parentTask = project.tasks.create<DokkaMultiModuleTask>("parent")
+
+ val sourceOutputDirectory = childTask.outputDirectory.getSafe()
+ sourceOutputDirectory.mkdirs()
+ sourceOutputDirectory.resolve("some.file").writeText("some text")
+ val subFolder = sourceOutputDirectory.resolve("subFolder")
+ subFolder.mkdirs()
+ subFolder.resolve("other.file").writeText("other text")
+
+ val layout = object : DokkaMultiModuleFileLayout {
+ override fun targetChildOutputDirectory(parent: AbstractDokkaParentTask, child: AbstractDokkaTask): File {
+ return parent.project.file("target/output")
+ }
+ }
+ layout.copyChildOutputDirectory(parentTask, childTask)
+
+ /* Assertions */
+ val targetOutputDirectory = project.file("target/output")
+ assertTrue(
+ targetOutputDirectory.exists() && targetOutputDirectory.isDirectory,
+ "Expected target output directory ${targetOutputDirectory.path} to exist"
+ )
+
+ val targetSomeFile = targetOutputDirectory.resolve("some.file")
+ assertTrue(
+ targetSomeFile.exists() && targetSomeFile.isFile,
+ "Expected sample file to exist in target output directory"
+ )
+
+ assertEquals(
+ "some text", targetSomeFile.readText(),
+ "Expected content to be written into sample file"
+ )
+
+ val targetSubFolder = targetOutputDirectory.resolve("subFolder")
+ assertTrue(
+ targetSubFolder.exists() && targetSubFolder.isDirectory,
+ "Expected sub folder being present in target output directory"
+ )
+
+ val targetOtherFile = targetSubFolder.resolve("other.file")
+ assertTrue(
+ targetOtherFile.exists() && targetOtherFile.isFile,
+ "Expected nested 'other.file' being copied into target"
+ )
+
+ assertEquals(
+ "other text", targetOtherFile.readText(),
+ "Expected content to be written into 'other.file'"
+ )
+ }
+}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt
index 8814a897..a7c9946d 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaMultiModuleTaskTest.kt
@@ -1,13 +1,17 @@
+@file:Suppress("UnstableApiUsage")
+
package org.jetbrains.dokka.gradle
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.DokkaConfigurationImpl
+import org.jetbrains.dokka.DokkaException
import org.jetbrains.dokka.DokkaModuleDescriptionImpl
import java.io.File
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
class DokkaMultiModuleTaskTest {
@@ -47,19 +51,19 @@ class DokkaMultiModuleTaskTest {
@Test
fun buildDokkaConfiguration() {
childProject.tasks.withType<DokkaTask>().configureEach { task ->
- task.outputDirectory = task.project.buildDir.resolve("output")
+ task.outputDirectory by task.project.buildDir.resolve("output")
}
- val multimoduleTasks = rootProject.tasks.withType<DokkaMultimoduleTask>()
+ val multimoduleTasks = rootProject.tasks.withType<DokkaMultiModuleTask>()
assertTrue(multimoduleTasks.isNotEmpty(), "Expected at least one multimodule task")
multimoduleTasks.configureEach { task ->
task.documentationFileName = "customDocumentationFileName.md"
- task.outputDirectory = task.project.buildDir.resolve("customOutputDirectory")
- task.cacheRoot = File("customCacheRoot")
- task.pluginsConfiguration["pluginA"] = "configA"
- task.failOnWarning = true
- task.offlineMode = true
+ task.outputDirectory by task.project.buildDir.resolve("customOutputDirectory")
+ task.cacheRoot by File("customCacheRoot")
+ task.pluginsConfiguration.put("pluginA", "configA")
+ task.failOnWarning by true
+ task.offlineMode by true
}
multimoduleTasks.forEach { task ->
@@ -75,7 +79,7 @@ class DokkaMultiModuleTaskTest {
modules = listOf(
DokkaModuleDescriptionImpl(
name = "child",
- path = File("../../child/build/output"),
+ path = File("child"),
docFile = childProject.projectDir.resolve("customDocumentationFileName.md")
)
)
@@ -87,7 +91,7 @@ class DokkaMultiModuleTaskTest {
@Test
fun `setting dokkaTaskNames declares proper task dependencies`() {
- val multimoduleTasks = rootProject.tasks.withType<DokkaMultimoduleTask>()
+ val multimoduleTasks = rootProject.tasks.withType<DokkaMultiModuleTask>()
assertTrue(multimoduleTasks.isNotEmpty(), "Expected at least one multimodule task")
multimoduleTasks.toList().forEach { task ->
@@ -102,11 +106,75 @@ class DokkaMultiModuleTaskTest {
val customDokkaTask = childProject.tasks.create<DokkaTask>("customDokkaTask")
multimoduleTasks.toList().forEach { task ->
- task.dokkaTaskNames += "customDokkaTask"
+ task.addSubprojectChildTasks("customDokkaTask")
val dependencies = task.taskDependencies.getDependencies(task).toSet()
assertEquals(2, dependencies.size, "Expected two dependencies")
assertTrue(customDokkaTask in dependencies, "Expected 'customDokkaTask' in dependencies")
}
}
+
+ @Test
+ fun `multimodule task with no child tasks throws DokkaException`() {
+ val project = ProjectBuilder.builder().build()
+ val multimodule = project.tasks.create<DokkaMultiModuleTask>("multimodule")
+ project.configurations.configureEach { it.withDependencies { it.clear() } }
+ assertFailsWith<DokkaException> { multimodule.generateDocumentation() }
+ }
+
+ @Test
+ fun childDocumentationFiles() {
+ val parent = ProjectBuilder.builder().build()
+ val child = ProjectBuilder.builder().withName("child").withParent(parent).build()
+
+ val parentTask = parent.tasks.create<DokkaMultiModuleTask>("parent")
+ val childTask = child.tasks.create<DokkaTask>("child")
+
+ parentTask.addChildTask(childTask)
+ parentTask.documentationFileName = "module.txt"
+
+ assertEquals(
+ listOf(parent.file("child/module.txt")), parentTask.childDocumentationFiles,
+ "Expected child documentation file being present"
+ )
+ }
+
+ @Test
+ fun sourceChildOutputDirectories() {
+ val parent = ProjectBuilder.builder().build()
+ val child = ProjectBuilder.builder().withName("child").withParent(parent).build()
+
+ val parentTask = parent.tasks.create<DokkaMultiModuleTask>("parent")
+ val childTask = child.tasks.create<DokkaTask>("child")
+
+ parentTask.addChildTask(childTask)
+ childTask.outputDirectory by child.file("custom/output")
+
+ assertEquals(
+ listOf(parent.file("child/custom/output")), parentTask.sourceChildOutputDirectories,
+ "Expected child output directory being present"
+ )
+ }
+
+ @Test
+ fun targetChildOutputDirectories() {
+ val parent = ProjectBuilder.builder().build()
+ val child = ProjectBuilder.builder().withName("child").withParent(parent).build()
+
+ val parentTask = parent.tasks.create<DokkaMultiModuleTask>("parent")
+ val childTask = child.tasks.create<DokkaTask>("child")
+
+ parentTask.addChildTask(childTask)
+ parentTask.fileLayout = object : DokkaMultiModuleFileLayout {
+ override fun targetChildOutputDirectory(parent: AbstractDokkaParentTask, child: AbstractDokkaTask): File {
+ return parent.project.buildDir.resolve(child.name)
+ }
+ }
+
+ assertEquals(
+ listOf(parent.project.buildDir.resolve("child")), parentTask.targetChildOutputDirectories,
+ "Expected child target output directory being present"
+ )
+
+ }
}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaTasksTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaPluginApplyTest.kt
index b948c540..db218b9f 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaTasksTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/DokkaPluginApplyTest.kt
@@ -8,7 +8,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertSame
import kotlin.test.assertTrue
-class DokkaTasksTest {
+class DokkaPluginApplyTest {
@Test
fun `one task per format is registered`() {
@@ -62,4 +62,23 @@ class DokkaTasksTest {
)
}
}
+
+ @Test
+ fun `parent dokka tasks have children configured`() {
+ val root = ProjectBuilder.builder().withName("root").build()
+ val child = ProjectBuilder.builder().withName("child").withParent(root).build()
+ root.plugins.apply("org.jetbrains.dokka")
+ child.plugins.apply("org.jetbrains.dokka")
+
+ val parentTasks = root.tasks.withType<AbstractDokkaParentTask>()
+ assertTrue(parentTasks.isNotEmpty(), "Expected at least one parent task being created")
+
+ parentTasks.toList().forEach { parentTask ->
+ assertEquals(1, parentTask.childDokkaTasks.size, "Expected one child dokka task")
+ assertEquals(
+ child, parentTask.childDokkaTasks.single().project,
+ "Expected child dokka task from child project"
+ )
+ }
+ }
}
diff --git a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
index 013ad3f2..6a356b79 100644
--- a/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
+++ b/runners/gradle-plugin/src/test/kotlin/org/jetbrains/dokka/gradle/KotlinDslDokkaTaskConfigurationTest.kt
@@ -1,6 +1,6 @@
package org.jetbrains.dokka.gradle
-import dokka
+import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.DokkaSourceSetID
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
@@ -9,17 +9,16 @@ import kotlin.test.Test
import kotlin.test.assertEquals
class KotlinDslDokkaTaskConfigurationTest {
-
@Test
- fun `configure project using dokka extension function`() {
+ fun `configure dokka task`() {
val project = ProjectBuilder.builder().build()
project.plugins.apply("org.jetbrains.dokka")
- project.dokka {
- outputDirectory = File("test")
+ project.tasks.withType<DokkaTask>().configureEach {
+ it.outputDirectory by File("test")
}
project.tasks.withType(DokkaTask::class.java).forEach { dokkaTask ->
- assertEquals(File("test"), dokkaTask.outputDirectory)
+ assertEquals(File("test"), dokkaTask.outputDirectory.getSafe())
}
}