From 177ede83228515f03436a4ac0ce1ce573fc3d74b Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Wed, 1 Jul 2020 16:57:58 +0200 Subject: Add functionality to plugin overrides --- core/src/main/kotlin/DokkaGenerator.kt | 5 +- core/src/main/kotlin/plugability/DokkaContext.kt | 85 ++++++++++++++++++------ core/src/main/kotlin/plugability/DokkaPlugin.kt | 2 +- 3 files changed, 68 insertions(+), 24 deletions(-) (limited to 'core') diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index ee1adf0b..d694cc8c 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -10,6 +10,7 @@ import org.jetbrains.dokka.utilities.DokkaLogger /** * DokkaGenerator is the main entry point for generating documentation + * * [generate] method has been split into submethods for test reasons */ class DokkaGenerator( @@ -62,8 +63,8 @@ class DokkaGenerator( fun initializePlugins( configuration: DokkaConfiguration, logger: DokkaLogger, - pluginOverrides: List = emptyList() - ) = DokkaContext.create(configuration, logger, pluginOverrides) + additionalPlugins: List = emptyList() + ) = DokkaContext.create(configuration, logger, additionalPlugins) fun createDocumentationModels( context: DokkaContext diff --git a/core/src/main/kotlin/plugability/DokkaContext.kt b/core/src/main/kotlin/plugability/DokkaContext.kt index 12b1557b..30566d15 100644 --- a/core/src/main/kotlin/plugability/DokkaContext.kt +++ b/core/src/main/kotlin/plugability/DokkaContext.kt @@ -37,7 +37,7 @@ interface DokkaContext { .let { ServiceLoader.load(DokkaPlugin::class.java, it) } .let { it + pluginOverrides } .forEach { install(it) } - applyExtensions() + topologicallySortAndPrune() }.also { it.logInitialisationInfo() } } } @@ -46,7 +46,7 @@ inline fun DokkaContext.plugin(): T = plugin(T::class) ?: throw java.lang.IllegalStateException("Plugin ${T::class.qualifiedName} is not present in context.") interface DokkaContextConfiguration { - fun addExtensionDependencies(extension: Extension<*, *, *>) + fun installExtension(extension: Extension<*, *, *>) } private class DokkaContextConfigurationImpl( @@ -67,11 +67,26 @@ private class DokkaContextConfigurationImpl( VISITED; } - val verticesWithState = mutableMapOf, State>() - val adjacencyList: MutableMap, MutableList>> = mutableMapOf() + private sealed class Suppression { + data class ByExtension(val extension: Extension<*, *, *>) : Suppression() - private fun topologicalSort() { + data class ByPlugin(val plugin: DokkaPlugin) : Suppression() + } + + private val rawExtensions = mutableListOf>() + private val rawAdjacencyList = mutableMapOf, MutableList>>() + private val suppressedExtensions = mutableMapOf, MutableList>() + + fun topologicallySortAndPrune() { + pointsPopulated.clear() + extensions.clear() + + val overridesInfo = processOverrides() + val extensionsToSort = overridesInfo.keys + val adjacencyList = translateAdjacencyList(overridesInfo) + + val verticesWithState = extensionsToSort.associateWithTo(mutableMapOf()) { State.UNVISITED } val result: MutableList> = mutableListOf() fun visit(n: Extension<*, *, *>) { @@ -86,14 +101,39 @@ private class DokkaContextConfigurationImpl( result += n } - for ((vertex, state) in verticesWithState) { - if (state == State.UNVISITED) - visit(vertex) - } - result.asReversed().forEach { - pointsPopulated += it.extensionPoint - extensions.getOrPut(it.extensionPoint, ::mutableListOf) += it + extensionsToSort.forEach(::visit) + + val filteredResult = result.asReversed().filterNot { it in suppressedExtensions } + + filteredResult.mapTo(pointsPopulated) { it.extensionPoint } + filteredResult.groupByTo(extensions) { it.extensionPoint } + } + + private fun processOverrides(): Map, Set>> { + val buckets = rawExtensions.associateWithTo(mutableMapOf()) { setOf(it) } + suppressedExtensions.forEach { (extension, suppressions) -> + val mergedBucket = suppressions.filterIsInstance() + .map { it.extension } + .plus(extension) + .flatMap { buckets[it].orEmpty() } + .toSet() + mergedBucket.forEach { buckets[it] = mergedBucket } } + return buckets.values.distinct().associateBy(::findNotOverridden) + } + + private fun findNotOverridden(bucket: Set>): Extension<*, *, *> { + val filtered = bucket.filter { it !in suppressedExtensions } + return filtered.singleOrNull() ?: throw Error("Conflicting overrides: $filtered") + } + + private fun translateAdjacencyList( + overridesInfo: Map, Set>> + ): Map, List>> { + val reverseOverrideInfo = overridesInfo.flatMap { (ext, set) -> set.map { it to ext } }.toMap() + return rawAdjacencyList.map { (ext, list) -> + reverseOverrideInfo.getValue(ext) to list.map { reverseOverrideInfo.getValue(it) } + }.toMap() } @Suppress("UNCHECKED_CAST") @@ -129,14 +169,19 @@ private class DokkaContextConfigurationImpl( plugin.internalInstall(this, this.configuration) } - override fun addExtensionDependencies(extension: Extension<*, *, *>) { + override fun installExtension(extension: Extension<*, *, *>) { + rawExtensions += extension + if (extension.ordering is OrderingKind.ByDsl) { val orderDsl = OrderDsl() - extension.ordering.block.invoke(orderDsl) + orderDsl.(extension.ordering.block)() - verticesWithState += extension to State.UNVISITED - adjacencyList.getOrPut(extension, ::mutableListOf) += orderDsl.following.toList() - orderDsl.previous.forEach { adjacencyList.getOrPut(it, ::mutableListOf) += extension } + rawAdjacencyList.listFor(extension) += orderDsl.following.toList() + orderDsl.previous.forEach { rawAdjacencyList.listFor(it) += extension } + } + + if (extension.override is OverrideKind.Present) { + suppressedExtensions.listFor(extension.override.overriden) += Suppression.ByExtension(extension) } } @@ -150,10 +195,6 @@ private class DokkaContextConfigurationImpl( logger.progress("Loaded: $loadedListForDebug") } - - fun applyExtensions() { - topologicalSort() - } } private fun checkClasspath(classLoader: URLClassLoader) { @@ -164,3 +205,5 @@ private fun checkClasspath(classLoader: URLClassLoader) { ) } } + +private fun MutableMap>.listFor(key: K) = getOrPut(key, ::mutableListOf) \ No newline at end of file diff --git a/core/src/main/kotlin/plugability/DokkaPlugin.kt b/core/src/main/kotlin/plugability/DokkaPlugin.kt index bf82daa7..671cefad 100644 --- a/core/src/main/kotlin/plugability/DokkaPlugin.kt +++ b/core/src/main/kotlin/plugability/DokkaPlugin.kt @@ -40,7 +40,7 @@ abstract class DokkaPlugin { extensionDelegates.asSequence() .filterIsInstance>>() // should be always true .map { it.get(this) } - .forEach { if (it.condition.invoke(configuration)) ctx.addExtensionDependencies(it) } + .forEach { if (configuration.(it.condition)()) ctx.installExtension(it) } } } -- cgit