• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.jetbrains.dokka.javadoc
2 
3 import com.sun.javadoc.*
4 import org.jetbrains.dokka.*
5 import java.util.*
6 
7 class TagImpl(val holder: Doc, val name: String, val text: String): Tag {
textnull8     override fun text(): String? = text
9 
10     override fun holder(): Doc = holder
11     override fun firstSentenceTags(): Array<out Tag>? = arrayOf()
12     override fun inlineTags(): Array<out Tag>?  = arrayOf()
13 
14     override fun name(): String = name
15     override fun kind(): String = name
16 
17     override fun position(): SourcePosition = holder.position()
18 }
19 
20 class TextTag(val holder: Doc, val content: ContentText) : Tag {
21     val plainText: String
22         get() = content.text
23 
24     override fun name(): String = "Text"
25     override fun kind(): String = name()
26     override fun text(): String? = plainText
27     override fun inlineTags(): Array<out Tag> = arrayOf(this)
28     override fun holder(): Doc = holder
29     override fun firstSentenceTags(): Array<out Tag> = arrayOf(this)
30     override fun position(): SourcePosition = holder.position()
31 }
32 
33 abstract class SeeTagAdapter(val holder: Doc, val content: ContentNodeLink) : SeeTag {
positionnull34     override fun position(): SourcePosition? = holder.position()
35     override fun name(): String = "@see"
36     override fun kind(): String = "@see"
37     override fun holder(): Doc = holder
38 
39     override fun text(): String? = content.node?.name ?: "(?)"
40 }
41 
42 class SeeExternalLinkTagAdapter(val holder: Doc, val link: ContentExternalLink) : SeeTag {
43     override fun position(): SourcePosition = holder.position()
44     override fun text(): String = label()
45     override fun inlineTags(): Array<out Tag> = emptyArray() // TODO
46 
47     override fun label(): String {
48         val label = link.asText() ?: link.href
49         return "<a href=\"${link.href}\">$label</a>"
50     }
51 
52     override fun referencedPackage(): PackageDoc? = null
53     override fun referencedClass(): ClassDoc? = null
54     override fun referencedMemberName(): String? = null
55     override fun referencedClassName(): String? = null
56     override fun referencedMember(): MemberDoc? = null
57     override fun holder(): Doc = holder
58     override fun firstSentenceTags(): Array<out Tag> = inlineTags()
59     override fun name(): String = "@link"
60     override fun kind(): String = "@see"
61 }
62 
ContentBlocknull63 fun ContentBlock.asText(): String? {
64     val contentText = children.singleOrNull() as? ContentText
65     return contentText?.text
66 }
67 
68 class SeeMethodTagAdapter(holder: Doc, val method: MethodAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) {
referencedMembernull69     override fun referencedMember(): MemberDoc = method
70     override fun referencedMemberName(): String = method.name()
71     override fun referencedPackage(): PackageDoc? = null
72     override fun referencedClass(): ClassDoc? = method.containingClass()
73     override fun referencedClassName(): String = method.containingClass()?.name() ?: ""
74     override fun label(): String = "${method.containingClass()?.name()}.${method.name()}"
75 
76     override fun inlineTags(): Array<out Tag> = emptyArray() // TODO
77     override fun firstSentenceTags(): Array<out Tag> = inlineTags() // TODO
78 }
79 
80 class SeeClassTagAdapter(holder: Doc, val clazz: ClassDocumentationNodeAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) {
81     override fun referencedMember(): MemberDoc? = null
82     override fun referencedMemberName(): String? = null
83     override fun referencedPackage(): PackageDoc? = null
84     override fun referencedClass(): ClassDoc = clazz
85     override fun referencedClassName(): String = clazz.name()
86     override fun label(): String = "${clazz.classNode.kind.name.toLowerCase()} ${clazz.name()}"
87 
88     override fun inlineTags(): Array<out Tag> = emptyArray() // TODO
89     override fun firstSentenceTags(): Array<out Tag> = inlineTags() // TODO
90 }
91 
92 class ParamTagAdapter(val module: ModuleNodeAdapter,
93                       val holder: Doc,
94                       val parameterName: String,
95                       val typeParameter: Boolean,
96                       val content: List<ContentNode>) : ParamTag {
97 
98     constructor(module: ModuleNodeAdapter, holder: Doc, parameterName: String, isTypeParameter: Boolean, content: ContentNode)
99         : this(module, holder, parameterName, isTypeParameter, listOf(content)) {
100     }
101 
namenull102     override fun name(): String = "@param"
103     override fun kind(): String = name()
104     override fun holder(): Doc = holder
105     override fun position(): SourcePosition? = holder.position()
106 
107     override fun text(): String = "@param $parameterName ${parameterComment()}" // Seems has no effect, so used for debug
108     override fun inlineTags(): Array<out Tag> = buildInlineTags(module, holder, content).toTypedArray()
109     override fun firstSentenceTags(): Array<out Tag> = arrayOf(TextTag(holder, ContentText(text())))
110 
111     override fun isTypeParameter(): Boolean = typeParameter
112     override fun parameterComment(): String = content.toString() // TODO
113     override fun parameterName(): String = parameterName
114 }
115 
116 
117 class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter, val content: List<ContentNode>) : ThrowsTag {
118     override fun name(): String = "@throws"
119     override fun kind(): String = name()
120     override fun holder(): Doc = holder
121     override fun position(): SourcePosition? = holder.position()
122 
123     override fun text(): String = "${name()} ${exceptionName()} ${exceptionComment()}"
124     override fun inlineTags(): Array<out Tag> = buildInlineTags(type.module, holder, content).toTypedArray()
125     override fun firstSentenceTags(): Array<out Tag> = emptyArray()
126 
127     override fun exceptionComment(): String = content.toString()
128     override fun exceptionType(): Type = type
129     override fun exception(): ClassDoc = type
130     override fun exceptionName(): String = type.qualifiedTypeName()
131 }
132 
133 class ReturnTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val content: List<ContentNode>) : Tag {
namenull134     override fun name(): String = "@return"
135     override fun kind() = name()
136     override fun holder() = holder
137     override fun position(): SourcePosition? = holder.position()
138 
139     override fun text(): String = "@return $content" // Seems has no effect, so used for debug
140     override fun inlineTags(): Array<Tag> = buildInlineTags(module, holder, content).toTypedArray()
141     override fun firstSentenceTags(): Array<Tag> = inlineTags()
142 }
143 
144 fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, tags: List<ContentNode>): List<Tag> = ArrayList<Tag>().apply { tags.forEach { buildInlineTags(module, holder, it, this) } }
145 
<lambda>null146 fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List<Tag> = ArrayList<Tag>().apply { buildInlineTags(module, holder, root, this) }
147 
buildInlineTagsnull148 private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, nodes: List<ContentNode>, result: MutableList<Tag>) {
149     nodes.forEach {
150         buildInlineTags(module, holder, it, result)
151     }
152 }
153 
154 
buildInlineTagsnull155 private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, node: ContentNode, result: MutableList<Tag>) {
156     fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentBlock, result: MutableList<Tag>) {
157         if (node.children.isNotEmpty()) {
158             val open = TextTag(holder, ContentText(prefix))
159             val close = TextTag(holder, ContentText(postfix))
160 
161             result.add(open)
162             buildInlineTags(module, holder, node.children, result)
163 
164             if (result.last() === open) {
165                 result.removeAt(result.lastIndex)
166             } else {
167                 result.add(close)
168             }
169         }
170     }
171 
172     fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentNode, result: MutableList<Tag>) {
173         if (node !is ContentEmpty) {
174             val open = TextTag(holder, ContentText(prefix))
175             val close = TextTag(holder, ContentText(postfix))
176 
177             result.add(open)
178             buildInlineTags(module, holder, node, result)
179             if (result.last() === open) {
180                 result.removeAt(result.lastIndex)
181             } else {
182                 result.add(close)
183             }
184         }
185     }
186 
187     when (node) {
188         is ContentText -> result.add(TextTag(holder, node))
189         is ContentNodeLink -> {
190             val target = node.node
191             when (target?.kind) {
192                 NodeKind.Function -> result.add(SeeMethodTagAdapter(holder, MethodAdapter(module, node.node!!), node))
193 
194                 in NodeKind.classLike -> result.add(SeeClassTagAdapter(holder, ClassDocumentationNodeAdapter(module, node.node!!), node))
195 
196                 else -> buildInlineTags(module, holder, node.children, result)
197             }
198         }
199         is ContentExternalLink -> result.add(SeeExternalLinkTagAdapter(holder, node))
200         is ContentSpecialReference -> surroundWith(module, holder, "<aside class=\"note\">", "</aside>", node, result)
201         is ContentCode -> surroundWith(module, holder, "<code>", "</code>", node, result)
202         is ContentBlockCode -> surroundWith(module, holder, "<code><pre>", "</pre></code>", node, result)
203         is ContentEmpty -> {}
204         is ContentEmphasis -> surroundWith(module, holder, "<em>", "</em>", node, result)
205         is ContentHeading -> surroundWith(module, holder, "<h${node.level}>", "</h${node.level}>", node, result)
206         is ContentEntity -> result.add(TextTag(holder, ContentText(node.text))) // TODO ??
207         is ContentIdentifier -> result.add(TextTag(holder, ContentText(node.text))) // TODO
208         is ContentKeyword -> result.add(TextTag(holder, ContentText(node.text))) // TODO
209         is ContentListItem ->  surroundWith(module, holder, "<li>", "</li>", node, result)
210         is ContentOrderedList -> surroundWith(module, holder, "<ol>", "</ol>", node, result)
211         is ContentUnorderedList -> surroundWith(module, holder, "<ul>", "</ul>", node, result)
212         is ContentParagraph -> surroundWith(module, holder, "<p>", "</p>", node, result)
213 
214         is ContentDescriptionList -> surroundWith(module, holder, "<dl>", "</dl>", node, result)
215         is ContentDescriptionTerm -> surroundWith(module, holder, "<dt>", "</dt>", node, result)
216         is ContentDescriptionDefinition -> surroundWith(module, holder, "<dd>", "</dd>", node, result)
217 
218         is ContentTable -> surroundWith(module, holder, "<table>", "</table>", node, result)
219         is ContentTableBody -> surroundWith(module, holder, "<tbody>", "</tbody>", node, result)
220         is ContentTableRow -> surroundWith(module, holder, "<tr>", "</tr>", node, result)
221         is ContentTableHeader -> surroundWith(module, holder, "<th>", "</th>", node, result)
222         is ContentTableCell -> surroundWith(module, holder, "<td>", "</td>", node, result)
223 
224         is ContentSection -> surroundWith(module, holder, "<p>", "</p>", node, result) // TODO how section should be represented?
225         is ContentNonBreakingSpace -> result.add(TextTag(holder, ContentText("&nbsp;")))
226         is ContentStrikethrough -> surroundWith(module, holder, "<strike>", "</strike>", node, result)
227         is ContentStrong -> surroundWith(module, holder, "<strong>", "</strong>", node, result)
228         is ContentSymbol -> result.add(TextTag(holder, ContentText(node.text))) // TODO?
229         is Content -> {
230             surroundWith(module, holder, "<p>", "</p>", node.summary, result)
231             surroundWith(module, holder, "<p>", "</p>", node.description, result)
232         }
233         is ContentBlock -> {
234             surroundWith(module, holder, "", "", node, result)
235         }
236         is ContentHardLineBreak -> result.add(TextTag(holder, ContentText("<br/>")))
237 
238         else -> result.add(TextTag(holder, ContentText("$node")))
239     }
240 }