aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/model
diff options
context:
space:
mode:
authorPaweł Marks <pmarks@virtuslab.com>2020-07-17 16:36:09 +0200
committerPaweł Marks <pmarks@virtuslab.com>2020-07-17 16:36:09 +0200
commit6996b1135f61c7d2cb60b0652c6a2691dda31990 (patch)
treed568096c25e31c28d14d518a63458b5a7526b896 /core/src/main/kotlin/model
parentde56cab76f556e5b4af0b8c8cb08d8b482b86d0a (diff)
parent1c3530dcbb50c347f80bef694829dbefe89eca77 (diff)
downloaddokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.gz
dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.tar.bz2
dokka-6996b1135f61c7d2cb60b0652c6a2691dda31990.zip
Merge branch 'dev-0.11.0'
Diffstat (limited to 'core/src/main/kotlin/model')
-rw-r--r--core/src/main/kotlin/model/Documentable.kt398
-rw-r--r--core/src/main/kotlin/model/WithChildren.kt64
-rw-r--r--core/src/main/kotlin/model/additionalExtras.kt75
-rw-r--r--core/src/main/kotlin/model/classKinds.kt20
-rw-r--r--core/src/main/kotlin/model/defaultValues.kt13
-rw-r--r--core/src/main/kotlin/model/doc/DocTag.kt96
-rw-r--r--core/src/main/kotlin/model/doc/DocumentationNode.kt5
-rw-r--r--core/src/main/kotlin/model/doc/TagWrapper.kt39
-rw-r--r--core/src/main/kotlin/model/documentableProperties.kt27
-rw-r--r--core/src/main/kotlin/model/documentableUtils.kt22
-rw-r--r--core/src/main/kotlin/model/extraModifiers.kt62
-rw-r--r--core/src/main/kotlin/model/properties/PropertyContainer.kt60
-rw-r--r--core/src/main/kotlin/model/properties/properties.kt22
13 files changed, 903 insertions, 0 deletions
diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt
new file mode 100644
index 00000000..2c3e1323
--- /dev/null
+++ b/core/src/main/kotlin/model/Documentable.kt
@@ -0,0 +1,398 @@
+package org.jetbrains.dokka.model
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.DriWithKind
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.model.properties.PropertyContainer
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+
+
+abstract class Documentable : WithChildren<Documentable> {
+ abstract val name: String?
+ abstract val dri: DRI
+ abstract val documentation: SourceSetDependent<DocumentationNode>
+ abstract val sourceSets: Set<DokkaSourceSet>
+ abstract val expectPresentInSet: DokkaSourceSet?
+
+ override fun toString(): String =
+ "${javaClass.simpleName}($dri)"
+
+ override fun equals(other: Any?) =
+ other is Documentable && this.dri == other.dri // TODO: https://github.com/Kotlin/dokka/pull/667#discussion_r382555806
+
+ override fun hashCode() = dri.hashCode()
+}
+
+typealias SourceSetDependent<T> = Map<DokkaSourceSet, T>
+
+interface WithExpectActual {
+ val sources: SourceSetDependent<DocumentableSource>
+}
+
+interface WithScope {
+ val functions: List<DFunction>
+ val properties: List<DProperty>
+ val classlikes: List<DClasslike>
+}
+
+interface WithVisibility {
+ val visibility: SourceSetDependent<Visibility>
+}
+
+interface WithType {
+ val type: Bound
+}
+
+interface WithAbstraction {
+ val modifier: SourceSetDependent<Modifier>
+}
+
+sealed class Modifier(val name: String)
+sealed class KotlinModifier(name: String) : Modifier(name) {
+ object Abstract : KotlinModifier("abstract")
+ object Open : KotlinModifier("open")
+ object Final : KotlinModifier("final")
+ object Sealed : KotlinModifier("sealed")
+ object Empty : KotlinModifier("")
+}
+
+sealed class JavaModifier(name: String) : Modifier(name) {
+ object Abstract : JavaModifier("abstract")
+ object Final : JavaModifier("final")
+ object Empty : JavaModifier("")
+}
+
+interface WithCompanion {
+ val companion: DObject?
+}
+
+interface WithConstructors {
+ val constructors: List<DFunction>
+}
+
+interface WithGenerics {
+ val generics: List<DTypeParameter>
+}
+
+interface WithSupertypes {
+ val supertypes: SourceSetDependent<List<DriWithKind>>
+}
+
+interface Callable : WithVisibility, WithType, WithAbstraction, WithExpectActual {
+ val receiver: DParameter?
+}
+
+sealed class DClasslike : Documentable(), WithScope, WithVisibility, WithExpectActual
+
+data class DModule(
+ override val name: String,
+ val packages: List<DPackage>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet? = null,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DModule> = PropertyContainer.empty()
+) : Documentable(), WithExtraProperties<DModule> {
+ override val dri: DRI = DRI.topLevel
+ override val children: List<Documentable>
+ get() = packages
+
+ override fun withNewExtras(newExtras: PropertyContainer<DModule>) = copy(extra = newExtras)
+}
+
+data class DPackage(
+ override val dri: DRI,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ val typealiases: List<DTypeAlias>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet? = null,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DPackage> = PropertyContainer.empty()
+) : Documentable(), WithScope, WithExtraProperties<DPackage> {
+ override val name = dri.packageName.orEmpty()
+ override val children: List<Documentable>
+ get() = (properties + functions + classlikes)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DPackage>) = copy(extra = newExtras)
+}
+
+data class DClass(
+ override val dri: DRI,
+ override val name: String,
+ override val constructors: List<DFunction>,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val companion: DObject?,
+ override val generics: List<DTypeParameter>,
+ override val supertypes: SourceSetDependent<List<DriWithKind>>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val modifier: SourceSetDependent<Modifier>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DClass> = PropertyContainer.empty()
+) : DClasslike(), WithAbstraction, WithCompanion, WithConstructors, WithGenerics, WithSupertypes,
+ WithExtraProperties<DClass> {
+
+ override val children: List<Documentable>
+ get() = (functions + properties + classlikes + constructors)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DClass>) = copy(extra = newExtras)
+}
+
+data class DEnum(
+ override val dri: DRI,
+ override val name: String,
+ val entries: List<DEnumEntry>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val companion: DObject?,
+ override val constructors: List<DFunction>,
+ override val supertypes: SourceSetDependent<List<DriWithKind>>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DEnum> = PropertyContainer.empty()
+) : DClasslike(), WithCompanion, WithConstructors, WithSupertypes, WithExtraProperties<DEnum> {
+ override val children: List<Documentable>
+ get() = (entries + functions + properties + classlikes + constructors)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DEnum>) = copy(extra = newExtras)
+}
+
+data class DEnumEntry(
+ override val dri: DRI,
+ override val name: String,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DEnumEntry> = PropertyContainer.empty()
+) : Documentable(), WithScope, WithExtraProperties<DEnumEntry> {
+ override val children: List<Documentable>
+ get() = (functions + properties + classlikes)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DEnumEntry>) = copy(extra = newExtras)
+}
+
+data class DFunction(
+ override val dri: DRI,
+ override val name: String,
+ val isConstructor: Boolean,
+ val parameters: List<DParameter>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val type: Bound,
+ override val generics: List<DTypeParameter>,
+ override val receiver: DParameter?,
+ override val modifier: SourceSetDependent<Modifier>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DFunction> = PropertyContainer.empty()
+) : Documentable(), Callable, WithGenerics, WithExtraProperties<DFunction> {
+ override val children: List<Documentable>
+ get() = parameters
+
+ override fun withNewExtras(newExtras: PropertyContainer<DFunction>) = copy(extra = newExtras)
+}
+
+data class DInterface(
+ override val dri: DRI,
+ override val name: String,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val companion: DObject?,
+ override val generics: List<DTypeParameter>,
+ override val supertypes: SourceSetDependent<List<DriWithKind>>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DInterface> = PropertyContainer.empty()
+) : DClasslike(), WithCompanion, WithGenerics, WithSupertypes, WithExtraProperties<DInterface> {
+ override val children: List<Documentable>
+ get() = (functions + properties + classlikes)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DInterface>) = copy(extra = newExtras)
+}
+
+data class DObject(
+ override val name: String?,
+ override val dri: DRI,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val supertypes: SourceSetDependent<List<DriWithKind>>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DObject> = PropertyContainer.empty()
+) : DClasslike(), WithSupertypes, WithExtraProperties<DObject> {
+ override val children: List<Documentable>
+ get() = (functions + properties + classlikes) as List<Documentable>
+
+ override fun withNewExtras(newExtras: PropertyContainer<DObject>) = copy(extra = newExtras)
+}
+
+data class DAnnotation(
+ override val name: String,
+ override val dri: DRI,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val functions: List<DFunction>,
+ override val properties: List<DProperty>,
+ override val classlikes: List<DClasslike>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val companion: DObject?,
+ override val constructors: List<DFunction>,
+ override val generics: List<DTypeParameter>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DAnnotation> = PropertyContainer.empty()
+) : DClasslike(), WithCompanion, WithConstructors, WithExtraProperties<DAnnotation>, WithGenerics {
+ override val children: List<Documentable>
+ get() = (functions + properties + classlikes + constructors)
+
+ override fun withNewExtras(newExtras: PropertyContainer<DAnnotation>) = copy(extra = newExtras)
+}
+
+data class DProperty(
+ override val dri: DRI,
+ override val name: String,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sources: SourceSetDependent<DocumentableSource>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val type: Bound,
+ override val receiver: DParameter?,
+ val setter: DFunction?,
+ val getter: DFunction?,
+ override val modifier: SourceSetDependent<Modifier>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val generics: List<DTypeParameter>,
+ override val extra: PropertyContainer<DProperty> = PropertyContainer.empty()
+) : Documentable(), Callable, WithExtraProperties<DProperty>, WithGenerics {
+ override val children: List<Nothing>
+ get() = emptyList()
+
+ override fun withNewExtras(newExtras: PropertyContainer<DProperty>) = copy(extra = newExtras)
+}
+
+// TODO: treat named Parameters and receivers differently
+data class DParameter(
+ override val dri: DRI,
+ override val name: String?,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ val type: Bound,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DParameter> = PropertyContainer.empty()
+) : Documentable(), WithExtraProperties<DParameter> {
+ override val children: List<Nothing>
+ get() = emptyList()
+
+ override fun withNewExtras(newExtras: PropertyContainer<DParameter>) = copy(extra = newExtras)
+}
+
+data class DTypeParameter(
+ override val dri: DRI,
+ override val name: String,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ val bounds: List<Bound>,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DTypeParameter> = PropertyContainer.empty()
+) : Documentable(), WithExtraProperties<DTypeParameter> {
+ override val children: List<Nothing>
+ get() = emptyList()
+
+ override fun withNewExtras(newExtras: PropertyContainer<DTypeParameter>) = copy(extra = newExtras)
+}
+
+data class DTypeAlias(
+ override val dri: DRI,
+ override val name: String,
+ override val type: Bound,
+ val underlyingType: SourceSetDependent<Bound>,
+ override val visibility: SourceSetDependent<Visibility>,
+ override val documentation: SourceSetDependent<DocumentationNode>,
+ override val expectPresentInSet: DokkaSourceSet?,
+ override val sourceSets: Set<DokkaSourceSet>,
+ override val extra: PropertyContainer<DTypeAlias> = PropertyContainer.empty()
+) : Documentable(), WithType, WithVisibility, WithExtraProperties<DTypeAlias> {
+ override val children: List<Nothing>
+ get() = emptyList()
+
+ override fun withNewExtras(newExtras: PropertyContainer<DTypeAlias>) = copy(extra = newExtras)
+}
+
+sealed class Projection
+sealed class Bound : Projection()
+data class OtherParameter(val declarationDRI: DRI, val name: String) : Bound()
+object Star : Projection()
+data class TypeConstructor(
+ val dri: DRI,
+ val projections: List<Projection>,
+ val modifier: FunctionModifiers = FunctionModifiers.NONE
+) : Bound()
+
+data class Nullable(val inner: Bound) : Bound()
+data class Variance(val kind: Kind, val inner: Bound) : Projection() {
+ enum class Kind { In, Out }
+}
+
+data class PrimitiveJavaType(val name: String) : Bound()
+object Void : Bound()
+object JavaObject : Bound()
+object Dynamic : Bound()
+data class UnresolvedBound(val name: String) : Bound()
+
+enum class FunctionModifiers {
+ NONE, FUNCTION, EXTENSION
+}
+
+private fun String.shorten(maxLength: Int) = lineSequence().first().let {
+ if (it.length != length || it.length > maxLength) it.take(maxLength - 3) + "..." else it
+}
+
+fun Documentable.dfs(predicate: (Documentable) -> Boolean): Documentable? =
+ if (predicate(this)) {
+ this
+ } else {
+ this.children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull()
+ }
+
+sealed class Visibility(val name: String)
+sealed class KotlinVisibility(name: String) : Visibility(name) {
+ object Public : KotlinVisibility("public")
+ object Private : KotlinVisibility("private")
+ object Protected : KotlinVisibility("protected")
+ object Internal : KotlinVisibility("internal")
+}
+
+sealed class JavaVisibility(name: String) : Visibility(name) {
+ object Public : JavaVisibility("public")
+ object Private : JavaVisibility("private")
+ object Protected : JavaVisibility("protected")
+ object Default : JavaVisibility("")
+}
+
+fun <T> SourceSetDependent<T>?.orEmpty(): SourceSetDependent<T> = this ?: emptyMap()
+
+interface DocumentableSource {
+ val path: String
+}
diff --git a/core/src/main/kotlin/model/WithChildren.kt b/core/src/main/kotlin/model/WithChildren.kt
new file mode 100644
index 00000000..589bcd2a
--- /dev/null
+++ b/core/src/main/kotlin/model/WithChildren.kt
@@ -0,0 +1,64 @@
+package org.jetbrains.dokka.model
+
+interface WithChildren<out T> {
+ val children: List<T>
+}
+
+inline fun <reified T> WithChildren<*>.firstChildOfTypeOrNull(): T? =
+ children.filterIsInstance<T>().firstOrNull()
+
+inline fun <reified T> WithChildren<*>.firstChildOfTypeOrNull(predicate: (T) -> Boolean): T? =
+ children.filterIsInstance<T>().firstOrNull(predicate)
+
+inline fun <reified T> WithChildren<*>.firstChildOfType(): T =
+ children.filterIsInstance<T>().first()
+
+inline fun <reified T> WithChildren<*>.firstChildOfType(predicate: (T) -> Boolean): T =
+ children.filterIsInstance<T>().first(predicate)
+
+inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfType(): T where T : WithChildren<*> {
+ return withDescendants().filterIsInstance<T>().first()
+}
+
+inline fun <reified T> WithChildren<WithChildren<*>>.firstMemberOfTypeOrNull(): T? where T : WithChildren<*> {
+ return withDescendants().filterIsInstance<T>().firstOrNull()
+}
+
+fun <T> T.withDescendants(): Sequence<T> where T : WithChildren<T> {
+ return sequence {
+ yield(this@withDescendants)
+ children.forEach { child ->
+ yieldAll(child.withDescendants())
+ }
+ }
+}
+
+@JvmName("withDescendantsProjection")
+fun WithChildren<*>.withDescendants(): Sequence<Any?> {
+ return sequence {
+ yield(this@withDescendants)
+ children.forEach { child ->
+ if (child is WithChildren<*>) {
+ yieldAll(child.withDescendants())
+ }
+ }
+ }
+}
+
+@JvmName("withDescendantsAny")
+fun WithChildren<Any>.withDescendants(): Sequence<Any> {
+ return sequence {
+ yield(this@withDescendants)
+ children.forEach { child ->
+ if (child is WithChildren<*>) {
+ yieldAll(child.withDescendants().filterNotNull())
+ }
+ }
+ }
+}
+
+fun <T> T.dfs(predicate: (T) -> Boolean): T? where T : WithChildren<T> = if (predicate(this)) {
+ this
+} else {
+ children.asSequence().mapNotNull { it.dfs(predicate) }.firstOrNull()
+}
diff --git a/core/src/main/kotlin/model/additionalExtras.kt b/core/src/main/kotlin/model/additionalExtras.kt
new file mode 100644
index 00000000..94d0e751
--- /dev/null
+++ b/core/src/main/kotlin/model/additionalExtras.kt
@@ -0,0 +1,75 @@
+package org.jetbrains.dokka.model
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.model.properties.MergeStrategy
+
+class AdditionalModifiers(val content: SourceSetDependent<Set<ExtraModifiers>>) : ExtraProperty<Documentable> {
+ companion object : ExtraProperty.Key<Documentable, AdditionalModifiers> {
+ override fun mergeStrategyFor(
+ left: AdditionalModifiers,
+ right: AdditionalModifiers
+ ): MergeStrategy<Documentable> = MergeStrategy.Replace(AdditionalModifiers(left.content + right.content))
+ }
+
+ override fun equals(other: Any?): Boolean =
+ if (other is AdditionalModifiers) other.content == content else false
+
+ override fun hashCode() = content.hashCode()
+ override val key: ExtraProperty.Key<Documentable, *> = AdditionalModifiers
+}
+
+fun SourceSetDependent<Set<ExtraModifiers>>.toAdditionalModifiers() = AdditionalModifiers(this)
+
+class Annotations(val content: SourceSetDependent<List<Annotation>>) : ExtraProperty<Documentable> {
+ companion object : ExtraProperty.Key<Documentable, Annotations> {
+ override fun mergeStrategyFor(left: Annotations, right: Annotations): MergeStrategy<Documentable> =
+ MergeStrategy.Replace(Annotations(left.content + right.content))
+ }
+
+ override val key: ExtraProperty.Key<Documentable, *> = Annotations
+
+ data class Annotation(val dri: DRI, val params: Map<String, AnnotationParameterValue>, val mustBeDocumented: Boolean = false) {
+ override fun equals(other: Any?): Boolean = when (other) {
+ is Annotation -> dri == other.dri
+ else -> false
+ }
+
+ override fun hashCode(): Int = dri.hashCode()
+ }
+}
+
+fun SourceSetDependent<List<Annotations.Annotation>>.toAnnotations() = Annotations(this)
+
+sealed class AnnotationParameterValue
+data class AnnotationValue(val annotation: Annotations.Annotation) : AnnotationParameterValue()
+data class ArrayValue(val value: List<AnnotationParameterValue>) : AnnotationParameterValue()
+data class EnumValue(val enumName: String, val enumDri: DRI) : AnnotationParameterValue()
+data class ClassValue(val className: String, val classDRI: DRI) : AnnotationParameterValue()
+data class StringValue(val value: String) : AnnotationParameterValue()
+
+
+object PrimaryConstructorExtra : ExtraProperty<DFunction>, ExtraProperty.Key<DFunction, PrimaryConstructorExtra> {
+ override val key: ExtraProperty.Key<DFunction, *> = this
+}
+
+data class ActualTypealias(val underlyingType: SourceSetDependent<Bound>) : ExtraProperty<DClasslike> {
+ companion object : ExtraProperty.Key<DClasslike, ActualTypealias> {
+ override fun mergeStrategyFor(
+ left: ActualTypealias,
+ right: ActualTypealias
+ ) =
+ MergeStrategy.Replace(ActualTypealias(left.underlyingType + right.underlyingType))
+ }
+
+ override val key: ExtraProperty.Key<DClasslike, ActualTypealias> = ActualTypealias
+}
+
+data class ConstructorValues(val values: SourceSetDependent<List<String>>) : ExtraProperty<DEnumEntry>{
+ companion object : ExtraProperty.Key<DEnumEntry, ConstructorValues> {
+ override fun mergeStrategyFor(left: ConstructorValues, right: ConstructorValues) =
+ MergeStrategy.Replace(ConstructorValues(left.values + right.values))
+ }
+
+ override val key: ExtraProperty.Key<DEnumEntry, ConstructorValues> = ConstructorValues
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/classKinds.kt b/core/src/main/kotlin/model/classKinds.kt
new file mode 100644
index 00000000..be8c47b0
--- /dev/null
+++ b/core/src/main/kotlin/model/classKinds.kt
@@ -0,0 +1,20 @@
+package org.jetbrains.dokka.model
+
+interface ClassKind
+
+enum class KotlinClassKindTypes : ClassKind {
+ CLASS,
+ INTERFACE,
+ ENUM_CLASS,
+ ENUM_ENTRY,
+ ANNOTATION_CLASS,
+ OBJECT;
+}
+
+enum class JavaClassKindTypes : ClassKind {
+ CLASS,
+ INTERFACE,
+ ENUM_CLASS,
+ ENUM_ENTRY,
+ ANNOTATION_CLASS;
+}
diff --git a/core/src/main/kotlin/model/defaultValues.kt b/core/src/main/kotlin/model/defaultValues.kt
new file mode 100644
index 00000000..ab6cd376
--- /dev/null
+++ b/core/src/main/kotlin/model/defaultValues.kt
@@ -0,0 +1,13 @@
+package org.jetbrains.dokka.model
+
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.model.properties.MergeStrategy
+
+class DefaultValue(val value: String): ExtraProperty<DParameter> {
+ companion object : ExtraProperty.Key<DParameter, DefaultValue> {
+ override fun mergeStrategyFor(left: DefaultValue, right: DefaultValue): MergeStrategy<DParameter> = MergeStrategy.Remove // TODO pass a logger somehow and log this
+ }
+
+ override val key: ExtraProperty.Key<DParameter, *>
+ get() = Companion
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/doc/DocTag.kt b/core/src/main/kotlin/model/doc/DocTag.kt
new file mode 100644
index 00000000..dc2cd2be
--- /dev/null
+++ b/core/src/main/kotlin/model/doc/DocTag.kt
@@ -0,0 +1,96 @@
+package org.jetbrains.dokka.model.doc
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.WithChildren
+
+sealed class DocTag(
+ override val children: List<DocTag>,
+ val params: Map<String, String>
+) : WithChildren<DocTag> {
+ override fun equals(other: Any?): Boolean =
+ (
+ other != null &&
+ other::class == this::class &&
+ this.children == (other as DocTag).children &&
+ this.params == other.params
+ )
+
+ override fun hashCode(): Int = children.hashCode() + params.hashCode()
+}
+
+class A(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Big(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class B(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class BlockQuote(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+object Br : DocTag(emptyList(), emptyMap())
+class Cite(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+sealed class Code(children: List<DocTag>, params: Map<String, String>) : DocTag(children, params)
+class CodeInline(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : Code(children, params)
+class CodeBlock(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : Code(children, params)
+class Dd(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Dfn(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Dir(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Div(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Dl(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Dt(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Em(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Font(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Footer(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Frame(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class FrameSet(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H1(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H2(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H3(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H4(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H5(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class H6(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Head(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Header(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Html(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class I(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class IFrame(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Img(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Input(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Li(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Link(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Listing(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Main(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Menu(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Meta(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Nav(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class NoFrames(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class NoScript(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Ol(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class P(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Pre(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Script(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Section(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Small(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Span(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Strikethrough(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Strong(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Sub(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Sup(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Table(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Text(val body: String = "", children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params) {
+ override fun equals(other: Any?): Boolean = super.equals(other) && this.body == (other as Text).body
+ override fun hashCode(): Int = super.hashCode() + body.hashCode()
+}
+class TBody(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Td(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class TFoot(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Th(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class THead(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Title(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Tr(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Tt(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class U(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Ul(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class Var(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class DocumentationLink(val dri: DRI, children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params) {
+ override fun equals(other: Any?): Boolean = super.equals(other) && this.dri == (other as DocumentationLink).dri
+ override fun hashCode(): Int = super.hashCode() + dri.hashCode()
+}
+object HorizontalRule : DocTag(emptyList(), emptyMap())
+class Index(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
+class CustomDocTag(children: List<DocTag> = emptyList(), params: Map<String, String> = emptyMap()) : DocTag(children, params)
diff --git a/core/src/main/kotlin/model/doc/DocumentationNode.kt b/core/src/main/kotlin/model/doc/DocumentationNode.kt
new file mode 100644
index 00000000..6eb26a6a
--- /dev/null
+++ b/core/src/main/kotlin/model/doc/DocumentationNode.kt
@@ -0,0 +1,5 @@
+package org.jetbrains.dokka.model.doc
+
+import org.jetbrains.dokka.model.WithChildren
+
+data class DocumentationNode(override val children: List<TagWrapper>): WithChildren<TagWrapper>
diff --git a/core/src/main/kotlin/model/doc/TagWrapper.kt b/core/src/main/kotlin/model/doc/TagWrapper.kt
new file mode 100644
index 00000000..095f3eaf
--- /dev/null
+++ b/core/src/main/kotlin/model/doc/TagWrapper.kt
@@ -0,0 +1,39 @@
+package org.jetbrains.dokka.model.doc
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.WithChildren
+
+sealed class TagWrapper(val root: DocTag) : WithChildren<DocTag> {
+
+ override val children: List<DocTag>
+ get() = root.children
+
+ override fun equals(other: Any?): Boolean =
+ (
+ other != null &&
+ this::class == other::class &&
+ this.root == (other as TagWrapper).root
+ )
+
+ override fun hashCode(): Int = root.hashCode()
+}
+sealed class NamedTagWrapper(root: DocTag, val name: String) : TagWrapper(root) {
+ override fun equals(other: Any?): Boolean = super.equals(other) && this.name == (other as NamedTagWrapper).name
+ override fun hashCode(): Int = super.hashCode() + name.hashCode()
+}
+
+class Description(root: DocTag) : TagWrapper(root)
+class Author(root: DocTag) : TagWrapper(root)
+class Version(root: DocTag) : TagWrapper(root)
+class Since(root: DocTag) : TagWrapper(root)
+class See(root: DocTag, name: String, val address: DRI?) : NamedTagWrapper(root, name)
+class Param(root: DocTag, name: String) : NamedTagWrapper(root, name)
+class Return(root: DocTag) : TagWrapper(root)
+class Receiver(root: DocTag) : TagWrapper(root)
+class Constructor(root: DocTag) : TagWrapper(root)
+class Throws(root: DocTag, name: String) : NamedTagWrapper(root, name)
+class Sample(root: DocTag, name: String) : NamedTagWrapper(root, name)
+class Deprecated(root: DocTag) : TagWrapper(root)
+class Property(root: DocTag, name: String) : NamedTagWrapper(root, name)
+class Suppress(root: DocTag) : TagWrapper(root)
+class CustomTagWrapper(root: DocTag, name: String) : NamedTagWrapper(root, name)
diff --git a/core/src/main/kotlin/model/documentableProperties.kt b/core/src/main/kotlin/model/documentableProperties.kt
new file mode 100644
index 00000000..cd6a9335
--- /dev/null
+++ b/core/src/main/kotlin/model/documentableProperties.kt
@@ -0,0 +1,27 @@
+package org.jetbrains.dokka.model
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.properties.ExtraProperty
+import org.jetbrains.dokka.model.properties.MergeStrategy
+
+data class InheritedFunction(val inheritedFrom: SourceSetDependent<DRI?>) : ExtraProperty<DFunction> {
+ companion object : ExtraProperty.Key<DFunction, InheritedFunction> {
+ override fun mergeStrategyFor(left: InheritedFunction, right: InheritedFunction) = MergeStrategy.Replace(
+ InheritedFunction(left.inheritedFrom + right.inheritedFrom)
+ )
+ }
+
+ fun isInherited(sourceSetDependent: DokkaSourceSet): Boolean = inheritedFrom[sourceSetDependent] != null
+
+ override val key: ExtraProperty.Key<DFunction, *> = InheritedFunction
+}
+
+data class ImplementedInterfaces(val interfaces: SourceSetDependent<List<DRI>>) : ExtraProperty<Documentable> {
+ companion object : ExtraProperty.Key<Documentable, ImplementedInterfaces> {
+ override fun mergeStrategyFor(left: ImplementedInterfaces, right: ImplementedInterfaces) =
+ MergeStrategy.Replace(ImplementedInterfaces(left.interfaces + right.interfaces))
+ }
+
+ override val key: ExtraProperty.Key<Documentable, *> = ImplementedInterfaces
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/documentableUtils.kt b/core/src/main/kotlin/model/documentableUtils.kt
new file mode 100644
index 00000000..287cf313
--- /dev/null
+++ b/core/src/main/kotlin/model/documentableUtils.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.dokka.model
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+
+fun <T> SourceSetDependent<T>.filtered(sourceSets: Set<DokkaSourceSet>) = filter { it.key in sourceSets }
+fun DokkaSourceSet?.filtered(sourceSets: Set<DokkaSourceSet>) = takeIf { this in sourceSets }
+
+fun DTypeParameter.filter(filteredSet: Set<DokkaSourceSet>) =
+ if (filteredSet.containsAll(sourceSets)) this
+ else {
+ val intersection = filteredSet.intersect(sourceSets)
+ if (intersection.isEmpty()) null
+ else DTypeParameter(
+ dri,
+ name,
+ documentation.filtered(intersection),
+ expectPresentInSet?.takeIf { intersection.contains(expectPresentInSet) },
+ bounds,
+ intersection,
+ extra
+ )
+ }
diff --git a/core/src/main/kotlin/model/extraModifiers.kt b/core/src/main/kotlin/model/extraModifiers.kt
new file mode 100644
index 00000000..efaa3d60
--- /dev/null
+++ b/core/src/main/kotlin/model/extraModifiers.kt
@@ -0,0 +1,62 @@
+package org.jetbrains.dokka.model
+
+sealed class ExtraModifiers(val name: String) {
+
+ sealed class KotlinOnlyModifiers(name: String) : ExtraModifiers(name) {
+ object Inline : KotlinOnlyModifiers("inline")
+ object Infix : KotlinOnlyModifiers("infix")
+ object External : KotlinOnlyModifiers("external")
+ object Suspend : KotlinOnlyModifiers("suspend")
+ object Reified : KotlinOnlyModifiers("reified")
+ object CrossInline : KotlinOnlyModifiers("crossinline")
+ object NoInline : KotlinOnlyModifiers("noinline")
+ object Override : KotlinOnlyModifiers("override")
+ object Data : KotlinOnlyModifiers("data")
+ object Const : KotlinOnlyModifiers("const")
+ object Inner : KotlinOnlyModifiers("inner")
+ object LateInit : KotlinOnlyModifiers("lateinit")
+ object Operator : KotlinOnlyModifiers("operator")
+ object TailRec : KotlinOnlyModifiers("tailrec")
+ object VarArg : KotlinOnlyModifiers("vararg")
+ object Fun : KotlinOnlyModifiers("fun")
+ }
+
+ sealed class JavaOnlyModifiers(name: String) : ExtraModifiers(name) {
+ object Static : JavaOnlyModifiers("static")
+ object Native : JavaOnlyModifiers("native")
+ object Synchronized : JavaOnlyModifiers("synchronized")
+ object StrictFP : JavaOnlyModifiers("strictfp")
+ object Transient : JavaOnlyModifiers("transient")
+ object Volatile : JavaOnlyModifiers("volatile")
+ object Transitive : JavaOnlyModifiers("transitive")
+ }
+
+ companion object {
+ fun valueOf(str: String) = when (str) {
+ "inline" -> KotlinOnlyModifiers.Inline
+ "infix" -> KotlinOnlyModifiers.Infix
+ "external" -> KotlinOnlyModifiers.External
+ "suspend" -> KotlinOnlyModifiers.Suspend
+ "reified" -> KotlinOnlyModifiers.Reified
+ "crossinline" -> KotlinOnlyModifiers.CrossInline
+ "noinline" -> KotlinOnlyModifiers.NoInline
+ "override" -> KotlinOnlyModifiers.Override
+ "data" -> KotlinOnlyModifiers.Data
+ "const" -> KotlinOnlyModifiers.Const
+ "inner" -> KotlinOnlyModifiers.Inner
+ "lateinit" -> KotlinOnlyModifiers.LateInit
+ "operator" -> KotlinOnlyModifiers.Operator
+ "tailrec" -> KotlinOnlyModifiers.TailRec
+ "vararg" -> KotlinOnlyModifiers.VarArg
+ "static" -> JavaOnlyModifiers.Static
+ "native" -> JavaOnlyModifiers.Native
+ "synchronized" -> JavaOnlyModifiers.Synchronized
+ "strictfp" -> JavaOnlyModifiers.StrictFP
+ "transient" -> JavaOnlyModifiers.Transient
+ "volatile" -> JavaOnlyModifiers.Volatile
+ "transitive" -> JavaOnlyModifiers.Transitive
+ "fun" -> KotlinOnlyModifiers.Fun
+ else -> throw IllegalArgumentException("There is no Extra Modifier for given name $str")
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/properties/PropertyContainer.kt b/core/src/main/kotlin/model/properties/PropertyContainer.kt
new file mode 100644
index 00000000..6009bfe0
--- /dev/null
+++ b/core/src/main/kotlin/model/properties/PropertyContainer.kt
@@ -0,0 +1,60 @@
+package org.jetbrains.dokka.model.properties
+
+class PropertyContainer<C : Any> internal constructor(
+ @PublishedApi internal val map: Map<ExtraProperty.Key<C, *>, ExtraProperty<C>>
+) {
+ operator fun <D : C> plus(prop: ExtraProperty<D>): PropertyContainer<D> =
+ PropertyContainer(map + (prop.key to prop))
+
+ // TODO: Add logic for caching calculated properties
+ inline operator fun <reified T : Any> get(key: ExtraProperty.Key<C, T>): T? = when (val prop = map[key]) {
+ is T? -> prop
+ else -> throw ClassCastException("Property for $key stored under not matching key type.")
+ }
+
+ inline fun <reified T : Any> allOfType(): List<T> = map.values.filterIsInstance<T>()
+ fun <D : C> addAll(extras: Collection<ExtraProperty<D>>): PropertyContainer<D> =
+ PropertyContainer(map + extras.map { p -> p.key to p })
+
+ companion object {
+ fun <T : Any> empty(): PropertyContainer<T> = PropertyContainer(emptyMap())
+ fun <T : Any> withAll(vararg extras: ExtraProperty<T>) = empty<T>().addAll(extras.toList())
+ fun <T : Any> withAll(extras: Collection<ExtraProperty<T>>) = empty<T>().addAll(extras)
+ }
+}
+
+operator fun <D: Any> PropertyContainer<D>.plus(prop: ExtraProperty<D>?): PropertyContainer<D> =
+ if (prop == null) this else PropertyContainer(map + (prop.key to prop))
+
+interface WithExtraProperties<C : Any> {
+ val extra: PropertyContainer<C>
+
+ fun withNewExtras(newExtras: PropertyContainer<C>): C
+}
+
+fun <C> C.mergeExtras(left: C, right: C): C where C : Any, C : WithExtraProperties<C> {
+ val aggregatedExtras: List<List<ExtraProperty<C>>> =
+ (left.extra.map.values + right.extra.map.values)
+ .groupBy { it.key }
+ .values
+ .map { it.distinct() }
+
+ val (unambiguous, toMerge) = aggregatedExtras.partition { it.size == 1 }
+
+ @Suppress("UNCHECKED_CAST")
+ val strategies: List<MergeStrategy<C>> = toMerge.map { (l, r) ->
+ (l.key as ExtraProperty.Key<C, ExtraProperty<C>>).mergeStrategyFor(l, r)
+ }
+
+ strategies.filterIsInstance<MergeStrategy.Fail>().firstOrNull()?.error?.invoke()
+
+ val replaces: List<ExtraProperty<C>> =
+ strategies.filterIsInstance<MergeStrategy.Replace<C>>().map { it.newProperty }
+
+ val needingFullMerge: List<(preMerged: C, left: C, right: C) -> C> =
+ strategies.filterIsInstance<MergeStrategy.Full<C>>().map { it.merger }
+
+ val newExtras = PropertyContainer((unambiguous.flatten() + replaces).associateBy { it.key })
+
+ return needingFullMerge.fold(withNewExtras(newExtras)) { acc, merger -> merger(acc, left, right) }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/properties/properties.kt b/core/src/main/kotlin/model/properties/properties.kt
new file mode 100644
index 00000000..7010d0df
--- /dev/null
+++ b/core/src/main/kotlin/model/properties/properties.kt
@@ -0,0 +1,22 @@
+package org.jetbrains.dokka.model.properties
+
+interface ExtraProperty<in C : Any> {
+ interface Key<in C : Any, T : Any> {
+ fun mergeStrategyFor(left: T, right: T): MergeStrategy<C> = MergeStrategy.Fail {
+ throw NotImplementedError("Property merging for $this is not implemented")
+ }
+ }
+
+ val key: Key<C, *>
+}
+
+interface CalculatedProperty<in C : Any, T : Any> : ExtraProperty.Key<C, T> {
+ fun calculate(subject: C): T
+}
+
+sealed class MergeStrategy<in C> {
+ class Replace<in C : Any>(val newProperty: ExtraProperty<C>) : MergeStrategy<C>()
+ object Remove : MergeStrategy<Any>()
+ class Full<C : Any>(val merger: (preMerged: C, left: C, right: C) -> C) : MergeStrategy<C>()
+ class Fail(val error: () -> Nothing) : MergeStrategy<Any>()
+}