aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/plugability
diff options
context:
space:
mode:
authorAndrzej Ratajczak <andrzej.ratajczak98@gmail.com>2019-12-19 15:02:03 +0100
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-01-08 14:30:00 +0100
commite1dad14904ca0e3b727cf0d7239db35f5402e775 (patch)
tree193b9b6da9d41d871180b51becd385f47800653b /core/src/main/kotlin/plugability
parentc36c6ae3b8c9e47afc7adabd4624c1a95039596f (diff)
downloaddokka-e1dad14904ca0e3b727cf0d7239db35f5402e775.tar.gz
dokka-e1dad14904ca0e3b727cf0d7239db35f5402e775.tar.bz2
dokka-e1dad14904ca0e3b727cf0d7239db35f5402e775.zip
Resolved problems with plugins loading ordering and added type safe ordering function
Diffstat (limited to 'core/src/main/kotlin/plugability')
-rw-r--r--core/src/main/kotlin/plugability/DokkaContext.kt52
-rw-r--r--core/src/main/kotlin/plugability/DokkaPlugin.kt4
-rw-r--r--core/src/main/kotlin/plugability/extensions.kt41
3 files changed, 82 insertions, 15 deletions
diff --git a/core/src/main/kotlin/plugability/DokkaContext.kt b/core/src/main/kotlin/plugability/DokkaContext.kt
index 7b1c1306..8709b74f 100644
--- a/core/src/main/kotlin/plugability/DokkaContext.kt
+++ b/core/src/main/kotlin/plugability/DokkaContext.kt
@@ -36,6 +36,7 @@ interface DokkaContext : DokkaExtensionHandler {
.also { checkClasspath(it) }
.let { ServiceLoader.load(DokkaPlugin::class.java, it) }
.forEach { install(it) }
+ applyExtensions()
}.also { it.logInitialisationInfo() }
}
}
@@ -54,7 +55,7 @@ fun <T, E> DokkaContext.single(point: E): T where T : Any, E : ExtensionPoint<T>
}
interface DokkaContextConfiguration {
- fun addExtension(extension: Extension<*>)
+ fun addExtensionDependencies(extension: Extension<*>)
}
private class DokkaContextConfigurationImpl(
@@ -63,11 +64,43 @@ private class DokkaContextConfigurationImpl(
override val platforms: Map<PlatformData, EnvironmentAndFacade>
) : DokkaContext, DokkaContextConfiguration {
private val plugins = mutableMapOf<KClass<*>, DokkaPlugin>()
-
private val pluginStubs = mutableMapOf<KClass<*>, DokkaPlugin>()
-
internal val extensions = mutableMapOf<ExtensionPoint<*>, MutableList<Extension<*>>>()
+ private enum class State {
+ UNVISITED,
+ VISITING,
+ VISITED;
+ }
+
+ internal val verticesWithState = mutableMapOf<Extension<*>, State>()
+ internal val adjacencyList: MutableMap<Extension<*>, MutableList<Extension<*>>> = mutableMapOf()
+
+ private fun topologicalSort() {
+
+ val result: MutableList<Extension<*>> = mutableListOf()
+
+ fun visit(n: Extension<*>) {
+ val state = verticesWithState[n]
+ if(state == State.VISITED)
+ return
+ if(state == State.VISITING)
+ throw Error("Detected cycle in plugins graph")
+ verticesWithState[n] = State.VISITING
+ adjacencyList[n]?.forEach { visit(it) }
+ verticesWithState[n] = State.VISITED
+ result += n
+ }
+
+ for((vertex, state) in verticesWithState) {
+ if(state == State.UNVISITED)
+ visit(vertex)
+ }
+ result.asReversed().forEach {
+ extensions.getOrPut(it.extensionPoint, ::mutableListOf) += it
+ }
+ }
+
@Suppress("UNCHECKED_CAST")
override operator fun <T, E> get(point: E, askDefault: AskDefault) where T : Any, E : ExtensionPoint<T> =
when (askDefault) {
@@ -91,8 +124,13 @@ private class DokkaContextConfigurationImpl(
plugin.internalInstall(this)
}
- override fun addExtension(extension: Extension<*>) {
- extensions.getOrPut(extension.extensionPoint, ::mutableListOf) += extension
+ override fun addExtensionDependencies(extension: Extension<*>) {
+ val orderDsl = OrderDsl()
+ extension.ordering?.invoke(orderDsl)
+
+ verticesWithState += extension to State.UNVISITED
+ adjacencyList.getOrPut(extension, ::mutableListOf) += orderDsl.following.toList()
+ orderDsl.previous.forEach { adjacencyList.getOrPut(it, ::mutableListOf) += extension }
}
fun logInitialisationInfo() {
@@ -105,6 +143,10 @@ private class DokkaContextConfigurationImpl(
logger.progress("Loaded: $loadedListForDebug")
}
+
+ fun applyExtensions() {
+ topologicalSort()
+ }
}
private fun checkClasspath(classLoader: URLClassLoader) {
diff --git a/core/src/main/kotlin/plugability/DokkaPlugin.kt b/core/src/main/kotlin/plugability/DokkaPlugin.kt
index 7a968b8b..3f82000d 100644
--- a/core/src/main/kotlin/plugability/DokkaPlugin.kt
+++ b/core/src/main/kotlin/plugability/DokkaPlugin.kt
@@ -40,8 +40,6 @@ abstract class DokkaPlugin {
extensionDelegates.asSequence()
.filterIsInstance<KProperty1<DokkaPlugin, Extension<*>>>() // should be always true
.map { it.get(this) }
- .forEach { ctx.addExtension(it) }
+ .forEach { ctx.addExtensionDependencies(it) }
}
-
-
} \ No newline at end of file
diff --git a/core/src/main/kotlin/plugability/extensions.kt b/core/src/main/kotlin/plugability/extensions.kt
index 3039cb5a..8d1a7ba0 100644
--- a/core/src/main/kotlin/plugability/extensions.kt
+++ b/core/src/main/kotlin/plugability/extensions.kt
@@ -7,7 +7,7 @@ data class ExtensionPoint<T : Any> internal constructor(
override fun toString() = "ExtensionPoint: $pluginClass/$pointName"
}
-class Extension<T : Any> internal constructor(
+abstract class Extension<T : Any> internal constructor(
internal val extensionPoint: ExtensionPoint<T>,
internal val pluginClass: String,
internal val extensionName: String,
@@ -17,12 +17,39 @@ class Extension<T : Any> internal constructor(
override fun toString() = "Extension: $pluginClass/$extensionName"
override fun equals(other: Any?) =
- if (other is Extension<*>) this.pluginClass == other.extensionName && 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()
}
+class ExtensionOrdered<T : Any>(
+ extensionPoint: ExtensionPoint<T>,
+ pluginClass: String,
+ extensionName: String,
+ action: T,
+ ordering: (OrderDsl.() -> Unit)
+) : Extension<T>(
+ extensionPoint,
+ pluginClass,
+ extensionName,
+ action,
+ ordering
+)
+
+class ExtensionUnordered<T : Any>(
+ extensionPoint: ExtensionPoint<T>,
+ pluginClass: String,
+ extensionName: String,
+ action: T
+) : Extension<T>(
+ extensionPoint,
+ pluginClass,
+ extensionName,
+ action,
+ null
+)
+
internal data class Ordering(val previous: Set<Extension<*>>, val following: Set<Extension<*>>)
@DslMarker
@@ -31,16 +58,16 @@ annotation class ExtensionsDsl
@ExtensionsDsl
class ExtendingDSL(private val pluginClass: String, private val extensionName: String) {
infix fun <T: Any> ExtensionPoint<T>.with(action: T) =
- Extension(this, this@ExtendingDSL.pluginClass, extensionName, action)
+ ExtensionUnordered(this, this@ExtendingDSL.pluginClass, extensionName, action)
- infix fun <T: Any> Extension<T>.order(block: OrderDsl.() -> Unit) =
- Extension(extensionPoint, pluginClass, extensionName, action, block)
+ infix fun <T: Any> ExtensionUnordered<T>.order(block: OrderDsl.() -> Unit) =
+ ExtensionOrdered(extensionPoint, pluginClass, extensionName, action, block)
}
@ExtensionsDsl
class OrderDsl {
- private val previous = mutableSetOf<Extension<*>>()
- private val following = mutableSetOf<Extension<*>>()
+ internal val previous = mutableSetOf<Extension<*>>()
+ internal val following = mutableSetOf<Extension<*>>()
fun after(vararg extensions: Extension<*>) {
previous += extensions