aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/links
diff options
context:
space:
mode:
authorBłażej Kardyś <bkardys@virtuslab.com>2019-11-21 02:10:26 +0100
committerBłażej Kardyś <bkardys@virtuslab.com>2019-11-25 17:17:01 +0100
commit193b8c0bcebdcdfd749090a408149cac06203614 (patch)
tree8875ec08e1ddac7a5d6c8708bd1a6a918c4380b0 /core/src/main/kotlin/links
parent4f59d3df7a0a3525bf3a0dab8617746a4db30f67 (diff)
downloaddokka-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.kt72
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)