From 499d082186fcda877a216d536cf9512d0f0265ac Mon Sep 17 00:00:00 2001 From: Ilya Ryzhenkov Date: Tue, 15 Jul 2014 16:18:53 +0400 Subject: Cleaning, generalizing, added outline support (hardcoded yml for now) --- src/Languages/JavaLanguageService.kt | 148 +++++++++++++++++++++++++++++ src/Languages/KotlinLanguageService.kt | 167 +++++++++++++++++++++++++++++++++ src/Languages/LanguageService.kt | 17 ++++ 3 files changed, 332 insertions(+) create mode 100644 src/Languages/JavaLanguageService.kt create mode 100644 src/Languages/KotlinLanguageService.kt create mode 100644 src/Languages/LanguageService.kt (limited to 'src/Languages') diff --git a/src/Languages/JavaLanguageService.kt b/src/Languages/JavaLanguageService.kt new file mode 100644 index 00000000..8cc185f4 --- /dev/null +++ b/src/Languages/JavaLanguageService.kt @@ -0,0 +1,148 @@ +package org.jetbrains.dokka + +import org.jetbrains.dokka.DocumentationNode.* + +class JavaLanguageService : LanguageService { + override fun render(node: DocumentationNode): String { + return when (node.kind) { + Kind.Package -> renderPackage(node) + Kind.Class, + Kind.Interface, + Kind.Enum, + Kind.EnumItem, + Kind.Object -> renderClass(node) + + Kind.TypeParameter -> renderTypeParameter(node) + Kind.Type, + Kind.UpperBound -> renderType(node) + + Kind.Constructor, + Kind.Function -> renderFunction(node) + Kind.Property -> renderProperty(node) + else -> "${node.kind}: ${node.name}" + } + } + + override fun renderName(node: DocumentationNode): String { + return when (node.kind) { + Kind.Constructor -> node.owner!!.name + else -> node.name + } + } + + override fun renderPackage(node: DocumentationNode): String { + return "package ${node.name}" + } + + override fun renderModifier(node: DocumentationNode): String { + return when (node.name) { + "open" -> "" + "internal" -> "" + else -> node.name + } + } + + override fun renderType(node: DocumentationNode): String { + return when (node.name) { + "Unit" -> "void" + "Int" -> "int" + "Long" -> "long" + "Double" -> "double" + "Float" -> "float" + "Char" -> "char" + "Boolean" -> "bool" + // TODO: render arrays + else -> node.name + } + } + + override fun renderTypeParameter(node: DocumentationNode): String { + val constraints = node.details(Kind.UpperBound) + return if (constraints.none()) + node.name + else { + node.name + " extends " + constraints.map { renderType(node) }.join() + } + } + + override fun renderParameter(node: DocumentationNode): String { + return "${renderType(node.detail(Kind.Type))} ${node.name}" + } + + override fun renderTypeParametersForNode(node: DocumentationNode): String { + return StringBuilder { + val typeParameters = node.details(Kind.TypeParameter) + if (typeParameters.any()) { + append("<") + append(typeParameters.map { renderTypeParameter(it) }.join()) + append("> ") + } + }.toString() + } + + override fun renderModifiersForNode(node: DocumentationNode): String { + val modifiers = node.details(Kind.Modifier).map { renderModifier(it) }.filter { it != "" } + if (modifiers.none()) + return "" + return modifiers.join(" ", postfix = " ") + } + + override fun renderClass(node: DocumentationNode): String { + return StringBuilder { + when (node.kind) { + Kind.Class -> append("class ") + Kind.Interface -> append("interface ") + Kind.Enum -> append("enum ") + Kind.EnumItem -> append("enum value ") + Kind.Object -> append("class ") + else -> throw IllegalArgumentException("Node $node is not a class-like object") + } + + append(node.name) + append(renderTypeParametersForNode(node)) + }.toString() + } + + override fun renderFunction(node: DocumentationNode): String { + return StringBuilder { + when (node.kind) { + Kind.Constructor -> append(node.owner?.name) + Kind.Function -> { + append(renderTypeParametersForNode(node)) + append(renderType(node.detail(Kind.Type))) + append(" ") + append(node.name) + } + else -> throw IllegalArgumentException("Node $node is not a function-like object") + } + + val receiver = node.details(Kind.Receiver).firstOrNull() // TODO: replace with singleOrNull when fixed + append("(") + if (receiver != null) + append((listOf(receiver) + node.details(Kind.Parameter)).map { renderParameter(it) }.join()) + else + append(node.details(Kind.Parameter).map { renderParameter(it) }.join()) + + append(")") + }.toString() + } + + override fun renderProperty(node: DocumentationNode): String { + return StringBuilder { + when (node.kind) { + Kind.Property -> append("val ") + else -> throw IllegalArgumentException("Node $node is not a property") + } + append(renderTypeParametersForNode(node)) + val receiver = node.details(Kind.Receiver).firstOrNull() // TODO: replace with singleOrNull when fixed + if (receiver != null) { + append(renderType(receiver.detail(Kind.Type))) + append(".") + } + + append(node.name) + append(": ") + append(renderType(node.detail(Kind.Type))) + }.toString() + } +} \ No newline at end of file diff --git a/src/Languages/KotlinLanguageService.kt b/src/Languages/KotlinLanguageService.kt new file mode 100644 index 00000000..7ae043b0 --- /dev/null +++ b/src/Languages/KotlinLanguageService.kt @@ -0,0 +1,167 @@ +package org.jetbrains.dokka + +import org.jetbrains.dokka.DocumentationNode.* + +class KotlinLanguageService : LanguageService { + override fun render(node: DocumentationNode): String { + return when (node.kind) { + Kind.Package -> renderPackage(node) + Kind.Class, + Kind.Interface, + Kind.Enum, + Kind.EnumItem, + Kind.Object -> renderClass(node) + + Kind.TypeParameter -> renderTypeParameter(node) + Kind.Type, + Kind.UpperBound -> renderType(node) + + Kind.Modifier -> renderModifier(node) + Kind.Constructor, + Kind.Function -> renderFunction(node) + Kind.Property -> renderProperty(node) + else -> "${node.kind}: ${node.name}" + } + } + + override fun renderName(node: DocumentationNode): String { + return when (node.kind) { + Kind.Constructor -> node.owner!!.name + else -> node.name + } + } + + override fun renderPackage(node: DocumentationNode): String { + return "package ${node.name}" + } + + override fun renderType(node: DocumentationNode): String { + val typeArguments = node.details(Kind.Type) + val renders = typeArguments.map { renderType(it) } + + if (node.name == "Function${typeArguments.count() - 1}") { + // lambda + return "(${renders.take(renders.size - 1).join()})->${renders.last()}" + } + if (node.name == "ExtensionFunction${typeArguments.count() - 2}") { + // extension lambda + return "${renders.first()}.(${renders.drop(1).take(renders.size - 2).join()})->${renders.last()}" + } + if (typeArguments.none()) + return node.name + return "${node.name}<${renders.join()}>" + } + + override fun renderModifier(node: DocumentationNode): String { + return when (node.name) { + "final" -> "" + "internal" -> "" + else -> node.name + } + } + + override fun renderTypeParameter(node: DocumentationNode): String { + val constraints = node.details(Kind.UpperBound) + return if (constraints.none()) + node.name + else { + node.name + " : " + constraints.map { renderType(node) }.join() + } + } + + override fun renderParameter(node: DocumentationNode): String { + return node.name + ": " + renderType(node.detail(Kind.Type)) + } + + override fun renderTypeParametersForNode(node: DocumentationNode): String { + return StringBuilder { + val typeParameters = node.details(Kind.TypeParameter) + if (typeParameters.any()) { + append("<") + append(typeParameters.map { renderTypeParameter(it) }.join()) + append("> ") + } + }.toString() + } + + override fun renderModifiersForNode(node: DocumentationNode): String { + val modifiers = node.details(Kind.Modifier).map { renderModifier(it) }.filter { it != "" } + if (modifiers.none()) + return "" + return modifiers.join(" ", postfix = " ") + } + + override fun renderClass(node: DocumentationNode): String { + return StringBuilder { + append(renderModifiersForNode(node)) + when (node.kind) { + Kind.Class -> append("class ") + Kind.Interface -> append("trait ") + Kind.Enum -> append("enum class ") + Kind.EnumItem -> append("enum val ") + Kind.Object -> append("object ") + else -> throw IllegalArgumentException("Node $node is not a class-like object") + } + + append(node.name) + append(renderTypeParametersForNode(node)) + + /* + val constructors = node.members(Kind.Constructor) + if (constructors.count() == 1) { + append("(") + append(constructors[0].details(Kind.Parameter).map { renderParameter(it) }.join()) + append(")") + } + */ + }.toString() + } + + override fun renderFunction(node: DocumentationNode): String { + return StringBuilder { + append(renderModifiersForNode(node)) + when (node.kind) { + Kind.Constructor -> append(node.owner!!.name) + Kind.Function -> append("fun ") + else -> throw IllegalArgumentException("Node $node is not a function-like object") + } + append(renderTypeParametersForNode(node)) + val receiver = node.details(Kind.Receiver).firstOrNull() // TODO: replace with singleOrNull when fixed + if (receiver != null) { + append(renderType(receiver.detail(Kind.Type))) + append(".") + } + + if (node.kind != Kind.Constructor) + append(node.name) + + append("(") + append(node.details(Kind.Parameter).map { renderParameter(it) }.join()) + append(")") + if (node.kind != Kind.Constructor) { + append(": ") + append(renderType(node.detail(Kind.Type))) + } + }.toString() + } + + override fun renderProperty(node: DocumentationNode): String { + return StringBuilder { + append(renderModifiersForNode(node)) + when (node.kind) { + Kind.Property -> append("val ") + else -> throw IllegalArgumentException("Node $node is not a property") + } + append(renderTypeParametersForNode(node)) + val receiver = node.details(Kind.Receiver).firstOrNull() // TODO: replace with singleOrNull when fixed + if (receiver != null) { + append(renderType(receiver.detail(Kind.Type))) + append(".") + } + + append(node.name) + append(": ") + append(renderType(node.detail(Kind.Type))) + }.toString() + } +} \ No newline at end of file diff --git a/src/Languages/LanguageService.kt b/src/Languages/LanguageService.kt new file mode 100644 index 00000000..728503b0 --- /dev/null +++ b/src/Languages/LanguageService.kt @@ -0,0 +1,17 @@ +package org.jetbrains.dokka + +trait LanguageService { + fun render(node: DocumentationNode): String + fun renderName(node: DocumentationNode): String + fun renderFunction(node: DocumentationNode): String + fun renderClass(node: DocumentationNode): String + fun renderTypeParametersForNode(node: DocumentationNode): String + fun renderTypeParameter(node: DocumentationNode): String + fun renderParameter(node: DocumentationNode): String + fun renderType(node: DocumentationNode): String + fun renderPackage(node: DocumentationNode): String + fun renderProperty(node: DocumentationNode): String + fun renderModifier(node: DocumentationNode): String + fun renderModifiersForNode(node: DocumentationNode): String +} + -- cgit