aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/Model/DocumentationNode.kt
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/kotlin/Model/DocumentationNode.kt')
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt314
1 files changed, 184 insertions, 130 deletions
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index 311b46e4..66ee33e1 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -1,89 +1,160 @@
package org.jetbrains.dokka
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import java.util.*
+import kotlin.reflect.KClass
+import kotlin.reflect.full.primaryConstructor
-enum class NodeKind {
- Unknown,
+class DocumentationNodes {
- Package,
- Class,
- Interface,
- Enum,
- AnnotationClass,
- Exception,
- EnumItem,
- Object,
- TypeAlias,
+ class Unknown(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
- Constructor,
- Function,
- Property,
- Field,
+ class Package(name: String) :
+ DocumentationNode(name)
- CompanionObjectProperty,
- CompanionObjectFunction,
+ class Class(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ }
- Parameter,
- Receiver,
- TypeParameter,
- Type,
- Supertype,
- UpperBound,
- LowerBound,
+ class Interface(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ override val superclassType: DocumentationNode? = null
+ }
- TypeAliasUnderlyingType,
+ class Enum(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ }
- Modifier,
- NullabilityModifier,
+ class AnnotationClass(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ }
- Module,
+ class Exception(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ }
- ExternalClass,
- Annotation,
+ class EnumItem(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- Value,
+ class Object(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val classLike: Boolean = true
+ }
- SourceUrl,
- SourcePosition,
- Signature,
+ class TypeAlias(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
- ExternalLink,
- QualifiedName,
- Platform,
+ class Constructor(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- AllTypes,
+ class Function(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- /**
- * A note which is rendered once on a page documenting a group of overloaded functions.
- * Needs to be generated equally on all overloads.
- */
- OverloadGroupNote,
+ class Property(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- GroupNode;
+ class Field(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- companion object {
- val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias)
- val memberLike = setOf(Function, Property, Field, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem)
+ class CompanionObjectProperty(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
}
-}
-open class DocumentationNode(val name: String,
- content: Content,
- val kind: NodeKind) {
+ class CompanionObjectFunction(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val memberLike = true
+ }
- private val references = LinkedHashSet<DocumentationReference>()
+ class Parameter(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
- var content: Content = content
- private set
+ class Receiver(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
- val summary: ContentNode get() = when (kind) {
- NodeKind.GroupNode -> this.origins
- .map { it.content }
- .firstOrNull { !it.isEmpty() }
- ?.summary ?: ContentEmpty
- else -> content.summary
+ class TypeParameter(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Type(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Supertype(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor) {
+ override val superclassType: DocumentationNode? =
+ (links + listOfNotNull(externalType)).firstOrNull { it.classLike }?.superclassType
}
+ class UpperBound(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class LowerBound(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class TypeAliasUnderlyingType(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class NullabilityModifier(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Module(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class ExternalClass(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Annotation(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Value(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class SourceUrl(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class SourcePosition(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class ExternalLink(name: String) : DocumentationNode(name)
+
+ class QualifiedName(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class Platform(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class AllTypes(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+
+ class OverloadGroupNote(name: String, descriptor: DeclarationDescriptor?) :
+ DocumentationNode(name, descriptor)
+}
+
+abstract class DocumentationNode(
+ var name: String,
+ val descriptor: DeclarationDescriptor? = null
+) {
+
+ private val references = LinkedHashSet<DocumentationReference>()
+
+ open val classLike = false
+
+ open val memberLike = false
val owner: DocumentationNode?
get() = references(RefKind.Owner).singleOrNull()?.to
@@ -119,29 +190,12 @@ open class DocumentationNode(val name: String,
val externalType: DocumentationNode?
get() = references(RefKind.ExternalType).map { it.to }.firstOrNull()
- var sinceKotlin: String?
- get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name
- set(value) {
- dropReferences { it.kind == RefKind.SinceKotlin }
- if (value != null) {
- append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin)
- }
- }
-
- val supertypes: List<DocumentationNode>
- get() = details(NodeKind.Supertype)
-
- val superclassType: DocumentationNode?
- get() = when (kind) {
- NodeKind.Supertype -> {
- (links + listOfNotNull(externalType)).firstOrNull { it.kind in NodeKind.classLike }?.superclassType
- }
- NodeKind.Interface -> null
- in NodeKind.classLike -> supertypes.firstOrNull {
+ open val superclassType: DocumentationNode?
+ get() = if (classLike) {
+ supertypes.firstOrNull {
(it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) }
}
- else -> null
- }
+ } else null
val superclassTypeSequence: Sequence<DocumentationNode>
get() = generateSequence(superclassType) {
@@ -165,36 +219,46 @@ open class DocumentationNode(val name: String,
references.addAll(other.references)
}
- fun updateContent(body: MutableContent.() -> Unit) {
- if (content !is MutableContent) {
- content = MutableContent()
- }
- (content as MutableContent).body()
- }
- fun details(kind: NodeKind): List<DocumentationNode> = details.filter { it.kind == kind }
- fun members(kind: NodeKind): List<DocumentationNode> = members.filter { it.kind == kind }
- fun inheritedMembers(kind: NodeKind): List<DocumentationNode> = inheritedMembers.filter { it.kind == kind }
- fun inheritedCompanionObjectMembers(kind: NodeKind): List<DocumentationNode> = inheritedCompanionObjectMembers.filter { it.kind == kind }
- fun links(kind: NodeKind): List<DocumentationNode> = links.filter { it.kind == kind }
+ private fun Collection<DocumentationNode>.filterByKind(kind: KClass<out DocumentationNode>) =
+ filter { node: DocumentationNode -> node::class == kind }
+
+ private fun Collection<DocumentationNode>.singleByKind(kind: KClass<out DocumentationNode>) =
+ single { node: DocumentationNode -> node::class == kind }
+
+ fun details(kind: KClass<out DocumentationNode>) = details.filterByKind(kind)
+ fun members(kind: KClass<out DocumentationNode>) = members.filterByKind(kind)
+ fun inheritedMembers(kind: KClass<out DocumentationNode>): List<DocumentationNode> =
+ inheritedMembers.filterByKind(kind)
+
+ fun inheritedCompanionObjectMembers(kind: KClass<out DocumentationNode>): List<DocumentationNode> =
+ inheritedCompanionObjectMembers.filterByKind(kind)
+
+ fun links(kind: KClass<out DocumentationNode>): List<DocumentationNode> = links.filterByKind(kind)
+
+ fun detail(kind: KClass<out DocumentationNode>): DocumentationNode = details.singleByKind(kind)
+ fun detailOrNull(kind: KClass<out DocumentationNode>): DocumentationNode? =
+ details.singleOrNull { it::class == kind }
- fun detail(kind: NodeKind): DocumentationNode = details.single { it.kind == kind }
- fun detailOrNull(kind: NodeKind): DocumentationNode? = details.singleOrNull { it.kind == kind }
- fun member(kind: NodeKind): DocumentationNode = members.single { it.kind == kind }
- fun link(kind: NodeKind): DocumentationNode = links.single { it.kind == kind }
+ fun member(kind: KClass<out DocumentationNode>): DocumentationNode = members.singleByKind(kind)
+ fun link(kind: KClass<out DocumentationNode>): DocumentationNode = links.singleByKind(kind)
fun references(kind: RefKind): List<DocumentationReference> = references.filter { it.kind == kind }
fun allReferences(): Set<DocumentationReference> = references
override fun toString(): String {
- return "$kind:$name"
+ return "${javaClass.name}:$name"
}
}
-class DocumentationModule(name: String, content: Content = Content.Empty, val nodeRefGraph: NodeReferenceGraph = NodeReferenceGraph())
- : DocumentationNode(name, content, NodeKind.Module) {
+fun KClass<out DocumentationNode>.createNode(name: String, descriptor: DeclarationDescriptor? = null) =
+ primaryConstructor?.call(name, descriptor)
+ ?: throw IllegalArgumentException("Cannot create node of type ${this::class}: invalid primary constructor")
-}
+val DocumentationNode.supertypes: List<DocumentationNode>
+ get() = details(DocumentationNodes.Supertype::class)
+
+class DocumentationModule(name: String) : DocumentationNode(name)
val DocumentationNode.path: List<DocumentationNode>
get() {
@@ -202,23 +266,6 @@ val DocumentationNode.path: List<DocumentationNode>
return parent.path + this
}
-fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map<String, Content>, refGraph: NodeReferenceGraph): DocumentationNode {
- val node = refGraph.lookup(packageName) ?: run {
- val newNode = DocumentationNode(
- packageName,
- packageContent.getOrElse(packageName) { Content.Empty },
- NodeKind.Package
- )
-
- refGraph.register(packageName, newNode)
- newNode
- }
- if (module != null && node !in module.members) {
- module.append(node, RefKind.Member)
- }
- return node
-}
-
fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
addReferenceTo(child, kind)
when (kind) {
@@ -231,19 +278,23 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
}
}
-fun DocumentationNode.appendTextNode(text: String,
- kind: NodeKind,
- refKind: RefKind = RefKind.Detail) {
- append(DocumentationNode(text, Content.Empty, kind), refKind)
+fun DocumentationNode.appendTextNode(
+ text: String,
+ kind: KClass<out DocumentationNode>,
+ descriptor: DeclarationDescriptor? = null,
+ refKind: RefKind = RefKind.Detail
+) {
+ append(kind.createNode(text, descriptor), refKind)
}
fun DocumentationNode.qualifiedName(): String {
- if (kind == NodeKind.Type) {
+ if (this is DocumentationNodes.Type) {
return qualifiedNameFromType()
- } else if (kind == NodeKind.Package) {
+ } else if (this is DocumentationNodes.Package) {
return name
}
- return path.dropWhile { it.kind == NodeKind.Module }.map { it.name }.filter { it.isNotEmpty() }.joinToString(".")
+ return path.dropWhile { it is DocumentationNodes.Module }.map { it.name }.filter { it.isNotEmpty() }
+ .joinToString(".")
}
fun DocumentationNode.simpleName() = name.substringAfterLast('.')
@@ -257,20 +308,23 @@ private fun DocumentationNode.recursiveInheritedMembers(): List<DocumentationNod
private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: MutableList<DocumentationNode>) {
allInheritedMembers.addAll(inheritedMembers)
System.out.println(allInheritedMembers.size)
- inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) ->
+ inheritedMembers.groupBy { it.owner!! }.forEach { (node, _) ->
node.recursiveInheritedMembers(allInheritedMembers)
}
}
private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean {
- return when(node.kind) {
- NodeKind.Object, NodeKind.Class, NodeKind.Enum -> kind == NodeKind.Class
- NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception
+ return when (node) {
+ is DocumentationNodes.Object,
+ is DocumentationNodes.Class,
+ is DocumentationNodes.Enum -> this is DocumentationNodes.Class
+ is DocumentationNodes.Exception -> this is DocumentationNodes.Class || this is DocumentationNodes.Exception
else -> false
}
}
fun DocumentationNode.classNodeNameWithOuterClass(): String {
- assert(kind in NodeKind.classLike)
- return path.dropWhile { it.kind == NodeKind.Package || it.kind == NodeKind.Module }.joinToString(separator = ".") { it.name }
+ assert(classLike)
+ return path.dropWhile { it is DocumentationNodes.Package || it is DocumentationNodes.Module }
+ .joinToString(separator = ".") { it.name }
} \ No newline at end of file