diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/Template.kt b/idea/src/org/jetbrains/kotlin/idea/kdoc/Template.kt new file mode 100644 index 00000000000..14274e07b94 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/kdoc/Template.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.kdoc + +import java.util.* + +/** + * A template that expands inside [TOuter] + */ +interface Template { + fun TOuter.apply() +} + +/** + * A placeholder that is inserted inside [TOuter] + */ +open class Placeholder { + private var contentStack = mutableListOf<(TOuter.(Placeholder.Exec) -> Unit)>() + + var meta: String = "" + + operator fun invoke(meta: String = "", content: TOuter.(Placeholder.Exec) -> Unit) { + this.contentStack.add(content) + this.meta = meta + } + + inner class Exec(var depth: Int, val outer: TOuter) { + + fun inherit() { + depth-- + contentStack.getOrNull(depth)?.invoke(outer, this@Exec) + depth++ + } + } + + fun isEmpty() = contentStack.isEmpty() + + fun apply(destination: TOuter) { + val top = contentStack.lastOrNull() + val exec = Exec(contentStack.lastIndex, destination) + top?.invoke(destination, exec) + } +} + +/** + * Placeholder that can appear multiple times + */ +open class PlaceholderList() { + private var items = ArrayList>() + operator fun invoke(meta: String = "", content: TInner.(Placeholder.Exec) -> Unit = {}) { + val placeholder = PlaceholderItem(items.size, items) + placeholder(meta, content) + items.add(placeholder) + } + + fun isEmpty(): Boolean = items.size == 0 + fun apply(destination: TOuter, render: TOuter.(PlaceholderItem) -> Unit) { + for (item in items) { + destination.render(item) + } + } +} + +/** + * Item of a placeholder list when it is expanded + */ +class PlaceholderItem(val index: Int, val collection: List>) : Placeholder() { + val first: Boolean get() = index == 0 + val last: Boolean get() = index == collection.lastIndex +} + + +/** + * Inserts every element of placeholder list + */ +fun TOuter.each(items: PlaceholderList, itemTemplate: TOuter.(PlaceholderItem) -> Unit): Unit { + items.apply(this, itemTemplate) +} + +/** + * Inserts placeholder + */ +fun TOuter.insert(placeholder: Placeholder): Unit = placeholder.apply(this) + +/** + * A placeholder that is also a template + */ +open class TemplatePlaceholder { + private var content: TTemplate.() -> Unit = { } + operator fun invoke(content: TTemplate.() -> Unit) { + this.content = content + } + + fun apply(template: TTemplate) { + template.content() + } +} + +fun , TOuter> TOuter.insert(template: TTemplate, placeholder: TemplatePlaceholder) { + placeholder.apply(template) + with (template) { apply() } +} + +fun > TOuter.insert(template: TTemplate, build: TTemplate.() -> Unit) { + template.build() + with (template) { apply() } +}