diff options
| -rw-r--r-- | core/src/main/kotlin/Model/Content.kt | 4 | ||||
| -rw-r--r-- | core/src/main/kotlin/javadoc/docbase.kt | 50 | ||||
| -rw-r--r-- | core/src/main/kotlin/javadoc/tags.kt | 29 | ||||
| -rw-r--r-- | core/src/test/kotlin/javadoc/JavadocTest.kt | 8 | ||||
| -rw-r--r-- | core/testdata/javadoc/kdocKeywordsOnMethod.kt | 12 | 
5 files changed, 78 insertions, 25 deletions
diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 0a38a524..1a8bc5d2 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -131,6 +131,8 @@ class ContentSection(val tag: String, val subjectName: String?) : ContentBlock()  object ContentTags {      val Description = "Description"      val SeeAlso = "See Also" +    val Return = "Return" +    val Exceptions = "Exceptions"  }  fun content(body: ContentBlock.() -> Unit): ContentBlock { @@ -236,6 +238,6 @@ open class MutableContent() : Content() {  fun javadocSectionDisplayName(sectionName: String?): String? =          when(sectionName) {              "param" -> "Parameters" -            "throws", "exception" -> "Exceptions" +            "throws", "exception" -> ContentTags.Exceptions              else -> sectionName?.capitalize()          } diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index 20d74088..eafa216b 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 @@ -305,20 +309,16 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio      override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO      override fun throwsTags(): Array<out ThrowsTag> =              node.content.sections -                    .filter { it.tag == "Exceptions" } -                    .map { it.subjectName } -                    .filterNotNull() -                    .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it, NodeKind.Exception))) } +                    .filter { it.tag == ContentTags.Exceptions && it.subjectName != null } +                    .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }                      .toTypedArray()      override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).any { false } // TODO      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> = +            collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })      override fun thrownExceptionTypes(): Array<out Type> = emptyArray()      override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) } @@ -332,9 +332,8 @@ 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> = +            collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })      private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->          when { @@ -365,6 +364,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 +426,8 @@ 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> = +            collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })      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() @@ -503,3 +510,14 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR      override fun specifiedClasses(): Array<out ClassDoc> = classes()  } + +private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFilter: (ContentSection) -> Boolean) = +        (node.details(kind) +                .filter(DocumentationNode::hasNonEmptyContent) +                .map { ParamTagAdapter(module, this, it.name, true, it.content.children) } + +                + node.content.sections +                .filter(sectionFilter) +                .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }) + +                .toTypedArray()
\ No newline at end of file diff --git a/core/src/main/kotlin/javadoc/tags.kt b/core/src/main/kotlin/javadoc/tags.kt index aab5ecf1..9e023a81 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 @@ -114,23 +114,36 @@ class ParamTagAdapter(val module: ModuleNodeAdapter,  } -class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter) : ThrowsTag { +class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter, val content: List<ContentNode>) : ThrowsTag {      override fun name(): String = "@throws"      override fun kind(): String = name()      override fun holder(): Doc = holder      override fun position(): SourcePosition? = holder.position() -    override fun text(): String = "@throws ${type.qualifiedTypeName()}" -    override fun inlineTags(): Array<out Tag> = emptyArray() +    override fun text(): String = "${name()} ${exceptionName()} ${exceptionComment()}" +    override fun inlineTags(): Array<out Tag> = buildInlineTags(type.module, holder, content).toTypedArray()      override fun firstSentenceTags(): Array<out Tag> = emptyArray() -    override fun exceptionComment(): String = "" +    override fun exceptionComment(): String = content.toString()      override fun exceptionType(): Type = type      override fun exception(): ClassDoc = type -    override fun exceptionName(): String = type.qualifiedName() +    override fun exceptionName(): String = type.qualifiedTypeName()  } -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..f7f86881 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -123,6 +123,14 @@ 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()) +            assertEquals("@throws FireException [ContentText(text=in case of fire)]", method.throwsTags().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..df5bbbe0 --- /dev/null +++ b/core/testdata/javadoc/kdocKeywordsOnMethod.kt @@ -0,0 +1,12 @@ +class FireException : Exception + + +/** + * COMM + * @param a Some string + * @return value of a + * @throws FireException in case of fire + */ +@Throws(FireException::class) +fun my(a: String): String = a +  | 
