Skip to content

Move external documentation links to a task input in Dackka #4033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import org.gradle.api.DefaultTask
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.process.ExecOperations
import org.gradle.workers.WorkAction
Expand All @@ -29,26 +32,48 @@ import org.json.JSONObject
* @property suppressedFiles a list of files to exclude from documentation
* @property outputDirectory where to store the generated files
*/
@CacheableTask
abstract class GenerateDocumentationTaskExtension : DefaultTask() {
@get:InputFile
@get:[InputFile Classpath]
abstract val dackkaJarFile: Property<File>

@get:Input
@get:[InputFiles Classpath]
abstract val dependencies: ListProperty<File>

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val kotlinSources: ListProperty<File>

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val javaSources: ListProperty<File>

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val suppressedFiles: ListProperty<File>

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val packageListFiles: ListProperty<File>

@get:OutputDirectory
abstract val outputDirectory: Property<File>
}

/**
* Wrapper data class for External package-lists in Dokka
*
* This class allows us to map package-lists in a type-safe way, versus inline straight to
* a map. This extra step could be removed- but it could also catch bugs in the future.
*
* @property packageList the prepared package-list file to map against
* @property externalLink the url to map with when generating the docs
*/
data class ExternalDocumentationLink(
val packageList: File,
val externalLink: String
)

/**
* Task to run Dackka on a project.
*
Expand All @@ -68,14 +93,6 @@ abstract class GenerateDocumentationTask @Inject constructor(
}

private fun constructArguments(): JSONObject {
// TODO(b/243675474): Move these to a task input for caching purposes
val linksMap = mapOf(
"android" to "https://developer.android.com/reference/kotlin/",
"google" to "https://developer.android.com/reference/",
"firebase" to "https://firebase.google.com/docs/reference/kotlin/",
"coroutines" to "https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/"
)

val jsonMap = mapOf(
"moduleName" to "",
"outputDir" to outputDirectory.get().path,
Expand All @@ -90,9 +107,9 @@ abstract class GenerateDocumentationTask @Inject constructor(
"documentedVisibilities" to listOf("PUBLIC", "PROTECTED"),
"skipEmptyPackages" to "true",
"suppressedFiles" to suppressedFiles.get().map { it.path },
"externalDocumentationLinks" to linksMap.map { (name, url) -> mapOf(
"url" to url,
"packageListUrl" to "file://${project.rootDir.absolutePath}/kotlindoc/package-lists/$name/package-list"
"externalDocumentationLinks" to createExternalLinks(packageListFiles).map { mapOf(
"url" to it.externalLink,
"packageListUrl" to it.packageList.toURI()
) }
)),
"offlineMode" to "true",
Expand All @@ -102,6 +119,20 @@ abstract class GenerateDocumentationTask @Inject constructor(
return JSONObject(jsonMap)
}

private fun createExternalLinks(packageLists: ListProperty<File>): List<ExternalDocumentationLink> {
val linksMap = mapOf(
"android" to "https://developer.android.com/reference/kotlin/",
"google" to "https://developer.android.com/reference/",
"firebase" to "https://firebase.google.com/docs/reference/kotlin/",
"coroutines" to "https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/"
)

return packageLists.get().map {
val externalLink = linksMap[it.parentFile.nameWithoutExtension] ?: throw RuntimeException("Unexpected package-list found: ${it.name}")
ExternalDocumentationLink(it, externalLink)
}
}

private fun saveToJsonFile(jsonObject: JSONObject): File {
val outputFile = File.createTempFile("dackkaArgs", ".json")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,16 @@ abstract class DackkaPlugin : Plugin<Project> {
}

docsTask.configure {
// this will become useful with the agp upgrade, as they're separate in 7.x+
val sourcesForKotlin = emptyList<File>()
val packageLists = fetchPackageLists(project)

val excludedFiles = if (!isKotlin) projectSpecificSuppressedFiles(project) else emptyList()
val fixedJavaSources = if (!isKotlin) listOf(project.docStubs) else sourcesForJava

javaSources.set(fixedJavaSources)
suppressedFiles.set(excludedFiles)
packageListFiles.set(packageLists)

kotlinSources.set(sourcesForKotlin)
dependencies.set(classpath)
Expand All @@ -107,6 +110,11 @@ abstract class DackkaPlugin : Plugin<Project> {
return docsTask
}

private fun fetchPackageLists(project: Project) =
project.rootProject.fileTree("kotlindoc/package-lists").matching {
include("**/package-list")
}.toList()

// TODO(b/243534168): Remove when fixed
private fun projectSpecificSuppressedFiles(project: Project): List<File> =
when (project.name) {
Expand All @@ -129,12 +137,14 @@ abstract class DackkaPlugin : Plugin<Project> {
outputDirectory.set(dackkaOutputDirectory)
}

// TODO(b/243833009): Make task cacheable
private fun registerFiresiteTransformTask(project: Project, outputDirectory: Provider<File>) =
project.tasks.register<FiresiteTransformTask>("firesiteTransform") {
dackkaFiles.set(outputDirectory)
}

// If we decide to publish java variants, we'll need to address the generated format as well
// TODO(b/243833009): Make task cacheable
private fun registerDeleteDackkaGeneratedJavaReferencesTask(project: Project, outputDirectory: Provider<File>) =
project.tasks.register<Delete>("deleteDackkaGeneratedJavaReferences") {
mustRunAfter("generateDackkaDocumentation")
Expand Down