diff options
27 files changed, 318 insertions, 207 deletions
diff --git a/core/src/main/kotlin/CoreExtensions.kt b/core/src/main/kotlin/CoreExtensions.kt index f5fb7604..0eea416a 100644 --- a/core/src/main/kotlin/CoreExtensions.kt +++ b/core/src/main/kotlin/CoreExtensions.kt @@ -1,6 +1,9 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.plugability.ExtensionPoint +import org.jetbrains.dokka.generation.Generation +import org.jetbrains.dokka.generation.SingleModuleGeneration +import org.jetbrains.dokka.plugability.* +import org.jetbrains.dokka.plugability.LazyEvaluated import org.jetbrains.dokka.renderers.Renderer import org.jetbrains.dokka.transformers.documentation.DocumentableMerger import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator @@ -13,19 +16,36 @@ import org.jetbrains.dokka.validity.PreGenerationChecker import kotlin.reflect.KProperty object CoreExtensions { - val preGenerationCheck by coreExtension<PreGenerationChecker>() - val sourceToDocumentableTranslator by coreExtension<SourceToDocumentableTranslator>() - val preMergeDocumentableTransformer by coreExtension<PreMergeDocumentableTransformer>() - val documentableMerger by coreExtension<DocumentableMerger>() - val documentableTransformer by coreExtension<DocumentableTransformer>() - val documentableToPageTranslator by coreExtension<DocumentableToPageTranslator>() - val allModulePageCreator by coreExtension<PageCreator>() - val pageTransformer by coreExtension<PageTransformer>() - val allModulePageTransformer by coreExtension<PageTransformer>() - val renderer by coreExtension<Renderer>() + private val extensionDelegates = mutableListOf<Lazy<Extension<*, *, *>>>() - private fun <T : Any> coreExtension() = object { + val preGenerationCheck by coreExtensionPoint<PreGenerationChecker>() + val generation by coreExtensionPoint<Generation>() + val sourceToDocumentableTranslator by coreExtensionPoint<SourceToDocumentableTranslator>() + val preMergeDocumentableTransformer by coreExtensionPoint<PreMergeDocumentableTransformer>() + val documentableMerger by coreExtensionPoint<DocumentableMerger>() + val documentableTransformer by coreExtensionPoint<DocumentableTransformer>() + val documentableToPageTranslator by coreExtensionPoint<DocumentableToPageTranslator>() + val allModulePageCreator by coreExtensionPoint<PageCreator>() + val pageTransformer by coreExtensionPoint<PageTransformer>() + val allModulePageTransformer by coreExtensionPoint<PageTransformer>() + val renderer by coreExtensionPoint<Renderer>() + + val singleGeneration by generation extendWith LazyEvaluated.fromRecipe(::SingleModuleGeneration) + + private fun <T : Any> coreExtensionPoint() = object { operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy<ExtensionPoint<T>> = lazy { ExtensionPoint<T>(thisRef::class.qualifiedName!!, property.name) } } + + private infix fun <T: Any> ExtensionPoint<T>.extendWith(action: LazyEvaluated<T>) = object { + operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy<Extension<T, OrderingKind.None, OverrideKind.None>> = + lazy { Extension(this@extendWith, thisRef::class.qualifiedName!!, property.name, action) } + .also { extensionDelegates += it } + } + + internal fun installTo(context: DokkaContextConfiguration) { + extensionDelegates.forEach { + context.installExtension(it.value) + } + } }
\ No newline at end of file diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index b3d58439..947fa737 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -2,17 +2,10 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.DokkaConfiguration.* -import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.generation.GracefulGenerationExit import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.DokkaPlugin import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.dokka.utilities.report -import kotlinx.coroutines.* -import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator -import org.jetbrains.dokka.utilities.parallelMap - /** * DokkaGenerator is the main entry point for generating documentation @@ -29,136 +22,21 @@ class DokkaGenerator( report("Initializing plugins") val context = initializePlugins(configuration, logger) - report("Validity check") - validityCheck(context) - - report("Creating documentation models") - val modulesFromPlatforms = createDocumentationModels(context) - - report("Transforming documentation model before merging") - val transformedDocumentationBeforeMerge = transformDocumentationModelBeforeMerge(modulesFromPlatforms, context) - - report("Merging documentation models") - val documentationModel = mergeDocumentationModels(transformedDocumentationBeforeMerge, context) - - report("Transforming documentation model after merging") - val transformedDocumentation = transformDocumentationModelAfterMerge(documentationModel, context) - - report("Creating pages") - val pages = createPages(transformedDocumentation, context) - - report("Transforming pages") - val transformedPages = transformPages(pages, context) - - report("Rendering") - render(transformedPages, context) - - reportAfterRendering(context) - }.dump("\n\n === TIME MEASUREMENT ===\n") - - fun generateAllModulesPage() = timed { - report("Initializing plugins") - val context = initializePlugins(configuration, logger) - - report("Creating all modules page") - val pages = createAllModulePage(context) - - report("Transforming pages") - val transformedPages = transformAllModulesPage(pages, context) + context.single(CoreExtensions.generation).run { + logger.progress("Dokka is performing: $generationName") + generate() + } - report("Rendering") - render(transformedPages, context) }.dump("\n\n === TIME MEASUREMENT ===\n") - fun initializePlugins( configuration: DokkaConfiguration, logger: DokkaLogger, additionalPlugins: List<DokkaPlugin> = emptyList() ) = DokkaContext.create(configuration, logger, additionalPlugins) - - fun createDocumentationModels( - context: DokkaContext - ) = runBlocking(Dispatchers.Default) { - context.configuration.sourceSets.parallelMap { sourceSet -> translateSources(sourceSet, context) }.flatten() - .also { modules -> if (modules.isEmpty()) exitGenerationGracefully("Nothing to document") } - } - - fun transformDocumentationModelBeforeMerge( - modulesFromPlatforms: List<DModule>, - context: DokkaContext - ) = context[CoreExtensions.preMergeDocumentableTransformer].fold(modulesFromPlatforms) { acc, t -> t(acc) } - - fun mergeDocumentationModels( - modulesFromPlatforms: List<DModule>, - context: DokkaContext - ) = context.single(CoreExtensions.documentableMerger).invoke(modulesFromPlatforms) - - fun transformDocumentationModelAfterMerge( - documentationModel: DModule, - context: DokkaContext - ) = context[CoreExtensions.documentableTransformer].fold(documentationModel) { acc, t -> t(acc, context) } - - fun createPages( - transformedDocumentation: DModule, - context: DokkaContext - ) = context.single(CoreExtensions.documentableToPageTranslator).invoke(transformedDocumentation) - - fun createAllModulePage( - context: DokkaContext - ) = context.single(CoreExtensions.allModulePageCreator).invoke() - - fun transformPages( - pages: RootPageNode, - context: DokkaContext - ) = context[CoreExtensions.pageTransformer].fold(pages) { acc, t -> t(acc) } - - fun transformAllModulesPage( - pages: RootPageNode, - context: DokkaContext - ) = context[CoreExtensions.allModulePageTransformer].fold(pages) { acc, t -> t(acc) } - - fun render( - transformedPages: RootPageNode, - context: DokkaContext - ) { - val renderer = context.single(CoreExtensions.renderer) - renderer.render(transformedPages) - } - - fun reportAfterRendering(context: DokkaContext) { - context.unusedPoints.takeIf { it.isNotEmpty() }?.also { - logger.info("Unused extension points found: ${it.joinToString(", ")}") - } - - logger.report() - - if (context.configuration.failOnWarning && (logger.warningsCount > 0 || logger.errorsCount > 0)) { - throw DokkaException( - "Failed with warningCount=${logger.warningsCount} and errorCount=${logger.errorsCount}" - ) - } - } - - fun validityCheck(context: DokkaContext) { - val (preGenerationCheckResult, checkMessages) = context[CoreExtensions.preGenerationCheck].fold( - Pair(true, emptyList<String>()) - ) { acc, checker -> checker() + acc } - if (!preGenerationCheckResult) throw DokkaException( - "Pre-generation validity check failed: ${checkMessages.joinToString(",")}" - ) - } - - private suspend fun translateSources(sourceSet: DokkaSourceSet, context: DokkaContext) = - context[CoreExtensions.sourceToDocumentableTranslator].parallelMap { translator -> - when(translator){ - is AsyncSourceToDocumentableTranslator -> translator.invokeSuspending(sourceSet, context) - else -> translator.invoke(sourceSet, context) - } - } } -private class Timer(startTime: Long, private val logger: DokkaLogger?) { +class Timer internal constructor(startTime: Long, private val logger: DokkaLogger?) { private val steps = mutableListOf("" to startTime) fun report(name: String) { @@ -168,8 +46,8 @@ private class Timer(startTime: Long, private val logger: DokkaLogger?) { fun dump(prefix: String = "") { logger?.info(prefix) - val namePad = steps.map { it.first.length }.max() ?: 0 - val timePad = steps.windowed(2).map { (p1, p2) -> p2.second - p1.second }.max()?.toString()?.length ?: 0 + val namePad = steps.map { it.first.length }.maxOrNull() ?: 0 + val timePad = steps.windowed(2).map { (p1, p2) -> p2.second - p1.second }.maxOrNull()?.toString()?.length ?: 0 steps.windowed(2).forEach { (p1, p2) -> if (p1.first.isNotBlank()) { logger?.info("${p1.first.padStart(namePad)}: ${(p2.second - p1.second).toString().padStart(timePad)}") @@ -189,8 +67,3 @@ private fun timed(logger: DokkaLogger? = null, block: Timer.() -> Unit): Timer = } } -private fun exitGenerationGracefully(reason: String): Nothing { - throw GracefulGenerationExit(reason) -} - -private class GracefulGenerationExit(val reason: String) : Throwable() diff --git a/core/src/main/kotlin/DokkaMultimoduleBootstrapImpl.kt b/core/src/main/kotlin/DokkaMultimoduleBootstrapImpl.kt deleted file mode 100644 index c0726584..00000000 --- a/core/src/main/kotlin/DokkaMultimoduleBootstrapImpl.kt +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Accessed with reflection - */ -@file:Suppress("unused") - -package org.jetbrains.dokka - -import org.jetbrains.dokka.DokkaBootstrapImpl.DokkaProxyLogger -import org.jetbrains.dokka.utilities.DokkaLogger -import java.util.function.BiConsumer - -class DokkaMultimoduleBootstrapImpl : DokkaBootstrap { - - private lateinit var generator: DokkaGenerator - - fun configure(logger: DokkaLogger, configuration: DokkaConfiguration) { - generator = DokkaGenerator(configuration, logger) - } - - override fun configure(serializedConfigurationJSON: String, logger: BiConsumer<String, String>) = configure( - DokkaProxyLogger(logger), - DokkaConfigurationImpl(serializedConfigurationJSON) - ) - - override fun generate() { - generator.generateAllModulesPage() - } - -} diff --git a/core/src/main/kotlin/generation/Generation.kt b/core/src/main/kotlin/generation/Generation.kt new file mode 100644 index 00000000..230cdae1 --- /dev/null +++ b/core/src/main/kotlin/generation/Generation.kt @@ -0,0 +1,15 @@ +package org.jetbrains.dokka.generation + +import org.jetbrains.dokka.Timer + +interface Generation { + fun Timer.generate() + val generationName: String +} + +// This needs to be public for now but in the future it should be replaced with system of checks provided by EP +fun exitGenerationGracefully(reason: String): Nothing { + throw GracefulGenerationExit(reason) +} + +class GracefulGenerationExit(val reason: String) : Throwable()
\ No newline at end of file diff --git a/core/src/main/kotlin/generation/SingleModule.kt b/core/src/main/kotlin/generation/SingleModule.kt new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/core/src/main/kotlin/generation/SingleModule.kt diff --git a/core/src/main/kotlin/generation/SingleModuleGeneration.kt b/core/src/main/kotlin/generation/SingleModuleGeneration.kt new file mode 100644 index 00000000..59514632 --- /dev/null +++ b/core/src/main/kotlin/generation/SingleModuleGeneration.kt @@ -0,0 +1,124 @@ +package org.jetbrains.dokka.generation + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import org.jetbrains.dokka.* +import org.jetbrains.dokka.model.DModule +import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator +import org.jetbrains.dokka.utilities.parallelMap +import org.jetbrains.dokka.utilities.report + +class SingleModuleGeneration(private val context: DokkaContext): Generation { + override fun Timer.generate() { + report("Validity check") + validityCheck(context) + + report("Creating documentation models") + val modulesFromPlatforms = createDocumentationModels(context) + + report("Transforming documentation model before merging") + val transformedDocumentationBeforeMerge = transformDocumentationModelBeforeMerge(modulesFromPlatforms, context) + + report("Merging documentation models") + val documentationModel = mergeDocumentationModels(transformedDocumentationBeforeMerge, context) + + report("Transforming documentation model after merging") + val transformedDocumentation = transformDocumentationModelAfterMerge(documentationModel, context) + + report("Creating pages") + val pages = createPages(transformedDocumentation, context) + + report("Transforming pages") + val transformedPages = transformPages(pages, context) + + report("Rendering") + render(transformedPages, context) + + reportAfterRendering(context) + } + + override val generationName: String + get() = TODO("Not yet implemented") + + fun createDocumentationModels( + context: DokkaContext + ) = runBlocking(Dispatchers.Default) { + context.configuration.sourceSets.parallelMap { sourceSet -> translateSources(sourceSet, context) }.flatten() + .also { modules -> if (modules.isEmpty()) exitGenerationGracefully("Nothing to document") } + } + + fun transformDocumentationModelBeforeMerge( + modulesFromPlatforms: List<DModule>, + context: DokkaContext + ) = context[CoreExtensions.preMergeDocumentableTransformer].fold(modulesFromPlatforms) { acc, t -> t(acc) } + + fun mergeDocumentationModels( + modulesFromPlatforms: List<DModule>, + context: DokkaContext + ) = context.single(CoreExtensions.documentableMerger).invoke(modulesFromPlatforms) + + fun transformDocumentationModelAfterMerge( + documentationModel: DModule, + context: DokkaContext + ) = context[CoreExtensions.documentableTransformer].fold(documentationModel) { acc, t -> t(acc, context) } + + fun createPages( + transformedDocumentation: DModule, + context: DokkaContext + ) = context.single(CoreExtensions.documentableToPageTranslator).invoke(transformedDocumentation) + + fun createAllModulePage( + context: DokkaContext + ) = context.single(CoreExtensions.allModulePageCreator).invoke() + + fun transformPages( + pages: RootPageNode, + context: DokkaContext + ) = context[CoreExtensions.pageTransformer].fold(pages) { acc, t -> t(acc) } + + fun transformAllModulesPage( + pages: RootPageNode, + context: DokkaContext + ) = context[CoreExtensions.allModulePageTransformer].fold(pages) { acc, t -> t(acc) } + + fun render( + transformedPages: RootPageNode, + context: DokkaContext + ) { + val renderer = context.single(CoreExtensions.renderer) + renderer.render(transformedPages) + } + + fun validityCheck(context: DokkaContext) { + val (preGenerationCheckResult, checkMessages) = context[CoreExtensions.preGenerationCheck].fold( + Pair(true, emptyList<String>()) + ) { acc, checker -> checker() + acc } + if (!preGenerationCheckResult) throw DokkaException( + "Pre-generation validity check failed: ${checkMessages.joinToString(",")}" + ) + } + + fun reportAfterRendering(context: DokkaContext) { + context.unusedPoints.takeIf { it.isNotEmpty() }?.also { + context.logger.info("Unused extension points found: ${it.joinToString(", ")}") + } + + context.logger.report() + + if (context.configuration.failOnWarning && (context.logger.warningsCount > 0 || context.logger.errorsCount > 0)) { + throw DokkaException( + "Failed with warningCount=${context.logger.warningsCount} and errorCount=${context.logger.errorsCount}" + ) + } + } + + private suspend fun translateSources(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext) = + context[CoreExtensions.sourceToDocumentableTranslator].parallelMap { translator -> + when(translator){ + is AsyncSourceToDocumentableTranslator -> translator.invokeSuspending(sourceSet, context) + else -> translator.invoke(sourceSet, context) + } + } +}
\ No newline at end of file diff --git a/core/src/main/kotlin/plugability/DokkaContext.kt b/core/src/main/kotlin/plugability/DokkaContext.kt index 323039e9..1f5f6018 100644 --- a/core/src/main/kotlin/plugability/DokkaContext.kt +++ b/core/src/main/kotlin/plugability/DokkaContext.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka.plugability +import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.utilities.DokkaLogger import java.io.File @@ -29,6 +30,7 @@ interface DokkaContext { pluginOverrides: List<DokkaPlugin> ): DokkaContext = DokkaContextConfigurationImpl(logger, configuration).apply { + CoreExtensions.installTo(this) // File(it.path) is a workaround for an incorrect filesystem in a File instance returned by Gradle. configuration.pluginsClasspath.map { File(it.path).toURI().toURL() } .toTypedArray() diff --git a/core/src/main/kotlin/plugability/extensions.kt b/core/src/main/kotlin/plugability/extensions.kt index be45c237..46739951 100644 --- a/core/src/main/kotlin/plugability/extensions.kt +++ b/core/src/main/kotlin/plugability/extensions.kt @@ -40,7 +40,7 @@ class Extension<T : Any, Ordering : OrderingKind, Override : OverrideKind> inter get() = { conditions.all { it(this) } } } -private fun <T : Any> Extension( +internal fun <T : Any> Extension( extensionPoint: ExtensionPoint<T>, pluginClass: String, extensionName: String, diff --git a/core/test-api/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt b/core/test-api/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt index 98f8965c..0f5814f6 100644 --- a/core/test-api/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt +++ b/core/test-api/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt @@ -1,7 +1,9 @@ package org.jetbrains.dokka.testApi.testRunner +import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.DokkaGenerator +import org.jetbrains.dokka.generation.SingleModuleGeneration import org.jetbrains.dokka.plugability.DokkaPlugin import org.jetbrains.dokka.utilities.DokkaLogger @@ -19,31 +21,31 @@ internal class DokkaTestGenerator( dokkaGenerator.initializePlugins(configuration, logger, additionalPlugins) pluginsSetupStage(context) - verificationStage { - dokkaGenerator.validityCheck(context) - } + val singleModuleGeneration = context.single(CoreExtensions.generation) as SingleModuleGeneration - val modulesFromPlatforms = dokkaGenerator.createDocumentationModels(context) + val modulesFromPlatforms = singleModuleGeneration.createDocumentationModels() documentablesCreationStage(modulesFromPlatforms) - val filteredModules = dokkaGenerator.transformDocumentationModelBeforeMerge(modulesFromPlatforms, context) + verificationStage { singleModuleGeneration.validityCheck(context) } + + val filteredModules = singleModuleGeneration.transformDocumentationModelBeforeMerge(modulesFromPlatforms) documentablesFirstTransformationStep(filteredModules) - val documentationModel = dokkaGenerator.mergeDocumentationModels(filteredModules, context) + val documentationModel = singleModuleGeneration.mergeDocumentationModels(filteredModules) documentablesMergingStage(documentationModel) - val transformedDocumentation = dokkaGenerator.transformDocumentationModelAfterMerge(documentationModel, context) + val transformedDocumentation = singleModuleGeneration.transformDocumentationModelAfterMerge(documentationModel) documentablesTransformationStage(transformedDocumentation) - val pages = dokkaGenerator.createPages(transformedDocumentation, context) + val pages = singleModuleGeneration.createPages(transformedDocumentation) pagesGenerationStage(pages) - val transformedPages = dokkaGenerator.transformPages(pages, context) + val transformedPages = singleModuleGeneration.transformPages(pages) pagesTransformationStage(transformedPages) - dokkaGenerator.render(transformedPages, context) + singleModuleGeneration.render(transformedPages) renderingStage(transformedPages, context) - dokkaGenerator.reportAfterRendering(context) + singleModuleGeneration.reportAfterRendering() } } diff --git a/plugins/all-module-page/build.gradle.kts b/plugins/all-module-page/build.gradle.kts new file mode 100644 index 00000000..dc5e0a6a --- /dev/null +++ b/plugins/all-module-page/build.gradle.kts @@ -0,0 +1,9 @@ +import org.jetbrains.registerDokkaArtifactPublication + +registerDokkaArtifactPublication("dokkaAllModulesPage") { + artifactId = "all-modules-page-plugin" +} + +dependencies { + implementation(project(":plugins:base")) +}
\ No newline at end of file diff --git a/plugins/all-module-page/src/main/kotlin/AllModulesPageGeneration.kt b/plugins/all-module-page/src/main/kotlin/AllModulesPageGeneration.kt new file mode 100644 index 00000000..815cf160 --- /dev/null +++ b/plugins/all-module-page/src/main/kotlin/AllModulesPageGeneration.kt @@ -0,0 +1,31 @@ +package org.jetbrains.dokka.allModulesPage + +import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.Timer +import org.jetbrains.dokka.generation.Generation +import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.plugability.DokkaContext + +class AllModulesPageGeneration(private val context: DokkaContext) : Generation { + override fun Timer.generate() { + report("Creating all modules page") + val pages = createAllModulePage() + + report("Transforming pages") + val transformedPages = transformAllModulesPage(pages) + + report("Rendering") + render(transformedPages) + } + + override val generationName = "index page for project" + + fun createAllModulePage() = context.single(CoreExtensions.allModulePageCreator).invoke() + + fun transformAllModulesPage(pages: RootPageNode) = + context[CoreExtensions.allModulePageTransformer].fold(pages) { acc, t -> t(acc) } + + fun render(transformedPages: RootPageNode) { + context.single(CoreExtensions.renderer).render(transformedPages) + } +}
\ No newline at end of file diff --git a/plugins/all-module-page/src/main/kotlin/AllModulesPagePlugin.kt b/plugins/all-module-page/src/main/kotlin/AllModulesPagePlugin.kt new file mode 100644 index 00000000..163f13ab --- /dev/null +++ b/plugins/all-module-page/src/main/kotlin/AllModulesPagePlugin.kt @@ -0,0 +1,25 @@ +package org.jetbrains.dokka.allModulesPage + +import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.plugability.DokkaPlugin + +class AllModulesPagePlugin : DokkaPlugin() { + val allModulePageCreators by extending { + (CoreExtensions.allModulePageCreator + providing ::MultimodulePageCreator) + } + + val multimoduleLocationProvider by extending { + (plugin<DokkaBase>().locationProviderFactory + providing MultimoduleLocationProvider::Factory + override plugin<DokkaBase>().locationProvider + applyIf { modules.size > 1 }) + } + + val allModulesPageGeneration by extending { + (CoreExtensions.generation + providing ::AllModulesPageGeneration + override CoreExtensions.singleGeneration) + } +}
\ No newline at end of file diff --git a/plugins/all-module-page/src/main/kotlin/MultimoduleLocationProvider.kt b/plugins/all-module-page/src/main/kotlin/MultimoduleLocationProvider.kt new file mode 100644 index 00000000..29107136 --- /dev/null +++ b/plugins/all-module-page/src/main/kotlin/MultimoduleLocationProvider.kt @@ -0,0 +1,41 @@ +package org.jetbrains.dokka.allModulesPage + +import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider +import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider.Companion.identifierToFilename +import org.jetbrains.dokka.base.resolvers.local.LocationProvider +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.PageNode +import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.plugability.DokkaContext + +class MultimoduleLocationProvider(private val root: RootPageNode, context: DokkaContext) : LocationProvider { + + private val defaultLocationProvider = DokkaLocationProvider(root, context) + + val paths = context.configuration.modules.map { + it.name to it.relativePathToOutputDirectory + }.toMap() + + override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?) = + dri.takeIf { it.packageName == MULTIMODULE_PACKAGE_PLACEHOLDER }?.classNames?.let { paths[it] }?.let { + "$it/${identifierToFilename(dri.classNames.orEmpty())}/index.html" + } ?: defaultLocationProvider.resolve(dri, sourceSets, context) + + override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean) = + defaultLocationProvider.resolve(node, context, skipExtension) + + override fun pathToRoot(from: PageNode): String = defaultLocationProvider.pathToRoot(from) + + override fun ancestors(node: PageNode): List<PageNode> = listOf(root) + + companion object { + const val MULTIMODULE_PACKAGE_PLACEHOLDER = ".ext" + } + + class Factory(private val context: DokkaContext): LocationProviderFactory { + override fun getLocationProvider(pageNode: RootPageNode) = + MultimoduleLocationProvider(pageNode, context) + } +}
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt b/plugins/all-module-page/src/main/kotlin/MultimodulePageCreator.kt index 3c4f1dea..3ad3e0ce 100644 --- a/plugins/base/src/main/kotlin/allModulePage/MultimodulePageCreator.kt +++ b/plugins/all-module-page/src/main/kotlin/MultimodulePageCreator.kt @@ -1,4 +1,4 @@ -package org.jetbrains.dokka.base.allModulePage +package org.jetbrains.dokka.allModulesPage import org.jetbrains.dokka.DokkaConfiguration.DokkaModuleDescription import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet diff --git a/plugins/all-module-page/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/all-module-page/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin new file mode 100644 index 00000000..3ac59dc6 --- /dev/null +++ b/plugins/all-module-page/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin @@ -0,0 +1 @@ +org.jetbrains.dokka.allModulesPage.AllModulesPagePlugin diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index e92759ff..de7e1e5e 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -4,7 +4,6 @@ package org.jetbrains.dokka.base import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.analysis.KotlinAnalysis -import org.jetbrains.dokka.base.allModulePage.MultimodulePageCreator import org.jetbrains.dokka.base.renderers.* import org.jetbrains.dokka.base.renderers.html.* import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactory @@ -205,12 +204,6 @@ class DokkaBase : DokkaPlugin() { htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator) } } - val allModulePageCreators by extending { - CoreExtensions.allModulePageCreator providing { - MultimodulePageCreator(it) - } - } - val baseSearchbarDataInstaller by extending { htmlPreprocessors providing ::SearchbarDataInstaller order { after(sourceLinksTransformer) } } diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentation.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentation.kt index 5139c872..ee67fad1 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentation.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentation.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.base.parsers.moduleAndPackage import org.jetbrains.dokka.model.doc.DocumentationNode -internal data class ModuleAndPackageDocumentation( +data class ModuleAndPackageDocumentation( val name: String, val classifier: Classifier, val documentation: DocumentationNode diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationFragment.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationFragment.kt index fa99a8e2..06fef72c 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationFragment.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationFragment.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.base.parsers.moduleAndPackage import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumentation.* -internal data class ModuleAndPackageDocumentationFragment( +data class ModuleAndPackageDocumentationFragment( val name: String, val classifier: Classifier, val documentation: String, diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationParsingContext.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationParsingContext.kt index 64441447..afdcc43f 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationParsingContext.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationParsingContext.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -internal fun interface ModuleAndPackageDocumentationParsingContext { +fun interface ModuleAndPackageDocumentationParsingContext { fun markdownParserFor(fragment: ModuleAndPackageDocumentationFragment): MarkdownParser } @@ -27,7 +27,7 @@ internal fun ModuleAndPackageDocumentationParsingContext.parse( return markdownParserFor(fragment).parse(fragment.documentation) } -internal fun ModuleAndPackageDocumentationParsingContext( +fun ModuleAndPackageDocumentationParsingContext( logger: DokkaLogger, facade: DokkaResolutionFacade? = null ) = ModuleAndPackageDocumentationParsingContext { fragment -> diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationSource.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationSource.kt index 90dc9ca8..9514adb4 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationSource.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/ModuleAndPackageDocumentationSource.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.base.parsers.moduleAndPackage import java.io.File -internal abstract class ModuleAndPackageDocumentationSource { +abstract class ModuleAndPackageDocumentationSource { abstract val sourceDescription: String abstract val documentation: String override fun toString(): String = sourceDescription diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentation.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentation.kt index a2876308..5ef9d7ef 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentation.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentation.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.base.parsers.moduleAndPackage -internal fun parseModuleAndPackageDocumentation( +fun parseModuleAndPackageDocumentation( context: ModuleAndPackageDocumentationParsingContext, fragment: ModuleAndPackageDocumentationFragment ): ModuleAndPackageDocumentation { diff --git a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentationFragments.kt b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentationFragments.kt index 7dcaccfa..d193ec0a 100644 --- a/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentationFragments.kt +++ b/plugins/base/src/main/kotlin/parsers/moduleAndPackage/parseModuleAndPackageDocumentationFragments.kt @@ -4,11 +4,11 @@ import org.jetbrains.dokka.base.parsers.moduleAndPackage.ModuleAndPackageDocumen import java.io.File -internal fun parseModuleAndPackageDocumentationFragments(source: File): List<ModuleAndPackageDocumentationFragment> { +fun parseModuleAndPackageDocumentationFragments(source: File): List<ModuleAndPackageDocumentationFragment> { return parseModuleAndPackageDocumentationFragments(ModuleAndPackageDocumentationFile(source)) } -internal fun parseModuleAndPackageDocumentationFragments( +fun parseModuleAndPackageDocumentationFragments( source: ModuleAndPackageDocumentationSource ): List<ModuleAndPackageDocumentationFragment> { val fragmentStrings = source.documentation.split(Regex("(|^)#\\s*(?=(Module|Package))")) diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt index 3ef8bcce..030197a5 100644 --- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt +++ b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt @@ -129,12 +129,12 @@ open class DokkaLocationProvider( protected data class PageWithKind(val page: ContentPage, val kind: Kind) companion object { - internal val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out") + val reservedFilenames = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out") //Taken from: https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names internal val reservedCharacters = setOf('|', '>', '<', '*', ':', '"', '?', '%') - internal fun identifierToFilename(name: String): String { + fun identifierToFilename(name: String): String { if (name.isEmpty()) return "--root--" return sanitizeFileName(name, reservedFilenames, reservedCharacters) } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt index 90d51015..726dd950 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaArtifacts.kt @@ -9,6 +9,7 @@ internal class DokkaArtifacts(private val project: Project) { private fun fromModuleName(name: String) = project.dependencies.create("org.jetbrains.dokka:$name:${DokkaVersion.version}") + val allModulesPage get() = fromModuleName("all-modules-page-plugin") val dokkaCore get() = fromModuleName("dokka-core") val dokkaBase get() = fromModuleName("dokka-base") val javadocPlugin get() = fromModuleName("javadoc-plugin") 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 index 03e0b4d7..74f17215 100644 --- 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 @@ -3,6 +3,7 @@ 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.DokkaBootstrapImpl import org.jetbrains.dokka.DokkaConfigurationImpl import org.jetbrains.dokka.DokkaModuleDescriptionImpl import org.jetbrains.dokka.DokkaMultimoduleBootstrapImpl @@ -15,7 +16,7 @@ typealias DokkaMultimoduleTask = DokkaMultiModuleTask private typealias TaskPath = String -abstract class DokkaMultiModuleTask : AbstractDokkaParentTask(DokkaMultimoduleBootstrapImpl::class) { +abstract class DokkaMultiModuleTask : AbstractDokkaParentTask(DokkaBootstrapImpl::class) { @Internal val fileLayout: Property<DokkaMultiModuleFileLayout> = project.objects.safeProperty<DokkaMultiModuleFileLayout>() 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 f5dc9366..1cda5c39 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 @@ -57,6 +57,7 @@ open class DokkaPlugin : Plugin<Project> { addSubprojectChildTasks(name) configuration() description = "Runs all subprojects '$name' tasks and generates module navigation page" + plugins.dependencies.add(project.dokkaArtifacts.allModulesPage) } project.tasks.register<DefaultTask>("${name}Multimodule") { diff --git a/settings.gradle.kts b/settings.gradle.kts index f40e88d8..52b16dc3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,6 +16,7 @@ include("plugins:base") include("plugins:base:frontend") include("plugins:base:search-component") include("plugins:base:base-test-utils") +include("plugins:all-module-page") include("plugins:mathjax") include("plugins:gfm") |