Skip to content

Commit

Permalink
Use Gradle file property types for task inputs & outputs (#2707)
Browse files Browse the repository at this point in the history
  • Loading branch information
aSemy committed Feb 27, 2023
1 parent f5581c5 commit 6af794d
Show file tree
Hide file tree
Showing 16 changed files with 284 additions and 107 deletions.
@@ -1,6 +1,10 @@
package org.jetbrains.dokka.gradle

import org.gradle.api.file.Directory
import org.gradle.api.provider.Provider
import org.jetbrains.dokka.DokkaException
import org.jetbrains.dokka.gradle.DokkaMultiModuleFileLayout.CompactInParent
import org.jetbrains.dokka.gradle.DokkaMultiModuleFileLayout.NoCopy
import java.io.File

/**
Expand All @@ -16,14 +20,16 @@ fun interface DokkaMultiModuleFileLayout {
* @return The target output directory of the [child] dokka task referenced by [parent]. This should
* be unique for all registered child tasks.
*/
fun targetChildOutputDirectory(parent: DokkaMultiModuleTask, child: AbstractDokkaTask): File
fun targetChildOutputDirectory(parent: DokkaMultiModuleTask, child: AbstractDokkaTask): Provider<Directory>

/**
* Will link to the original [AbstractDokkaTask.outputDirectory]. This requires no copying of the output files.
*/
object NoCopy : DokkaMultiModuleFileLayout {
override fun targetChildOutputDirectory(parent: DokkaMultiModuleTask, child: AbstractDokkaTask): File =
child.outputDirectory.get()
override fun targetChildOutputDirectory(
parent: DokkaMultiModuleTask,
child: AbstractDokkaTask
): Provider<Directory> = child.outputDirectory
}

/**
Expand All @@ -34,18 +40,21 @@ fun interface DokkaMultiModuleFileLayout {
* {parent output directory}/firstAncestor/secondAncestor
*/
object CompactInParent : DokkaMultiModuleFileLayout {
override fun targetChildOutputDirectory(parent: DokkaMultiModuleTask, child: AbstractDokkaTask): File {
override fun targetChildOutputDirectory(
parent: DokkaMultiModuleTask,
child: AbstractDokkaTask
): Provider<Directory> {
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.get().resolve(relativeFilePath)
return parent.outputDirectory.dir(relativeFilePath)
}
}
}

internal fun DokkaMultiModuleTask.targetChildOutputDirectory(
child: AbstractDokkaTask
): File = fileLayout.get().targetChildOutputDirectory(this, child)
): Provider<Directory> = fileLayout.get().targetChildOutputDirectory(this, child)


