aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2016-11-28 21:42:39 +0300
committerSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2016-11-28 21:42:39 +0300
commit5ab32ba0dd61585459bb32bb31fe7b19493c980e (patch)
tree3fecb7ad3d94a20f05cfcaf5006bbe9a58906fb8 /core
parente9cf2d779c03e278ddfd5adb0d1c743961d8d07a (diff)
downloaddokka-5ab32ba0dd61585459bb32bb31fe7b19493c980e.tar.gz
dokka-5ab32ba0dd61585459bb32bb31fe7b19493c980e.tar.bz2
dokka-5ab32ba0dd61585459bb32bb31fe7b19493c980e.zip
Fix for GH-115, `@param` and `@return` tags is missing in javadoc output
Diffstat (limited to 'core')
-rw-r--r--core/src/main/kotlin/Model/Content.kt1
-rw-r--r--core/src/main/kotlin/javadoc/docbase.kt54
-rw-r--r--core/src/main/kotlin/javadoc/tags.kt19
-rw-r--r--core/src/test/kotlin/javadoc/JavadocTest.kt7
-rw-r--r--core/testdata/javadoc/kdocKeywordsOnMethod.kt7
5 files changed, 73 insertions, 15 deletions
diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt
index 0a38a524..7464d510 100644
--- a/core/src/main/kotlin/Model/Content.kt
+++ b/core/src/main/kotlin/Model/Content.kt
@@ -131,6 +131,7 @@ class ContentSection(val tag: String, val subjectName: String?) : ContentBlock()
object ContentTags {
val Description = "Description"
val SeeAlso = "See Also"
+ val Return = "Return"
}
fun content(body: ContentBlock.() -> Unit): ContentBlock {
diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt
index 20d74088..b125a7d4 100644
--- a/core/src/main/kotlin/javadoc/docbase.kt
+++ b/core/src/main/kotlin/javadoc/docbase.kt
@@ -297,6 +297,10 @@ fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode
node
}
+private fun DocumentationNode.hasNonEmptyContent() =
+ this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
+
+
open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), ExecutableMemberDoc {
override fun isSynthetic(): Boolean = false
@@ -315,10 +319,15 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }
- override fun paramTags(): Array<out ParamTag> = node.details(NodeKind.Parameter)
- .filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }
- .map { ParamTagAdapter(module, this, it.name, false, it.content.children) }
- .toTypedArray()
+ override fun paramTags(): Array<out ParamTag> =
+ (node.details(NodeKind.Parameter)
+ .filter(DocumentationNode::hasNonEmptyContent)
+ .map { ParamTagAdapter(module, this, it.name, false, it.content.children) }
+
+ + node.content.sections
+ .filter { it.subjectName in parameters().map { it.name() } }
+ .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }
+ ).toTypedArray()
override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
@@ -332,9 +341,15 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
- override fun typeParamTags(): Array<out ParamTag> = node.details(NodeKind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map {
- ParamTagAdapter(module, this, it.name, true, it.content.children)
- }.toTypedArray()
+ override fun typeParamTags(): Array<out ParamTag> =
+ (node.details(NodeKind.TypeParameter)
+ .filter(DocumentationNode::hasNonEmptyContent)
+ .map { ParamTagAdapter(module, this, it.name, true, it.content.children) }
+
+ + node.content.sections
+ .filter { it.subjectName in typeParameters().map { it.simpleTypeName() } }
+ .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }
+ ).toTypedArray()
private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
when {
@@ -365,6 +380,17 @@ class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : Docume
override fun isDefault(): Boolean = false
override fun returnType(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
+
+ override fun tags(tagname: String?) = super.tags(tagname)
+
+ override fun tags(): Array<out Tag> {
+ val tags = super.tags().toMutableList()
+ node.content.findSectionByTag(ContentTags.Return)?.let {
+ tags += ReturnTagAdapter(module, this, it.children)
+ }
+
+ return tags.toTypedArray()
+ }
}
class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), FieldDoc {
@@ -416,11 +442,15 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod
.map { ClassDocumentationNodeAdapter(module, it) }
.toTypedArray()
- override fun typeParamTags(): Array<out ParamTag> = (classNode.details(NodeKind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map {
- ParamTagAdapter(module, this, it.name, true, it.content.children)
- } + classNode.content.sections.filter { it.subjectName in typeParameters().map { it.simpleTypeName() } }.map {
- ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children)
- }).toTypedArray()
+ override fun typeParamTags(): Array<out ParamTag> =
+ (classNode.details(NodeKind.TypeParameter)
+ .filter(DocumentationNode::hasNonEmptyContent)
+ .map { ParamTagAdapter(module, this, it.name, true, it.content.children) }
+
+ + classNode.content.sections
+ .filter { it.subjectName in typeParameters().map { it.simpleTypeName() } }
+ .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }
+ ).toTypedArray()
override fun fields(): Array<out FieldDoc> = fields(true)
override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()
diff --git a/core/src/main/kotlin/javadoc/tags.kt b/core/src/main/kotlin/javadoc/tags.kt
index aab5ecf1..5ee2cbac 100644
--- a/core/src/main/kotlin/javadoc/tags.kt
+++ b/core/src/main/kotlin/javadoc/tags.kt
@@ -104,8 +104,8 @@ class ParamTagAdapter(val module: ModuleNodeAdapter,
override fun holder(): Doc = holder
override fun position(): SourcePosition? = holder.position()
- override fun text(): String = "@param $parameterName ..."
- override fun inlineTags(): Array<out Tag> = content.flatMap { buildInlineTags(module, holder, it) }.toTypedArray()
+ override fun text(): String = "@param $parameterName ${parameterComment()}" // Seems has no effect, so used for debug
+ override fun inlineTags(): Array<out Tag> = buildInlineTags(module, holder, content).toTypedArray()
override fun firstSentenceTags(): Array<out Tag> = arrayOf(TextTag(holder, ContentText(text())))
override fun isTypeParameter(): Boolean = typeParameter
@@ -130,7 +130,20 @@ class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter)
override fun exceptionName(): String = type.qualifiedName()
}
-fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List<Tag> = ArrayList<Tag>().let { buildInlineTags(module, holder, root, it); it }
+class ReturnTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val content: List<ContentNode>) : Tag {
+ override fun name(): String = "@return"
+ override fun kind() = name()
+ override fun holder() = holder
+ override fun position(): SourcePosition? = holder.position()
+
+ override fun text(): String = "@return $content" // Seems has no effect, so used for debug
+ override fun inlineTags(): Array<Tag> = buildInlineTags(module, holder, content).toTypedArray()
+ override fun firstSentenceTags(): Array<Tag> = inlineTags()
+}
+
+fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, tags: List<ContentNode>): List<Tag> = ArrayList<Tag>().apply { tags.forEach { buildInlineTags(module, holder, it, this) } }
+
+fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List<Tag> = ArrayList<Tag>().apply { buildInlineTags(module, holder, root, this) }
private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, nodes: List<ContentNode>, result: MutableList<Tag>) {
nodes.forEach {
diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt
index 4c0f7f0f..f60c49fd 100644
--- a/core/src/test/kotlin/javadoc/JavadocTest.kt
+++ b/core/src/test/kotlin/javadoc/JavadocTest.kt
@@ -123,6 +123,13 @@ class JavadocTest {
}
}
+ @Test fun testKDocKeywordsOnMethod() {
+ verifyJavadoc("testdata/javadoc/kdocKeywordsOnMethod.kt", withKotlinRuntime = true) { doc ->
+ val method = doc.classNamed("KdocKeywordsOnMethodKt")!!.methods()[0]
+ assertEquals("@return [ContentText(text=value of a)]", method.tags("return").first().text())
+ assertEquals("@param a [ContentText(text=Some string)]", method.paramTags().first().text())
+ }
+ }
private fun verifyJavadoc(name: String,
withJdk: Boolean = false,
diff --git a/core/testdata/javadoc/kdocKeywordsOnMethod.kt b/core/testdata/javadoc/kdocKeywordsOnMethod.kt
new file mode 100644
index 00000000..63bbaba4
--- /dev/null
+++ b/core/testdata/javadoc/kdocKeywordsOnMethod.kt
@@ -0,0 +1,7 @@
+/**
+ * COMM
+ * @param a Some string
+ * @return value of a
+ */
+fun my(a: String): String = a
+