package org.jetbrains.dokka.plugability import org.jetbrains.dokka.DokkaConfiguration data class ExtensionPoint internal constructor( internal val pluginClass: String, internal val pointName: String ) { override fun toString() = "ExtensionPoint: $pluginClass/$pointName" } abstract 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 ) { override fun toString() = "Extension: $pluginClass/$extensionName" override fun equals(other: Any?) = 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) }} } class ExtensionOrdered internal constructor( 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>) @DslMarker annotation class ExtensionsDsl @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)) infix fun ExtensionPoint.providing(action: (DokkaContext) -> T) = ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromRecipe(action)) infix fun ExtensionUnordered.order(block: OrderDsl.() -> Unit) = ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, block) infix fun Extension.applyIf(condition: DokkaConfiguration.() -> Boolean): Extension = this.addCondition(condition) } @ExtensionsDsl class OrderDsl { internal val previous = mutableSetOf>() internal val following = mutableSetOf>() fun after(vararg extensions: Extension<*>) { previous += extensions } fun before(vararg extensions: Extension<*>) { following += extensions } }