aboutsummaryrefslogtreecommitdiff
path: root/plugins/kotlin-as-java/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/kotlin-as-java/src/main/kotlin')
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt12
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt176
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/jvmName.kt19
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt2
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameDocumentableTransformer.kt96
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameProvider.kt36
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt2
-rw-r--r--plugins/kotlin-as-java/src/main/kotlin/transformers/withCallableName.kt5
8 files changed, 260 insertions, 88 deletions
diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt
index 2a9b857a..b8e12553 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt
@@ -4,6 +4,7 @@ import org.jetbrains.dokka.CoreExtensions
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration
import org.jetbrains.dokka.kotlinAsJava.signatures.JavaSignatureProvider
+import org.jetbrains.dokka.kotlinAsJava.transformers.JvmNameDocumentableTransformer
import org.jetbrains.dokka.kotlinAsJava.transformers.KotlinAsJavaDocumentableTransformer
import org.jetbrains.dokka.kotlinAsJava.translators.KotlinAsJavaDocumentableToPageTranslator
import org.jetbrains.dokka.plugability.DokkaPlugin
@@ -13,13 +14,20 @@ class KotlinAsJavaPlugin : DokkaPlugin() {
val kotlinAsJavaDocumentableTransformer by extending {
CoreExtensions.documentableTransformer with KotlinAsJavaDocumentableTransformer()
}
+
+ val jvmNameTransformer by extending {
+ CoreExtensions.documentableTransformer with JvmNameDocumentableTransformer() order {
+ after(kotlinAsJavaDocumentableTransformer)
+ }
+ }
+
val javaSignatureProvider by extending {
with(plugin<DokkaBase>()) {
signatureProvider providing ::JavaSignatureProvider override kotlinSignatureProvider
}
}
val kotlinAsJavaDocumentableToPageTranslator by extending {
- CoreExtensions.documentableToPageTranslator providing ::KotlinAsJavaDocumentableToPageTranslator override
- plugin<DokkaBase>().documentableToPageTranslator
+ CoreExtensions.documentableToPageTranslator providing ::KotlinAsJavaDocumentableToPageTranslator override
+ plugin<DokkaBase>().documentableToPageTranslator
}
} \ 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 0f7d5c7a..4ecc84a7 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt
@@ -1,27 +1,19 @@
package org.jetbrains.dokka.kotlinAsJava.converters
-import org.jetbrains.dokka.links.*
+import org.jetbrains.dokka.kotlinAsJava.transformers.JvmNameProvider
+import org.jetbrains.dokka.kotlinAsJava.transformers.withCallableName
import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.PointingToDeclaration
+import org.jetbrains.dokka.links.withClass
import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.DAnnotation
-import org.jetbrains.dokka.model.DEnum
-import org.jetbrains.dokka.model.DFunction
-import org.jetbrains.dokka.model.Nullable
-import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
-import java.lang.IllegalStateException
-private fun <T : WithSources> List<T>.groupedByLocation() =
- map { it.sources to it }
- .groupBy({ (location, _) ->
- location.let {
- it.entries.first().value.path.split("/").last().split(".").first() + "Kt"
- } // TODO: first() does not look reasonable
- }) { it.second }
+val jvmNameProvider = JvmNameProvider()
private val DProperty.isConst: Boolean
get() = extra[AdditionalModifiers]
@@ -31,38 +23,39 @@ private val DProperty.isConst: Boolean
} == true
internal fun DPackage.asJava(): DPackage {
- @Suppress("UNCHECKED_CAST")
- val syntheticClasses = ((properties + functions) as List<WithSources>)
- .groupedByLocation()
- .map { (syntheticClassName, nodes) ->
- DClass(
- dri = dri.withClass(syntheticClassName),
- name = syntheticClassName,
- properties = nodes.filterIsInstance<DProperty>().map { it.asJava(true) },
- constructors = emptyList(),
- functions = (
- nodes
- .filterIsInstance<DProperty>()
- .filterNot { it.isConst }
- .flatMap { it.javaAccessors() } +
- nodes.filterIsInstance<DFunction>()
- .map { it.asJava(syntheticClassName) }), // TODO: methods are static and receiver is a param
- classlikes = emptyList(),
- sources = emptyMap(),
- expectPresentInSet = null,
- visibility = sourceSets.map {
- it to JavaVisibility.Public
- }.toMap(),
- companion = null,
- generics = emptyList(),
- supertypes = emptyMap(),
- documentation = emptyMap(),
- modifier = sourceSets.map { it to JavaModifier.Final }.toMap(),
- sourceSets = sourceSets,
- isExpectActual = false,
- extra = PropertyContainer.empty()
- )
- }
+ val syntheticClasses =
+ (properties.map { jvmNameProvider.nameForSyntheticClass(it) to it }
+ + functions.map { jvmNameProvider.nameForSyntheticClass(it) to it })
+ .groupBy({ it.first }) { it.second }
+ .map { (syntheticClassName, nodes) ->
+ DClass(
+ dri = dri.withClass(syntheticClassName.name),
+ name = syntheticClassName.name,
+ properties = nodes.filterIsInstance<DProperty>().map { it.asJava(true) },
+ constructors = emptyList(),
+ functions = (
+ nodes
+ .filterIsInstance<DProperty>()
+ .filterNot { it.isConst }
+ .flatMap { it.javaAccessors(relocateToClass = syntheticClassName.name) } +
+ nodes.filterIsInstance<DFunction>()
+ .map { it.asJava(syntheticClassName.name) }), // TODO: methods are static and receiver is a param
+ classlikes = emptyList(),
+ sources = emptyMap(),
+ expectPresentInSet = null,
+ visibility = sourceSets.map {
+ it to JavaVisibility.Public
+ }.toMap(),
+ companion = null,
+ generics = emptyList(),
+ supertypes = emptyMap(),
+ documentation = emptyMap(),
+ modifier = sourceSets.map { it to JavaModifier.Final }.toMap(),
+ sourceSets = sourceSets,
+ isExpectActual = false,
+ extra = PropertyContainer.empty()
+ )
+ }
return copy(
functions = emptyList(),
@@ -110,41 +103,56 @@ internal fun DProperty.javaModifierFromSetter() =
internal fun DProperty.javaAccessors(isTopLevel: Boolean = false, relocateToClass: String? = null): List<DFunction> =
listOfNotNull(
- getter?.copy(
- dri = if (relocateToClass.isNullOrBlank()) {
- dri
+ getter?.let { getter ->
+ val name = "get" + name.capitalize()
+ getter.copy(
+ dri = if (relocateToClass.isNullOrBlank()) {
+ getter.dri
+ } else {
+ getter.dri.withClass(relocateToClass)
+ }.withCallableName(name),
+ name = name,
+ modifier = javaModifierFromSetter(),
+ visibility = visibility.mapValues { JavaVisibility.Public },
+ type = getter.type.asJava(),
+ extra = if (isTopLevel) getter.extra +
+ getter.extra.mergeAdditionalModifiers(
+ sourceSets.map {
+ it to setOf(ExtraModifiers.JavaOnlyModifiers.Static)
+ }.toMap()
+ )
+ else getter.extra
+ )
+ },
+ setter?.let { setter ->
+ val name = "set" + name.capitalize()
+ val baseDRI = (if (relocateToClass.isNullOrBlank()) {
+ setter.dri
} else {
- dri.withClass(relocateToClass)
- },
- name = "get" + name.capitalize(),
- modifier = javaModifierFromSetter(),
- visibility = visibility.mapValues { JavaVisibility.Public },
- type = type.asJava(), // TODO: check
- extra = if (isTopLevel) getter!!.extra +
- getter!!.extra.mergeAdditionalModifiers(
- sourceSets.map {
- it to setOf(ExtraModifiers.JavaOnlyModifiers.Static)
- }.toMap()
+ setter.dri.withClass(relocateToClass)
+ }).withCallableName(name)
+ setter.copy(
+ dri = baseDRI,
+ name = name,
+ parameters = setter.parameters.map {
+ it.copy(
+ dri = baseDRI.copy(
+ target = it.dri.target,
+ extra = it.dri.extra
+ ), type = it.type.asJava()
)
- else getter!!.extra
- ),
- setter?.copy(
- dri = if (relocateToClass.isNullOrBlank()) {
- dri
- } else {
- dri.withClass(relocateToClass)
- },
- name = "set" + name.capitalize(),
- modifier = javaModifierFromSetter(),
- visibility = visibility.mapValues { JavaVisibility.Public },
- type = type.asJava(), // TODO: check
- extra = if (isTopLevel) setter!!.extra + setter!!.extra.mergeAdditionalModifiers(
- sourceSets.map {
- it to setOf(ExtraModifiers.JavaOnlyModifiers.Static)
- }.toMap()
+ },
+ modifier = javaModifierFromSetter(),
+ visibility = visibility.mapValues { JavaVisibility.Public },
+ type = Void,
+ extra = if (isTopLevel) setter.extra + setter.extra.mergeAdditionalModifiers(
+ sourceSets.map {
+ it to setOf(ExtraModifiers.JavaOnlyModifiers.Static)
+ }.toMap()
+ )
+ else setter.extra
)
- else setter!!.extra
- )
+ }
)
@@ -154,7 +162,7 @@ internal fun DFunction.asJava(containingClassName: String): DFunction {
else -> name
}
return copy(
-// dri = dri.copy(callable = dri.callable?.asJava()),
+ dri = dri.copy(classNames = containingClassName, callable = dri.callable?.copy(name = newName)),
name = newName,
type = type.asJava(),
modifier = if (modifier.all { (_, v) -> v is KotlinModifier.Final } && isConstructor)
@@ -193,7 +201,7 @@ private fun DTypeParameter.asJava(): DTypeParameter = copy(
bounds = bounds.map { it.asJava() }
)
-private fun Projection.asJava(): Projection = when(this) {
+private fun Projection.asJava(): Projection = when (this) {
is Star -> Star
is Covariance<*> -> copy(inner.asJava())
is Contravariance<*> -> copy(inner.asJava())
@@ -201,7 +209,7 @@ private fun Projection.asJava(): Projection = when(this) {
is Bound -> asJava()
}
-private fun Bound.asJava(): Bound = when(this) {
+private fun Bound.asJava(): Bound = when (this) {
is TypeParameter -> copy(dri.possiblyAsJava())
is GenericTypeConstructor -> copy(
dri = dri.possiblyAsJava(),
@@ -286,7 +294,7 @@ internal fun DParameter.asJava(): DParameter = copy(
)
internal fun Visibility.propertyVisibilityAsJava(): Visibility =
- if(this is JavaVisibility) this
+ if (this is JavaVisibility) this
else JavaVisibility.Private
internal fun String.getAsPrimitive(): JvmPrimitiveType? = org.jetbrains.kotlin.builtins.PrimitiveType.values()
@@ -295,7 +303,7 @@ internal fun String.getAsPrimitive(): JvmPrimitiveType? = org.jetbrains.kotlin.b
private fun DRI.partialFqName() = packageName?.let { "$it." } + classNames
private fun DRI.possiblyAsJava() = this.partialFqName().mapToJava()?.toDRI(this) ?: this
-private fun TypeConstructor.possiblyAsJava() = when(this) {
+private fun TypeConstructor.possiblyAsJava() = when (this) {
is GenericTypeConstructor -> copy(dri = this.dri.possiblyAsJava())
is FunctionalTypeConstructor -> copy(dri = this.dri.possiblyAsJava())
}
@@ -318,7 +326,7 @@ internal fun TypeConstructorWithKind.asJava(): TypeConstructorWithKind =
)
internal fun ClassKind.asJava(): ClassKind {
- return when(this){
+ return when (this) {
is JavaClassKindTypes -> this
KotlinClassKindTypes.CLASS -> JavaClassKindTypes.CLASS
KotlinClassKindTypes.INTERFACE -> JavaClassKindTypes.INTERFACE
diff --git a/plugins/kotlin-as-java/src/main/kotlin/jvmName.kt b/plugins/kotlin-as-java/src/main/kotlin/jvmName.kt
new file mode 100644
index 00000000..c81210d6
--- /dev/null
+++ b/plugins/kotlin-as-java/src/main/kotlin/jvmName.kt
@@ -0,0 +1,19 @@
+package org.jetbrains.dokka.kotlinAsJava
+
+import org.jetbrains.dokka.model.Annotations
+import org.jetbrains.dokka.model.Documentable
+import org.jetbrains.dokka.model.StringValue
+import org.jetbrains.dokka.model.isJvmName
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+
+internal fun WithExtraProperties<out Documentable>.directlyAnnotatedJvmName(): Annotations.Annotation? =
+ extra[Annotations]?.directAnnotations?.entries?.firstNotNullResult { (_, annotations) -> annotations.jvmNameAnnotation() }
+
+internal fun WithExtraProperties<out Documentable>.fileLevelJvmName(): Annotations.Annotation? =
+ extra[Annotations]?.fileLevelAnnotations?.entries?.firstNotNullResult { (_, annotations) -> annotations.jvmNameAnnotation() }
+
+internal fun List<Annotations.Annotation>.jvmNameAnnotation(): Annotations.Annotation? =
+ firstOrNull { it.isJvmName() }
+
+internal fun Annotations.Annotation.jvmNameAsString(): String? = (params["name"] as? StringValue)?.value \ No newline at end of file
diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
index 60c2e5cc..fd40366f 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
@@ -140,7 +140,7 @@ class JavaSignatureProvider internal constructor(ctcc: CommentsToContentConverte
text(it.modifiers()[it]?.toSignatureString() ?: "")
signatureForProjection(it.type)
text(nbsp.toString())
- link(it.name!!, it.dri)
+ text(it.name!!)
}
text(")")
}
diff --git a/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameDocumentableTransformer.kt b/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameDocumentableTransformer.kt
new file mode 100644
index 00000000..3fb26034
--- /dev/null
+++ b/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameDocumentableTransformer.kt
@@ -0,0 +1,96 @@
+package org.jetbrains.dokka.kotlinAsJava.transformers
+
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
+
+class JvmNameDocumentableTransformer : DocumentableTransformer {
+ private val jvmNameProvider = JvmNameProvider()
+ private lateinit var context: DokkaContext
+
+ override fun invoke(original: DModule, context: DokkaContext): DModule {
+ this.context = context
+ return original.copy(packages = original.packages.map { transform(it) })
+ }
+
+ private fun <T : Documentable> transform(documentable: T): T =
+ with(documentable) {
+ when (this) {
+ is DPackage -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ is DFunction -> {
+ val name = jvmNameProvider.nameFor(this)
+ copy(
+ dri = documentable.dri.withCallableName(name),
+ name = name
+ )
+ }
+ is DProperty -> transformGetterAndSetter(this)
+ is DClasslike -> transformClassLike(this)
+ is DEnumEntry -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ else -> {
+ context.logger.warn("Failed to translate a JvmName for ${this.javaClass.canonicalName}")
+ this
+ }
+ }
+ } as T
+
+ private fun transformClassLike(documentable: DClasslike): DClasslike =
+ with(documentable) {
+ when (this) {
+ is DClass -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ is DAnnotation -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ is DObject -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ is DEnum -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ is DInterface -> copy(
+ functions = functions.map { transform(it) },
+ properties = properties.map { transform(it) },
+ classlikes = classlikes.map { transform(it) },
+ )
+ }
+ }
+
+ private fun transformGetterAndSetter(entry: DProperty): DProperty =
+ with(entry) {
+ copy(
+ setter = jvmNameProvider.nameForSetter(this)?.let { setterName ->
+ setter?.let { setter ->
+ setter.copy(
+ dri = setter.dri.withCallableName(setterName),
+ name = setterName
+ )
+ }
+ },
+ getter = jvmNameProvider.nameForGetter(this)?.let { getterName ->
+ getter?.let { getter ->
+ getter.copy(
+ dri = getter.dri.withCallableName(getterName),
+ name = getterName
+ )
+ }
+ })
+ }
+} \ No newline at end of file
diff --git a/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameProvider.kt
new file mode 100644
index 00000000..4e0ff7d7
--- /dev/null
+++ b/plugins/kotlin-as-java/src/main/kotlin/transformers/JvmNameProvider.kt
@@ -0,0 +1,36 @@
+package org.jetbrains.dokka.kotlinAsJava.transformers
+
+import org.jetbrains.dokka.kotlinAsJava.directlyAnnotatedJvmName
+import org.jetbrains.dokka.kotlinAsJava.jvmNameAsString
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.model.properties.WithExtraProperties
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+
+data class Name(val fqName: String){
+ val name = fqName.substringAfterLast(".")
+}
+
+class JvmNameProvider {
+ fun <T> nameFor(entry: T): String where T : Documentable, T : WithExtraProperties<out Documentable> =
+ entry.directlyAnnotatedJvmName()?.jvmNameAsString()
+ ?: entry.name
+ ?: throw IllegalStateException("Failed to provide a name for ${entry.javaClass.canonicalName}")
+
+ fun <T> nameForSyntheticClass(entry: T): Name where T : WithSources, T : WithExtraProperties<out Documentable>, T: Documentable {
+ val name = entry.extra[Annotations]?.let {
+ it.fileLevelAnnotations.entries.firstNotNullResult { (_, annotations) ->
+ annotations.jvmNameAnnotation()?.jvmNameAsString()
+ }
+ } ?: entry.sources.entries.first().value.path.split("/").last().split(".").first().capitalize() + "Kt"
+ return Name("${entry.dri.packageName}.$name")
+ }
+
+ fun nameForGetter(entry: DProperty): String? =
+ entry.getter?.directlyAnnotatedJvmName()?.jvmNameAsString()
+
+ fun nameForSetter(entry: DProperty): String? =
+ entry.setter?.directlyAnnotatedJvmName()?.jvmNameAsString()
+
+ private fun List<Annotations.Annotation>.jvmNameAnnotation(): Annotations.Annotation? =
+ firstOrNull { it.isJvmName() }
+} \ No newline at end of file
diff --git a/plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt b/plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt
index 8b07670f..5916a11c 100644
--- a/plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt
+++ b/plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt
@@ -8,4 +8,4 @@ import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
class KotlinAsJavaDocumentableTransformer : DocumentableTransformer {
override fun invoke(original: DModule, context: DokkaContext): DModule =
original.copy(packages = original.packages.map { it.asJava() })
-}
+} \ No newline at end of file
diff --git a/plugins/kotlin-as-java/src/main/kotlin/transformers/withCallableName.kt b/plugins/kotlin-as-java/src/main/kotlin/transformers/withCallableName.kt
new file mode 100644
index 00000000..30f6a217
--- /dev/null
+++ b/plugins/kotlin-as-java/src/main/kotlin/transformers/withCallableName.kt
@@ -0,0 +1,5 @@
+package org.jetbrains.dokka.kotlinAsJava.transformers
+
+import org.jetbrains.dokka.links.DRI
+
+internal fun DRI.withCallableName(newName: String): DRI = copy(callable = callable?.copy(name = newName)) \ No newline at end of file