aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/plugability/extensions.kt
blob: 20b604690bb05abd2b5e57d057da8d3ea6a1dafe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package org.jetbrains.dokka.plugability

import org.jetbrains.dokka.DokkaConfiguration

data class ExtensionPoint<T : Any> internal constructor(
    internal val pluginClass: String,
    internal val pointName: String
) {
    override fun toString() = "ExtensionPoint: $pluginClass/$pointName"
}

abstract class Extension<T : Any> internal constructor(
    internal val extensionPoint: ExtensionPoint<T>,
    internal val pluginClass: String,
    internal val extensionName: String,
    internal val action: LazyEvaluated<T>,
    internal val ordering: (OrderDsl.() -> Unit)? = null,
    internal val conditions: Array<DokkaConfiguration.() -> 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<T>

    abstract fun markedAsFallback(): Extension<T>

    open val condition: DokkaConfiguration.() -> Boolean
        get() = { conditions.all { it(this) }}
}

class ExtensionOrdered<T : Any> internal constructor(
    extensionPoint: ExtensionPoint<T>,
    pluginClass: String,
    extensionName: String,
    action: LazyEvaluated<T>,
    ordering: (OrderDsl.() -> Unit),
    conditions: Array<DokkaConfiguration.() -> Boolean> = emptyArray(),
    isFallback: Boolean = false
) : Extension<T>(
    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<T : Any> internal constructor(
    extensionPoint: ExtensionPoint<T>,
    pluginClass: String,
    extensionName: String,
    action: LazyEvaluated<T>,
    conditions: Array<DokkaConfiguration.() -> Boolean> = emptyArray(),
    isFallback: Boolean = false
) : Extension<T>(
    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<Extension<*>>, val following: Set<Extension<*>>)

@DslMarker
annotation class ExtensionsDsl

@ExtensionsDsl
class ExtendingDSL(private val pluginClass: String, private val extensionName: String) {

    infix fun <T : Any> ExtensionPoint<T>.with(action: T) =
        ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromInstance(action))

    infix fun <T : Any> ExtensionPoint<T>.providing(action: (DokkaContext) -> T) =
        ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, LazyEvaluated.fromRecipe(action))

    infix fun <T : Any> ExtensionUnordered<T>.order(block: OrderDsl.() -> Unit) =
        ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, block)

    infix fun <T : Any> Extension<T>.applyIf(condition: DokkaConfiguration.() -> Boolean): Extension<T> =
        this.addCondition(condition)

}

@ExtensionsDsl
class OrderDsl {
    internal val previous = mutableSetOf<Extension<*>>()
    internal val following = mutableSetOf<Extension<*>>()

    fun after(vararg extensions: Extension<*>) {
        previous += extensions
    }

    fun before(vararg extensions: Extension<*>) {
        following += extensions
    }
}