aboutsummaryrefslogtreecommitdiff
path: root/plugins/kotlin-as-java
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kotlin-as-java')
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt88
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt81
2 files changed, 105 insertions, 64 deletions
diff --git a/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt
index 2e3ec152..8e2c783e 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt
@@ -3,7 +3,6 @@ package org.jetbrains.dokka.kotlinAsJava
import org.jetbrains.dokka.base.signatures.SignatureProvider
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.Annotation
@@ -17,48 +16,50 @@ import org.jetbrains.dokka.utilities.DokkaLogger
class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider {
private val contentBuilder = PageContentBuilder(ctcc, this, logger)
- override fun signature(documentable: Documentable): List<ContentNode> = when (documentable) {
+ private val ignoredVisibilities = setOf(JavaVisibility.Default, KotlinVisibility.Public)
+ private val ignoredModifiers =
+ setOf(WithAbstraction.Modifier.Open, WithAbstraction.Modifier.Empty, WithAbstraction.Modifier.Sealed)
+
+
+ override fun signature(documentable: Documentable): ContentNode = when (documentable) {
is Function -> signature(documentable)
is Classlike -> signature(documentable)
+ is TypeParameter -> 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) = contentBuilder.contentFor(c, ContentKind.Symbol) {
+ platformText(c.visibility) { (it.takeIf { it !in ignoredVisibilities }?.name ?: "") + " " }
- private fun signature(c: Classlike, platform: PlatformData) = contentBuilder.contentFor(c, ContentKind.Symbol) {
if (c is Class) {
- text(c.modifier.takeIf { it != WithAbstraction.Modifier.Empty }?.toString()?.toLowerCase().orEmpty())
+ text(c.modifier.takeIf { it !in ignoredModifiers }?.toString()?.toLowerCase().orEmpty() + " ")
}
+
when (c) {
- is Class -> text(" class ")
- is Interface -> text(" interface ")
- is Enum -> text(" enum ")
- is Object -> text(" class ")
- is Annotation -> text(" @interface ")
+ is Class -> text("class ")
+ is Interface -> text("interface ")
+ is Enum -> text("enum ")
+ is Object -> text("class ")
+ is Annotation -> text("@interface ")
}
text(c.name!!)
if (c is WithGenerics) {
- val generics = c.generics.filterOnPlatform(platform)
- if (generics.isNotEmpty()) {
- text("<")
- list(generics) {
- +this@JavaSignatureProvider.signature(it)
- }
- text(">")
+ list(c.generics, prefix = "<", suffix = ">") {
+ +buildSignature(it)
}
}
- if (c is WithSupertypes && c.supertypes.containsKey(platform)) {
- list(c.supertypes.getValue(platform), prefix = " extends ") {
- link(it.sureClassNames, it)
+ if (c is WithSupertypes) {
+ c.supertypes.map { (p, dris) ->
+ list(dris, prefix = " extends ", platformData = setOf(p)) {
+ link(it.sureClassNames, it, platformData = setOf(p))
+ }
}
}
}
- private fun signature(f: Function, platform: PlatformData) = contentBuilder.contentFor(f, ContentKind.Symbol) {
+ private fun signature(f: Function) = contentBuilder.contentFor(f, ContentKind.Symbol) {
text(f.modifier.takeIf { it != WithAbstraction.Modifier.Empty }?.toString()?.toLowerCase().orEmpty() + " ")
val returnType = f.type
if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) {
@@ -66,16 +67,11 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge
}
text(" ")
link(f.name, f.dri)
- val generics = f.generics.filterOnPlatform(platform)
- if (generics.isNotEmpty()) {
- text("<")
- generics.forEach {
- this@JavaSignatureProvider.signature(it)
- }
- text(">")
+ list(f.generics, prefix = "<", suffix = ">") {
+ +buildSignature(it)
}
text("(")
- list(f.parameters.filterOnPlatform(platform)) {
+ list(f.parameters) {
type(it.type)
text(" ")
link(it.name!!, it.dri)
@@ -85,34 +81,30 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge
private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) {
text(t.name.substringAfterLast("."))
- if (t.bounds.isNotEmpty()) {
- text(" extends ")
- t.bounds.forEach {
- +signature(it, t.dri, t.platformData)
- }
+ list(t.bounds, prefix = " extends ") {
+ signatureForProjection(it)
}
}
- 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()) {
+ private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(p: Projection): Unit = when (p) {
+ is OtherParameter -> text(p.name)
+
+ is TypeConstructor -> group {
link(p.dri.classNames.orEmpty(), p.dri)
list(p.projections, prefix = "<", suffix = ">") {
- +signature(it, dri, platforms)
+ signatureForProjection(it)
}
- }.children
+ }
- is Variance -> contentBuilder.contentFor(dri, platforms.toSet()) {
+ is Variance -> group {
text(p.kind.toString() + " ")
- }.children + signature(p.inner, dri, platforms)
+ signatureForProjection(p.inner)
+ }
- is Star -> contentBuilder.contentFor(dri, platforms.toSet()) { text("?") }.children
+ is Star -> text("?")
- is Nullable -> signature(p.inner, dri, platforms) + contentBuilder.contentFor(
- dri,
- platforms.toSet()
- ) { text("?") }.children
+ is Nullable -> signatureForProjection(p.inner)
}
private fun <T : Documentable> Collection<T>.filterOnPlatform(platformData: PlatformData) =
diff --git a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt
index f7fc57ff..a8b45db0 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt
@@ -16,7 +16,9 @@ import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
private fun <T : WithExpectActual> List<T>.groupedByLocation() =
map { it.sources to it }
.groupBy({ (location, _) ->
- location.let { it.map.entries.first().value.path.split("/").last().split(".").first() + "Kt" } // TODO: first() does not look reasonable
+ location.let {
+ it.map.entries.first().value.path.split("/").last().split(".").first() + "Kt"
+ } // TODO: first() does not look reasonable
}) { it.second }
internal fun Package.asJava(): Package {
@@ -61,16 +63,19 @@ internal fun Property.asJava(isTopLevel: Boolean = false, relocateToClass: Strin
} else {
dri.withClass(relocateToClass)
},
-// name = name.o,
modifier = if (setter == null) {
WithAbstraction.Modifier.Final
} else {
WithAbstraction.Modifier.Empty
},
- type = type.asJava(isTopLevel), // TODO: check,
+ visibility = visibility.copy(
+ map = visibility.mapValues { JavaVisibility.Private }
+ ),
+ type = type.asJava(isTopLevel), // TODO: check
setter = null,
- getter = null // Removing getters and setters as they will be available as functions
- ) // TODO: visibility -> always private; if (isTopLevel) -> static
+ getter = null, // Removing getters and setters as they will be available as functions
+ extra = if (isTopLevel) extra.plus(extra.mergeAdditionalModifiers(listOf(ExtraModifiers.STATIC))) else extra
+ )
internal fun Property.javaAccessors(isTopLevel: Boolean = false, relocateToClass: String? = null): List<Function> =
listOfNotNull(
@@ -86,7 +91,11 @@ internal fun Property.javaAccessors(isTopLevel: Boolean = false, relocateToClass
} else {
WithAbstraction.Modifier.Empty
},
- type = type.asJava(isTopLevel) // TODO: check,
+ visibility = visibility.copy(
+ map = visibility.mapValues { JavaVisibility.Public }
+ ),
+ type = type.asJava(isTopLevel), // TODO: check
+ extra = if (isTopLevel) getter!!.extra.plus(getter!!.extra.mergeAdditionalModifiers(listOf(ExtraModifiers.STATIC))) else getter!!.extra
),
setter?.copy(
dri = if (relocateToClass.isNullOrBlank()) {
@@ -100,9 +109,13 @@ internal fun Property.javaAccessors(isTopLevel: Boolean = false, relocateToClass
} else {
WithAbstraction.Modifier.Empty
},
- type = type.asJava(isTopLevel) // TODO: check,
+ visibility = visibility.copy(
+ map = visibility.mapValues { JavaVisibility.Public }
+ ),
+ type = type.asJava(isTopLevel), // TODO: check
+ extra = if (isTopLevel) setter!!.extra.plus(setter!!.extra.mergeAdditionalModifiers(listOf(ExtraModifiers.STATIC))) else setter!!.extra
)
- ) // TODO: if (isTopLevel) -> static; visibility -> always? public
+ )
internal fun Function.asJava(containingClassName: String): Function {
@@ -134,18 +147,38 @@ internal fun Class.asJava(): Class = copy(
it.asJava(name)
},
properties = properties.map { it.asJava() },
- classlikes = classlikes.map { it.asJava() }
+ classlikes = classlikes.map { it.asJava() },
+ generics = generics.map { it.asJava() },
+ supertypes = supertypes.copy(
+ map = supertypes.mapValues { it.value.map { it.possiblyAsJava() } }
+ )
) // TODO: if modifier is from Kotlin, then Empty -> Final I think, Java ones stay the same
+private fun TypeParameter.asJava(): TypeParameter = copy(
+ dri = dri.possiblyAsJava(),
+ bounds = bounds.map { it.asJava() }
+)
+
+private fun Bound.asJava(): Bound = when (this) {
+ is TypeConstructor -> copy(
+ dri = dri.possiblyAsJava()
+ )
+ is Nullable -> copy(
+ inner = inner.asJava()
+ )
+ else -> this
+}
+
internal fun Enum.asJava(): Enum = copy(
constructors = constructors.map { it.asJava(name) },
functions = (functions + properties.map { it.getter } + properties.map { it.setter }).filterNotNull().map {
- it.asJava(
- name
- )
+ it.asJava(name)
},
properties = properties.map { it.asJava() },
- classlikes = classlikes.map { it.asJava() }
+ classlikes = classlikes.map { it.asJava() },
+ supertypes = supertypes.copy(
+ map = supertypes.mapValues { it.value.map { it.possiblyAsJava() } }
+ )
// , entries = entries.map { it.asJava() }
) // TODO: if modifier is from Kotlin, then Empty -> Final I think, Java ones stay the same
@@ -173,7 +206,10 @@ internal fun Object.asJava(): Object = copy(
platformData = platformData,
receiver = null
),
- classlikes = classlikes.map { it.asJava() }
+ classlikes = classlikes.map { it.asJava() },
+ supertypes = supertypes.copy(
+ map = supertypes.mapValues { it.value.map { it.possiblyAsJava() } }
+ )
)
internal fun Interface.asJava(): Interface = copy(
@@ -181,7 +217,11 @@ internal fun Interface.asJava(): Interface = copy(
.filterNotNull()
.map { it.asJava(name) },
properties = emptyList(),
- classlikes = classlikes.map { it.asJava() } // TODO: public static final class DefaultImpls with impls for methods (killme please)
+ classlikes = classlikes.map { it.asJava() }, // TODO: public static final class DefaultImpls with impls for methods
+ generics = generics.map { it.asJava() },
+ supertypes = supertypes.copy(
+ map = supertypes.mapValues { it.value.map { it.possiblyAsJava() } }
+ )
)
internal fun Annotation.asJava(): Annotation = copy(
@@ -215,8 +255,11 @@ internal fun TypeWrapper.getAsType(classId: ClassId, fqName: String, top: Boolea
)
}
+private fun DRI.partialFqName() = packageName?.let { "$it." } + classNames
+private fun DRI.possiblyAsJava() = this.partialFqName().mapToJava()?.toDRI(this) ?: this
+
internal fun TypeWrapper.asJava(top: Boolean = true): TypeWrapper = constructorFqName
- ?.takeUnless { it.endsWith(".Unit") } // TODO: ???
+// ?.takeUnless { it.endsWith(".Unit") } // TODO: ???
?.let { fqName -> fqName.mapToJava()?.let { getAsType(it, fqName, top) } } ?: this
@@ -231,6 +274,12 @@ internal fun ClassId.toDRI(dri: DRI?): DRI = DRI(
target = null
)
+private fun PropertyContainer<out Documentable>.mergeAdditionalModifiers(second: List<ExtraModifiers>) =
+ this[AdditionalModifiers.AdditionalKey]?.squash(AdditionalModifiers(second)) ?: AdditionalModifiers(second)
+
+private fun AdditionalModifiers.squash(second: AdditionalModifiers) =
+ AdditionalModifiers((content + second.content).distinct())
+
internal fun ClassId.classNames(): String =
shortClassName.identifier + (outerClassId?.classNames()?.let { ".$it" } ?: "")