Skip to content

Commit

Permalink
Re-use includes form child tasks for all modules page generation
Browse files Browse the repository at this point in the history
  • Loading branch information
sellmair committed Aug 28, 2020
1 parent 2ecca14 commit 17c4ab9
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 117 deletions.
12 changes: 10 additions & 2 deletions core/src/main/kotlin/configuration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ fun <T : Any> Iterable<DokkaConfigurationBuilder<T>>.build(): List<T> = this.map


data class DokkaSourceSetID(
/**
* Unique identifier of the scope that this source set is placed in.
* Each scope provide only unique source set names.
*
* E.g. One DokkaTask inside the Gradle plugin represents one source set scope, since there cannot be multiple
* source sets with the same name. However, a Gradle project will not be a proper scope, since there can be
* multple DokkaTasks that contain source sets with the same name (but different configuration)
*/
val scopeId: String,
val sourceSetName: String
) : Serializable {
Expand Down Expand Up @@ -116,8 +124,8 @@ interface DokkaConfiguration : Serializable {

interface DokkaModuleDescription : Serializable {
val name: String
val path: File
val docFile: File
val relativePathToOutputDirectory: File
val includes: Set<File>
}

interface PackageOptions : Serializable {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/kotlin/defaultConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ data class DokkaSourceSetImpl(

data class DokkaModuleDescriptionImpl(
override val name: String,
override val path: File,
override val docFile: File
override val relativePathToOutputDirectory: File,
override val includes: Set<File>
) : DokkaConfiguration.DokkaModuleDescription

data class SourceLinkDefinitionImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ val defaultSourceSet = DokkaSourceSetImpl(
analysisPlatform = Platform.DEFAULT
)

// TODO NOW: Clean up
fun sourceSet(name: String): DokkaConfiguration.DokkaSourceSet {
return defaultSourceSet.copy(
displayName = name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Module !Module B!
Here is some description for Module B

Module B: Second paragraph
# Module moduleB
§IGNORED$This documentation shall be ignored, because wrong module name§IGNORED$

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.dokka.gradle.DokkaTask

plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
Expand All @@ -6,3 +8,10 @@ plugins {
dependencies {
implementation(kotlin("stdlib"))
}

tasks.withType<DokkaTask>().configureEach {
moduleName.set("!Module B!")
dokkaSourceSets.configureEach {
includes.from("Module.md")
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.dokka.gradle.DokkaTask

plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
Expand All @@ -6,3 +8,9 @@ plugins {
dependencies {
implementation(kotlin("stdlib"))
}

tasks.withType<DokkaTask>().configureEach {
dokkaSourceSets.configureEach {
includes.from("Module.md")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import org.jetbrains.dokka.gradle.DokkaTask

plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
}

dependencies {
implementation(kotlin("stdlib"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.jetbrains.dokka.it.moduleD

@Suppress("unused")
class ModuleD {
fun undocumentedPublicFunction() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ rootProject.name = "it-multimodule-0"
include(":moduleA")
include(":moduleA:moduleB")
include(":moduleA:moduleC")
include(":moduleA:moduleD")
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.jetbrains.dokka.base.allModulePage

import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfiguration.DokkaModuleDescription
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.DokkaException
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.resolvers.local.MultimoduleLocationProvider.Companion.MULTIMODULE_PACKAGE_PLACEHOLDER
import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
Expand All @@ -12,20 +11,24 @@ import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.doc.P
import org.jetbrains.dokka.pages.*
import org.jetbrains.dokka.base.parsers.MarkdownParser
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentation.Classifier.Module
import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentationParsingContext
import org.jetbrains.dokka.base.parsers.moduleAndPackage.parseModuleAndPackageDocumentation
import org.jetbrains.dokka.base.parsers.moduleAndPackage.parseModuleAndPackageDocumentationFragments
import org.jetbrains.dokka.base.transformers.documentables.ModuleAndPackageDocumentationReader
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.transformers.pages.PageCreator
import org.jetbrains.dokka.utilities.DokkaLogger

class MultimodulePageCreator(
val context: DokkaContext
class MultimodulePageCreator (
private val context: DokkaContext,
) : PageCreator {
private val logger: DokkaLogger = context.logger

override fun invoke(): RootPageNode {
val parser = MarkdownParser(logger = logger)
val modules = context.configuration.modules
modules.forEach(::throwOnMissingModuleDocFile)

val commentsConverter = context.plugin(DokkaBase::class)?.querySingle { commentsToContentConverter }
val signatureProvider = context.plugin(DokkaBase::class)?.querySingle { signatureProvider }
Expand All @@ -41,21 +44,22 @@ class MultimodulePageCreator(
) {
header(2, "All modules:")
table(styles = setOf(MultimoduleTable)) {
modules.mapNotNull { module ->
val paragraph = module.docFile.readText().let { parser.parse(it).firstParagraph() }
paragraph?.let {
val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name)
val dci = DCI(setOf(dri), ContentKind.Main)
val header =
ContentHeader(listOf(linkNode(module.name, dri)), 2, dci, emptySet(), emptySet())
val content = ContentGroup(
DocTagToContentConverter.buildContent(it, dci, emptySet()),
dci,
emptySet(),
emptySet()
)
ContentGroup(listOf(header, content), dci, emptySet(), emptySet())
}
modules.map { module ->
val displayedModuleDocumentation = getDisplayedModuleDocumentation(module)
val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name)
val dci = DCI(setOf(dri), ContentKind.Main)
val header =
ContentHeader(listOf(linkNode(module.name, dri)), 2, dci, emptySet(), emptySet())
val content = ContentGroup(
children =
if (displayedModuleDocumentation != null)
DocTagToContentConverter.buildContent(displayedModuleDocumentation, dci, emptySet())
else emptyList(),
dci = dci,
sourceSets = emptySet(),
style = emptySet()
)
ContentGroup(listOf(header, content), dci, emptySet(), emptySet())
}
}
}
Expand All @@ -66,12 +70,16 @@ class MultimodulePageCreator(
)
}

private fun throwOnMissingModuleDocFile(module: DokkaConfiguration.DokkaModuleDescription) {
if (!module.docFile.exists() || !module.docFile.isFile) {
throw DokkaException(
"Missing documentation file for module ${module.name}: ${module.docFile.absolutePath}"
)
}
private fun getDisplayedModuleDocumentation(module: DokkaModuleDescription): P? {
val parsingContext = ModuleAndPackageDocumentationParsingContext(logger)
return module.includes
.flatMap { include -> parseModuleAndPackageDocumentationFragments(include) }
.map { fragment -> parseModuleAndPackageDocumentation(parsingContext, fragment) }
.firstOrNull { documentation -> documentation.classifier == Module && documentation.name == module.name }
?.documentation?.children.orEmpty()
.flatMap { it.root.children }
.filterIsInstance<P>()
.firstOrNull()
}

private fun DocumentationNode.firstParagraph() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MultimoduleLocationProvider(private val root: RootPageNode, context: Dokka
private val defaultLocationProvider = DokkaLocationProvider(root, context)

val paths = context.configuration.modules.map {
it.name to it.path
it.name to it.relativePathToOutputDirectory
}.toMap()

override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?) =
Expand Down
2 changes: 0 additions & 2 deletions plugins/base/src/test/kotlin/model/PackagesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ class PackagesTest : AbstractModelTest("/src/main/kotlin/packages/Test.kt", "pac
}
}

// TODO NOW test displayName

// todo
// @Test fun suppressAtPackageLevel() {
// verifyModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package org.jetbrains.dokka.gradle
import org.gradle.api.internal.tasks.TaskDependencyInternal
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.DokkaConfigurationImpl
import org.jetbrains.dokka.DokkaModuleDescriptionImpl
import org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl
Expand All @@ -14,25 +12,14 @@ import java.io.File
@Deprecated("Use 'DokkaMultimoduleTask' instead", ReplaceWith("DokkaMultimoduleTask"))
typealias DokkaMultimoduleTask = DokkaMultiModuleTask

private typealias TaskPath = String

abstract 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
val documentationFileName: Property<String> = project.objects.safeProperty<String>()
.safeConvention("README.md")

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

@get:InputFiles
internal val childDocumentationFiles: Iterable<File>
get() = childDokkaTasks.map { task -> task.project.projectDir.resolve(documentationFileName.getSafe()) }

@get:InputFiles
internal val sourceChildOutputDirectories: Iterable<File>
get() = childDokkaTasks.map { task -> task.outputDirectory.getSafe() }
Expand All @@ -41,6 +28,12 @@ abstract class DokkaMultiModuleTask : AbstractDokkaParentTask(DokkaMultimoduleBo
internal val targetChildOutputDirectories: Iterable<File>
get() = childDokkaTasks.map { task -> targetChildOutputDirectory(task) }

@get:Input
internal val childDokkaTaskIncludes: Map<TaskPath, Set<File>>
get() = childDokkaTasks.filterIsInstance<DokkaTask>().associate { task ->
task.path to task.dokkaSourceSets.flatMap { it.includes }.toSet()
}

@Internal
override fun getTaskDependencies(): TaskDependencyInternal =
super.getTaskDependencies() + childDokkaTasks
Expand All @@ -62,9 +55,9 @@ abstract class DokkaMultiModuleTask : AbstractDokkaParentTask(DokkaMultimoduleBo
pluginsClasspath = plugins.resolve().toList(),
modules = childDokkaTasks.map { dokkaTask ->
DokkaModuleDescriptionImpl(
name = dokkaTask.project.name,
path = targetChildOutputDirectory(dokkaTask).relativeTo(outputDirectory.getSafe()),
docFile = dokkaTask.project.projectDir.resolve(documentationFileName.get()).absoluteFile
name = dokkaTask.moduleName.getSafe(),
relativePathToOutputDirectory = targetChildOutputDirectory(dokkaTask).relativeTo(outputDirectory.getSafe()),
includes = childDokkaTaskIncludes[dokkaTask.path].orEmpty()
)
}
)
Expand Down
Loading

0 comments on commit 17c4ab9

Please sign in to comment.