diff --git a/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/base.kt b/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/base.kt index f96997e..dcbc7f3 100644 --- a/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/base.kt +++ b/dokka-json-models/src/main/kotlin/com/copperleaf/dokka/json/models/base.kt @@ -12,4 +12,11 @@ interface KotlinClasslike : KotlinDocElement interface KotlinMemberlike : KotlinDocElement { val modifiers: List +} + +interface KotlinType : KotlinDocElement { + val type: String + val qualifiedType: String + val signature: List + val simpleSignature: String } \ No newline at end of file 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 a5f9ed3..604bd5d 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 @@ -105,8 +105,10 @@ data class KotlinMethod( override val comment: String, override val summaryPos: Int, override val modifiers: List, + val parameters: List, - val returnValue: KotlinReturnValue, + val receiver: KotlinReceiverType? = null, + val returnValue: KotlinReturnType, val signature: List, val simpleSignature: String = signature.map { it.name }.joinToString("") ) : KotlinMemberlike { @@ -126,12 +128,12 @@ data class KotlinField( override val comment: String, override val summaryPos: Int, override val modifiers: List, - val type: String, - val qualifiedType: String, - val nullable: Boolean, - val signature: List, - val simpleSignature: String = signature.map { it.name }.joinToString("") -) : KotlinMemberlike { + + override val type: String, + override val qualifiedType: String, + override val signature: List, + override val simpleSignature: String = signature.map { it.name }.joinToString("") +) : KotlinMemberlike, KotlinType { override val kind = "Field" } @@ -147,19 +149,22 @@ data class KotlinParameter( override val qualifiedName: String, override val comment: String, override val summaryPos: Int, - val type: String, - val qualifiedType: String, - val nullable: Boolean, - val defaultValue: String? -) : KotlinDocElement { + + override val type: String, + override val qualifiedType: String, + val defaultValue: String?, + override val signature: List, + override val simpleSignature: String = signature.map { it.name }.joinToString("") + +) : KotlinDocElement, KotlinType { override val kind = "Parameter" } /** - * The docs for a parameter of a constructor or method + * The docs for a method return type */ @Serializable -data class KotlinReturnValue( +data class KotlinReturnType( @Transient val node: Any? = null, @@ -167,15 +172,39 @@ data class KotlinReturnValue( override val qualifiedName: String, override val comment: String, override val summaryPos: Int, - val type: String, - val nullable: Boolean -) : KotlinDocElement { - override val kind = "ReturnValue" + + override val type: String, + override val qualifiedType: String, + override val signature: List, + override val simpleSignature: String = signature.map { it.name }.joinToString("") +) : KotlinDocElement, KotlinType { + override val kind = "ReturnType" +} + +/** + * The docs for a method receiver type + */ +@Serializable +data class KotlinReceiverType( + @Transient + val node: Any? = null, + + override val name: String, + override val qualifiedName: String, + override val comment: String, + override val summaryPos: Int, + + override val type: String, + override val qualifiedType: String, + override val signature: List, + override val simpleSignature: String = signature.map { it.name }.joinToString("") +) : KotlinDocElement, KotlinType { + override val kind = "ReceiverType" } /** * A component to the rich signature. The complete signature can be created by joining all components together, - * optionally generating + * optionally generating links for individual components of the signature. */ @Serializable data class SignatureComponent( 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 bd05691..304770c 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 @@ -33,9 +33,9 @@ fun DocumentationNode.constructorSignature( ): List { val signatureComponents = mutableListOf() - signatureComponents.appendModifierList(modifiers) + signatureComponents.addAll(modifiers.toModifierListSignature()) signatureComponents.add(SignatureComponent("keyword", "constructor", "")) - signatureComponents.appendParameterList(parameters) + signatureComponents.addAll(parameters.toParameterListSignature()) return signatureComponents } \ 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 d2e685c..b1aed41 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 @@ -10,7 +10,6 @@ val DocumentationNode.isField: Boolean get() = this.kind == NodeKind.Field || th fun DocumentationNode.toField(): KotlinField { assert(this.isField) { "node must be a Field or Property" } val modifiers = this.modifiers - val nullable = this.nullable return KotlinField( this, this.simpleName, @@ -20,7 +19,6 @@ fun DocumentationNode.toField(): KotlinField { modifiers, this.simpleType, this.qualifiedType, - nullable, this.fieldSignature( modifiers, this.asType() @@ -34,10 +32,10 @@ fun DocumentationNode.fieldSignature( ): List { val signatureComponents = mutableListOf() - signatureComponents.appendModifierList(modifiers) + signatureComponents.addAll(modifiers.toModifierListSignature()) signatureComponents.add(SignatureComponent("name", this.simpleName, "")) signatureComponents.add(SignatureComponent("punctuation", ": ", "")) - signatureComponents.appendParameterType(type) + signatureComponents.addAll(type.toTypeSignature()) return signatureComponents } \ 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 4ef1aac..082701b 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 @@ -44,8 +44,6 @@ val DocumentationNode.nullable: Boolean return asType().details(NodeKind.NullabilityModifier).singleOrNull() != null } -fun MutableList.appendModifierList(modifiers: List) { - for (modifier in modifiers) { - add(SignatureComponent("modifier", "$modifier ", "")) - } +fun List.toModifierListSignature(): List { + return this.map { SignatureComponent("modifier", "$it ", "") } } 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 8334df5..e9fe817 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 @@ -2,7 +2,8 @@ package com.copperleaf.dokka.json.generator.formatter import com.copperleaf.dokka.json.models.KotlinMethod import com.copperleaf.dokka.json.models.KotlinParameter -import com.copperleaf.dokka.json.models.KotlinReturnValue +import com.copperleaf.dokka.json.models.KotlinReceiverType +import com.copperleaf.dokka.json.models.KotlinReturnType import com.copperleaf.dokka.json.models.SignatureComponent import org.jetbrains.dokka.DocumentationNode import org.jetbrains.dokka.NodeKind @@ -13,7 +14,8 @@ fun DocumentationNode.toMethod(): KotlinMethod { assert(this.isMethod) { "node must be a Function" } val modifiers = this.modifiers val parameters = this.parameters - val returnValue = this.returnValue + val receiverType = this.receiverType + val returnType = this.returnType return KotlinMethod( this, this.simpleName, @@ -22,11 +24,13 @@ fun DocumentationNode.toMethod(): KotlinMethod { this.summary.textLength, modifiers, parameters, - returnValue, + receiverType, + returnType, this.methodSignature( modifiers, parameters, - returnValue + receiverType, + returnType ) ) } @@ -34,35 +38,60 @@ fun DocumentationNode.toMethod(): KotlinMethod { fun DocumentationNode.methodSignature( modifiers: List, parameters: List, - returnValue: KotlinReturnValue + receiverType: KotlinReceiverType?, + returnType: KotlinReturnType ): List { val signatureComponents = mutableListOf() - signatureComponents.appendModifierList(modifiers) + signatureComponents.addAll(modifiers.toModifierListSignature()) signatureComponents.add(SignatureComponent("keyword", "fun ", "")) + + if (receiverType != null) { + signatureComponents.addAll(receiverType.signature) + signatureComponents.add(SignatureComponent("punctuation", ".", "")) + } + signatureComponents.add(SignatureComponent("name", this.simpleName, "")) - signatureComponents.appendParameterList(parameters) + signatureComponents.addAll(parameters.toParameterListSignature()) - if (returnValue.name != "Unit") { + if (returnType.name != "Unit") { signatureComponents.add(SignatureComponent("punctuation", ": ", "")) - val node = returnValue.node as DocumentationNode - val nodeType = node.asType() - signatureComponents.appendParameterType(nodeType) + signatureComponents.addAll(returnType.signature) } return signatureComponents } -val DocumentationNode.returnValue: KotlinReturnValue +val DocumentationNode.returnType: KotlinReturnType get() { val it = this.detail(NodeKind.Type) - return KotlinReturnValue( + return KotlinReturnType( it, it.simpleName, it.qualifiedName, it.contentText, it.summary.textLength, it.simpleType, - it.nullable + it.qualifiedType, + it.asType().toTypeSignature() ) - } \ No newline at end of file + } + +val DocumentationNode.receiverType: KotlinReceiverType? + get() { + val it = this.detailOrNull(NodeKind.Receiver) + return if (it == null) + null + else + KotlinReceiverType( + it, + it.simpleName, + it.qualifiedName, + it.contentText, + it.summary.textLength, + it.simpleType, + it.qualifiedType, + it.asType().toTypeSignature() + ) + } + 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 b103c32..853568e 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 @@ -17,33 +17,28 @@ val DocumentationNode.parameters: List it.summary.textLength, it.simpleType, it.qualifiedType, - it.nullable, - it.detailOrNull(NodeKind.Value)?.name + it.detailOrNull(NodeKind.Value)?.name, + it.toTypeSignature() ) } } -fun MutableList.appendParameterList(params: List) { - add(SignatureComponent("punctuation", "(", "")) - params.forEachIndexed { index, parameter -> - val node = parameter.node as DocumentationNode - val nodeType = node.asType() +fun List.toParameterListSignature(): List { + val list = mutableListOf() + list.add(SignatureComponent("punctuation", "(", "")) + this.forEachIndexed { index, parameter -> + list.add(SignatureComponent("name", parameter.name, "")) + list.add(SignatureComponent("punctuation", ": ", "")) - add(SignatureComponent("name", parameter.name, "")) - add(SignatureComponent("punctuation", ": ", "")) + list.addAll(parameter.signature) - appendParameterType(nodeType) - - if (parameter.defaultValue != null) { - add(SignatureComponent("punctuation", " = ", "")) - add(SignatureComponent("value", parameter.defaultValue!!, parameter.defaultValue!!)) - } - - if (index < params.size - 1) { - add(SignatureComponent("punctuation", ", ", "")) + if (index < this.size - 1) { + list.add(SignatureComponent("punctuation", ", ", "")) } } - add(SignatureComponent("punctuation", ")", "")) + list.add(SignatureComponent("punctuation", ")", "")) + + return list } fun DocumentationNode.isFunctionalType(): Boolean { @@ -53,61 +48,78 @@ fun DocumentationNode.isFunctionalType(): Boolean { return name == functionalTypeName || name == suspendFunctionalTypeName } -fun MutableList.appendParameterType(node: DocumentationNode) { - if (node.isFunctionalType()) { - appendFunctionalType(node) +fun DocumentationNode.toTypeSignature(): List { + val list = mutableListOf() + if (isFunctionalType()) { + list.addAll(this.toFunctionalTypeSignature()) } else { - appendNonFunctionalType(node) + list.addAll(this.toNonFunctionalTypeSignature()) + } + + val defaultValue = this.detailOrNull(NodeKind.Value)?.name + if (defaultValue != null) { + list.add(SignatureComponent("punctuation", " = ", "")) + list.add(SignatureComponent("value", defaultValue, defaultValue)) } + + return list } -fun MutableList.appendNonFunctionalType(node: DocumentationNode) { - add(SignatureComponent("type", node.simpleType, node.qualifiedType)) +fun DocumentationNode.toNonFunctionalTypeSignature(): List { + val list = mutableListOf() + + list.add(SignatureComponent("type", this.simpleType, this.qualifiedType)) - val typeArguments = node.details(NodeKind.Type) + val typeArguments = this.details(NodeKind.Type) if (typeArguments.isNotEmpty()) { - add(SignatureComponent("punctuation", "<", "")) + list.add(SignatureComponent("punctuation", "<", "")) typeArguments.forEachIndexed { index, parameter -> - appendParameterType(parameter) + list.addAll(parameter.toTypeSignature()) if (index < typeArguments.size - 1) { - add(SignatureComponent("punctuation", ", ", "")) + list.add(SignatureComponent("punctuation", ", ", "")) } } - add(SignatureComponent("punctuation", ">", "")) + list.add(SignatureComponent("punctuation", ">", "")) } - if (node.nullable) { - add(SignatureComponent("punctuation", "?", "")) + if (this.nullable) { + list.add(SignatureComponent("punctuation", "?", "")) } + + return list } -fun MutableList.appendFunctionalType(node: DocumentationNode) { - var typeArguments = node.details(NodeKind.Type) +fun DocumentationNode.toFunctionalTypeSignature(): List { + val list = mutableListOf() - if (node.name.startsWith("Suspend")) { - add(SignatureComponent("keyword", "suspend ", "")) + var typeArguments = this.details(NodeKind.Type) + + if (this.name.startsWith("Suspend")) { + list.add(SignatureComponent("keyword", "suspend ", "")) } // function receiver - val isExtension = node.annotations.any { it.name == "ExtensionFunctionType" } + val isExtension = this.annotations.any { it.name == "ExtensionFunctionType" } if (isExtension) { - appendParameterType(typeArguments.first()) - add(SignatureComponent("punctuation", ".", "")) + list.addAll(typeArguments.first().toTypeSignature()) + list.add(SignatureComponent("punctuation", ".", "")) typeArguments = typeArguments.drop(1) } // function parameters - add(SignatureComponent("punctuation", "(", "")) + list.add(SignatureComponent("punctuation", "(", "")) typeArguments.dropLast(1).forEachIndexed { index, parameter -> - appendParameterType(parameter) + list.addAll(parameter.toTypeSignature()) if (index < typeArguments.size - 2) { - add(SignatureComponent("punctuation", ", ", "")) + list.add(SignatureComponent("punctuation", ", ", "")) } } - add(SignatureComponent("punctuation", ")", "")) + list.add(SignatureComponent("punctuation", ")", "")) // function return - add(SignatureComponent("punctuation", "->", "")) - appendParameterType(typeArguments.last()) + list.add(SignatureComponent("punctuation", "->", "")) + list.addAll(typeArguments.last().toTypeSignature()) + + 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 5abc181..2c1debf 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 @@ -137,4 +137,34 @@ class KotlinClass( } + /** + * This is a method defined in the class body, which has parameters and a return value with internal types + * + * @receiver This is the receiver for the method + * @return This is the returned string value + */ + fun String?.methodWithReceiver() { + + } + + /** + * This is a method defined in the class body, which has parameters and a return value with internal types + * + * @receiver This is the receiver for the method + * @return This is the returned string value + */ + fun List.methodWithReceiverTypeParameter() { + + } + + /** + * This is a method defined in the class body, which has parameters and a return value with internal types + * + * @receiver This is the receiver for the method + * @return This is the returned string value + */ + fun KotlinMarkdown?.methodWithInternalReceiver() { + + } + } \ No newline at end of file