internal fun DokkaMultiModuleTask.copyChildOutputDirectories() {
Expand All @@ -56,7 +65,7 @@ internal fun DokkaMultiModuleTask.copyChildOutputDirectories() {

internal fun DokkaMultiModuleTask.copyChildOutputDirectory(child: AbstractDokkaTask) {
val targetChildOutputDirectory = project.file(fileLayout.get().targetChildOutputDirectory(this, child))
val sourceChildOutputDirectory = child.outputDirectory.get()
val sourceChildOutputDirectory = child.outputDirectory.asFile.get()

/* Pointing to the same directory -> No copy necessary */
if (sourceChildOutputDirectory.absoluteFile == targetChildOutputDirectory.absoluteFile) {
Expand Down
Expand Up @@ -5,7 +5,9 @@ import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
import org.gradle.util.GradleVersion
import org.jetbrains.dokka.DokkaDefaults

open class DokkaPlugin : Plugin<Project> {
override fun apply(project: Project) {
Expand All @@ -25,15 +27,24 @@ open class DokkaPlugin : Plugin<Project> {
description = "Generates documentation in 'javadoc' format"
}

project.setupDokkaTasks("dokkaGfm", allModulesPageAndTemplateProcessing = project.dokkaArtifacts.gfmTemplateProcessing) {
project.setupDokkaTasks(
"dokkaGfm",
allModulesPageAndTemplateProcessing = project.dokkaArtifacts.gfmTemplateProcessing
) {
plugins.dependencies.add(project.dokkaArtifacts.gfmPlugin)
description = "Generates documentation in GitHub flavored markdown format"
}

project.setupDokkaTasks("dokkaJekyll", allModulesPageAndTemplateProcessing = project.dokkaArtifacts.jekyllTemplateProcessing) {
project.setupDokkaTasks(
"dokkaJekyll",
allModulesPageAndTemplateProcessing = project.dokkaArtifacts.jekyllTemplateProcessing
) {
plugins.dependencies.add(project.dokkaArtifacts.jekyllPlugin)
description = "Generates documentation in Jekyll flavored markdown format"
}

project.configureEachAbstractDokkaTask()
project.configureEachDokkaMultiModuleTask()
}

/**
Expand Down Expand Up @@ -92,4 +103,18 @@ open class DokkaPlugin : Plugin<Project> {
}
}
}

private fun Project.configureEachAbstractDokkaTask() {
tasks.withType<AbstractDokkaTask>().configureEach {
val formatClassifier = name.removePrefix("dokka").decapitalize()
outputDirectory.convention(project.layout.buildDirectory.dir("dokka/$formatClassifier"))
cacheRoot.set(DokkaDefaults.cacheRoot)
}
}

private fun Project.configureEachDokkaMultiModuleTask() {
tasks.withType<DokkaMultiModuleTask>().configureEach {
sourceChildOutputDirectories.from({ childDokkaTasks.map { it.outputDirectory } })
}
}
}
Expand Up @@ -7,6 +7,7 @@ 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.file.DirectoryProperty
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
Expand All @@ -19,7 +20,6 @@ import org.gradle.work.DisableCachingByDefault
import org.jetbrains.dokka.*
import org.jetbrains.dokka.plugability.ConfigurableBlock
import org.jetbrains.dokka.plugability.DokkaPlugin
import java.io.File
import java.util.function.BiConsumer
import kotlin.reflect.full.createInstance

Expand Down Expand Up @@ -56,9 +56,8 @@ abstract class AbstractDokkaTask : DefaultTask() {
* Default is `project/buildDir/taskName.removePrefix("dokka").decapitalize()`, so
* for `dokkaHtmlMultiModule` task it will be `project/buildDir/htmlMultiModule`
*/
@OutputDirectory
val outputDirectory: Property<File> = project.objects.property<File>()
.convention(project.provider { defaultDokkaOutputDirectory() })
@get:OutputDirectory
abstract val outputDirectory: DirectoryProperty

/**
* Configuration for Dokka plugins. This property is not expected to be used directly - if possible, use
Expand Down Expand Up @@ -151,10 +150,10 @@ abstract class AbstractDokkaTask : DefaultTask() {
val failOnWarning: Property<Boolean> = project.objects.property<Boolean>()
.convention(DokkaDefaults.failOnWarning)

@Optional
@InputDirectory
@PathSensitive(PathSensitivity.RELATIVE)
val cacheRoot: Property<File?> = project.objects.property()
@get:Optional
@get:InputDirectory
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val cacheRoot: DirectoryProperty

/**
* Type-safe configuration for a Dokka plugin.
Expand Down
Expand Up @@ -16,8 +16,8 @@ abstract class DokkaCollectorTask : AbstractDokkaParentTask() {
override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
val initialDokkaConfiguration = DokkaConfigurationImpl(
moduleName = moduleName.get(),
outputDir = outputDirectory.get(),
cacheRoot = cacheRoot.orNull,
outputDir = outputDirectory.asFile.get(),
cacheRoot = cacheRoot.asFile.orNull,
failOnWarning = failOnWarning.get(),
offlineMode = offlineMode.get(),
pluginsClasspath = plugins.resolve().toList(),
Expand Down
Expand Up @@ -3,8 +3,10 @@
package org.jetbrains.dokka.gradle

import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.Directory
import org.gradle.api.internal.tasks.TaskDependencyInternal
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.property
import org.jetbrains.dokka.DokkaConfigurationImpl
Expand Down Expand Up @@ -46,23 +48,23 @@ abstract class DokkaMultiModuleTask : AbstractDokkaParentTask() {
* Useful stuff in another package.
* ```
*/
@InputFiles
@Optional
@PathSensitive(PathSensitivity.RELATIVE)
val includes: ConfigurableFileCollection = project.files()
@get:InputFiles
@get:Optional
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val includes: ConfigurableFileCollection

@Internal
val fileLayout: Property<DokkaMultiModuleFileLayout> = project.objects.property<DokkaMultiModuleFileLayout>()
.convention(DokkaMultiModuleFileLayout.CompactInParent)

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
internal val sourceChildOutputDirectories: Iterable<File>
get() = childDokkaTasks.map { task -> task.outputDirectory.get() }
internal abstract val sourceChildOutputDirectories: ConfigurableFileCollection

@get:OutputDirectories
internal val targetChildOutputDirectories: Iterable<File>
get() = childDokkaTasks.map { task -> targetChildOutputDirectory(task) }
internal val targetChildOutputDirectories: Provider<Iterable<Directory>> = project.provider {
childDokkaTasks.map { task -> targetChildOutputDirectory(task).get() }
}

@get:Input
internal val childDokkaTaskIncludes: Map<TaskPath, Set<File>>
Expand All @@ -83,23 +85,27 @@ abstract class DokkaMultiModuleTask : AbstractDokkaParentTask() {
super.generateDocumentation()
}

override fun buildDokkaConfiguration(): DokkaConfigurationImpl = DokkaConfigurationImpl(
moduleName = moduleName.get(),
moduleVersion = moduleVersion.getValidVersionOrNull(),
outputDir = outputDirectory.get(),
cacheRoot = cacheRoot.orNull,
pluginsConfiguration = buildPluginsConfiguration(),
override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
return DokkaConfigurationImpl(
moduleName = moduleName.get(),
moduleVersion = moduleVersion.getValidVersionOrNull(),
outputDir = outputDirectory.asFile.get(),
cacheRoot = cacheRoot.asFile.orNull,
pluginsConfiguration = buildPluginsConfiguration(),
failOnWarning = failOnWarning.get(),
offlineMode = offlineMode.get(),
pluginsClasspath = plugins.resolve().toList(),
modules = childDokkaTasks.map { dokkaTask ->
DokkaModuleDescriptionImpl(
name = dokkaTask.moduleName.get(),
relativePathToOutputDirectory = targetChildOutputDirectory(dokkaTask).relativeTo(outputDirectory.get()),
includes = childDokkaTaskIncludes[dokkaTask.path].orEmpty(),
sourceOutputDirectory = dokkaTask.outputDirectory.get()
)
},
includes = includes.toSet(),
)
pluginsClasspath = plugins.resolve().toList(),
modules = childDokkaTasks.map { dokkaTask ->
DokkaModuleDescriptionImpl(
name = dokkaTask.moduleName.get(),
relativePathToOutputDirectory = targetChildOutputDirectory(dokkaTask).get().asFile.relativeTo(
outputDirectory.asFile.get()
),
includes = childDokkaTaskIncludes[dokkaTask.path].orEmpty(),
sourceOutputDirectory = dokkaTask.outputDirectory.asFile.get(),
)
},
includes = includes.toSet(),
)
}
}
Expand Up @@ -2,18 +2,18 @@

package org.jetbrains.dokka.gradle

import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.build
import org.gradle.api.tasks.*

@CacheableTask
abstract class DokkaTask : AbstractDokkaLeafTask() {
override fun buildDokkaConfiguration(): DokkaConfigurationImpl =
DokkaConfigurationImpl(
moduleName = moduleName.get(),
moduleVersion = moduleVersion.getValidVersionOrNull(),
outputDir = outputDirectory.get(),
cacheRoot = cacheRoot.orNull,
outputDir = outputDirectory.asFile.get(),
cacheRoot = cacheRoot.asFile.orNull,
offlineMode = offlineMode.get(),
failOnWarning = failOnWarning.get(),
sourceSets = unsuppressedSourceSets.build(),
Expand Down
Expand Up @@ -2,9 +2,9 @@

package org.jetbrains.dokka.gradle

import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.build
import org.gradle.api.tasks.*

@CacheableTask
abstract class DokkaTaskPartial : AbstractDokkaLeafTask() {
Expand All @@ -13,8 +13,8 @@ abstract class DokkaTaskPartial : AbstractDokkaLeafTask() {
return DokkaConfigurationImpl(
moduleName = moduleName.get(),
moduleVersion = moduleVersion.orNull,
outputDir = outputDirectory.get(),
cacheRoot = cacheRoot.orNull,
outputDir = outputDirectory.asFile.get(),
cacheRoot = cacheRoot.asFile.orNull,
offlineMode = offlineMode.get(),
failOnWarning = failOnWarning.get(),
sourceSets = unsuppressedSourceSets.build(),
Expand Down
Expand Up @@ -7,6 +7,7 @@ import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.getByName
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.gradle.utils.subprojects_
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
Expand All @@ -19,7 +20,7 @@ class AbstractDokkaParentTaskTest {
private val subSubproject0 = ProjectBuilder.builder().withName("subSubproject0").withParent(subproject0).build()

init {
rootProject.subprojects {
rootProject.subprojects_ {
tasks.create<DokkaTask>("dokkaTask")
}
}
Expand Down Expand Up @@ -190,12 +191,10 @@ class AbstractDokkaParentTaskTest {
}
}

internal open class TestDokkaParentTask : AbstractDokkaParentTask() {
internal abstract class TestDokkaParentTask : AbstractDokkaParentTask() {
override fun buildDokkaConfiguration(): DokkaConfigurationImpl {
throw NotImplementedError()
}
}

private val Project.dokkaTask: DokkaTask get() = tasks.getByName<DokkaTask>("dokkaTask")


Expand Up @@ -2,7 +2,13 @@ package org.jetbrains.dokka.gradle

import org.gradle.kotlin.dsl.withType
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.dokka.*
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.PluginConfigurationImpl
import org.jetbrains.dokka.gradle.utils.create_
import org.jetbrains.dokka.gradle.utils.externalDocumentationLink_
import org.jetbrains.dokka.gradle.utils.withDependencies_
import org.jetbrains.dokka.toCompactJsonString
import java.io.File
import java.net.URL
import kotlin.test.Test
Expand All @@ -15,23 +21,31 @@ class DokkaConfigurationJsonTest {
val project = ProjectBuilder.builder().build()
project.plugins.apply("org.jetbrains.dokka")
val dokkaTask = project.tasks.withType<DokkaTask>().first()
dokkaTask.plugins.withDependencies { clear() }
dokkaTask.plugins.withDependencies_ { clear() }
dokkaTask.apply {
this.failOnWarning.set(true)
this.offlineMode.set(true)
this.outputDirectory.set(File("customOutputDir"))
this.cacheRoot.set(File("customCacheRoot"))
this.pluginsConfiguration.add(
PluginConfigurationImpl("A", DokkaConfiguration.SerializationFormat.JSON, """ { "key" : "value1" } """)
PluginConfigurationImpl(
"A",
DokkaConfiguration.SerializationFormat.JSON,
""" { "key" : "value1" } """
)
)
this.pluginsConfiguration.add(
PluginConfigurationImpl("B", DokkaConfiguration.SerializationFormat.JSON, """ { "key" : "value2" } """)
PluginConfigurationImpl(
"B",
DokkaConfiguration.SerializationFormat.JSON,
""" { "key" : "value2" } """
)
)
this.dokkaSourceSets.create("main") {
this.dokkaSourceSets.create_("main") {
displayName.set("customSourceSetDisplayName")
reportUndocumented.set(true)

externalDocumentationLink {
externalDocumentationLink_ {
packageListUrl.set(URL("http://some.url"))
url.set(URL("http://some.other.url"))
}
Expand Down

0 comments on commit 6af794d

Please sign in to comment.