• 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     SdkExtSince,
68 
69     DeprecatedLevel,
70 
71     ArtifactId,
72 
73     GroupNode;
74 
75     companion object {
76         val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias)
77         val memberLike = setOf(Function, Property, Field, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem, Attribute)
78     }
79 }
80 
81 open class DocumentationNode(val name: String,
82                              content: Content,
83                              val kind: NodeKind) {
84 
85     private val references = LinkedHashSet<DocumentationReference>()
86 
87     var content: Content = content
88         private set
89 
90     val summary: ContentNode get() = content.summary
91 
92     val owner: DocumentationNode?
93         get() = references(RefKind.Owner).singleOrNull()?.to
94     val details: List<DocumentationNode>
<lambda>null95         get() = references(RefKind.Detail).map { it.to }
96     val members: List<DocumentationNode>
<lambda>null97         get() = references(RefKind.Member).map { it.to }.sortedBy { it.name }
98     val inheritedMembers: List<DocumentationNode>
<lambda>null99         get() = references(RefKind.InheritedMember).map { it.to }
100     val allInheritedMembers: List<DocumentationNode>
<lambda>null101         get() = recursiveInheritedMembers().sortedBy { it.name }
102     val inheritedCompanionObjectMembers: List<DocumentationNode>
<lambda>null103         get() = references(RefKind.InheritedCompanionObjectMember).map { it.to }
104     val extensions: List<DocumentationNode>
<lambda>null105         get() = references(RefKind.Extension).map { it.to }
106     val inheritors: List<DocumentationNode>
<lambda>null107         get() = references(RefKind.Inheritor).map { it.to }
108     val overrides: List<DocumentationNode>
<lambda>null109         get() = references(RefKind.Override).map { it.to }
110     val links: List<DocumentationNode>
<lambda>null111         get() = references(RefKind.Link).map { it.to }
112     val hiddenLinks: List<DocumentationNode>
<lambda>null113         get() = references(RefKind.HiddenLink).map { it.to }
114     val annotations: List<DocumentationNode>
<lambda>null115         get() = references(RefKind.Annotation).map { it.to }
116     val deprecation: DocumentationNode?
<lambda>null117         get() = references(RefKind.Deprecation).map { it.to }.firstOrNull()
118     val platforms: List<String>
<lambda>null119         get() = references(RefKind.Platform).map { it.to.name }
120     val externalType: DocumentationNode?
<lambda>null121         get() = references(RefKind.ExternalType).map { it.to }.firstOrNull()
122     val apiLevel: DocumentationNode
123         get() = detailOrNull(NodeKind.ApiLevel) ?: DocumentationNode("", Content.Empty, NodeKind.ApiLevel)
124     val sdkExtSince: DocumentationNode
125         get() = detailOrNull(NodeKind.SdkExtSince) ?: DocumentationNode("", Content.Empty, NodeKind.SdkExtSince)
126     val deprecatedLevel: DocumentationNode
127         get() = detailOrNull(NodeKind.DeprecatedLevel) ?: DocumentationNode("", Content.Empty, NodeKind.DeprecatedLevel)
128     val artifactId: DocumentationNode
129         get() = detailOrNull(NodeKind.ArtifactId) ?: DocumentationNode("", Content.Empty, NodeKind.ArtifactId)
130     val attributes: List<DocumentationNode>
<lambda>null131         get() = details(NodeKind.Attribute).sortedBy { it.attributeRef!!.name }
132     val attributeRef: DocumentationNode?
<lambda>null133         get() = references(RefKind.AttributeRef).map { it.to }.firstOrNull()
134     val relatedAttributes: List<DocumentationNode>
135         get() = hiddenLinks(NodeKind.Attribute)
136     val supertypes: List<DocumentationNode>
137         get() = details(NodeKind.Supertype)
138     val signatureName = detailOrNull(NodeKind.Signature)?.name
139 
140     val prettyName : String
141         get() = when(kind) {
142             NodeKind.Constructor -> owner!!.name
143             else -> name
144         }
145 
146     val superclassType: DocumentationNode?
147         get() = when (kind) {
148             NodeKind.Supertype -> {
<lambda>null149                 (links + listOfNotNull(externalType)).firstOrNull { it.kind in NodeKind.classLike }?.superclassType
150             }
151             NodeKind.Interface -> null
<lambda>null152             in NodeKind.classLike -> supertypes.firstOrNull {
153                 (it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) }
154             }
155             else -> null
156         }
157 
158     val superclassTypeSequence: Sequence<DocumentationNode>
<lambda>null159         get() = generateSequence(superclassType) {
160             it.superclassType
161         }
162 
163     // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice
addReferenceTonull164     fun addReferenceTo(to: DocumentationNode, kind: RefKind) {
165         references.add(DocumentationReference(this, to, kind))
166     }
167 
dropReferencesnull168     fun dropReferences(predicate: (DocumentationReference) -> Boolean) {
169         references.removeAll(predicate)
170     }
171 
addAllReferencesFromnull172     fun addAllReferencesFrom(other: DocumentationNode) {
173         references.addAll(other.references)
174     }
175 
updateContentnull176     fun updateContent(body: MutableContent.() -> Unit) {
177         if (content !is MutableContent) {
178             content = MutableContent()
179         }
180         (content as MutableContent).body()
181     }
<lambda>null182     fun details(kind: NodeKind): List<DocumentationNode> = details.filter { it.kind == kind }
<lambda>null183     fun members(kind: NodeKind): List<DocumentationNode> = members.filter { it.kind == kind }
<lambda>null184     fun hiddenLinks(kind: NodeKind): List<DocumentationNode> = hiddenLinks.filter { it.kind == kind }
<lambda>null185     fun inheritedMembers(kind: NodeKind): List<DocumentationNode> = inheritedMembers.filter { it.kind == kind }
<lambda>null186     fun inheritedCompanionObjectMembers(kind: NodeKind): List<DocumentationNode> = inheritedCompanionObjectMembers.filter { it.kind == kind }
<lambda>null187     fun links(kind: NodeKind): List<DocumentationNode> = links.filter { it.kind == kind }
188 
<lambda>null189     fun detail(kind: NodeKind): DocumentationNode = details.filter { it.kind == kind }.single()
detailOrNullnull190     fun detailOrNull(kind: NodeKind): DocumentationNode? = details.filter { it.kind == kind }.singleOrNull()
<lambda>null191     fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single()
<lambda>null192     fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single()
193 
<lambda>null194     fun references(kind: RefKind): List<DocumentationReference> = references.filter { it.kind == kind }
allReferencesnull195     fun allReferences(): Set<DocumentationReference> = references
196 
197     override fun toString(): String {
198         return "$kind:$name"
199     }
200 }
201 
202 class DocumentationModule(name: String, content: Content = Content.Empty)
203     : DocumentationNode(name, content, NodeKind.Module) {
204     val nodeRefGraph = NodeReferenceGraph()
205 }
206 
207 val DocumentationNode.path: List<DocumentationNode>
208     get() {
209         val parent = owner ?: return listOf(this)
210         return parent.path + this
211     }
212 
findOrCreatePackageNodenull213 fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map<String, Content>, refGraph: NodeReferenceGraph): DocumentationNode {
214     val existingNode = refGraph.lookup(packageName)
215     if (existingNode != null) {
216         return existingNode
217     }
218     val newNode = DocumentationNode(packageName,
219             packageContent.getOrElse(packageName) { Content.Empty },
220             NodeKind.Package)
221 
222     refGraph.register(packageName, newNode)
223     module?.append(newNode, RefKind.Member)
224     return newNode
225 }
226 
appendnull227 fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
228     addReferenceTo(child, kind)
229     when (kind) {
230         RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner)
231         RefKind.Member -> child.addReferenceTo(this, RefKind.Owner)
232         RefKind.Owner -> child.addReferenceTo(this, RefKind.Member)
233         else -> { /* Do not add any links back for other types */
234         }
235     }
236 }
237 
appendTextNodenull238 fun DocumentationNode.appendTextNode(text: String,
239                                      kind: NodeKind,
240                                      refKind: RefKind = RefKind.Detail) {
241     append(DocumentationNode(text, Content.Empty, kind), refKind)
242 }
243 
qualifiedNamenull244 fun DocumentationNode.qualifiedName(): String {
245     if (kind == NodeKind.Type) {
246         return qualifiedNameFromType()
247     } else if (kind == NodeKind.Package) {
248         return name
249     }
250     return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".")
251 }
252 
simpleNamenull253 fun DocumentationNode.simpleName() = name.substringAfterLast('.')
254 
255 private fun DocumentationNode.recursiveInheritedMembers(): List<DocumentationNode> {
256     val allInheritedMembers = mutableListOf<DocumentationNode>()
257     recursiveInheritedMembers(allInheritedMembers)
258     return allInheritedMembers
259 }
260 
recursiveInheritedMembersnull261 private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: MutableList<DocumentationNode>) {
262     allInheritedMembers.addAll(inheritedMembers)
263     inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) ->
264         node.recursiveInheritedMembers(allInheritedMembers)
265     }
266 }
267 
isSuperclassFornull268 private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean {
269     return when(node.kind) {
270         NodeKind.Object, NodeKind.Class, NodeKind.Enum -> kind == NodeKind.Class
271         NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception
272         else -> false
273     }
274 }
275 
classNodeNameWithOuterClassnull276 fun DocumentationNode.classNodeNameWithOuterClass(): String {
277     assert(kind in NodeKind.classLike)
278     return path.dropWhile { it.kind !in NodeKind.classLike }.joinToString(separator = ".") { it.name }
279 }
280 
deprecatedLevelMessagenull281 fun DocumentationNode.deprecatedLevelMessage(): String {
282     val kindName = when(kind) {
283         NodeKind.Enum -> "enum"
284         NodeKind.Interface -> "interface"
285         NodeKind.AnnotationClass -> "annotation"
286         NodeKind.Exception -> "exception"
287         else -> "class"
288     }
289     return "This $kindName was deprecated in API level ${deprecatedLevel.name}."
290 }
291 
convertDeprecationDetailsToChildrennull292 fun DocumentationNode.convertDeprecationDetailsToChildren() {
293     val toProcess = details.toMutableList()
294     while (!toProcess.isEmpty()) {
295         var child = toProcess.removeAt(0)
296         if (child.details.isEmpty() && child.name != "") {
297             updateContent { text(child.name.cleanForAppending()) }
298         }
299         else toProcess.addAll(0, child.details)
300     }
301 }
302 
303    /*
304     * Removes extraneous quotation marks and adds a ". " to make appending children readable.
305     */
Stringnull306 fun String.cleanForAppending(): String {
307     var result = this
308     if (this.first() == this.last() && this.first() == '"') result = result.substring(1, result.length - 1)
309     if (result[result.length - 2] != '.' && result.last() != ' ') result += ". "
310     return result
311 }