diff options
-rw-r--r-- | src/Java/JavaDocumentationBuilder.kt | 85 | ||||
-rw-r--r-- | src/main.kt | 60 | ||||
-rw-r--r-- | test/data/java/member.java | 2 | ||||
-rw-r--r-- | test/src/model/JavaTest.kt | 28 |
4 files changed, 149 insertions, 26 deletions
diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt new file mode 100644 index 00000000..c9379386 --- /dev/null +++ b/src/Java/JavaDocumentationBuilder.kt @@ -0,0 +1,85 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.PsiClass +import org.jetbrains.dokka.DocumentationNode.Kind +import com.intellij.psi.PsiMethod +import com.intellij.psi.javadoc.PsiDocComment +import com.intellij.psi.PsiType +import com.intellij.psi.PsiParameter +import com.intellij.psi.PsiNamedElement +import com.intellij.psi.PsiDocCommentOwner +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiPrimitiveType + +public class JavaDocumentationBuilder() { + fun appendFile(file: PsiJavaFile, module: DocumentationModule) { + val packageNode = module.findOrCreatePackageNode(file.getPackageName()) + packageNode.appendChildren(file.getClasses()) { build() } + } + + fun parseDocumentation(docComment: PsiDocComment?): Content { + if (docComment == null) return Content.Empty + val result = Content() + docComment.getDescriptionElements().dropWhile { it.getText().trim().isEmpty() }.forEach { + val text = if (result.isEmpty()) it.getText().trimLeading() else it.getText() + result.append(ContentText(text)) + } + return result + } + + fun DocumentationNode(element: PsiNamedElement, kind: Kind): DocumentationNode { + val docComment = if (element is PsiDocCommentOwner) parseDocumentation(element.getDocComment()) else Content.Empty + val node = DocumentationNode(element.getName() ?: "<anonymous>", docComment, kind) + return node + } + + fun DocumentationNode.appendChildren<T>(elements: Array<T>, + kind: DocumentationReference.Kind = DocumentationReference.Kind.Member, + buildFn: T.() -> DocumentationNode) { + elements.forEach { + append(it.buildFn(), kind) + } + } + + fun PsiClass.build(): DocumentationNode { + val kind = when { + isInterface() -> DocumentationNode.Kind.Interface + isEnum() -> DocumentationNode.Kind.Enum + isAnnotationType() -> DocumentationNode.Kind.AnnotationClass + else -> DocumentationNode.Kind.Class + } + val node = DocumentationNode(this, kind) + node.appendChildren(getMethods()) { build() } + return node + } + + fun PsiMethod.build(): DocumentationNode { + val node = DocumentationNode(this, Kind.Function) + node.appendType(getReturnType()) + node.appendChildren(getParameterList().getParameters(), DocumentationReference.Kind.Detail) { build() } + return node + } + + fun PsiParameter.build(): DocumentationNode { + val node = DocumentationNode(this, Kind.Parameter) + node.appendType(getType()) + return node + } + + fun DocumentationNode.appendType(psiType: PsiType?, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type) { + if (psiType == null) { + return + } + val name = mapTypeName(psiType) + val node = DocumentationNode(name, Content.Empty, kind) + append(node, DocumentationReference.Kind.Detail) + } + + private fun mapTypeName(psiType: PsiType): String = when (psiType) { + PsiType.VOID -> "Unit" + is PsiPrimitiveType -> psiType.getCanonicalText().capitalize() + is PsiClassType -> psiType.getClassName() + else -> psiType.getCanonicalText() + } +} diff --git a/src/main.kt b/src/main.kt index 1c480f22..d5384ea0 100644 --- a/src/main.kt +++ b/src/main.kt @@ -7,6 +7,11 @@ import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.utils.PathUtil import java.io.File import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.cli.jvm.compiler.JetCoreEnvironment +import com.intellij.psi.PsiJavaFile +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import com.intellij.psi.PsiManager +import com.intellij.openapi.vfs.VirtualFileManager class DokkaArguments { Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)") @@ -190,29 +195,52 @@ fun buildDocumentationModule(environment: AnalysisEnvironment, val documentation = environment.withContext { environment, session -> val fragmentFiles = environment.getSourceFiles().filter(filesToDocumentFilter) val fragments = fragmentFiles.map { session.getPackageFragment(it.getPackageFqName()) }.filterNotNull().distinct() - val documentationBuilder = DocumentationBuilder(session, options, logger) - - with(documentationBuilder) { - val moduleContent = Content() - for (include in includes) { - val file = File(include) - if (file.exists()) { - val text = file.readText() - val tree = parseMarkdown(text) - val content = buildContent(tree) - moduleContent.children.addAll(content.children) - } else { - logger.warn("Include file $file was not found.") - } + val moduleContent = Content() + for (include in includes) { + val file = File(include) + if (file.exists()) { + val text = file.readText() + val tree = parseMarkdown(text) + val content = buildContent(tree) + moduleContent.children.addAll(content.children) + } else { + logger.warn("Include file $file was not found.") } + } + val documentationModule = DocumentationModule(moduleName, moduleContent) - val documentationModule = DocumentationModule(moduleName, moduleContent) + val documentationBuilder = DocumentationBuilder(session, options, logger) + with(documentationBuilder) { documentationModule.appendFragments(fragments) documentationBuilder.resolveReferences(documentationModule) - documentationModule } + + val javaFiles = environment.getJavaSourceFiles().filter(filesToDocumentFilter) + val javaDocumentationBuilder = JavaDocumentationBuilder() + javaFiles.map { javaDocumentationBuilder.appendFile(it, documentationModule) } + + documentationModule } return documentation } + + +fun JetCoreEnvironment.getJavaSourceFiles(): List<PsiJavaFile> { + val sourceRoots = getConfiguration().getList(CommonConfigurationKeys.SOURCE_ROOTS_KEY).map { File(it) } + val result = arrayListOf<PsiJavaFile>() + val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file") + sourceRoots.forEach { sourceRoot -> + sourceRoot.getAbsoluteFile().recurse { + val vFile = localFileSystem.findFileByPath(it.path) + if (vFile != null) { + val psiFile = PsiManager.getInstance(getProject()).findFile(vFile) + if (psiFile is PsiJavaFile) { + result.add(psiFile) + } + } + } + } + return result +} diff --git a/test/data/java/member.java b/test/data/java/member.java index 5eb9209f..cf978444 100644 --- a/test/data/java/member.java +++ b/test/data/java/member.java @@ -6,7 +6,7 @@ class Test { * @param name is String parameter * @param value is int parameter */ - public void Function(String name, int value) { + public void fn(String name, int value) { } }
\ No newline at end of file diff --git a/test/src/model/JavaTest.kt b/test/src/model/JavaTest.kt index e57be4a9..602e1382 100644 --- a/test/src/model/JavaTest.kt +++ b/test/src/model/JavaTest.kt @@ -5,19 +5,29 @@ import org.jetbrains.dokka.* import org.junit.* public class JavaTest { - Ignore Test fun function() { + Test fun function() { verifyModel("test/data/java/") { model -> val pkg = model.members.single() with(pkg.members.single()) { - assertEquals("fn", name) - assertEquals(DocumentationNode.Kind.Function, kind) - assertEquals("Function fn", content.summary) - assertEquals("Unit", detail(DocumentationNode.Kind.Type).name) - assertTrue(members.none()) - assertTrue(links.none()) + assertEquals("Test", name) + assertEquals(DocumentationNode.Kind.Class, kind) + with(members.single()) { + assertEquals("fn", name) + assertEquals(DocumentationNode.Kind.Function, kind) + assertEquals("Summary for Function", content.summary.toTestString()) + assertEquals("Unit", detail(DocumentationNode.Kind.Type).name) + assertTrue(members.none()) + assertTrue(links.none()) + with(details.first { it.name == "name" }) { + assertEquals(DocumentationNode.Kind.Parameter, kind) + assertEquals("String", detail(DocumentationNode.Kind.Type).name) + } + with(details.first { it.name == "value" }) { + assertEquals(DocumentationNode.Kind.Parameter, kind) + assertEquals("Int", detail(DocumentationNode.Kind.Type).name) + } + } } } } - } - |