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

<lambda>null1 package org.jetbrains.dokka
2 
3 import org.jetbrains.dokka.classNodeNameWithOuterClass
4 import org.jetbrains.dokka.LanguageService.RenderMode
5 
6 /**
7  * Implements [LanguageService] and provides rendering of symbols in Java language
8  */
9 class NewJavaLanguageService : CommonLanguageService() {
10     override fun showModifierInSummary(node: DocumentationNode): Boolean {
11         return node.name !in fullOnlyModifiers
12     }
13 
14     private val fullOnlyModifiers = setOf("public", "protected", "private")
15 
16     override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode {
17         return content {
18             (when (node.kind) {
19                 NodeKind.Package -> renderPackage(node)
20                 in NodeKind.classLike -> renderClass(node, renderMode)
21 
22                 NodeKind.Modifier -> renderModifier(this, node, renderMode)
23                 NodeKind.TypeParameter -> renderTypeParameter(node)
24                 NodeKind.Type,
25                 NodeKind.UpperBound -> renderType(node)
26                 NodeKind.Parameter -> renderParameter(node)
27                 NodeKind.Constructor,
28                 NodeKind.Function -> renderFunction(node, renderMode)
29                 NodeKind.Property -> renderProperty(node)
30                 NodeKind.Field -> renderField(node, renderMode)
31                 NodeKind.EnumItem -> renderClass(node, renderMode)
32                 else -> "${node.kind}: ${node.name}"
33             })
34         }
35     }
36 
37     override fun summarizeSignatures(nodes: List<DocumentationNode>): ContentNode? = null
38 
39 
40     override fun renderModifier(block: ContentBlock, node: DocumentationNode, renderMode: RenderMode, nowrap: Boolean) {
41         when (node.name) {
42             "open", "internal" -> {
43             }
44             else -> {
45                 if (node.name !in fullOnlyModifiers || renderMode == RenderMode.FULL) {
46                     super.renderModifier(block, node, renderMode, nowrap)
47                 }
48             }
49         }
50     }
51 
52     fun getArrayElementType(node: DocumentationNode): DocumentationNode? = when (node.qualifiedName()) {
53         "kotlin.Array" ->
54             node.details(NodeKind.Type).singleOrNull()?.let { et -> getArrayElementType(et) ?: et }
55                     ?: DocumentationNode("Object", node.content, NodeKind.ExternalClass)
56 
57         "kotlin.IntArray", "kotlin.LongArray", "kotlin.ShortArray", "kotlin.ByteArray",
58         "kotlin.CharArray", "kotlin.DoubleArray", "kotlin.FloatArray", "kotlin.BooleanArray" ->
59             DocumentationNode(node.name.removeSuffix("Array").toLowerCase(), node.content, NodeKind.Type)
60 
61         else -> null
62     }
63 
64     fun getArrayDimension(node: DocumentationNode): Int = when (node.qualifiedName()) {
65         "kotlin.Array" ->
66             1 + (node.details(NodeKind.Type).singleOrNull()?.let { getArrayDimension(it) } ?: 0)
67 
68         "kotlin.IntArray", "kotlin.LongArray", "kotlin.ShortArray", "kotlin.ByteArray",
69         "kotlin.CharArray", "kotlin.DoubleArray", "kotlin.FloatArray", "kotlin.BooleanArray" ->
70             1
71         else -> 0
72     }
73 
74     fun ContentBlock.renderType(node: DocumentationNode) {
75         when (node.name) {
76             "Unit" -> identifier("void")
77             "Int" -> identifier("int")
78             "Long" -> identifier("long")
79             "Double" -> identifier("double")
80             "Float" -> identifier("float")
81             "Char" -> identifier("char")
82             "Boolean" -> identifier("bool")
83         // TODO: render arrays
84             else -> {
85                 renderLinked(this, node) {
86                     identifier(
87                         it.typeDeclarationClass?.classNodeNameWithOuterClass() ?: it.name,
88                         IdentifierKind.TypeName
89                     )
90                 }
91                 renderTypeArgumentsForType(node)
92             }
93         }
94     }
95 
96     private fun ContentBlock.renderTypeParameter(node: DocumentationNode) {
97         val constraints = node.details(NodeKind.UpperBound)
98         if (constraints.none())
99             identifier(node.name)
100         else {
101             identifier(node.name)
102             text(" ")
103             keyword("extends")
104             text(" ")
105             constraints.forEach { renderType(node) }
106         }
107     }
108 
109     private fun ContentBlock.renderParameter(node: DocumentationNode) {
110         renderType(node.detail(NodeKind.Type))
111         text(" ")
112         identifier(node.name)
113     }
114 
115     private fun ContentBlock.renderTypeParametersForNode(node: DocumentationNode) {
116         val typeParameters = node.details(NodeKind.TypeParameter)
117         if (typeParameters.any()) {
118             symbol("<")
119             renderList(typeParameters, noWrap = true) {
120                 renderTypeParameter(it)
121             }
122             symbol(">")
123             text(" ")
124         }
125     }
126 
127     private fun ContentBlock.renderTypeArgumentsForType(node: DocumentationNode) {
128         val typeArguments = node.details(NodeKind.Type)
129         if (typeArguments.any()) {
130             symbol("<")
131             renderList(typeArguments, noWrap = true) {
132                 renderType(it)
133             }
134             symbol(">")
135         }
136     }
137 
138 //    private fun renderModifiersForNode(node: DocumentationNode): String {
139 //        val modifiers = node.details(NodeKind.Modifier).map { renderModifier(it) }.filter { it != "" }
140 //        if (modifiers.none())
141 //            return ""
142 //        return modifiers.joinToString(" ", postfix = " ")
143 //    }
144 
145     private fun ContentBlock.renderClassKind(node: DocumentationNode) {
146         when (node.kind) {
147             NodeKind.Interface -> {
148                 keyword("interface")
149             }
150             NodeKind.EnumItem -> {
151                 keyword("enum value")
152             }
153             NodeKind.Enum -> {
154                 keyword("enum")
155             }
156             NodeKind.Class, NodeKind.Exception, NodeKind.Object -> {
157                 keyword("class")
158             }
159             else -> throw IllegalArgumentException("Node $node is not a class-like object")
160         }
161         text(" ")
162     }
163 
164     private fun ContentBlock.renderClass(node: DocumentationNode, renderMode: RenderMode) {
165         renderModifiersForNode(node, renderMode)
166         renderClassKind(node)
167 
168         identifier(node.name)
169         renderTypeParametersForNode(node)
170         val superClassType = node.superclassType
171         val interfaces = node.supertypes - superClassType
172         if (superClassType != null) {
173             text(" ")
174             keyword("extends")
175             text(" ")
176             renderType(superClassType)
177         }
178         if (interfaces.isNotEmpty()) {
179             text(" ")
180             keyword("implements")
181             text(" ")
182             renderList(interfaces.filterNotNull()) {
183                 renderType(it)
184             }
185         }
186     }
187 
188     private fun ContentBlock.renderParameters(nodes: List<DocumentationNode>) {
189         renderList(nodes) {
190             renderParameter(it)
191         }
192     }
193 
194     private fun ContentBlock.renderFunction(
195         node: DocumentationNode,
196         renderMode: RenderMode
197     ) {
198         renderModifiersForNode(node, renderMode)
199         when (node.kind) {
200             NodeKind.Constructor -> identifier(node.owner?.name ?: "")
201             NodeKind.Function -> {
202                 renderTypeParametersForNode(node)
203                 renderType(node.detail(NodeKind.Type))
204                 text(" ")
205                 identifier(node.name)
206 
207             }
208             else -> throw IllegalArgumentException("Node $node is not a function-like object")
209         }
210 
211         val receiver = node.details(NodeKind.Receiver).singleOrNull()
212         symbol("(")
213         if (receiver != null)
214             renderParameters(listOf(receiver) + node.details(NodeKind.Parameter))
215         else
216             renderParameters(node.details(NodeKind.Parameter))
217 
218         symbol(")")
219     }
220 
221     private fun ContentBlock.renderProperty(node: DocumentationNode) {
222 
223         when (node.kind) {
224             NodeKind.Property -> {
225                 keyword("val")
226                 text(" ")
227             }
228             else -> throw IllegalArgumentException("Node $node is not a property")
229         }
230         renderTypeParametersForNode(node)
231         val receiver = node.details(NodeKind.Receiver).singleOrNull()
232         if (receiver != null) {
233             renderType(receiver.detail(NodeKind.Type))
234             symbol(".")
235         }
236 
237         identifier(node.name)
238         symbol(":")
239         text(" ")
240         renderType(node.detail(NodeKind.Type))
241 
242     }
243 
244     private fun ContentBlock.renderField(node: DocumentationNode, renderMode: RenderMode) {
245         renderModifiersForNode(node, renderMode)
246         renderType(node.detail(NodeKind.Type))
247         text(" ")
248         identifier(node.name)
249     }
250 }
251