diff options
author | Marcin Aman <marcin.aman@gmail.com> | 2021-01-21 00:34:43 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-21 00:34:43 +0100 |
commit | fdf8a298f586d7e334c312346b70b59c64c8d037 (patch) | |
tree | d9e92e920c24f442df6339e19b27225d7d01d21b | |
parent | 1f592a7ec2786e0a0b77d224d1414ef3042caae4 (diff) | |
download | dokka-fdf8a298f586d7e334c312346b70b59c64c8d037.tar.gz dokka-fdf8a298f586d7e334c312346b70b59c64c8d037.tar.bz2 dokka-fdf8a298f586d7e334c312346b70b59c64c8d037.zip |
Empty modules filtering (#1699)
29 files changed, 257 insertions, 113 deletions
diff --git a/core/src/main/kotlin/transformers/documentation/DocumentableMerger.kt b/core/src/main/kotlin/transformers/documentation/DocumentableMerger.kt index 81c1f470..aa878873 100644 --- a/core/src/main/kotlin/transformers/documentation/DocumentableMerger.kt +++ b/core/src/main/kotlin/transformers/documentation/DocumentableMerger.kt @@ -4,5 +4,5 @@ import org.jetbrains.dokka.model.DModule import org.jetbrains.dokka.plugability.DokkaContext interface DocumentableMerger { - operator fun invoke(modules: Collection<DModule>): DModule + operator fun invoke(modules: Collection<DModule>): DModule? }
\ No newline at end of file diff --git a/core/src/main/kotlin/transformers/pages/PageCreator.kt b/core/src/main/kotlin/transformers/pages/PageCreator.kt index f74b5efa..ebb9dac5 100644 --- a/core/src/main/kotlin/transformers/pages/PageCreator.kt +++ b/core/src/main/kotlin/transformers/pages/PageCreator.kt @@ -3,6 +3,10 @@ package org.jetbrains.dokka.transformers.pages import org.jetbrains.dokka.pages.RootPageNode import org.jetbrains.dokka.plugability.DokkaContext -interface PageCreator { - operator fun invoke(): RootPageNode +interface CreationContext + +object NoCreationContext : CreationContext + +interface PageCreator<T: CreationContext> { + operator fun invoke(creationContext: T): RootPageNode }
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt b/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt index 0013feed..c11b18b2 100644 --- a/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt +++ b/plugins/all-modules-page/src/main/kotlin/AllModulesPageGeneration.kt @@ -9,6 +9,8 @@ import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.query import org.jetbrains.dokka.plugability.querySingle import org.jetbrains.dokka.templates.TemplatingPlugin +import org.jetbrains.dokka.templates.TemplatingResult +import org.jetbrains.dokka.transformers.pages.CreationContext import org.jetbrains.dokka.versioning.VersioningPlugin class AllModulesPageGeneration(private val context: DokkaContext) : Generation { @@ -18,9 +20,11 @@ class AllModulesPageGeneration(private val context: DokkaContext) : Generation { private val versioningPlugin by lazy { context.plugin<VersioningPlugin>() } override fun Timer.generate() { + report("Processing submodules") + val generationContext = processSubmodules() report("Creating all modules page") - val pages = createAllModulesPage() + val pages = createAllModulesPage(generationContext) report("Copy previous documentation") handlePreviousDocs() @@ -31,15 +35,19 @@ class AllModulesPageGeneration(private val context: DokkaContext) : Generation { report("Rendering") render(transformedPages) - report("Processing submodules") - processSubmodules() + report("Processing multimodule") + processMultiModule(transformedPages) + + report("Finish submodule processing") + finishProcessingSubmodules() } override val generationName = "index page for project" fun handlePreviousDocs() = versioningPlugin.querySingle { versioningHandler }.invoke() - fun createAllModulesPage() = allModulesPagePlugin.querySingle { allModulesPageCreator }.invoke() + fun createAllModulesPage(allModulesContext: DefaultAllModulesContext) = + allModulesPagePlugin.querySingle { allModulesPageCreator }.invoke(allModulesContext) fun transformAllModulesPage(pages: RootPageNode) = allModulesPagePlugin.query { allModulesPageTransformer }.fold(pages) { acc, t -> t(acc) } @@ -49,5 +57,17 @@ class AllModulesPageGeneration(private val context: DokkaContext) : Generation { } fun processSubmodules() = - templatingPlugin.querySingle { templateProcessor }.process() + templatingPlugin.querySingle { submoduleTemplateProcessor } + .process(context.configuration.modules) + .let { DefaultAllModulesContext(it) } + + fun processMultiModule(root: RootPageNode) = + templatingPlugin.querySingle { multimoduleTemplateProcessor }.process(root) + + fun finishProcessingSubmodules() = + templatingPlugin.query { templateProcessingStrategy }.forEach { it.finish(context.configuration.outputDir) } + + data class DefaultAllModulesContext(val nonEmptyModules: List<String>) : CreationContext { + constructor(templating: TemplatingResult) : this(templating.modules) + } }
\ No newline at end of file diff --git a/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt b/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt index 9f4b62ee..e6556b07 100644 --- a/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt +++ b/plugins/all-modules-page/src/main/kotlin/AllModulesPagePlugin.kt @@ -12,7 +12,7 @@ import org.jetbrains.dokka.transformers.pages.PageTransformer class AllModulesPagePlugin : DokkaPlugin() { val partialLocationProviderFactory by extensionPoint<LocationProviderFactory>() - val allModulesPageCreator by extensionPoint<PageCreator>() + val allModulesPageCreator by extensionPoint<PageCreator<AllModulesPageGeneration.DefaultAllModulesContext>>() val allModulesPageTransformer by extensionPoint<PageTransformer>() val externalModuleLinkResolver by extensionPoint<ExternalModuleLinkResolver>() diff --git a/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt b/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt index c7c32d55..1a323f63 100644 --- a/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt +++ b/plugins/all-modules-page/src/main/kotlin/MultimoduleLocationProvider.kt @@ -5,24 +5,30 @@ import org.jetbrains.dokka.base.resolvers.local.DokkaBaseLocationProvider import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.DisplaySourceSet +import org.jetbrains.dokka.pages.ContentPage import org.jetbrains.dokka.pages.PageNode import org.jetbrains.dokka.pages.RootPageNode import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle -open class MultimoduleLocationProvider(private val root: RootPageNode, dokkaContext: DokkaContext) : DokkaBaseLocationProvider(root, dokkaContext) { +open class MultimoduleLocationProvider(private val root: RootPageNode, dokkaContext: DokkaContext) : + DokkaBaseLocationProvider(root, dokkaContext) { - private val defaultLocationProvider = dokkaContext.plugin<AllModulesPagePlugin>().querySingle { partialLocationProviderFactory }.getLocationProvider(root) - private val externalModuleLinkResolver = dokkaContext.plugin<AllModulesPagePlugin>().querySingle { externalModuleLinkResolver } + private val defaultLocationProvider = + dokkaContext.plugin<AllModulesPagePlugin>().querySingle { partialLocationProviderFactory } + .getLocationProvider(root) + private val externalModuleLinkResolver = + dokkaContext.plugin<AllModulesPagePlugin>().querySingle { externalModuleLinkResolver } override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?) = - if (dri == MultimodulePageCreator.MULTIMODULE_ROOT_DRI) pathToRoot(root) - else dri.takeIf { it.packageName == MULTIMODULE_PACKAGE_PLACEHOLDER }?.classNames - ?.let(externalModuleLinkResolver::resolveLinkToModuleIndex) + if (dri == MultimodulePageCreator.MULTIMODULE_ROOT_DRI) pathToRoot(root) + "index" + else dri.takeIf { it.packageName == MULTIMODULE_PACKAGE_PLACEHOLDER }?.classNames + ?.let(externalModuleLinkResolver::resolveLinkToModuleIndex) override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean) = - defaultLocationProvider.resolve(node, context, skipExtension) + if (node is ContentPage && MultimodulePageCreator.MULTIMODULE_ROOT_DRI in node.dri) pathToRoot(root) + "index" + else defaultLocationProvider.resolve(node, context, skipExtension) override fun pathToRoot(from: PageNode): String = defaultLocationProvider.pathToRoot(from) @@ -30,6 +36,6 @@ open class MultimoduleLocationProvider(private val root: RootPageNode, dokkaCont class Factory(private val context: DokkaContext) : LocationProviderFactory { override fun getLocationProvider(pageNode: RootPageNode) = - MultimoduleLocationProvider(pageNode, context) + MultimoduleLocationProvider(pageNode, context) } } diff --git a/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt b/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt index dec850b2..bcab4e65 100644 --- a/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt +++ b/plugins/all-modules-page/src/main/kotlin/MultimodulePageCreator.kt @@ -29,13 +29,13 @@ import org.jetbrains.dokka.versioning.VersioningPlugin class MultimodulePageCreator( private val context: DokkaContext, -) : PageCreator { +) : PageCreator<AllModulesPageGeneration.DefaultAllModulesContext> { private val logger: DokkaLogger = context.logger private val commentsConverter by lazy { context.plugin<DokkaBase>().querySingle { commentsToContentConverter } } private val signatureProvider by lazy { context.plugin<DokkaBase>().querySingle { signatureProvider } } - override fun invoke(): RootPageNode { + override fun invoke(creationContext: AllModulesPageGeneration.DefaultAllModulesContext): RootPageNode { val modules = context.configuration.modules val sourceSetData = emptySet<DokkaSourceSet>() val builder = PageContentBuilder(commentsConverter, signatureProvider, context.logger) @@ -51,24 +51,29 @@ class MultimodulePageCreator( } header(2, "All modules:") table(styles = setOf(MultimoduleTable)) { - modules.forEach { module -> - val displayedModuleDocumentation = getDisplayedModuleDocumentation(module) - val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name) - val dci = DCI(setOf(dri), ContentKind.Comment) - val extraWithAnchor = PropertyContainer.withAll(SymbolAnchorHint(module.name, ContentKind.Main)) - row(setOf(dri), emptySet(), styles = emptySet(), extra = extraWithAnchor) { - +linkNode(module.name, dri, DCI(setOf(dri), ContentKind.Main), extra = extraWithAnchor) - +ContentGroup( - children = - if (displayedModuleDocumentation != null) - DocTagToContentConverter().buildContent(displayedModuleDocumentation, dci, emptySet()) - else emptyList(), - dci = dci, - sourceSets = emptySet(), - style = emptySet() - ) + modules.filter { it.name in creationContext.nonEmptyModules }.sortedByDescending { it.name } + .forEach { module -> + val displayedModuleDocumentation = getDisplayedModuleDocumentation(module) + val dri = DRI(packageName = MULTIMODULE_PACKAGE_PLACEHOLDER, classNames = module.name) + val dci = DCI(setOf(dri), ContentKind.Comment) + val extraWithAnchor = PropertyContainer.withAll(SymbolAnchorHint(module.name, ContentKind.Main)) + row(setOf(dri), emptySet(), styles = emptySet(), extra = extraWithAnchor) { + +linkNode(module.name, dri, DCI(setOf(dri), ContentKind.Main), extra = extraWithAnchor) + +ContentGroup( + children = + if (displayedModuleDocumentation != null) + DocTagToContentConverter().buildContent( + displayedModuleDocumentation, + dci, + emptySet() + ) + else emptyList(), + dci = dci, + sourceSets = emptySet(), + style = emptySet() + ) + } } - } } } return MultimoduleRootPageNode( diff --git a/plugins/all-modules-page/src/test/kotlin/MultiModuleDokkaTestGenerator.kt b/plugins/all-modules-page/src/test/kotlin/MultiModuleDokkaTestGenerator.kt index c8542dfe..9213c90b 100644 --- a/plugins/all-modules-page/src/test/kotlin/MultiModuleDokkaTestGenerator.kt +++ b/plugins/all-modules-page/src/test/kotlin/MultiModuleDokkaTestGenerator.kt @@ -34,7 +34,10 @@ class MultiModuleDokkaTestGenerator( val generation = context.single(CoreExtensions.generation) as AllModulesPageGeneration - val allModulesPage = generation.createAllModulesPage() + val generationContext = generation.processSubmodules() + submoduleProcessingStage(context) + + val allModulesPage = generation.createAllModulesPage(generationContext) allModulesPageCreationStage(allModulesPage) val transformedPages = generation.transformAllModulesPage(allModulesPage) @@ -43,8 +46,11 @@ class MultiModuleDokkaTestGenerator( generation.render(transformedPages) renderingStage(transformedPages, context) - generation.processSubmodules() - submoduleProcessingStage(context) + generation.processMultiModule(transformedPages) + processMultiModule(transformedPages) + + generation.finishProcessingSubmodules() + finishProcessingSubmodules(context) } } @@ -55,6 +61,8 @@ open class MultiModuleTestMethods( open val pagesTransformationStage: (RootPageNode) -> Unit, open val renderingStage: (RootPageNode, DokkaContext) -> Unit, open val submoduleProcessingStage: (DokkaContext) -> Unit, + open val processMultiModule: (RootPageNode) -> Unit, + open val finishProcessingSubmodules: (DokkaContext) -> Unit, ) : TestMethods class MultiModuleTestBuilder : TestBuilder<MultiModuleTestMethods>() { @@ -63,6 +71,8 @@ class MultiModuleTestBuilder : TestBuilder<MultiModuleTestMethods>() { var pagesTransformationStage: (RootPageNode) -> Unit = {} var renderingStage: (RootPageNode, DokkaContext) -> Unit = { _, _ -> } var submoduleProcessingStage: (DokkaContext) -> Unit = {} + var processMultiModule: (RootPageNode) -> Unit = {} + var finishProcessingSubmodules: (DokkaContext) -> Unit = {} override fun build() = MultiModuleTestMethods( pluginsSetupStage, @@ -70,6 +80,8 @@ class MultiModuleTestBuilder : TestBuilder<MultiModuleTestMethods>() { pagesTransformationStage, renderingStage, submoduleProcessingStage, + processMultiModule, + finishProcessingSubmodules ) } diff --git a/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt index cbf254a0..2637714f 100644 --- a/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt +++ b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkCommandResolutionTest.kt @@ -60,7 +60,7 @@ class ResolveLinkCommandResolutionTest : MultiModuleAbstractTest() { val configuration = configuration() testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { + finishProcessingSubmodules = { assertHtmlEqualsIgnoringWhitespace(expected, contentFile.readText()) } } @@ -89,7 +89,7 @@ class ResolveLinkCommandResolutionTest : MultiModuleAbstractTest() { val configuration = configuration() testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { + finishProcessingSubmodules = { assertHtmlEqualsIgnoringWhitespace(expected, contentFile.readText()) } } diff --git a/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt index 75576727..185a179d 100644 --- a/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt +++ b/plugins/all-modules-page/src/test/kotlin/templates/ResolveLinkGfmCommandResolutionTest.kt @@ -55,7 +55,7 @@ class ResolveLinkGfmCommandResolutionTest : MultiModuleAbstractTest() { val configuration = configuration() testFromData(configuration, pluginOverrides = listOf(GfmTemplateProcessingPlugin(), GfmPlugin()), preserveOutputLocation = true) { - submoduleProcessingStage = { + finishProcessingSubmodules = { assertEquals(expected, content.readText().trim()) } } diff --git a/plugins/base/base-test-utils/src/main/kotlin/testRunner/baseTestApi.kt b/plugins/base/base-test-utils/src/main/kotlin/testRunner/baseTestApi.kt index b8143a30..72fdc07a 100644 --- a/plugins/base/base-test-utils/src/main/kotlin/testRunner/baseTestApi.kt +++ b/plugins/base/base-test-utils/src/main/kotlin/testRunner/baseTestApi.kt @@ -38,7 +38,7 @@ class BaseDokkaTestGenerator( documentablesFirstTransformationStep(filteredModules) val documentationModel = singleModuleGeneration.mergeDocumentationModels(filteredModules) - documentablesMergingStage(documentationModel) + documentablesMergingStage(documentationModel!!) val transformedDocumentation = singleModuleGeneration.transformDocumentationModelAfterMerge(documentationModel) documentablesTransformationStage(transformedDocumentation) diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index ac070ab4..938c7701 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -80,6 +80,12 @@ class DokkaBase : DokkaPlugin() { } } + val emptyModulesFilter by extending { + preMergeDocumentableTransformer with EmptyModulesFilterTransformer() order { + after(emptyPackagesFilter) + } + } + val modulesAndPackagesDocumentation by extending { preMergeDocumentableTransformer providing ::ModuleAndPackageDocumentationTransformer } diff --git a/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt b/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt index 1689a1dd..9bf61af9 100644 --- a/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt +++ b/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt @@ -1,4 +1,3 @@ - package org.jetbrains.dokka.base.generation import kotlinx.coroutines.Dispatchers @@ -32,6 +31,7 @@ class SingleModuleGeneration(private val context: DokkaContext) : Generation { report("Merging documentation models") val documentationModel = mergeDocumentationModels(transformedDocumentationBeforeMerge) + ?: exitGenerationGracefully("Nothing to document") report("Transforming documentation model after merging") val transformedDocumentation = transformDocumentationModelAfterMerge(documentationModel) @@ -56,7 +56,8 @@ class SingleModuleGeneration(private val context: DokkaContext) : Generation { } fun transformDocumentationModelBeforeMerge(modulesFromPlatforms: List<DModule>) = - context.plugin<DokkaBase>().query { preMergeDocumentableTransformer }.fold(modulesFromPlatforms) { acc, t -> t(acc) } + context.plugin<DokkaBase>().query { preMergeDocumentableTransformer } + .fold(modulesFromPlatforms) { acc, t -> t(acc) } fun mergeDocumentationModels(modulesFromPlatforms: List<DModule>) = context.single(CoreExtensions.documentableMerger).invoke(modulesFromPlatforms) @@ -99,7 +100,7 @@ class SingleModuleGeneration(private val context: DokkaContext) : Generation { private suspend fun translateSources(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext) = context[CoreExtensions.sourceToDocumentableTranslator].parallelMap { translator -> - when(translator){ + when (translator) { is AsyncSourceToDocumentableTranslator -> translator.invokeSuspending(sourceSet, context) else -> translator.invoke(sourceSet, context) } diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt index d76ba597..2694adc9 100644 --- a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.runBlocking import org.jetbrains.dokka.DokkaException import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.resolvers.local.LocationProvider -import org.jetbrains.dokka.base.resolvers.local.resolveOrThrow import org.jetbrains.dokka.model.DisplaySourceSet import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext @@ -169,12 +168,20 @@ abstract class DefaultRenderer<T>( is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path) is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "") is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".html") - is RenderingStrategy.DriLocationResolvableWrite -> outputWriter.write(path, strategy.contentToResolve { dri, sourcesets -> - locationProvider.resolve(dri, sourcesets) - }, "") - is RenderingStrategy.PageLocationResolvableWrite -> outputWriter.write(path, strategy.contentToResolve { pageToLocate, context -> - locationProvider.resolve(pageToLocate, context) - }, "") + is RenderingStrategy.DriLocationResolvableWrite -> outputWriter.write( + path, + strategy.contentToResolve { dri, sourcesets -> + locationProvider.resolve(dri, sourcesets) + }, + "" + ) + is RenderingStrategy.PageLocationResolvableWrite -> outputWriter.write( + path, + strategy.contentToResolve { pageToLocate, context -> + locationProvider.resolve(pageToLocate, context) + }, + "" + ) RenderingStrategy.DoNothing -> Unit } else -> throw AssertionError( diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt index 4c931230..94e27424 100644 --- a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt +++ b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt @@ -12,9 +12,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal class DefaultDocumentableMerger(val context: DokkaContext) : DocumentableMerger { private val dependencyInfo = context.getDependencyInfo() - override fun invoke(modules: Collection<DModule>): DModule { - - return modules.reduce { left, right -> + override fun invoke(modules: Collection<DModule>): DModule? = + modules.reduceOrNull { left, right -> val list = listOf(left, right) DModule( name = modules.map { it.name }.distinct().joinToString("|"), @@ -26,7 +25,6 @@ internal class DefaultDocumentableMerger(val context: DokkaContext) : Documentab sourceSets = list.flatMap { it.sourceSets }.toSet() ).mergeExtras(left, right) } - } private fun DokkaContext.getDependencyInfo() : Map<DokkaConfiguration.DokkaSourceSet, List<DokkaConfiguration.DokkaSourceSet>> { diff --git a/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt new file mode 100644 index 00000000..fa31c5c3 --- /dev/null +++ b/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt @@ -0,0 +1,10 @@ +package org.jetbrains.dokka.base.transformers.documentables + +import org.jetbrains.dokka.model.DModule +import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer + +class EmptyModulesFilterTransformer : PreMergeDocumentableTransformer { + override fun invoke(modules: List<DModule>): List<DModule> { + return modules.filter { it.children.isNotEmpty() } + } +}
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt b/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt index 2a3e4267..2a927b97 100644 --- a/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt +++ b/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt @@ -24,8 +24,9 @@ class FailOnWarningTest : BaseAbstractTest() { assertThrows<DokkaException> { testInline( """ - |/src/main/kotlin + |/src/main/kotlin/Bar.kt |package sample + |class Bar {} """.trimIndent(), configuration ) { pluginsSetupStage = { @@ -49,8 +50,9 @@ class FailOnWarningTest : BaseAbstractTest() { assertThrows<DokkaException> { testInline( """ - |/src/main/kotlin + |/src/main/kotlin/Bar.kt |package sample + |class Bar {} """.trimIndent(), configuration ) { pluginsSetupStage = { @@ -75,8 +77,9 @@ class FailOnWarningTest : BaseAbstractTest() { testInline( """ - |/src/main/kotlin + |/src/main/kotlin/Bar.kt |package sample + |class Bar {} """.trimIndent(), configuration, loggerForTest = TestLogger(ZeroErrorOrWarningCountDokkaLogger()) @@ -99,8 +102,9 @@ class FailOnWarningTest : BaseAbstractTest() { testInline( """ - |/src/main/kotlin + |/src/main/kotlin/Bar.kt |package sample + |class Bar {} """.trimIndent(), configuration ) { pluginsSetupStage = { diff --git a/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt b/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt index cc5c2c29..ccb878d0 100644 --- a/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt +++ b/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt @@ -31,7 +31,7 @@ class DeprecationFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } @@ -61,7 +61,7 @@ class DeprecationFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } @@ -91,7 +91,7 @@ class DeprecationFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 0 + it.first().packages.first().functions.size == 0 ) } } @@ -130,7 +130,7 @@ class DeprecationFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 0 + it.first().packages.first().functions.size == 0 ) } } @@ -167,7 +167,7 @@ class DeprecationFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } diff --git a/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt b/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt index 356f66bf..2a5a5dd5 100644 --- a/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt +++ b/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt @@ -3,6 +3,7 @@ package filter import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import kotlin.test.assertEquals class EmptyPackagesFilterTest : BaseAbstractTest() { @Test @@ -28,7 +29,7 @@ class EmptyPackagesFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.isNotEmpty() + it.first().packages.isNotEmpty() ) } } @@ -39,7 +40,7 @@ class EmptyPackagesFilterTest : BaseAbstractTest() { sourceSets { sourceSet { skipEmptyPackages = true - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") + sourceRoots = listOf("src/main/kotlin") } } } @@ -49,15 +50,15 @@ class EmptyPackagesFilterTest : BaseAbstractTest() { |/src/main/kotlin/basic/Test.kt |package example | - | + | class ThisShouldBePresent { } + |/src/main/kotlin/empty/TestEmpty.kt + |package empty """.trimMargin(), configuration ) { documentablesFirstTransformationStep = { modules -> modules.forEach { module -> - Assertions.assertTrue( - module.packages.isEmpty() - ) + assertEquals(listOf("example"), module.packages.map { it.name }) } } } diff --git a/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt b/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt index 13997154..b0476b6e 100644 --- a/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt +++ b/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt @@ -33,7 +33,7 @@ class VisibilityFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } @@ -64,7 +64,7 @@ class VisibilityFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 0 + it.first().packages.first().functions.size == 0 ) } } @@ -95,7 +95,7 @@ class VisibilityFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } @@ -135,7 +135,7 @@ class VisibilityFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 1 + it.first().packages.first().functions.size == 1 ) } } @@ -175,7 +175,7 @@ class VisibilityFilterTest : BaseAbstractTest() { ) { documentablesFirstTransformationStep = { Assertions.assertTrue( - it.component2().packages.first().functions.size == 0 + it.first().packages.first().functions.size == 0 ) } } @@ -202,7 +202,7 @@ class VisibilityFilterTest : BaseAbstractTest() { configuration ) { documentablesFirstTransformationStep = { - assertEquals(0, it.component2().packages.first().typealiases.size) + assertEquals(0, it.first().packages.first().typealiases.size) } } } diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt index 5a0a8ba1..91f33acb 100644 --- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt +++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/transformers/documentables/JavadocDocumentableJVMSourceSetFilterTest.kt @@ -83,7 +83,7 @@ class JavadocDocumentableJVMSourceSetFilterTest: BaseAbstractTest() { fun `non-jvm and not dependent common source sets are ommited`() { testInline(query, config) { documentablesFirstTransformationStep = { modules -> - assertEquals(4, modules.size) + assertEquals(2, modules.size) } } } diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt index 1175e365..a892889d 100644 --- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt +++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt @@ -48,7 +48,12 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() { @Test fun `mpp config should fail for javadoc`() { - testInline("", mppConfig) { + testInline( + """ + |/src/main/kotlin/example/Test.kt + |class Test + """.trimMargin(), mppConfig + ) { verificationStage = { verification -> var mppDetected = false try { @@ -64,7 +69,12 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() { @Test fun `spp config should not fail for javadoc`() { - testInline("", sppConfig) { + testInline( + """ + |/src/main/kotlin/example/Test.kt + |class Test + """.trimMargin(), sppConfig + ) { verificationStage = { verification -> var mppDetected = false try { diff --git a/plugins/templating/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt b/plugins/templating/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt index a2d55209..5a97d216 100644 --- a/plugins/templating/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt +++ b/plugins/templating/src/main/kotlin/templates/JsonElementBasedTemplateProcessingStrategy.kt @@ -37,6 +37,7 @@ abstract class BaseJsonNavigationTemplateProcessingStrategy(val context: DokkaCo val content = toJsonString(fragments.entries.flatMap { (moduleName, navigation) -> navigation.map { it.withResolvedLocation(moduleName) } }) + output.resolve(path).mkdirs() output.resolve("$path/$navigationFileNameWithoutExtension.json").writeText(content) fragments.keys.forEach { diff --git a/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt b/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt index 8fbd76b6..c67654ec 100644 --- a/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt +++ b/plugins/templating/src/main/kotlin/templates/TemplateProcessor.kt @@ -1,15 +1,26 @@ package org.jetbrains.dokka.templates import kotlinx.coroutines.* +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.templating.Command +import org.jetbrains.dokka.model.withDescendants +import org.jetbrains.dokka.pages.RootPageNode import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.query +import org.jetbrains.dokka.plugability.querySingle import org.jsoup.nodes.Element import java.io.File -interface TemplateProcessor { - fun process() +interface TemplateProcessor + +interface SubmoduleTemplateProcessor : TemplateProcessor { + fun process(modules: List<DokkaConfiguration.DokkaModuleDescription>): TemplatingResult +} + +interface MultiModuleTemplateProcessor : TemplateProcessor { + fun process(generatedPagesTree: RootPageNode) } interface TemplateProcessingStrategy { @@ -17,40 +28,69 @@ interface TemplateProcessingStrategy { fun finish(output: File) {} } -class DefaultTemplateProcessor( +class DefaultSubmoduleTemplateProcessor( private val context: DokkaContext, -): TemplateProcessor { +) : SubmoduleTemplateProcessor { - private val strategies: List<TemplateProcessingStrategy> = context.plugin<TemplatingPlugin>().query { templateProcessingStrategy } + private val strategies: List<TemplateProcessingStrategy> = + context.plugin<TemplatingPlugin>().query { templateProcessingStrategy } - override fun process() = runBlocking(Dispatchers.Default) { - coroutineScope { - context.configuration.modules.forEach { - launch { - it.sourceOutputDirectory.visit(context.configuration.outputDir.resolve(it.relativePathToOutputDirectory)) + private val configuredModulesPaths = + context.configuration.modules.map { it.sourceOutputDirectory.absolutePath to it.name }.toMap() + + override fun process(modules: List<DokkaConfiguration.DokkaModuleDescription>) = + runBlocking(Dispatchers.Default) { + coroutineScope { + modules.fold(TemplatingResult()) { acc, module -> + acc + module.sourceOutputDirectory.visit(context.configuration.outputDir.resolve(module.relativePathToOutputDirectory)) } } } - strategies.map { it.finish(context.configuration.outputDir) } - Unit - } - private suspend fun File.visit(target: File): Unit = coroutineScope { - val source = this@visit - if (source.isDirectory) { - target.mkdir() - source.list()?.forEach { - launch { source.resolve(it).visit(target.resolve(it)) } - } - } else { - strategies.first { it.process(source, target) } + private suspend fun File.visit(target: File, acc: TemplatingResult = TemplatingResult()): TemplatingResult = + coroutineScope { + val source = this@visit + if (source.isDirectory) { + target.mkdir() + val files = source.list().orEmpty() + val accWithSelf = configuredModulesPaths[source.absolutePath] + ?.takeIf { files.firstOrNull { !it.startsWith(".") } != null } + ?.let { acc.copy(modules = acc.modules + it) } + ?: acc + + files.fold(accWithSelf) { acc, path -> + source.resolve(path).visit(target.resolve(path), acc) + } + } else { + strategies.first { it.process(source, target) } + acc + } } +} + +class DefaultMultiModuleTemplateProcessor( + context: DokkaContext, +) : MultiModuleTemplateProcessor { + private val strategies: List<TemplateProcessingStrategy> = + context.plugin<TemplatingPlugin>().query { templateProcessingStrategy } + + private val locationProviderFactory = context.plugin<DokkaBase>().querySingle { locationProviderFactory } + + override fun process(generatedPagesTree: RootPageNode) { + val locationProvider = locationProviderFactory.getLocationProvider(generatedPagesTree) + generatedPagesTree.withDescendants().mapNotNull { locationProvider.resolve(it)?.let { File(it) } } + .forEach { location -> strategies.first { it.process(location, location) } } } + } -data class TemplatingContext<out T: Command>( +data class TemplatingContext<out T : Command>( val input: File, val output: File, val element: Element, val command: T, -)
\ No newline at end of file +) + +data class TemplatingResult(val modules: List<String> = emptyList()) { + operator fun plus(rhs: TemplatingResult): TemplatingResult = TemplatingResult((modules + rhs.modules).distinct()) +}
\ No newline at end of file diff --git a/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt b/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt index 29ca4904..546a0443 100644 --- a/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt +++ b/plugins/templating/src/main/kotlin/templates/TemplatingPlugin.kt @@ -6,14 +6,19 @@ import org.jetbrains.dokka.plugability.DokkaPlugin class TemplatingPlugin : DokkaPlugin() { - val templateProcessor by extensionPoint<TemplateProcessor>() + val submoduleTemplateProcessor by extensionPoint<SubmoduleTemplateProcessor>() + val multimoduleTemplateProcessor by extensionPoint<MultiModuleTemplateProcessor>() val templateProcessingStrategy by extensionPoint<TemplateProcessingStrategy>() val directiveBasedCommandHandlers by extensionPoint<CommandHandler>() val substitutor by extensionPoint<Substitutor>() - val defaultTemplateProcessor by extending { - templateProcessor providing ::DefaultTemplateProcessor + val defaultSubmoduleTemplateProcessor by extending { + submoduleTemplateProcessor providing ::DefaultSubmoduleTemplateProcessor + } + + val defaultMultiModuleTemplateProcessor by extending { + multimoduleTemplateProcessor providing ::DefaultMultiModuleTemplateProcessor } val directiveBasedHtmlTemplateProcessingStrategy by extending { diff --git a/plugins/templating/src/test/kotlin/templates/AddToNavigationCommandResolutionTest.kt b/plugins/templating/src/test/kotlin/templates/AddToNavigationCommandResolutionTest.kt index 19c940c2..a1e11dfe 100644 --- a/plugins/templating/src/test/kotlin/templates/AddToNavigationCommandResolutionTest.kt +++ b/plugins/templating/src/test/kotlin/templates/AddToNavigationCommandResolutionTest.kt @@ -127,7 +127,7 @@ class AddToNavigationCommandResolutionTest : TemplatingAbstractTest() { module2Navigation.writeText(inputForModule("module2")) testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { ctx -> + finishProcessingSubmodules = { ctx -> test(ctx) } } diff --git a/plugins/templating/src/test/kotlin/templates/AddToSearchCommandResolutionTest.kt b/plugins/templating/src/test/kotlin/templates/AddToSearchCommandResolutionTest.kt index a962d524..049cef96 100644 --- a/plugins/templating/src/test/kotlin/templates/AddToSearchCommandResolutionTest.kt +++ b/plugins/templating/src/test/kotlin/templates/AddToSearchCommandResolutionTest.kt @@ -56,7 +56,7 @@ class AddToSearchCommandResolutionTest : TemplatingAbstractTest() { } testFromData(configuration, preserveOutputLocation = true) { - submoduleProcessingStage = { _ -> + finishProcessingSubmodules = { _ -> val expected = elements.map { it.copy(location = "module1/${it.location}") } + elements.map { it.copy(location = "module2/${it.location}") } diff --git a/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt b/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt index d7143f11..9d211876 100644 --- a/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt +++ b/plugins/templating/src/test/kotlin/templates/SubstitutionCommandResolutionTest.kt @@ -52,7 +52,7 @@ class SubstitutionCommandResolutionTest : TemplatingAbstractTest() { } testFromData(configuration, preserveOutputLocation = true){ - submoduleProcessingStage = { + finishProcessingSubmodules = { assertHtmlEqualsIgnoringWhitespace(expected, testedFile.readText()) } } diff --git a/plugins/templating/src/test/kotlin/templates/TemplatingDokkaTestGenerator.kt b/plugins/templating/src/test/kotlin/templates/TemplatingDokkaTestGenerator.kt index 906fb1ea..04420662 100644 --- a/plugins/templating/src/test/kotlin/templates/TemplatingDokkaTestGenerator.kt +++ b/plugins/templating/src/test/kotlin/templates/TemplatingDokkaTestGenerator.kt @@ -36,6 +36,9 @@ class TemplatingDokkaTestGenerator( generation.processSubmodules() submoduleProcessingStage(context) + + generation.finishProcessing() + finishProcessingSubmodules(context) } } @@ -43,15 +46,18 @@ class TemplatingDokkaTestGenerator( open class TemplatingTestMethods( open val pluginsSetupStage: (DokkaContext) -> Unit, open val submoduleProcessingStage: (DokkaContext) -> Unit, + open val finishProcessingSubmodules: (DokkaContext) -> Unit, ) : TestMethods class TemplatingTestBuilder : TestBuilder<TemplatingTestMethods>() { var pluginsSetupStage: (DokkaContext) -> Unit = {} var submoduleProcessingStage: (DokkaContext) -> Unit = {} + var finishProcessingSubmodules: (DokkaContext) -> Unit = {} override fun build() = TemplatingTestMethods( pluginsSetupStage, submoduleProcessingStage, + finishProcessingSubmodules, ) } diff --git a/plugins/templating/src/test/kotlin/templates/TestTemplatingGeneration.kt b/plugins/templating/src/test/kotlin/templates/TestTemplatingGeneration.kt index 0a5bae4b..5dbe2bbe 100644 --- a/plugins/templating/src/test/kotlin/templates/TestTemplatingGeneration.kt +++ b/plugins/templating/src/test/kotlin/templates/TestTemplatingGeneration.kt @@ -4,19 +4,27 @@ import org.jetbrains.dokka.Timer import org.jetbrains.dokka.generation.Generation import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin +import org.jetbrains.dokka.plugability.query import org.jetbrains.dokka.plugability.querySingle -class TestTemplatingGeneration(context: DokkaContext): Generation { +class TestTemplatingGeneration(private val context: DokkaContext) : Generation { val templatingPlugin by lazy { context.plugin<TemplatingPlugin>() } override fun Timer.generate() { report("Processing submodules") processSubmodules() + + report("Finishing processing") + finishProcessing() } fun processSubmodules() = - templatingPlugin.querySingle { templateProcessor }.process() + templatingPlugin.querySingle { submoduleTemplateProcessor }.process(context.configuration.modules) + + fun finishProcessing() = + templatingPlugin.query { templateProcessingStrategy }.forEach { it.finish(context.configuration.outputDir) } + override val generationName = "test template generation" }
\ No newline at end of file |