diff options
author | Paweł Marks <pmarks@virtuslab.com> | 2020-07-17 16:36:09 +0200 |
---|---|---|
committer | Paweł Marks <pmarks@virtuslab.com> | 2020-07-17 16:36:09 +0200 |
commit | 6996b1135f61c7d2cb60b0652c6a2691dda31990 (patch) | |
tree | d568096c25e31c28d14d518a63458b5a7526b896 /core/src/main/kotlin/model | |
parent | de56cab76f556e5b4af0b8c8cb08d8b482b86d0a (diff) | |
parent | 1c3530dcbb50c347f80bef694829dbefe89eca77 (diff) | |
download | dokka-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.kt | 398 | ||||
-rw-r--r-- | core/src/main/kotlin/model/WithChildren.kt | 64 | ||||
-rw-r--r-- | core/src/main/kotlin/model/additionalExtras.kt | 75 | ||||
-rw-r--r-- | core/src/main/kotlin/model/classKinds.kt | 20 | ||||
-rw-r--r-- | core/src/main/kotlin/model/defaultValues.kt | 13 | ||||
-rw-r--r-- | core/src/main/kotlin/model/doc/DocTag.kt | 96 | ||||
-rw-r--r-- | core/src/main/kotlin/model/doc/DocumentationNode.kt | 5 | ||||
-rw-r--r-- | core/src/main/kotlin/model/doc/TagWrapper.kt | 39 | ||||
-rw-r--r-- | core/src/main/kotlin/model/documentableProperties.kt | 27 | ||||
-rw-r--r-- | core/src/main/kotlin/model/documentableUtils.kt | 22 | ||||
-rw-r--r-- | core/src/main/kotlin/model/extraModifiers.kt | 62 | ||||
-rw-r--r-- | core/src/main/kotlin/model/properties/PropertyContainer.kt | 60 | ||||
-rw-r--r-- | core/src/main/kotlin/model/properties/properties.kt | 22 |
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>() +} |