aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin
diff options
context:
space:
mode:
authorKamil Doległo <kamilok1965@interia.pl>2020-02-26 13:16:31 +0100
committerPaweł Marks <Kordyjan@users.noreply.github.com>2020-03-04 14:28:14 +0100
commit10874a53b0db00c45d4ab44dfd226672dcf75115 (patch)
tree0ae29fcd867bf5c559d635d7d8e38183f10e25d0 /plugins/base/src/main/kotlin
parentd41b4c65a0ace7e60f19fc9211947d894a0442f1 (diff)
downloaddokka-10874a53b0db00c45d4ab44dfd226672dcf75115.tar.gz
dokka-10874a53b0db00c45d4ab44dfd226672dcf75115.tar.bz2
dokka-10874a53b0db00c45d4ab44dfd226672dcf75115.zip
Sketch of default signature provider
Diffstat (limited to 'plugins/base/src/main/kotlin')
-rw-r--r--plugins/base/src/main/kotlin/providers/KotlinSignatureProvider.kt113
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt35
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt2
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt10
4 files changed, 141 insertions, 19 deletions
diff --git a/plugins/base/src/main/kotlin/providers/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/providers/KotlinSignatureProvider.kt
new file mode 100644
index 00000000..efee39fd
--- /dev/null
+++ b/plugins/base/src/main/kotlin/providers/KotlinSignatureProvider.kt
@@ -0,0 +1,113 @@
+package org.jetbrains.dokka.base.providers
+
+import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
+import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.sureClassNames
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.Enum
+import org.jetbrains.dokka.model.Function
+import org.jetbrains.dokka.pages.ContentKind
+import org.jetbrains.dokka.pages.ContentNode
+import org.jetbrains.dokka.pages.PlatformData
+import org.jetbrains.dokka.utilities.DokkaLogger
+
+class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider {
+ private val contentBuilder = PageContentBuilder(ctcc, logger)
+
+ override fun signature(documentable: Documentable): List<ContentNode> = when (documentable) {
+ is Function -> signature(documentable)
+ is Classlike -> signature(documentable)
+ else -> throw NotImplementedError(
+ "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}"
+ )
+ }
+
+ private fun signature(f: Function) = f.platformData.map { signature(f, it) }.distinct()
+
+ private fun signature(c: Classlike) = c.platformData.map { signature(c, it) }.distinct()
+
+ private fun signature(c: Classlike, platform: PlatformData) = contentBuilder.contentFor(c, ContentKind.Symbol) {
+ text(c.visibility[platform]?.externalDisplayName ?: "")
+ if (c is Class) {
+ text(c.modifier.toString())
+ }
+ when (c) {
+ is Class -> text(" class ")
+ is Interface -> text(" interface ")
+ is Enum -> text(" enum ")
+ is Object -> text(" object ")
+ }
+ text(c.name!!)
+ if (c is WithSupertypes) {
+ list(c.supertypes.getValue(platform), prefix = " : ") {
+ link(it.sureClassNames, it)
+ }
+ }
+ }
+
+ private fun signature(f: Function, platform: PlatformData) = contentBuilder.contentFor(f, ContentKind.Symbol) {
+ text(f.visibility[platform]?.externalDisplayName ?: "")
+ text(f.modifier.toString())
+ text(" fun ")
+ f.receiver?.also {
+ type(it.type)
+ text(".")
+ }
+ link(f.name, f.dri)
+ val generics = f.generics.filterOnPlatform(platform)
+ if (generics.isNotEmpty()) {
+ text("<")
+ generics.forEach {
+ signature(it)
+ }
+ text(">")
+ }
+ text("(")
+ list(f.parameters.filterOnPlatform(platform)) {
+ link(it.name!!, it.dri)
+ text(": ")
+ type(it.type)
+ }
+ text(")")
+ val returnType = f.type
+ if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) {
+ text(": ")
+
+ type(returnType)
+ }
+ }
+
+ private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) {
+ link(t.name, t.dri)
+ if (t.bounds.isNotEmpty()) {
+ text("<")
+ t.bounds.forEach {
+ signature(it, t.dri, t.platformData)
+ }
+ text(">")
+ }
+ }
+
+ private fun signature(p: Projection, dri: DRI, platforms: List<PlatformData>): List<ContentNode> = when (p) {
+ is OtherParameter -> contentBuilder.contentFor(dri, platforms.toSet()) { text(p.name) }.children
+
+ is TypeConstructor -> contentBuilder.contentFor(dri, platforms.toSet()) {
+ link(p.dri.classNames.orEmpty(), p.dri)
+ }.children + p.projections.flatMap { signature(it, dri, platforms) }
+
+ is Variance -> contentBuilder.contentFor(dri, platforms.toSet()) {
+ text(p.kind.toString() + " ")
+ }.children + signature(p.inner, dri, platforms)
+
+ is Star -> contentBuilder.contentFor(dri, platforms.toSet()) { text("*") }.children
+
+ is Nullable -> signature(p.inner, dri, platforms) + contentBuilder.contentFor(
+ dri,
+ platforms.toSet()
+ ) { text("?") }.children
+ }
+
+ private fun <T : Documentable> Collection<T>.filterOnPlatform(platformData: PlatformData) =
+ this.filter { it.platformData.contains(platformData) }
+} \ No newline at end of file
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index 83d3d178..ad28a4bc 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -18,8 +18,6 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
-import org.jetbrains.kotlin.idea.kdoc.findKDoc
-import org.jetbrains.kotlin.idea.refactoring.fqName.fqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
@@ -31,6 +29,9 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjection
+import org.jetbrains.dokka.model.Variance
+import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf.fqName
+import org.jetbrains.kotlin.idea.kdoc.findKDoc
class DefaultDescriptorToDocumentableTranslator(
private val context: DokkaContext
@@ -134,7 +135,7 @@ open class DokkaDescriptorVisitor( // TODO: close this class and make it private
)
}
- fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Enum {
+ private fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Enum {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val info = descriptor.resolveClassDescriptionData(platformData)
@@ -157,7 +158,7 @@ open class DokkaDescriptorVisitor( // TODO: close this class and make it private
)
}
- fun enumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): EnumEntry {
+ private fun enumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): EnumEntry {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
@@ -173,7 +174,7 @@ open class DokkaDescriptorVisitor( // TODO: close this class and make it private
)
}
- fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Class {
+ private fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Class {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val info = descriptor.resolveClassDescriptionData(platformData)
@@ -395,26 +396,34 @@ open class DokkaDescriptorVisitor( // TODO: close this class and make it private
DRI.from(this),
fqNameSafe.asString(),
PlatformDependent.from(platformData, getDocumentation()),
- upperBounds.map { it.toProjection() },
+ upperBounds.map { it.toBound() },
listOf(platformData),
extra = additionalExtras()
)
- private fun KotlinType.toProjection(): Projection = when (constructor.declarationDescriptor) {
- is TypeParameterDescriptor -> Projection.OtherParameter(fqName.toString()).let {
- if (isMarkedNullable) Projection.Nullable(it) else it
+ private fun KotlinType.toBound(): Bound = when (constructor.declarationDescriptor) {
+ is TypeParameterDescriptor -> OtherParameter(fqName.toString()).let {
+ if (isMarkedNullable) Nullable(it) else it
}
- else -> Projection.TypeConstructor(
+ else -> TypeConstructor(
DRI.from(constructor.declarationDescriptor!!), // TODO: remove '!!'
arguments.map { it.toProjection() }
)
}
private fun TypeProjection.toProjection(): Projection =
- if (isStarProjection) Projection.Star else fromPossiblyNullable(type)
+ if (isStarProjection) Star else formPossiblyVariant()
+
+ private fun TypeProjection.formPossiblyVariant(): Projection = type.fromPossiblyNullable().let {
+ when (projectionKind) {
+ org.jetbrains.kotlin.types.Variance.INVARIANT -> it
+ org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Variance(Variance.Kind.In, it)
+ org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Variance(Variance.Kind.Out, it)
+ }
+ }
- private fun fromPossiblyNullable(t: KotlinType): Projection =
- t.toProjection().let { if (t.isMarkedNullable) Projection.Nullable(it) else it }
+ private fun KotlinType.fromPossiblyNullable(): Bound =
+ toBound().let { if (isMarkedNullable) Nullable(it) else it }
private fun DeclarationDescriptor.getDocumentation() = findKDoc().let {
MarkdownParser(resolutionFacade, this).parseFromKDocTag(it)
diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
index 9d153a19..176aa87f 100644
--- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
+++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
@@ -160,7 +160,7 @@ open class PageContentBuilder(
elements: List<T>,
prefix: String = "",
suffix: String = "",
- separator: String = ",",
+ separator: String = ", ",
operation: DocumentableContentBuilder.(T) -> Unit
) {
if (elements.isNotEmpty()) {
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 3e95865e..4b4cf8db 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -249,10 +249,10 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator {
}
private fun PsiTypeParameterListOwner.mapTypeParameters(dri: DRI): List<TypeParameter> {
- fun mapProjections(bounds: Array<JvmReferenceType>) =
- if (bounds.isEmpty()) listOf(Projection.Star) else bounds.mapNotNull {
- (it as PsiClassType).let { classType ->
- Projection.Nullable(Projection.TypeConstructor(classType.resolve()!!.toDRI(), emptyList()))
+ fun mapBounds(bounds: Array<JvmReferenceType>): List<Bound> =
+ if (bounds.isEmpty()) emptyList() else bounds.mapNotNull {
+ (it as? PsiClassType)?.let { classType ->
+ Nullable(TypeConstructor(classType.resolve()!!.toDRI(), emptyList()))
}
}
return typeParameters.mapIndexed { index, type ->
@@ -260,7 +260,7 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator {
dri.copy(genericTarget = index),
type.name.orEmpty(),
javadocParser.parseDocumentation(type).toPlatformDependant(),
- mapProjections(type.bounds),
+ mapBounds(type.bounds),
listOf(platformData)
)
}