• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

<lambda>null1 package org.jetbrains.dokka
2 
3 import java.util.*
4 
5 enum class NodeKind {
6     Unknown,
7 
8     Package,
9     Class,
10     Interface,
11     Enum,
12     AnnotationClass,
13     Exception,
14     EnumItem,
15     Object,
16     TypeAlias,
17 
18     Constructor,
19     Function,
20     Property,
21     Field,
22 
23     CompanionObjectProperty,
24     CompanionObjectFunction,
25 
26     Parameter,
27     Receiver,
28     TypeParameter,
29     Type,
30     Supertype,
31     UpperBound,
32     LowerBound,
33 
34     TypeAliasUnderlyingType,
35 
36     Modifier,
37     NullabilityModifier,
38 
39     Module,
40 
41     ExternalClass,
42     Annotation,
43 
44     Value,
45 
46     SourceUrl,
47     SourcePosition,
48     Signature,
49 
50     ExternalLink,
51     QualifiedName,
52     Platform,
53 
54     AllTypes,
55 
56     /**
57      * A note which is rendered once on a page documenting a group of overloaded functions.
58      * Needs to be generated equally on all overloads.
59      */
60     OverloadGroupNote,
61 
62     Attribute,
63 
64     AttributeRef,
65 
66     ApiLevel,
67 
68     DeprecatedLevel,
69 
70     ArtifactId,
71 
72     GroupNode;
73 
74     companion object {
75         val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias)
76         val memberLike = setOf(Function, Property, Field, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem, Attribute)
77     }
78 }
79 
80 open class DocumentationNode(val name: String,
81                              content: Content,
82                              val kind: NodeKind) {
83 
84     private val references = LinkedHashSet<DocumentationReference>()
85 
86     var content: Content = content
87         private set
88 
89     val summary: ContentNode get() = content.summary
90 
91     val owner: DocumentationNode?
92         get() = references(RefKind.Owner).singleOrNull()?.to
93     val details: List<DocumentationNode>
<lambda>null94         get() = references(RefKind.Detail).map { it.to }
95     val members: List<DocumentationNode>
<lambda>null96         get() = references(RefKind.Member).map { it.to }.sortedBy { it.name }
97     val inheritedMembers: List<DocumentationNode>
<lambda>null98         get() = references(RefKind.InheritedMember).map { it.to }
99     val allInheritedMembers: List<DocumentationNode>
<lambda>null100         get() = recursiveInheritedMembers().sortedBy { it.name }
101     val inheritedCompanionObjectMembers: List<DocumentationNode>
<lambda>null102         get() = references(RefKind.InheritedCompanionObjectMember).map { it.to }
103     val extensions: List<DocumentationNode>
<lambda>null104         get() = references(RefKind.Extension).map { it.to }
105     val inheritors: List<DocumentationNode>
<lambda>null106         get() = references(RefKind.Inheritor).map { it.to }
107     val overrides: List<DocumentationNode>
<lambda>null108         get() = references(RefKind.Override).map { it.to }
109     val links: List<DocumentationNode>
<lambda>null110         get() = references(RefKind.Link).map { it.to }
111     val hiddenLinks: List<DocumentationNode>
<lambda>null112         get() = references(RefKind.HiddenLink).map { it.to }
113     val annotations: List<DocumentationNode>
<lambda>null114         get() = references(RefKind.Annotation).map { it.to }
115     val deprecation: DocumentationNode?
<lambda>null116         get() = references(RefKind.Deprecation).map { it.to }.firstOrNull()
117     val platforms: List<String>
<lambda>null118         get() = references(RefKind.Platform).map { it.to.name }
119     val externalType: DocumentationNode?
<lambda>null120         get() = references(RefKind.ExternalType).map { it.to }.firstOrNull()
121     val apiLevel: DocumentationNode
122         get() = detailOrNull(NodeKind.ApiLevel) ?: DocumentationNode("", Content.Empty, NodeKind.ApiLevel)
123     val deprecatedLevel: DocumentationNode
124         get() = detailOrNull(NodeKind.DeprecatedLevel) ?: DocumentationNode("", Content.Empty, NodeKind.DeprecatedLevel)
125     val artifactId: DocumentationNode
126         get() = detailOrNull(NodeKind.ArtifactId) ?: DocumentationNode("", Content.Empty, NodeKind.ArtifactId)
127     val attributes: List<DocumentationNode>
<lambda>null128         get() = details(NodeKind.Attribute).sortedBy { it.attributeRef!!.name }
129     val attributeRef: DocumentationNode?
<lambda>null130         get() = references(RefKind.AttributeRef).map { it.to }.firstOrNull()
131     val relatedAttributes: List<DocumentationNode>
132         get() = hiddenLinks(NodeKind.Attribute)
133     val supertypes: List<DocumentationNode>
134         get() = details(NodeKind.Supertype)
135     val signatureName = detailOrNull(NodeKind.Signature)?.name
136 
137     val superclassType: DocumentationNode?
138         get() = when (kind) {
139             NodeKind.Supertype -> {
<lambda>null140                 (links + listOfNotNull(externalType)).firstOrNull { it.kind in NodeKind.classLike }?.superclassType
141             }
142             NodeKind.Interface -> null
<lambda>null143             in NodeKind.classLike -> supertypes.firstOrNull {
144                 (it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) }
145             }
146             else -> null
147         }
148 
149     val superclassTypeSequence: Sequence<DocumentationNode>
<lambda>null150         get() = generateSequence(superclassType) {
151             it.superclassType
152         }
153 
154     // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice
addReferenceTonull155     fun addReferenceTo(to: DocumentationNode, kind: RefKind) {
156         references.add(DocumentationReference(this, to, kind))
157     }
158 
dropReferencesnull159     fun dropReferences(predicate: (DocumentationReference) -> Boolean) {
160         references.removeAll(predicate)
161     }
162 
addAllReferencesFromnull163     fun addAllReferencesFrom(other: DocumentationNode) {
164         references.addAll(other.references)
165     }
166 
updateContentnull167     fun updateContent(body: MutableContent.() -> Unit) {
168         if (content !is MutableContent) {
169             content = MutableContent()
170         }
171         (content as MutableContent).body()
172     }
<lambda>null173     fun details(kind: NodeKind): List<DocumentationNode> = details.filter { it.kind == kind }
<lambda>null174     fun members(kind: NodeKind): List<DocumentationNode> = members.filter { it.kind == kind }
<lambda>null175     fun hiddenLinks(kind: NodeKind): List<DocumentationNode> = hiddenLinks.filter { it.kind == kind }
<lambda>null176     fun inheritedMembers(kind: NodeKind): List<DocumentationNode> = inheritedMembers.filter { it.kind == kind }
<lambda>null177     fun inheritedCompanionObjectMembers(kind: NodeKind): List<DocumentationNode> = inheritedCompanionObjectMembers.filter { it.kind == kind }
<lambda>null178     fun links(kind: NodeKind): List<DocumentationNode> = links.filter { it.kind == kind }
179 
<lambda>null180     fun detail(kind: NodeKind): DocumentationNode = details.filter { it.kind == kind }.single()
detailOrNullnull181     fun detailOrNull(kind: NodeKind): DocumentationNode? = details.filter { it.kind == kind }.singleOrNull()
<lambda>null182     fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single()
<lambda>null183     fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single()
184 
<lambda>null185     fun references(kind: RefKind): List<DocumentationReference> = references.filter { it.kind == kind }
allReferencesnull186     fun allReferences(): Set<DocumentationReference> = references
187 
188     override fun toString(): String {
189         return "$kind:$name"
190     }
191 }
192 
193 class DocumentationModule(name: String, content: Content = Content.Empty)
194     : DocumentationNode(name, content, NodeKind.Module) {
195     val nodeRefGraph = NodeReferenceGraph()
196 }
197 
198 val DocumentationNode.path: List<DocumentationNode>
199     get() {
200         val parent = owner ?: return listOf(this)
201         return parent.path + this
202     }
203 
findOrCreatePackageNodenull204 fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map<String, Content>, refGraph: NodeReferenceGraph): DocumentationNode {
205     val existingNode = refGraph.lookup(packageName)
206     if (existingNode != null) {
207         return existingNode
208     }
209     val newNode = DocumentationNode(packageName,
210             packageContent.getOrElse(packageName) { Content.Empty },
211             NodeKind.Package)
212 
213     refGraph.register(packageName, newNode)
214     module?.append(newNode, RefKind.Member)
215     return newNode
216 }
217 
appendnull218 fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
219     addReferenceTo(child, kind)
220     when (kind) {
221         RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner)
222         RefKind.Member -> child.addReferenceTo(this, RefKind.Owner)
223         RefKind.Owner -> child.addReferenceTo(this, RefKind.Member)
224         else -> { /* Do not add any links back for other types */
225         }
226     }
227 }
228 
appendTextNodenull229 fun DocumentationNode.appendTextNode(text: String,
230                                      kind: NodeKind,
231                                      refKind: RefKind = RefKind.Detail) {
232     append(DocumentationNode(text, Content.Empty, kind), refKind)
233 }
234 
qualifiedNamenull235 fun DocumentationNode.qualifiedName(): String {
236     if (kind == NodeKind.Type) {
237         return qualifiedNameFromType()
238     } else if (kind == NodeKind.Package) {
239         return name
240     }
241     return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".")
242 }
243 
simpleNamenull244 fun DocumentationNode.simpleName() = name.substringAfterLast('.')
245 
246 private fun DocumentationNode.recursiveInheritedMembers(): List<DocumentationNode> {
247     val allInheritedMembers = mutableListOf<DocumentationNode>()
248     recursiveInheritedMembers(allInheritedMembers)
249     return allInheritedMembers
250 }
251 
recursiveInheritedMembersnull252 private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: MutableList<DocumentationNode>) {
253     allInheritedMembers.addAll(inheritedMembers)
254     inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) ->
255         node.recursiveInheritedMembers(allInheritedMembers)
256     }
257 }
258 
isSuperclassFornull259 private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean {
260     return when(node.kind) {
261         NodeKind.Object, NodeKind.Class, NodeKind.Enum -> kind == NodeKind.Class
262         NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception
263         else -> false
264     }
265 }
266 
classNodeNameWithOuterClassnull267 fun DocumentationNode.classNodeNameWithOuterClass(): String {
268     assert(kind in NodeKind.classLike)
269     return path.dropWhile { it.kind == NodeKind.Package || it.kind == NodeKind.Module }.joinToString(separator = ".") { it.name }
270 }
271 
deprecatedLevelMessagenull272 fun DocumentationNode.deprecatedLevelMessage(): String {
273     val kindName = when(kind) {
274         NodeKind.Enum -> "enum"
275         NodeKind.Interface -> "interface"
276         NodeKind.AnnotationClass -> "annotation"
277         NodeKind.Exception -> "exception"
278         else -> "class"
279     }
280     return "This $kindName was deprecated in API level ${deprecatedLevel.name}."
281 }
282