diff options
author | Błażej Kardyś <bkardys@virtuslab.com> | 2019-11-21 02:10:26 +0100 |
---|---|---|
committer | Błażej Kardyś <bkardys@virtuslab.com> | 2019-11-25 17:17:01 +0100 |
commit | 193b8c0bcebdcdfd749090a408149cac06203614 (patch) | |
tree | 8875ec08e1ddac7a5d6c8708bd1a6a918c4380b0 /core/src/main/kotlin/links | |
parent | 4f59d3df7a0a3525bf3a0dab8617746a4db30f67 (diff) | |
download | dokka-193b8c0bcebdcdfd749090a408149cac06203614.tar.gz dokka-193b8c0bcebdcdfd749090a408149cac06203614.tar.bz2 dokka-193b8c0bcebdcdfd749090a408149cac06203614.zip |
Descriptor independent DocumentationNodes and seperate Page and PageContent builders
Diffstat (limited to 'core/src/main/kotlin/links')
-rw-r--r-- | core/src/main/kotlin/links/DRI.kt | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt index 605840a7..845388b5 100644 --- a/core/src/main/kotlin/links/DRI.kt +++ b/core/src/main/kotlin/links/DRI.kt @@ -1,8 +1,11 @@ package org.jetbrains.dokka.links import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf +import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjection import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.text.ParseException @@ -47,7 +50,7 @@ data class DRI( ) } } catch (e: Throwable) { - throw ParseException(s, 0) + throw ParseException("Can not create DRI from $s", 0) } fun from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run { @@ -67,7 +70,7 @@ data class DRI( } } -fun DRI.withClass(name: String) = copy(classNames = if(classNames.isNullOrBlank()) name else "$classNames.$name") +fun DRI.withClass(name: String) = copy(classNames = if (classNames.isNullOrBlank()) name else "$classNames.$name") val DRI.parent: DRI get() = when { @@ -78,7 +81,12 @@ val DRI.parent: DRI else -> DRI.topLevel } -data class Callable(val name: String, val receiver: String, val returnType: String, val params: List<String>) { +data class Callable( + val name: String, + val receiver: ClassReference? = null, + val returnType: String, + val params: List<ClassReference> +) { fun signature() = "$receiver#$returnType#${params.joinToString("#")}" companion object { @@ -88,9 +96,9 @@ data class Callable(val name: String, val receiver: String, val returnType: Stri .let { (receiver, returnType, params) -> Callable( name.toString(), - receiver, + ClassReference.from(receiver), returnType, - params.split('#').filter { it.isNotBlank() } + params.split('#').mapNotNull { if (it.isNotBlank()) ClassReference.from(it) else null } ) } } catch (e: Throwable) { @@ -106,17 +114,61 @@ data class Callable(val name: String, val receiver: String, val returnType: Stri fun from(descriptor: CallableDescriptor) = with(descriptor) { Callable( name.asString(), - extensionReceiverParameter?.value?.type?.constructorName.orEmpty(), + extensionReceiverParameter?.let { ClassReference.from(it) }, returnType?.constructorName.orEmpty(), - valueParameters.map { it.type.constructorName.orEmpty() } + valueParameters.map { ClassReference.from(it.type.constructorName.orEmpty()) } ) } } } -data class ClassReference(val dri: DRI, val subs: MutableList<ClassReference> = mutableListOf()) { - private val subsText = subs.takeIf { it.isNotEmpty() }?.toString().orEmpty() - override fun toString() = "$dri$subsText" +data class ClassReference(val classNames: String, val typeBounds: List<ClassReference> = emptyList()) { + override fun toString() = classNames + if (typeBounds.isNotEmpty()) { + "[${typeBounds.joinToString(",")}]" + } else { + "" + } + + companion object { + + fun from(s: String?): ClassReference = + s?.let { + "((?:\\w+\\.?)+)(?:\\[((?:\\w+,?)+)])?".toRegex() // This regex matches class names with or without typebounds + .matchEntire(it) + ?.let { m -> + ClassReference(m.groupValues[1], typeBoundsFrom(m.groupValues[2])) + } + } ?: throw ParseException(s, 0) + + fun from(d: ReceiverParameterDescriptor): ClassReference = + when (val value = d.value) { + is ExtensionReceiver -> ClassReference( + classNames = value.type.constructorName.orEmpty(), + typeBounds = value.declarationDescriptor.typeParameters.map { + ClassReference( + it.fqNameSafe.toString(), + it.upperBounds.map { from(it) } + ) + } + ) + else -> ClassReference(d.value.type.constructorName.orEmpty()) + } + + private fun from(t: KotlinType): ClassReference = + ClassReference(t.constructorName.orEmpty(), t.arguments.map { from(it) }) + + private fun from(t: TypeProjection): ClassReference = + if (t.isStarProjection) { + starProjection + } else { + from(t.type) + } + + private fun typeBoundsFrom(s: String) = + s.split(",").filter { it.isNotBlank() }.map { ClassReference.from(it) } + + val starProjection = ClassReference("*") + } } private operator fun <T> List<T>.component6(): T = get(5) |