aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Jemerov <yole@jetbrains.com>2015-10-30 19:33:29 +0100
committerDmitry Jemerov <yole@jetbrains.com>2015-10-30 19:33:29 +0100
commitded569657d1f16905180313593336963c467f242 (patch)
treeb25ff8eab14b565e6eb03b959c76e3a5601cd565
parente4b2ae90bf0e84f76ceb7c56b7c128d28adad917 (diff)
downloaddokka-ded569657d1f16905180313593336963c467f242.tar.gz
dokka-ded569657d1f16905180313593336963c467f242.tar.bz2
dokka-ded569657d1f16905180313593336963c467f242.zip
load KDoc comments when building javadoc
-rw-r--r--src/Java/JavaDocumentationBuilder.kt103
-rw-r--r--src/Kotlin/DocumentationBuilder.kt13
-rw-r--r--src/Kotlin/KotlinAsJavaDocumentationBuilder.kt37
-rw-r--r--test/src/TestAPI.kt1
-rw-r--r--test/src/model/KotlinAsJavaTest.kt9
5 files changed, 103 insertions, 60 deletions
diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt
index 660ac4a8..e0cc53a0 100644
--- a/src/Java/JavaDocumentationBuilder.kt
+++ b/src/Java/JavaDocumentationBuilder.kt
@@ -1,31 +1,30 @@
package org.jetbrains.dokka
import com.intellij.psi.*
-import com.intellij.psi.javadoc.*
+import com.intellij.psi.javadoc.PsiDocTag
+import com.intellij.psi.javadoc.PsiDocTagValue
+import com.intellij.psi.javadoc.PsiDocToken
+import com.intellij.psi.javadoc.PsiInlineDocTag
import org.jetbrains.dokka.DocumentationNode.Kind
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.nodes.Node
import org.jsoup.nodes.TextNode
-public class JavaDocumentationBuilder(private val options: DocumentationOptions,
- private val refGraph: NodeReferenceGraph) {
- fun appendFile(file: PsiJavaFile, module: DocumentationModule) {
- if (file.classes.all { skipElement(it) }) {
- return
- }
- val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap())
- appendClasses(packageNode, file.classes)
- }
-
- fun appendClasses(packageNode: DocumentationNode, classes: Array<PsiClass>) {
- packageNode.appendChildren(classes) { build() }
+data class JavadocParseResult(val content: Content, val deprecatedContent: Content?) {
+ companion object {
+ val Empty = JavadocParseResult(Content.Empty, null)
}
+}
- data class JavadocParseResult(val content: Content, val deprecatedContent: Content?)
+interface JavaDocumentationParser {
+ fun parseDocumentation(element: PsiNamedElement): JavadocParseResult
+}
- fun parseDocumentation(docComment: PsiDocComment?): JavadocParseResult {
- if (docComment == null) return JavadocParseResult(Content.Empty, null)
+class JavadocParser(private val refGraph: NodeReferenceGraph) : JavaDocumentationParser {
+ override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult {
+ val docComment = (element as? PsiDocCommentOwner)?.docComment
+ if (docComment == null) return JavadocParseResult.Empty
val result = MutableContent()
var deprecatedContent: Content? = null
val para = ContentParagraph()
@@ -169,6 +168,49 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions,
}
return null
}
+}
+
+
+private fun getSignature(element: PsiElement?) = when(element) {
+ is PsiClass -> element.qualifiedName
+ is PsiField -> element.containingClass!!.qualifiedName + "#" + element.name
+ is PsiMethod ->
+ element.containingClass!!.qualifiedName + "#" + element.name + "(" +
+ element.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")"
+ else -> null
+}
+
+private fun PsiType.typeSignature(): String = when(this) {
+ is PsiArrayType -> "Array<${componentType.typeSignature()}>"
+ else -> mapTypeName(this)
+}
+
+private fun mapTypeName(psiType: PsiType): String = when (psiType) {
+ PsiType.VOID -> "Unit"
+ is PsiPrimitiveType -> psiType.canonicalText.capitalize()
+ is PsiClassType -> {
+ val psiClass = psiType.resolve()
+ if (psiClass?.qualifiedName == "java.lang.Object") "Any" else psiType.className
+ }
+ is PsiEllipsisType -> mapTypeName(psiType.componentType)
+ is PsiArrayType -> "Array"
+ else -> psiType.canonicalText
+}
+
+class JavaDocumentationBuilder(private val options: DocumentationOptions,
+ private val refGraph: NodeReferenceGraph,
+ private val docParser: JavaDocumentationParser = JavadocParser(refGraph)) {
+ fun appendFile(file: PsiJavaFile, module: DocumentationModule) {
+ if (file.classes.all { skipElement(it) }) {
+ return
+ }
+ val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap())
+ appendClasses(packageNode, file.classes)
+ }
+
+ fun appendClasses(packageNode: DocumentationNode, classes: Array<PsiClass>) {
+ packageNode.appendChildren(classes) { build() }
+ }
fun register(element: PsiElement, node: DocumentationNode) {
val signature = getSignature(element)
@@ -190,25 +232,10 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions,
refGraph.link(qualifiedName, node, kind)
}
}
-
- private fun getSignature(element: PsiElement?) = when(element) {
- is PsiClass -> element.qualifiedName
- is PsiField -> element.containingClass!!.qualifiedName + "#" + element.name
- is PsiMethod ->
- element.containingClass!!.qualifiedName + "#" + element.name + "(" +
- element.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")"
- else -> null
- }
-
- private fun PsiType.typeSignature(): String = when(this) {
- is PsiArrayType -> "Array<${componentType.typeSignature()}>"
- else -> mapTypeName(this)
- }
-
fun DocumentationNode(element: PsiNamedElement,
kind: Kind,
name: String = element.name ?: "<anonymous>"): DocumentationNode {
- val (docComment, deprecatedContent) = parseDocumentation((element as? PsiDocCommentOwner)?.docComment)
+ val (docComment, deprecatedContent) = docParser.parseDocumentation(element)
val node = DocumentationNode(name, docComment, kind)
if (element is PsiModifierListOwner) {
node.appendModifiers(element)
@@ -378,18 +405,6 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions,
return node
}
- private fun mapTypeName(psiType: PsiType): String = when (psiType) {
- PsiType.VOID -> "Unit"
- is PsiPrimitiveType -> psiType.canonicalText.capitalize()
- is PsiClassType -> {
- val psiClass = psiType.resolve()
- if (psiClass?.qualifiedName == "java.lang.Object") "Any" else psiType.className
- }
- is PsiEllipsisType -> mapTypeName(psiType.componentType)
- is PsiArrayType -> "Array"
- else -> psiType.canonicalText
- }
-
fun PsiAnnotation.build(): DocumentationNode {
val node = DocumentationNode(nameReferenceElement?.text ?: "<?>", Content.Empty, DocumentationNode.Kind.Annotation)
parameterList.attributes.forEach {
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt
index 375ca4bd..b5b079de 100644
--- a/src/Kotlin/DocumentationBuilder.kt
+++ b/src/Kotlin/DocumentationBuilder.kt
@@ -45,11 +45,10 @@ private fun isSamePackage(descriptor1: DeclarationDescriptor, descriptor2: Decla
}
interface PackageDocumentationBuilder {
- fun buildPackageDocumentation(project: Project,
+ fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
packageName: FqName,
packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger)
+ declarations: List<DeclarationDescriptor>)
}
class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
@@ -426,7 +425,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
if (options.skipEmptyPackages && declarations.none { it.isDocumented() }) continue
logger.info(" package $packageName: ${declarations.count()} declarations")
val packageNode = findOrCreatePackageNode(packageName.asString(), packageContent)
- packageDocumentationBuilder.buildPackageDocumentation(resolutionFacade.project, packageName, packageNode, declarations, options, refGraph, logger)
+ packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, declarations)
}
}
@@ -666,12 +665,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
}
inner class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
- override fun buildPackageDocumentation(project: Project,
+ override fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
packageName: FqName,
packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- options: DocumentationOptions,
- refGraph: NodeReferenceGraph, logger: DokkaLogger) {
+ declarations: List<DeclarationDescriptor>) {
val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
declarations.forEach { descriptor ->
if (descriptor.isDocumented()) {
diff --git a/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt
index ae295769..a32e9a1f 100644
--- a/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt
+++ b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt
@@ -1,27 +1,48 @@
package org.jetbrains.dokka
-import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.asJava.KotlinLightElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
class KotlinAsJavaDocumentationBuilder() : PackageDocumentationBuilder {
- override fun buildPackageDocumentation(project: Project,
+ override fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
packageName: FqName,
packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- options: DocumentationOptions,
- refGraph: NodeReferenceGraph,
- logger: DokkaLogger) {
+ declarations: List<DeclarationDescriptor>) {
+ val project = documentationBuilder.resolutionFacade.project
val psiPackage = JavaPsiFacade.getInstance(project).findPackage(packageName.asString())
if (psiPackage == null) {
- logger.error("Cannot find Java package by qualified name: ${packageName.asString()}")
+ documentationBuilder.logger.error("Cannot find Java package by qualified name: ${packageName.asString()}")
return
}
- val javaDocumentationBuilder = JavaDocumentationBuilder(options, refGraph)
+
+ val javaDocumentationBuilder = JavaDocumentationBuilder(documentationBuilder.options,
+ documentationBuilder.refGraph,
+ KotlinAsJavaDocumentationParser(documentationBuilder))
+
psiPackage.classes.filter { it is KotlinLightElement<*, *> }.forEach {
javaDocumentationBuilder.appendClasses(packageNode, arrayOf(it))
}
}
}
+
+class KotlinAsJavaDocumentationParser(val documentationBuilder: DocumentationBuilder) : JavaDocumentationParser {
+ override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult {
+ val kotlinLightElement = element as? KotlinLightElement<*, *> ?: return JavadocParseResult.Empty
+ val origin = kotlinLightElement.getOrigin() ?: return JavadocParseResult.Empty
+ if (origin is KtParameter) {
+ // LazyDeclarationResolver does not support setter parameters
+ val grandFather = origin.parent?.parent
+ if (grandFather is KtPropertyAccessor) {
+ return JavadocParseResult.Empty
+ }
+ }
+ val descriptor = documentationBuilder.session.resolveToDescriptor(origin)
+ val content = documentationBuilder.parseDocumentation(descriptor)
+ return JavadocParseResult(content, null)
+ }
+}
diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt
index c4be6623..4a0e4fb4 100644
--- a/test/src/TestAPI.kt
+++ b/test/src/TestAPI.kt
@@ -133,6 +133,7 @@ fun StringBuilder.appendNode(node: ContentNode): StringBuilder {
is ContentBlock -> {
appendChildren(node)
}
+ is ContentEmpty -> { /* nothing */ }
else -> throw IllegalStateException("Don't know how to format node $node")
}
return this
diff --git a/test/src/model/KotlinAsJavaTest.kt b/test/src/model/KotlinAsJavaTest.kt
index 25ee5fad..0b609a2b 100644
--- a/test/src/model/KotlinAsJavaTest.kt
+++ b/test/src/model/KotlinAsJavaTest.kt
@@ -19,6 +19,15 @@ class KotlinAsJavaTest {
assertEquals(DocumentationNode.Kind.CompanionObjectFunction, fn.kind)
}
}
+
+ @Test fun propertyWithComment() {
+ verifyModelAsJava("test/data/comments/oneLineDoc.kt") { model ->
+ val facadeClass = model.members.single().members.single { it.name == "OneLineDocKt" }
+ val getter = facadeClass.members.single { it.name == "getProperty" }
+ assertEquals(DocumentationNode.Kind.CompanionObjectFunction, getter.kind)
+ assertEquals("doc", getter.content.summary.toTestString())
+ }
+ }
}
fun verifyModelAsJava(source: String,