From 9b7e163ae69272c7e56088d6f256d6b19f9a01d4 Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Tue, 30 Jun 2020 21:05:16 +0200 Subject: Refactor Extension DSL and remove fallback mechanism --- core/src/main/kotlin/plugability/DokkaContext.kt | 33 ++++---- core/src/main/kotlin/plugability/DokkaPlugin.kt | 17 ++-- core/src/main/kotlin/plugability/extensions.kt | 101 ++++++++--------------- plugins/base/src/main/kotlin/DokkaBase.kt | 24 +++--- 4 files changed, 68 insertions(+), 107 deletions(-) diff --git a/core/src/main/kotlin/plugability/DokkaContext.kt b/core/src/main/kotlin/plugability/DokkaContext.kt index 15349ff0..12b1557b 100644 --- a/core/src/main/kotlin/plugability/DokkaContext.kt +++ b/core/src/main/kotlin/plugability/DokkaContext.kt @@ -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 addExtensionDependencies(extension: Extension<*, *, *>) } private class DokkaContextConfigurationImpl( @@ -55,7 +55,7 @@ private class DokkaContextConfigurationImpl( ) : DokkaContext, DokkaContextConfiguration { private val plugins = mutableMapOf, DokkaPlugin>() private val pluginStubs = mutableMapOf, DokkaPlugin>() - internal val extensions = mutableMapOf, MutableList>>() + val extensions = mutableMapOf, MutableList>>() val pointsUsed: MutableSet> = mutableSetOf() val pointsPopulated: MutableSet> = mutableSetOf() override val unusedPoints: Set> @@ -67,14 +67,14 @@ private class DokkaContextConfigurationImpl( VISITED; } - internal val verticesWithState = mutableMapOf, State>() - internal val adjacencyList: MutableMap, MutableList>> = mutableMapOf() + val verticesWithState = mutableMapOf, State>() + val adjacencyList: MutableMap, MutableList>> = mutableMapOf() private fun topologicalSort() { - val result: MutableList> = mutableListOf() + val result: MutableList> = mutableListOf() - fun visit(n: Extension<*>) { + fun visit(n: Extension<*, *, *>) { val state = verticesWithState[n] if (state == State.VISITED) return @@ -107,14 +107,11 @@ private class DokkaContextConfigurationImpl( ) pointsUsed += point - val extensions = extensions[point].orEmpty() as List> + val extensions = extensions[point].orEmpty() as List> return when (extensions.size) { 0 -> throwBadArity("none was") 1 -> extensions.single().action.get(this) - else -> { - val notFallbacks = extensions.filterNot { it.isFallback } - if (notFallbacks.size == 1) notFallbacks.single().action.get(this) else throwBadArity("many were") - } + else -> throwBadArity("many were") } } @@ -132,13 +129,15 @@ private class DokkaContextConfigurationImpl( plugin.internalInstall(this, this.configuration) } - override fun addExtensionDependencies(extension: Extension<*>) { - val orderDsl = OrderDsl() - extension.ordering?.invoke(orderDsl) + override fun addExtensionDependencies(extension: Extension<*, *, *>) { + if (extension.ordering is OrderingKind.ByDsl) { + val orderDsl = OrderDsl() + extension.ordering.block.invoke(orderDsl) - verticesWithState += extension to State.UNVISITED - adjacencyList.getOrPut(extension, ::mutableListOf) += orderDsl.following.toList() - orderDsl.previous.forEach { adjacencyList.getOrPut(it, ::mutableListOf) += extension } + verticesWithState += extension to State.UNVISITED + adjacencyList.getOrPut(extension, ::mutableListOf) += orderDsl.following.toList() + orderDsl.previous.forEach { adjacencyList.getOrPut(it, ::mutableListOf) += extension } + } } fun logInitialisationInfo() { diff --git a/core/src/main/kotlin/plugability/DokkaPlugin.kt b/core/src/main/kotlin/plugability/DokkaPlugin.kt index 7ead43b8..bf82daa7 100644 --- a/core/src/main/kotlin/plugability/DokkaPlugin.kt +++ b/core/src/main/kotlin/plugability/DokkaPlugin.kt @@ -7,8 +7,6 @@ import kotlin.reflect.KProperty import kotlin.reflect.KProperty1 import kotlin.reflect.full.createInstance -private typealias ExtensionDelegate = ReadOnlyProperty> - abstract class DokkaPlugin { private val extensionDelegates = mutableListOf>() @@ -25,15 +23,10 @@ abstract class DokkaPlugin { ) } - protected fun extending(isFallback: Boolean = false, definition: ExtendingDSL.() -> Extension) = - if (isFallback) { - ExtensionProvider { definition().markedAsFallback() } - } else { - ExtensionProvider(definition) - } + protected fun extending(definition: ExtendingDSL.() -> Extension) = ExtensionProvider(definition) protected class ExtensionProvider internal constructor( - private val definition: ExtendingDSL.() -> Extension + private val definition: ExtendingDSL.() -> Extension ) { operator fun provideDelegate(thisRef: DokkaPlugin, property: KProperty<*>) = lazy { ExtendingDSL( @@ -45,7 +38,7 @@ abstract class DokkaPlugin { internal fun internalInstall(ctx: DokkaContextConfiguration, configuration: DokkaConfiguration) { extensionDelegates.asSequence() - .filterIsInstance>>() // should be always true + .filterIsInstance>>() // should be always true .map { it.get(this) } .forEach { if (it.condition.invoke(configuration)) ctx.addExtensionDependencies(it) } } @@ -76,8 +69,8 @@ fun throwIllegalQuery(): Nothing = inline fun configuration(context: DokkaContext): ReadOnlyProperty { return object : ReadOnlyProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): R { - return context.configuration.pluginsConfiguration.get(T::class.qualifiedName - ?: throw AssertionError("Plugin must be named class")).let { + return context.configuration.pluginsConfiguration[T::class.qualifiedName + ?: throw AssertionError("Plugin must be named class")].let { Gson().fromJson(it, R::class.java) } } diff --git a/core/src/main/kotlin/plugability/extensions.kt b/core/src/main/kotlin/plugability/extensions.kt index 20b60469..c6dd0b85 100644 --- a/core/src/main/kotlin/plugability/extensions.kt +++ b/core/src/main/kotlin/plugability/extensions.kt @@ -9,79 +9,43 @@ data class ExtensionPoint internal constructor( override fun toString() = "ExtensionPoint: $pluginClass/$pointName" } -abstract class Extension internal constructor( +sealed class OrderingKind { + object None : OrderingKind() + class ByDsl(val block: (OrderDsl.() -> Unit)) : OrderingKind() +} + +sealed class OverrideKind { + object None : OverrideKind() + class Present(val overriden: Extension<*, *, *>) : OverrideKind() +} + +class Extension internal constructor( internal val extensionPoint: ExtensionPoint, internal val pluginClass: String, internal val extensionName: String, internal val action: LazyEvaluated, - internal val ordering: (OrderDsl.() -> Unit)? = null, - internal val conditions: Array Boolean> = emptyArray(), - internal val isFallback: Boolean + internal val ordering: Ordering, + internal val override: Override, + internal val conditions: List Boolean> ) { override fun toString() = "Extension: $pluginClass/$extensionName" override fun equals(other: Any?) = - if (other is Extension<*>) this.pluginClass == other.pluginClass && this.extensionName == other.extensionName + if (other is Extension<*, *, *>) this.pluginClass == other.pluginClass && this.extensionName == other.extensionName else false override fun hashCode() = listOf(pluginClass, extensionName).hashCode() - abstract fun addCondition(condition: (DokkaConfiguration.() -> Boolean)): Extension - - abstract fun markedAsFallback(): Extension - - open val condition: DokkaConfiguration.() -> Boolean - get() = { conditions.all { it(this) }} + val condition: DokkaConfiguration.() -> Boolean + get() = { conditions.all { it(this) } } } -class ExtensionOrdered internal constructor( +private fun Extension( extensionPoint: ExtensionPoint, pluginClass: String, extensionName: String, - action: LazyEvaluated, - ordering: (OrderDsl.() -> Unit), - conditions: Array Boolean> = emptyArray(), - isFallback: Boolean = false -) : Extension( - extensionPoint, - pluginClass, - extensionName, - action, - ordering, - conditions, - isFallback -) { - override fun addCondition(condition: DokkaConfiguration.() -> Boolean) = - ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, ordering!!, conditions + condition) - - override fun markedAsFallback() = - ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, ordering!!, conditions, true) -} - -class ExtensionUnordered internal constructor( - extensionPoint: ExtensionPoint, - pluginClass: String, - extensionName: String, - action: LazyEvaluated, - conditions: Array Boolean> = emptyArray(), - isFallback: Boolean = false -) : Extension( - extensionPoint, - pluginClass, - extensionName, - action, - null, - conditions, - isFallback -) { - override fun addCondition(condition: DokkaConfiguration.() -> Boolean) = - ExtensionUnordered(extensionPoint, pluginClass, extensionName, action, conditions + condition) - - override fun markedAsFallback() = - ExtensionUnordered(extensionPoint, pluginClass, extensionName, action, conditions, true) -} - -internal data class Ordering(val previous: Set>, val following: Set>) + action: LazyEvaluated +) = Extension(extensionPoint, pluginClass, extensionName, action, OrderingKind.None, OverrideKind.None, emptyList()) @DslMarker annotation class ExtensionsDsl @@ -90,29 +54,34 @@ annotation class ExtensionsDsl class ExtendingDSL(private val pluginClass: String, private val extensionName: String) { infix fun ExtensionPoint.with(action: T) = - ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromInstance(action)) + Extension(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromInstance(action)) infix fun ExtensionPoint.providing(action: (DokkaContext) -> T) = - ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromRecipe(action)) + Extension(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromRecipe(action)) - infix fun ExtensionUnordered.order(block: OrderDsl.() -> Unit) = - ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, block) + infix fun Extension.order( + block: OrderDsl.() -> Unit + ) = Extension(extensionPoint, pluginClass, extensionName, action, OrderingKind.ByDsl(block), override, conditions) - infix fun Extension.applyIf(condition: DokkaConfiguration.() -> Boolean): Extension = - this.addCondition(condition) + infix fun Extension.applyIf( + condition: DokkaConfiguration.() -> Boolean + ) = Extension(extensionPoint, pluginClass, extensionName, action, ordering, override, conditions + condition) + infix fun Extension.override( + overriden: Extension + ) = Extension(extensionPoint, pluginClass, extensionName, action, ordering, OverrideKind.Present(overriden), conditions) } @ExtensionsDsl class OrderDsl { - internal val previous = mutableSetOf>() - internal val following = mutableSetOf>() + internal val previous = mutableSetOf>() + internal val following = mutableSetOf>() - fun after(vararg extensions: Extension<*>) { + fun after(vararg extensions: Extension<*, *, *>) { previous += extensions } - fun before(vararg extensions: Extension<*>) { + fun before(vararg extensions: Extension<*, *, *>) { following += extensions } } \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index 0e535c86..8fed0afd 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -55,19 +55,19 @@ class DokkaBase : DokkaPlugin() { } } - val documentableMerger by extending(isFallback = true) { + val documentableMerger by extending { CoreExtensions.documentableMerger with DefaultDocumentableMerger } - val deprecatedDocumentableFilter by extending(isFallback = true) { + val deprecatedDocumentableFilter by extending { CoreExtensions.preMergeDocumentableTransformer providing ::DeprecatedDocumentableFilterTransformer } - val documentableVisbilityFilter by extending(isFallback = true) { + val documentableVisbilityFilter by extending { CoreExtensions.preMergeDocumentableTransformer providing ::DocumentableVisibilityFilterTransformer } - val emptyPackagesFilter by extending(isFallback = true) { + val emptyPackagesFilter by extending { CoreExtensions.preMergeDocumentableTransformer providing ::EmptyPackagesFilterTransformer order { after(deprecatedDocumentableFilter, documentableVisbilityFilter) } @@ -77,13 +77,13 @@ class DokkaBase : DokkaPlugin() { CoreExtensions.documentableTransformer with ActualTypealiasAdder() } - val modulesAndPackagesDocumentation by extending(isFallback = true) { + val modulesAndPackagesDocumentation by extending { CoreExtensions.preMergeDocumentableTransformer providing { ctx -> ModuleAndPackageDocumentationTransformer(ctx, ctx.single(kotlinAnalysis)) } } - val kotlinSignatureProvider by extending(isFallback = true) { + val kotlinSignatureProvider by extending { signatureProvider providing { ctx -> KotlinSignatureProvider(ctx.single(commentsToContentConverter), ctx.logger) } @@ -106,7 +106,7 @@ class DokkaBase : DokkaPlugin() { CoreExtensions.documentableTransformer with ExtensionExtractorTransformer() } - val documentableToPageTranslator by extending(isFallback = true) { + val documentableToPageTranslator by extending { CoreExtensions.documentableToPageTranslator providing { ctx -> DefaultDocumentableToPageTranslator( ctx.single(commentsToContentConverter), @@ -116,7 +116,7 @@ class DokkaBase : DokkaPlugin() { } } - val docTagToContentConverter by extending(isFallback = true) { + val docTagToContentConverter by extending { commentsToContentConverter with DocTagToContentConverter } @@ -138,11 +138,11 @@ class DokkaBase : DokkaPlugin() { CoreExtensions.renderer providing ::HtmlRenderer applyIf { format == "html" } } - val defaultKotlinAnalysis by extending(isFallback = true) { + val defaultKotlinAnalysis by extending { kotlinAnalysis providing { ctx -> KotlinAnalysis(ctx) } } - val locationProvider by extending(isFallback = true) { + val locationProvider by extending { locationProviderFactory providing ::DefaultLocationProviderFactory } @@ -154,7 +154,7 @@ class DokkaBase : DokkaPlugin() { externalLocationProviderFactory with DokkaExternalLocationProviderFactory() } - val fileWriter by extending(isFallback = true) { + val fileWriter by extending { outputWriter providing ::FileWriter } @@ -211,7 +211,7 @@ class DokkaBase : DokkaPlugin() { htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator) } } - val allModulePageCreators by extending(isFallback = true) { + val allModulePageCreators by extending { CoreExtensions.allModulePageCreator providing { MultimodulePageCreator(it) } -- cgit