From f166bfae0f30b6d7de1e5f7b8dcc312ee981ed76 Mon Sep 17 00:00:00 2001 From: Casey Brooks <cjbrooks12@gmail.com> Date: Wed, 17 Oct 2018 18:08:44 -0500 Subject: [PATCH] Starts trying to add Dokka class signatures --- dokka-json-lib/build.gradle | 18 +++++++ .../copperleaf/dokka/json/models/models.kt | 5 +- .../json/generator/formatter/formatClass.kt | 30 +++++++++++- .../generator/formatter/formatConstructor.kt | 10 ++-- .../json/generator/formatter/formatField.kt | 12 ++--- .../json/generator/formatter/formatHelpers.kt | 38 ++++++++++++--- .../json/generator/formatter/formatMethod.kt | 22 +++++---- .../generator/formatter/formatParameters.kt | 45 ++++++++++++----- .../dokka/json/test/kotlin/KotlinClass.kt | 48 +++++++++++++++---- 9 files changed, 179 insertions(+), 49 deletions(-) diff --git a/dokka-json-lib/build.gradle b/dokka-json-lib/build.gradle index 3e5643c..4ec12c9 100644 --- a/dokka-json-lib/build.gradle +++ b/dokka-json-lib/build.gradle @@ -30,3 +30,21 @@ test { } } test.outputs.upToDateWhen {false} + + + +configurations { dokka } +repositories { + maven { url 'https://jitpack.io' } +} +dependencies { + dokka 'org.jetbrains.dokka:dokka-fatjar:0.9.17' +} +task runDefaultDokka(type: JavaExec) { + main = "org.jetbrains.dokka.MainKt" + classpath = configurations.dokka + args = [ + "-src", "${project(':dokka-json').projectDir}/src/test/kotlin", + "-output", "${project(':dokka-json').buildDir}/dokka/default" + ] +} diff --git a/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/models.kt b/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/models.kt index 91301f4..e809e47 100644 --- a/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/models.kt +++ b/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/models.kt @@ -27,10 +27,13 @@ data class KotlinClassDoc( override val qualifiedName: String, override val comment: String, override val summaryPos: Int, + val modifiers: List<String>, val constructors: List<KotlinConstructor>, val methods: List<KotlinMethod>, val fields: List<KotlinField>, - val extensions: List<KotlinMethod> + val extensions: List<KotlinMethod>, + val signature: List<SignatureComponent>, + val simpleSignature: String = signature.map { it.name }.joinToString("") ) : KotlinClasslike { companion object { fun fromJson(json: String): KotlinClassDoc { diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatClass.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatClass.kt index c77125c..7684b89 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatClass.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatClass.kt @@ -1,6 +1,7 @@ package com.copperleaf.dokka.json.generator.formatter import com.copperleaf.dokka.json.models.KotlinClassDoc +import com.copperleaf.dokka.json.models.SignatureComponent import org.jetbrains.dokka.DocumentationNode import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.path @@ -10,6 +11,8 @@ val DocumentationNode.classLike: Boolean get() = NodeKind.classLike.contains(thi fun DocumentationNode.toClassDoc(deep: Boolean = false): KotlinClassDoc { assert(this.classLike) { "node must be a Class-like" } + val modifiers = this.modifiers + return KotlinClassDoc( this, this.path.map { it.name }.filterNot { it.isEmpty() }.first(), @@ -18,9 +21,34 @@ fun DocumentationNode.toClassDoc(deep: Boolean = false): KotlinClassDoc { this.qualifiedName, this.contentText, this.summary.textLength, + modifiers, if (deep) this.members.filter { it.isConstructor }.map { it.toConstructor() } else emptyList(), if (deep) this.members.filter { it.isMethod }.map { it.toMethod() } else emptyList(), if (deep) this.members.filter { it.isField }.map { it.toField() } else emptyList(), - if (deep) this.extensions.filter { it.isMethod }.map { it.toMethod() } else emptyList() + if (deep) this.extensions.filter { it.isMethod }.map { it.toMethod() } else emptyList(), + this.classSignature( + modifiers + ) + ) +} + +fun DocumentationNode.classSignature( + modifiers: List<String> +): List<SignatureComponent> { + val list = mutableListOf<SignatureComponent>() + + list.addAll(modifiers.toModifierListSignature()) + list.add(SignatureComponent("keyword", "class ", "")) + list.add(SignatureComponent("type", this.simpleName, this.qualifiedName)) +// list.addAll(this.toTypeParameterDeclarationSignature()) +// list.addAll(this.toSuperclassDeclarationSignature()) + + return list +} + +fun DocumentationNode.toSuperclassDeclarationSignature(): List<SignatureComponent> { + return this.details(NodeKind.Supertype).toListSignature( + childMapper = { it.toTypeSignature() }, + prefix = listOf(SignatureComponent("punctuation", ": ", "")) ) } \ No newline at end of file diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatConstructor.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatConstructor.kt index 304770c..267738f 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatConstructor.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatConstructor.kt @@ -31,11 +31,11 @@ fun DocumentationNode.constructorSignature( modifiers: List<String>, parameters: List<KotlinParameter> ): List<SignatureComponent> { - val signatureComponents = mutableListOf<SignatureComponent>() + val list = mutableListOf<SignatureComponent>() - signatureComponents.addAll(modifiers.toModifierListSignature()) - signatureComponents.add(SignatureComponent("keyword", "constructor", "")) - signatureComponents.addAll(parameters.toParameterListSignature()) + list.addAll(modifiers.toModifierListSignature()) + list.add(SignatureComponent("keyword", "constructor", "")) + list.addAll(parameters.toParameterListSignature()) - return signatureComponents + return list } \ No newline at end of file diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatField.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatField.kt index 01e10d3..26a0a04 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatField.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatField.kt @@ -30,12 +30,12 @@ fun DocumentationNode.fieldSignature( modifiers: List<String>, type: DocumentationNode ): List<SignatureComponent> { - val signatureComponents = mutableListOf<SignatureComponent>() + val list = mutableListOf<SignatureComponent>() - signatureComponents.addAll(modifiers.toModifierListSignature()) - signatureComponents.add(SignatureComponent("name", this.simpleName, "")) - signatureComponents.add(SignatureComponent("punctuation", ": ", "")) - signatureComponents.addAll(type.asType().toTypeSignature()) + list.addAll(modifiers.toModifierListSignature()) + list.add(SignatureComponent("name", this.simpleName, "")) + list.add(SignatureComponent("punctuation", ": ", "")) + list.addAll(type.asType().toTypeSignature()) - return signatureComponents + return list } \ No newline at end of file diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatHelpers.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatHelpers.kt index 082701b..6050612 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatHelpers.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatHelpers.kt @@ -6,9 +6,10 @@ import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.path import org.jetbrains.dokka.qualifiedNameFromType -val DocumentationNode.modifiers: List<String> get() = this.details(NodeKind.Modifier) - .map { it.name } - .filter { !arrayOf("public", "final").contains(it) } +val DocumentationNode.modifiers: List<String> + get() = this.details(NodeKind.Modifier) + .map { it.name } + .filter { !arrayOf("public", "final").contains(it) } val DocumentationNode.simpleName: String get() { @@ -17,7 +18,7 @@ val DocumentationNode.simpleName: String val DocumentationNode.qualifiedName: String get() { - return if(kind == NodeKind.Type) { + return if (kind == NodeKind.Type) { this.qualifiedNameFromType() } else { @@ -26,8 +27,11 @@ val DocumentationNode.qualifiedName: String } fun DocumentationNode.asType(): DocumentationNode { - return if (kind == NodeKind.Type) this else this.detail(NodeKind.Type) - } + return if (kind == NodeKind.Type) this else this.detailOrNull(NodeKind.Type) ?: { + println("other node requesting type: ${this.kind} ${this.name}") + this + }() +} val DocumentationNode.simpleType: String get() { @@ -47,3 +51,25 @@ val DocumentationNode.nullable: Boolean fun List<String>.toModifierListSignature(): List<SignatureComponent> { return this.map { SignatureComponent("modifier", "$it ", "") } } + +fun List<DocumentationNode>.toListSignature( + childMapper: (DocumentationNode) -> List<SignatureComponent>, + prefix: List<SignatureComponent> = emptyList(), + postfix: List<SignatureComponent> = emptyList(), + separator: List<SignatureComponent> = listOf(SignatureComponent("punctuation", ", ", "")) +): List<SignatureComponent> { + val list = mutableListOf<SignatureComponent>() + + if (this.isNotEmpty()) { + list.addAll(prefix) + this.forEachIndexed { index, superclass -> + list.addAll(childMapper(superclass)) + if (index < this.size - 1) { + list.addAll(separator) + } + } + list.addAll(postfix) + } + + return list +} \ No newline at end of file diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatMethod.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatMethod.kt index 5b2ec0d..e74b88e 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatMethod.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatMethod.kt @@ -41,25 +41,27 @@ fun DocumentationNode.methodSignature( receiverType: KotlinReceiverType?, returnType: KotlinReturnType ): List<SignatureComponent> { - val signatureComponents = mutableListOf<SignatureComponent>() + val list = mutableListOf<SignatureComponent>() - signatureComponents.addAll(modifiers.toModifierListSignature()) - signatureComponents.add(SignatureComponent("keyword", "fun ", "")) + list.addAll(modifiers.toModifierListSignature()) + list.add(SignatureComponent("keyword", "fun ", "")) + + list.addAll(this.toTypeParameterDeclarationSignature()) if (receiverType != null) { - signatureComponents.addAll(receiverType.signature) - signatureComponents.add(SignatureComponent("punctuation", ".", "")) + list.addAll(receiverType.signature) + list.add(SignatureComponent("punctuation", ".", "")) } - signatureComponents.add(SignatureComponent("name", this.simpleName, "")) - signatureComponents.addAll(parameters.toParameterListSignature()) + list.add(SignatureComponent("name", this.simpleName, "")) + list.addAll(parameters.toParameterListSignature()) if (returnType.name != "Unit") { - signatureComponents.add(SignatureComponent("punctuation", ": ", "")) - signatureComponents.addAll(returnType.signature) + list.add(SignatureComponent("punctuation", ": ", "")) + list.addAll(returnType.signature) } - return signatureComponents + return list } val DocumentationNode.returnType: KotlinReturnType diff --git a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatParameters.kt b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatParameters.kt index 1ecfde7..f298c55 100644 --- a/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatParameters.kt +++ b/dokka-json/src/main/kotlin/com/copperleaf/dokka/json/generator/formatter/formatParameters.kt @@ -71,17 +71,11 @@ fun DocumentationNode.toNonFunctionalTypeSignature(): List<SignatureComponent> { list.add(SignatureComponent("type", this.simpleType, this.qualifiedType)) - val typeArguments = this.details(NodeKind.Type) - if (typeArguments.isNotEmpty()) { - list.add(SignatureComponent("punctuation", "<", "")) - typeArguments.forEachIndexed { index, parameter -> - list.addAll(parameter.toTypeSignature()) - if (index < typeArguments.size - 1) { - list.add(SignatureComponent("punctuation", ", ", "")) - } - } - list.add(SignatureComponent("punctuation", ">", "")) - } + this.details(NodeKind.Type).toListSignature( + childMapper = { it.toTypeSignature() }, + prefix = listOf(SignatureComponent("punctuation", "<", "")), + postfix = listOf(SignatureComponent("punctuation", ">", "")) + ) if (this.nullable) { list.add(SignatureComponent("punctuation", "?", "")) @@ -123,3 +117,32 @@ fun DocumentationNode.toFunctionalTypeSignature(): List<SignatureComponent> { return list } + + +// Type Params +//---------------------------------------------------------------------------------------------------------------------- + +fun DocumentationNode.toTypeParameterDeclarationSignature(): List<SignatureComponent> { + val list = mutableListOf<SignatureComponent>() + + val typeArguments = this.details(NodeKind.TypeParameter) + if (typeArguments.isNotEmpty()) { + list.add(SignatureComponent("punctuation", "<", "")) + typeArguments.forEachIndexed { index, typeParameter -> + list.add(SignatureComponent("name", typeParameter.name, "")) + + val upperBound = typeParameter.detailOrNull(NodeKind.UpperBound) + if (upperBound != null) { + list.add(SignatureComponent("punctuation", " : ", "")) + list.addAll(upperBound.asType().toTypeSignature()) + } + + if (index < typeArguments.size - 1) { + list.add(SignatureComponent("punctuation", ", ", "")) + } + } + list.add(SignatureComponent("punctuation", "> ", "")) + } + + return list +} diff --git a/dokka-json/src/test/kotlin/com/copperleaf/dokka/json/test/kotlin/KotlinClass.kt b/dokka-json/src/test/kotlin/com/copperleaf/dokka/json/test/kotlin/KotlinClass.kt index d1e8aee..ae37297 100644 --- a/dokka-json/src/test/kotlin/com/copperleaf/dokka/json/test/kotlin/KotlinClass.kt +++ b/dokka-json/src/test/kotlin/com/copperleaf/dokka/json/test/kotlin/KotlinClass.kt @@ -1,5 +1,7 @@ package com.copperleaf.dokka.json.test.kotlin +import java.io.Serializable + /** * This is a Kotlin class */ @@ -40,7 +42,7 @@ class KotlinClass( /** * This is a property defined in the class body, using an internal type */ - lateinit var genericProperty: List<(String?)->String> + lateinit var genericProperty: List<(String?) -> String> /** * This is a method defined in the class body @@ -93,7 +95,7 @@ class KotlinClass( * @param param This is the param1 for the method * @return This is the returned string value */ - fun classMethodWithFunctionParameter(param: (String)->String): String? { + fun classMethodWithFunctionParameter(param: (String) -> String): String? { return null } @@ -103,7 +105,7 @@ class KotlinClass( * @param param This is the param1 for the method * @return This is the returned string value */ - fun classMethodWithInternalFunctionParameter(param: (KotlinInterface?, (String?, Int)->String?)->KotlinMarkdown?): KotlinMarkdown? { + fun classMethodWithInternalFunctionParameter(param: (KotlinInterface?, (String?, Int) -> String?) -> KotlinMarkdown?): KotlinMarkdown? { return null } @@ -113,7 +115,7 @@ class KotlinClass( * @param param This is the param1 for the method * @return This is the returned string value */ - fun classMethodWithReceiverFunctionParameter(param: KotlinInterface.(String?)->KotlinMarkdown?): KotlinMarkdown? { + fun classMethodWithReceiverFunctionParameter(param: KotlinInterface.(String?) -> KotlinMarkdown?): KotlinMarkdown? { return null } @@ -123,7 +125,7 @@ class KotlinClass( * @param param This is the param1 for the method * @return This is the returned string value */ - fun classMethodWithGenericReceiverFunctionParameter(param: List<String?>?.(List<String?>?)->List<String?>?): List<String?>? { + fun classMethodWithGenericReceiverFunctionParameter(param: List<String?>?.(List<String?>?) -> List<String?>?): List<String?>? { return null } @@ -143,7 +145,7 @@ class KotlinClass( * @receiver This is the receiver for the method * @return This is the returned string value */ - fun String?.methodWithReceiver() { + fun String?.methodWithReceiver() { } @@ -153,7 +155,7 @@ class KotlinClass( * @receiver This is the receiver for the method * @return This is the returned string value */ - fun List<String>.methodWithReceiverTypeParameter() { + fun List<String>.methodWithReceiverTypeParameter() { } @@ -163,7 +165,7 @@ class KotlinClass( * @receiver This is the receiver for the method * @return This is the returned string value */ - fun KotlinMarkdown?.methodWithInternalReceiver() { + fun KotlinMarkdown?.methodWithInternalReceiver() { } @@ -185,4 +187,32 @@ class KotlinClass( return null } -} \ No newline at end of file +} + +@Suppress("UNUSED_PARAMETER") +open class KotlinClass2 + +@Suppress("UNUSED_PARAMETER") +abstract class KotlinClass3 + +@Suppress("UNUSED_PARAMETER") +public class KotlinClass4 + +@Suppress("UNUSED_PARAMETER") +private class KotlinClass5 + +@Suppress("UNUSED_PARAMETER") +internal class KotlinClass6 + +@Suppress("UNUSED_PARAMETER") +data class KotlinClass7(val s: String) + +@Suppress("UNUSED_PARAMETER") +sealed class KotlinClass8 + +@Suppress("UNUSED_PARAMETER") +enum class KotlinClass9 + +@Suppress("UNUSED_PARAMETER") +abstract class KotlinClass10<T : List<U>, U> : KotlinClass8(), List<T>, Serializable +