diff options
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>() +} | 
