From 91d785711dde2108f7494102eceb53ea8f4938ca Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Wed, 4 Mar 2020 17:49:28 +0100 Subject: Implement some additional modifiers --- .../src/main/kotlin/JavaSignatureProvider.kt | 112 --------------------- .../src/main/kotlin/KotlinAsJavaPlugin.kt | 7 +- .../kotlin/converters/KotlinToJavaConverter.kt | 42 +++++--- .../kotlin/signatures/JavaSignatureProvider.kt | 109 ++++++++++++++++++++ 4 files changed, 145 insertions(+), 125 deletions(-) delete mode 100644 plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt create mode 100644 plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt (limited to 'plugins/kotlin-as-java/src') diff --git a/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt deleted file mode 100644 index 06224a7a..00000000 --- a/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt +++ /dev/null @@ -1,112 +0,0 @@ -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.sureClassNames -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.Annotation -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 JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider { - private val contentBuilder = PageContentBuilder(ctcc, this, logger) - - private val ignoredVisibilities = setOf(JavaVisibility.Default, KotlinVisibility.Public) - private val ignoredModifiers = - setOf(KotlinModifier.Open, JavaModifier.Empty, KotlinModifier.Empty, KotlinModifier.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(c: Classlike) = contentBuilder.contentFor(c, ContentKind.Symbol) { - platformText(c.visibility) { (it.takeIf { it !in ignoredVisibilities }?.name ?: "") + " " } - - if (c is Class) { - text(c.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ") - } - - when (c) { - 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) { - list(c.generics, prefix = "<", suffix = ">") { - +buildSignature(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) = contentBuilder.contentFor(f, ContentKind.Symbol) { - text(f.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ") - val returnType = f.type - if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) { - type(returnType) - } - text(" ") - link(f.name, f.dri) - list(f.generics, prefix = "<", suffix = ">") { - +buildSignature(it) - } - text("(") - list(f.parameters) { - type(it.type) - text(" ") - link(it.name!!, it.dri) - } - text(")") - } - - private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) { - text(t.name.substringAfterLast(".")) - list(t.bounds, prefix = " extends ") { - signatureForProjection(it) - } - } - - - 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 = ">") { - signatureForProjection(it) - } - } - - is Variance -> group { - text(p.kind.toString() + " ") - signatureForProjection(p.inner) - } - - is Star -> text("?") - - is Nullable -> signatureForProjection(p.inner) - } - - private fun Collection.filterOnPlatform(platformData: PlatformData) = - this.filter { it.platformData.contains(platformData) } -} \ No newline at end of file diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt index 0ca278ce..bf9b8dc0 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka.kotlinAsJava import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.base.DokkaBase +import org.jetbrains.dokka.kotlinAsJava.signatures.JavaSignatureProvider import org.jetbrains.dokka.kotlinAsJava.transformers.KotlinAsJavaDocumentableTransformer import org.jetbrains.dokka.plugability.DokkaPlugin @@ -12,7 +13,11 @@ class KotlinAsJavaPlugin : DokkaPlugin() { val javaSignatureProvider by extending { val dokkaBasePlugin = plugin() dokkaBasePlugin.signatureProvider providing { ctx -> - JavaSignatureProvider(ctx.single(dokkaBasePlugin.commentsToContentConverter), ctx.logger) + JavaSignatureProvider( + ctx.single( + dokkaBasePlugin.commentsToContentConverter + ), ctx.logger + ) } } } \ No newline at end of file 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 7c66e91f..4bf75101 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt @@ -32,12 +32,17 @@ internal fun Package.asJava(): Package { properties = nodes.filterIsInstance().map { it.asJava() }, constructors = emptyList(), functions = ( - nodes.filterIsInstance().map { it.javaAccessors() } + - nodes.filterIsInstance().map { it.asJava(syntheticClassName) } - ) as List, // TODO: methods are static and receiver is a param + nodes.filterIsInstance() + .map { it.javaAccessors() } + + nodes.filterIsInstance() + .map { it.asJava(syntheticClassName) }) as List, // TODO: methods are static and receiver is a param classlikes = emptyList(), sources = PlatformDependent.empty(), - visibility = PlatformDependent.empty(), // TODO: fix this with the new visibility model -> public + visibility = PlatformDependent( + platformData.map { + it to JavaVisibility.Public + }.toMap() + ), companion = null, generics = emptyList(), supertypes = PlatformDependent.empty(), @@ -127,9 +132,10 @@ internal fun Function.asJava(containingClassName: String): Function { // dri = dri.copy(callable = dri.callable?.asJava()), name = newName, type = type.asJava(), + modifier = if(modifier is KotlinModifier.Final && isConstructor) JavaModifier.Empty else modifier, parameters = listOfNotNull(receiver?.asJava()) + parameters.map { it.asJava() }, receiver = null - ) // TODO: should receiver be the first param? + ) // TODO static if toplevel } internal fun Classlike.asJava(): Classlike = when (this) { @@ -151,8 +157,9 @@ internal fun Class.asJava(): Class = copy( 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 + ), + modifier = if (modifier is KotlinModifier.Empty) JavaModifier.Final else modifier +) private fun TypeParameter.asJava(): TypeParameter = copy( dri = dri.possiblyAsJava(), @@ -180,7 +187,7 @@ internal fun Enum.asJava(): Enum = 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 +) internal fun Object.asJava(): Object = copy( functions = (functions + properties.map { it.getter } + properties.map { it.setter }) @@ -193,7 +200,11 @@ internal fun Object.asJava(): Object = copy( dri = dri.copy(callable = Callable("INSTANCE", null, emptyList())), documentation = PlatformDependent.empty(), sources = PlatformDependent.empty(), - visibility = PlatformDependent.empty(), // TODO: public and static + visibility = PlatformDependent( + platformData.map { + it to JavaVisibility.Public + }.toMap() + ), type = JavaTypeWrapper( dri.packageName?.split(".").orEmpty() + dri.classNames?.split(".").orEmpty(), @@ -204,7 +215,8 @@ internal fun Object.asJava(): Object = copy( setter = null, getter = null, platformData = platformData, - receiver = null + receiver = null, + extra = PropertyContainer.empty() + AdditionalModifiers(listOf(ExtraModifiers.STATIC)) ), classlikes = classlikes.map { it.asJava() }, supertypes = supertypes.copy( @@ -259,9 +271,15 @@ 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: ??? + ?.let { if (it.endsWith(".Unit")) return VoidTypeWrapper() else it } ?.let { fqName -> fqName.mapToJava()?.let { getAsType(it, fqName, top) } } ?: this +private data class VoidTypeWrapper( + override val constructorFqName: String = "void", + override val constructorNamePathSegments: List = listOf("void"), + override val arguments: List = emptyList(), + override val dri: DRI = DRI("java.lang", "Void") +) : TypeWrapper private fun String.mapToJava(): ClassId? = JavaToKotlinClassMap.mapKotlinToJava(FqName(this).toUnsafe()) @@ -269,7 +287,7 @@ private fun String.mapToJava(): ClassId? = internal fun ClassId.toDRI(dri: DRI?): DRI = DRI( packageName = packageFqName.asString(), classNames = classNames(), - callable = dri?.callable,//?.asJava(), TODO: ???? + callable = dri?.callable,//?.asJava(), TODO: check this extra = null, target = null ) diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt new file mode 100644 index 00000000..91e5164d --- /dev/null +++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt @@ -0,0 +1,109 @@ +package org.jetbrains.dokka.kotlinAsJava.signatures + +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.sureClassNames +import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.model.Annotation +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 JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider { + private val contentBuilder = PageContentBuilder(ctcc, this, logger) + + private val ignoredVisibilities = setOf(JavaVisibility.Default, KotlinVisibility.Public) + private val ignoredModifiers = + setOf(KotlinModifier.Open, JavaModifier.Empty, KotlinModifier.Empty, KotlinModifier.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(c: Classlike) = contentBuilder.contentFor(c, ContentKind.Symbol) { + platformText(c.visibility) { (it.takeIf { it !in ignoredVisibilities }?.name ?: "") + " " } + + if (c is Class) { + text(c.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ") + } + + when (c) { + 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) { + list(c.generics, prefix = "<", suffix = ">") { + +buildSignature(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) = contentBuilder.contentFor(f, ContentKind.Symbol) { + text(f.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ") + val returnType = f.type + if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) { + type(returnType) + } + text(" ") + link(f.name, f.dri) + list(f.generics, prefix = "<", suffix = ">") { + +buildSignature(it) + } + text("(") + list(f.parameters) { + type(it.type) + text(" ") + link(it.name!!, it.dri) + } + text(")") + } + + private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) { + text(t.name.substringAfterLast(".")) + list(t.bounds, prefix = " extends ") { + signatureForProjection(it) + } + } + + + 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 = ">") { + signatureForProjection(it) + } + } + + is Variance -> group { + text(p.kind.toString() + " ") + signatureForProjection(p.inner) + } + + is Star -> text("?") + + is Nullable -> signatureForProjection(p.inner) + } +} \ No newline at end of file -- cgit