diff options
author | Ilya Ryzhenkov <orangy@jetbrains.com> | 2014-10-12 23:25:12 +0400 |
---|---|---|
committer | Ilya Ryzhenkov <orangy@jetbrains.com> | 2014-10-12 23:25:12 +0400 |
commit | ba1f12daf927d95a0a8c24c9f3e4a07274451b32 (patch) | |
tree | 6cac677106bda18101ddd2266ac158bb5b802ed3 /src/Kotlin | |
parent | 471039eeb5c1aca11076a17814debce59ac12dcc (diff) | |
download | dokka-ba1f12daf927d95a0a8c24c9f3e4a07274451b32.tar.gz dokka-ba1f12daf927d95a0a8c24c9f3e4a07274451b32.tar.bz2 dokka-ba1f12daf927d95a0a8c24c9f3e4a07274451b32.zip |
Cleanup
Diffstat (limited to 'src/Kotlin')
-rw-r--r-- | src/Kotlin/DocumentationBuilder.kt | 24 | ||||
-rw-r--r-- | src/Kotlin/KotlinLanguageService.kt | 229 |
2 files changed, 242 insertions, 11 deletions
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index d8162c44..adb2b4c6 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName public data class DocumentationOptions(val includeNonPublic: Boolean = false) class DocumentationBuilder(val context: BindingContext, val options: DocumentationOptions) { + val visibleToDocumentation = setOf(Visibilities.INTERNAL, Visibilities.PROTECTED, Visibilities.PUBLIC) val descriptorToNode = hashMapOf<DeclarationDescriptor, DocumentationNode>() val nodeToDescriptor = hashMapOf<DocumentationNode, DeclarationDescriptor>() val links = hashMapOf<DocumentationNode, DeclarationDescriptor>() @@ -104,8 +105,6 @@ class DocumentationBuilder(val context: BindingContext, val options: Documentati node.appendProjection(typeArgument) } - val visibleToDocumentation = setOf(Visibilities.INTERNAL, Visibilities.PROTECTED, Visibilities.PUBLIC) - fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: DocumentationReference.Kind) { // do not include generated code if (descriptor is CallableMemberDescriptor && descriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) @@ -122,15 +121,19 @@ class DocumentationBuilder(val context: BindingContext, val options: Documentati descriptors.forEach { descriptor -> appendChild(descriptor, kind) } } + fun DocumentationNode.appendFile(sourceFile : JetFile) { + val fragment = context.getPackageFragment(sourceFile)!! + val packageNode = packages.getOrPut(fragment.fqName) { + val packageNode = DocumentationNode(fragment.fqName.asString(), Content.Empty, Kind.Package) + append(packageNode, DocumentationReference.Kind.Member) + packageNode + } + packageNode.appendChildren(fragment.getMemberScope().getAllDescriptors(), DocumentationReference.Kind.Member) + } + fun DocumentationNode.appendFiles(sourceFiles : List<JetFile>) { for (sourceFile in sourceFiles) { - val fragment = context.getPackageFragment(sourceFile)!! - val packageNode = packages.getOrPut(fragment.fqName) { - val packageNode = DocumentationNode(fragment.fqName.asString(), Content.Empty, Kind.Package) - append(packageNode, DocumentationReference.Kind.Member) - packageNode - } - packageNode.appendChildren(fragment.getMemberScope().getAllDescriptors(), DocumentationReference.Kind.Member) + appendFile(sourceFile) } } @@ -172,7 +175,6 @@ class DocumentationBuilder(val context: BindingContext, val options: Documentati return node } - fun ConstructorDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Constructor) node.appendChildren(getValueParameters(), DocumentationReference.Kind.Detail) @@ -244,7 +246,7 @@ class DocumentationBuilder(val context: BindingContext, val options: Documentati } fun ReceiverParameterDescriptor.build(): DocumentationNode { - val node = DocumentationNode(this, Kind.Receiver) + val node = DocumentationNode(getName().asString(), Content.Empty, Kind.Receiver) node.appendType(getType()) return node } diff --git a/src/Kotlin/KotlinLanguageService.kt b/src/Kotlin/KotlinLanguageService.kt new file mode 100644 index 00000000..80467914 --- /dev/null +++ b/src/Kotlin/KotlinLanguageService.kt @@ -0,0 +1,229 @@ +package org.jetbrains.dokka + +import org.jetbrains.dokka.symbol +import org.jetbrains.dokka.text +import org.jetbrains.dokka.identifier +import org.jetbrains.dokka.link +import org.jetbrains.dokka.keyword +import org.jetbrains.dokka.LanguageService +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.ContentNode +import org.jetbrains.dokka +import org.jetbrains.dokka.ContentText + +class KotlinLanguageService : LanguageService { + override fun render(node: DocumentationNode): ContentNode { + return dokka.content { + when (node.kind) { + DocumentationNode.Kind.Package -> renderPackage(node) + DocumentationNode.Kind.Class, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Enum, + DocumentationNode.Kind.EnumItem, + DocumentationNode.Kind.Object -> renderClass(node) + + DocumentationNode.Kind.TypeParameter -> renderTypeParameter(node) + DocumentationNode.Kind.Type, + DocumentationNode.Kind.UpperBound -> renderType(node) + + DocumentationNode.Kind.Modifier -> renderModifier(node) + DocumentationNode.Kind.Constructor, + DocumentationNode.Kind.Function -> renderFunction(node) + DocumentationNode.Kind.Property -> renderProperty(node) + else -> ContentText("${node.kind}: ${node.name}") + } + } + } + + override fun renderName(node: DocumentationNode): String { + return when (node.kind) { + DocumentationNode.Kind.Constructor -> node.owner!!.name + else -> node.name + } + } + + private fun ContentNode.renderPackage(node: DocumentationNode) { + keyword("package") + text(" ") + identifier(node.name) + } + + private fun ContentNode.renderList(nodes: List<DocumentationNode>, separator: String = ", ", renderItem: (DocumentationNode) -> Unit) { + if (nodes.none()) + return + renderItem(nodes.first()) + nodes.drop(1).forEach { + symbol(separator) + renderItem(it) + } + } + + private fun ContentNode.renderLinked(node: DocumentationNode, body: ContentNode.(DocumentationNode)->Unit) { + val to = node.links.firstOrNull() + if (to == null) + body(node) + else + link(to) { + body(node) + } + } + + private fun ContentNode.renderType(node: DocumentationNode) { + val typeArguments = node.details(DocumentationNode.Kind.Type) + if (node.name == "Function${typeArguments.count() - 1}") { + // lambda + symbol("(") + renderList(typeArguments.take(typeArguments.size - 1)) { + renderType(it) + } + symbol(")") + text(" ") + symbol("->") + text(" ") + renderType(typeArguments.last()) + return + } + if (node.name == "ExtensionFunction${typeArguments.count() - 2}") { + // extension lambda + renderType(typeArguments.first()) + symbol(".") + symbol("(") + renderList(typeArguments.drop(1).take(typeArguments.size - 2)) { + renderType(it) + } + symbol(")") + text(" ") + symbol("->") + text(" ") + renderType(typeArguments.last()) + return + } + renderLinked(node) { identifier(it.name) } + if (typeArguments.any()) { + symbol("<") + renderList(typeArguments) { + renderType(it) + } + symbol(">") + } + } + + private fun ContentNode.renderModifier(node: DocumentationNode) { + when (node.name) { + "final", "internal" -> { + } + else -> keyword(node.name) + } + } + + private fun ContentNode.renderTypeParameter(node: DocumentationNode) { + val constraints = node.details(DocumentationNode.Kind.UpperBound) + identifier(node.name) + if (constraints.any()) { + symbol(" : ") + renderList(constraints) { + renderType(it) + } + } + } + + private fun ContentNode.renderParameter(node: DocumentationNode) { + identifier(node.name) + symbol(": ") + val parameterType = node.detail(DocumentationNode.Kind.Type) + renderType(parameterType) + } + + private fun ContentNode.renderTypeParametersForNode(node: DocumentationNode) { + val typeParameters = node.details(DocumentationNode.Kind.TypeParameter) + if (typeParameters.any()) { + symbol("<") + renderList(typeParameters) { + renderType(it) + } + symbol("> ") + } + } + + private fun ContentNode.renderSupertypesForNode(node: DocumentationNode) { + val supertypes = node.details(DocumentationNode.Kind.Supertype) + if (supertypes.any()) { + symbol(" : ") + renderList(supertypes) { + renderType(it) + } + } + } + + private fun ContentNode.renderModifiersForNode(node: DocumentationNode) { + val modifiers = node.details(DocumentationNode.Kind.Modifier) + for (it in modifiers) { + if (node.kind == org.jetbrains.dokka.DocumentationNode.Kind.Interface && it.name == "abstract") + continue + renderModifier(it) + text(" ") + } + } + + private fun ContentNode.renderClass(node: DocumentationNode) { + renderModifiersForNode(node) + when (node.kind) { + DocumentationNode.Kind.Class -> keyword("class ") + DocumentationNode.Kind.Interface -> keyword("trait ") + DocumentationNode.Kind.Enum -> keyword("enum class ") + DocumentationNode.Kind.EnumItem -> keyword("enum val ") + DocumentationNode.Kind.Object -> keyword("object ") + else -> throw IllegalArgumentException("Node $node is not a class-like object") + } + + identifier(node.name) + renderTypeParametersForNode(node) + renderSupertypesForNode(node) + } + + private fun ContentNode.renderFunction(node: DocumentationNode) { + renderModifiersForNode(node) + when (node.kind) { + DocumentationNode.Kind.Constructor -> identifier(node.owner!!.name) + DocumentationNode.Kind.Function -> keyword("fun ") + else -> throw IllegalArgumentException("Node $node is not a function-like object") + } + renderTypeParametersForNode(node) + val receiver = node.details(DocumentationNode.Kind.Receiver).singleOrNull() + if (receiver != null) { + renderType(receiver.detail(DocumentationNode.Kind.Type)) + symbol(".") + } + + if (node.kind != org.jetbrains.dokka.DocumentationNode.Kind.Constructor) + identifier(node.name) + + symbol("(") + renderList(node.details(DocumentationNode.Kind.Parameter)) { + renderParameter(it) + } + symbol(")") + if (node.kind != org.jetbrains.dokka.DocumentationNode.Kind.Constructor) { + symbol(": ") + renderType(node.detail(DocumentationNode.Kind.Type)) + } + } + + private fun ContentNode.renderProperty(node: DocumentationNode) { + renderModifiersForNode(node) + when (node.kind) { + DocumentationNode.Kind.Property -> keyword("val ") + else -> throw IllegalArgumentException("Node $node is not a property") + } + renderTypeParametersForNode(node) + val receiver = node.details(DocumentationNode.Kind.Receiver).singleOrNull() + if (receiver != null) { + renderType(receiver.detail(DocumentationNode.Kind.Type)) + symbol(".") + } + + identifier(node.name) + symbol(": ") + renderType(node.detail(DocumentationNode.Kind.Type)) + } +}
\ No newline at end of file |