aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorMarcin Aman <marcin.aman@gmail.com>2020-12-29 14:38:19 +0100
committerGitHub <noreply@github.com>2020-12-29 14:38:19 +0100
commitf5e7cffbebb66b989c64bdda61e1f7809ddc6068 (patch)
treeea0ef4b550f9a55681a915d5cb4d9f1beca22041 /plugins
parente55f3b015faec3f62e829a2aa5984e4bd6d5037e (diff)
downloaddokka-f5e7cffbebb66b989c64bdda61e1f7809ddc6068.tar.gz
dokka-f5e7cffbebb66b989c64bdda61e1f7809ddc6068.tar.bz2
dokka-f5e7cffbebb66b989c64bdda61e1f7809ddc6068.zip
Parsing of JvmName (#1675)
* Parsing of JvmName * Make JvmName processor run after KaJ
Diffstat (limited to 'plugins')
-rw-r--r--plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt4
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/utils.kt2
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt2
-rw-r--r--plugins/base/src/main/kotlin/translators/annotationsValue.kt3
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt52
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt4
-rw-r--r--plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt46
-rw-r--r--plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt111
-rw-r--r--plugins/base/src/test/kotlin/model/ClassesTest.kt14
-rw-r--r--plugins/base/src/test/kotlin/model/FunctionsTest.kt16
-rw-r--r--plugins/base/src/test/kotlin/model/JavaTest.kt2
-rw-r--r--plugins/base/src/test/kotlin/model/PropertyTest.kt6
-rw-r--r--plugins/base/src/test/kotlin/signatures/SignatureTest.kt12
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt4
-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
-rw-r--r--plugins/kotlin-as-java/src/test/kotlin/JvmNameTest.kt158
-rw-r--r--plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt4
24 files changed, 646 insertions, 142 deletions
diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
index f934faa5..3851b39c 100644
--- a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
+++ b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
@@ -21,7 +21,7 @@ interface JvmSignatureUtils {
joinToString("") { it.name.toLowerCase() + " " }
fun <T : Documentable> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
- extra[Annotations]?.content ?: emptyMap()
+ extra[Annotations]?.directAnnotations ?: emptyMap()
private fun PageContentBuilder.DocumentableContentBuilder.annotations(
d: Documentable,
@@ -131,7 +131,7 @@ interface JvmSignatureUtils {
}
fun <T : Documentable> WithExtraProperties<T>.stylesIfDeprecated(sourceSetData: DokkaSourceSet): Set<TextStyle> =
- if (extra[Annotations]?.content?.get(sourceSetData)?.any {
+ if (extra[Annotations]?.directAnnotations?.get(sourceSetData)?.any {
it.dri == DRI("kotlin", "Deprecated")
|| it.dri == DRI("java.lang", "Deprecated")
} == true) setOf(TextStyle.Strikethrough) else emptySet()
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt b/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
index ecf75a1f..961d2aca 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
@@ -11,7 +11,7 @@ fun <T> T.isDeprecated() where T : WithExtraProperties<out Documentable> =
val <T> T.deprecatedAnnotation where T : WithExtraProperties<out Documentable>
get() = extra[Annotations]?.let { annotations ->
- annotations.content.values.flatten().firstOrNull {
+ annotations.directAnnotations.values.flatten().firstOrNull {
it.dri.toString() == "kotlin/Deprecated///PointingToDeclaration/" ||
it.dri.toString() == "java.lang/Deprecated///PointingToDeclaration/"
}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
index acff5ada..f437ebe3 100644
--- a/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
+++ b/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
@@ -69,7 +69,7 @@ class SinceKotlinTransformer(val context: DokkaContext) : DocumentableTransforme
private fun Documentable.appendSinceKotlin() =
sourceSets.fold(documentation) { acc, sourceSet ->
- safeAs<WithExtraProperties<Documentable>>()?.extra?.get(Annotations)?.content?.get(sourceSet)?.find {
+ safeAs<WithExtraProperties<Documentable>>()?.extra?.get(Annotations)?.directAnnotations?.get(sourceSet)?.find {
it.dri == DRI("kotlin", "SinceKotlin")
}?.params?.get("version").safeAs<StringValue>()?.value?.let { version ->
acc.mapValues {
diff --git a/plugins/base/src/main/kotlin/translators/annotationsValue.kt b/plugins/base/src/main/kotlin/translators/annotationsValue.kt
new file mode 100644
index 00000000..a840816a
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/annotationsValue.kt
@@ -0,0 +1,3 @@
+package org.jetbrains.dokka.base.translators
+
+internal fun unquotedValue(value: String): String = value.removeSurrounding("\"") \ 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 5185dc3e..00c9a8e1 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -10,6 +10,7 @@ import org.jetbrains.dokka.analysis.from
import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.parsers.MarkdownParser
import org.jetbrains.dokka.base.translators.isDirectlyAnException
+import org.jetbrains.dokka.base.translators.unquotedValue
import org.jetbrains.dokka.links.*
import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.model.*
@@ -19,10 +20,8 @@ import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator
-import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
import org.jetbrains.dokka.utilities.DokkaLogger
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
@@ -33,7 +32,6 @@ import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.isJvmStaticInObjectOrClassOrInterface
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassKind
-import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.idea.kdoc.findKDoc
@@ -51,8 +49,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
+import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.types.*
-import org.jetbrains.kotlin.types.model.typeConstructor
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
@@ -117,7 +115,7 @@ private class DokkaDescriptorVisitor(
}
}
- private fun <T> T.toSourceSetDependent() = mapOf(sourceSet to this)
+ private fun <T> T.toSourceSetDependent() = if(this != null) mapOf(sourceSet to this) else emptyMap()
suspend fun visitPackageFragmentDescriptor(
descriptor: PackageFragmentDescriptor,
@@ -436,13 +434,16 @@ private class DokkaDescriptorVisitor(
sourceSets = setOf(sourceSet),
generics = generics.await(),
isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(listOfNotNull(
- (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
- .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations(),
- descriptor.getDefaultValue()?.let { DefaultValue(it) },
- InheritedMember(inheritedFrom.toSourceSetDependent()),
- ))
+ extra = PropertyContainer.withAll(
+ listOfNotNull(
+ (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
+ .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
+ (descriptor.getAnnotationsWithBackingField() + descriptor.fileLevelAnnotations()).toSourceSetDependent()
+ .toAnnotations(),
+ descriptor.getDefaultValue()?.let { DefaultValue(it) },
+ InheritedMember(inheritedFrom.toSourceSetDependent()),
+ )
+ )
)
}
}
@@ -489,7 +490,7 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
InheritedMember(inheritedFrom.toSourceSetDependent()),
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ (descriptor.getAnnotations() + descriptor.fileLevelAnnotations()).toSourceSetDependent().toAnnotations(),
)
)
}
@@ -588,7 +589,7 @@ private class DokkaDescriptorVisitor(
val name = run {
val modifier = if (isGetter) "get" else "set"
val rawName = propertyDescriptor.name.asString()
- "$modifier${rawName[0].toUpperCase()}${rawName.drop(1)}"
+ "$modifier${rawName.capitalize()}"
}
val parameters =
@@ -782,8 +783,7 @@ private class DokkaDescriptorVisitor(
private suspend fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? =
map { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name")
- .safeAs<StringValue>()?.value?.drop(1)
- ?.dropLast(1) // Dropping enclosing doublequotes because we don't want to have it in our custom signature serializer
+ .safeAs<StringValue>()?.value?.let { unquotedValue(it) }
private suspend fun KotlinType.toBound(): Bound = when (this) {
@@ -928,19 +928,25 @@ private class DokkaDescriptorVisitor(
)
}
}
- else -> StringValue(toString())
+ else -> StringValue(unquotedValue(toString()))
}
- private suspend fun AnnotationDescriptor.toAnnotation(): Annotations.Annotation {
+ private suspend fun AnnotationDescriptor.toAnnotation(scope: Annotations.AnnotationScope = Annotations.AnnotationScope.DIRECT): Annotations.Annotation {
+ val dri = DRI.from(annotationClass as DeclarationDescriptor)
return Annotations.Annotation(
DRI.from(annotationClass as DeclarationDescriptor),
allValueArguments.map { it.key.asString() to it.value.toValue() }.filter {
it.second != null
}.toMap() as Map<String, AnnotationParameterValue>,
- annotationClass!!.annotations.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented"))
+ mustBeDocumented(dri),
+ scope
)
}
+ private fun AnnotationDescriptor.mustBeDocumented(dri: DRI): Boolean =
+ if (dri.isJvmName()) false
+ else annotationClass!!.annotations.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented"))
+
private suspend fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> =
getAnnotations() + (backingField?.getAnnotations() ?: emptyList())
@@ -1004,6 +1010,14 @@ private class DokkaDescriptorVisitor(
private fun ConstantsEnumValue.fullEnumEntryName() =
"${this.enumClassId.relativeClassName.asString()}.${this.enumEntryName.identifier}"
+
+ private fun DeclarationDescriptorWithSource.ktFile(): KtFile? = (source.containingFile as? PsiSourceFile)?.psiFile as? KtFile
+
+ private suspend fun DeclarationDescriptorWithSource.fileLevelAnnotations() = ktFile()
+ ?.let { file -> resolutionFacade.resolveSession.getFileAnnotations(file) }
+ ?.toList()
+ .orEmpty()
+ .parallelMap { it.toAnnotation(scope = Annotations.AnnotationScope.FILE) }
}
private data class AncestryLevel(
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 9a1b05d5..cd51e9dd 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -17,6 +17,7 @@ import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.translators.isDirectlyAnException
import org.jetbrains.dokka.base.translators.psi.parsers.JavaDocumentationParser
import org.jetbrains.dokka.base.translators.psi.parsers.JavadocParser
+import org.jetbrains.dokka.base.translators.unquotedValue
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.nextTarget
import org.jetbrains.dokka.links.withClass
@@ -530,6 +531,9 @@ class DefaultPsiToDocumentableTranslator(
private fun JvmAnnotationAttribute.toValue(): AnnotationParameterValue = when (this) {
is PsiNameValuePair -> value?.toValue() ?: StringValue("")
else -> StringValue(this.attributeName)
+ }.let { annotationValue ->
+ if (annotationValue is StringValue) annotationValue.copy(unquotedValue(annotationValue.value))
+ else annotationValue
}
private fun PsiAnnotationMemberValue.toValue(): AnnotationParameterValue? = when (this) {
diff --git a/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt b/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt
index b90c7350..d88d9505 100644
--- a/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt
+++ b/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt
@@ -4,10 +4,16 @@ import matchers.content.*
import org.jetbrains.dokka.pages.ContentPage
import org.jetbrains.dokka.pages.PackagePageNode
import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.Annotations
+import org.jetbrains.dokka.model.StringValue
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.junit.jupiter.api.Test
import utils.ParamAttributes
import utils.bareSignature
import utils.propertySignature
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
class ContentForAnnotationsTest : BaseAbstractTest() {
@@ -18,6 +24,7 @@ class ContentForAnnotationsTest : BaseAbstractTest() {
sourceSet {
sourceRoots = listOf("src/")
analysisPlatform = "jvm"
+ classpath += jvmStdlibPath!!
}
}
}
@@ -218,4 +225,43 @@ class ContentForAnnotationsTest : BaseAbstractTest() {
}
}
}
+
+ @Test
+ fun `JvmName for property with setter and getter`(){
+ testInline(
+ """
+ |/src/main/kotlin/test/source.kt
+ |package test
+ |@get:JvmName("xd")
+ |@set:JvmName("asd")
+ |var property: String
+ | get() = ""
+ | set(value) {}
+ """.trimIndent(), testConfiguration) {
+ documentablesCreationStage = { modules ->
+ fun expectedAnnotation(name: String) = Annotations.Annotation(
+ dri = DRI("kotlin.jvm", "JvmName"),
+ params = mapOf("name" to StringValue(name)),
+ scope = Annotations.AnnotationScope.DIRECT,
+ mustBeDocumented = false
+ )
+
+ val property = modules.flatMap { it.packages }.flatMap { it.properties }.first()
+ val getterAnnotation = property.getter?.extra?.get(Annotations)?.let {
+ it.directAnnotations.entries.firstNotNullResult { (_, annotations) -> annotations.firstOrNull() }
+ }
+ val setterAnnotation = property.getter?.extra?.get(Annotations)?.let {
+ it.directAnnotations.entries.firstNotNullResult { (_, annotations) -> annotations.firstOrNull() }
+ }
+
+ assertEquals(expectedAnnotation("xd"), getterAnnotation)
+ assertFalse(getterAnnotation?.mustBeDocumented!!)
+ assertEquals(Annotations.AnnotationScope.DIRECT, getterAnnotation.scope)
+
+ assertEquals(expectedAnnotation("asd"), setterAnnotation)
+ assertFalse(setterAnnotation?.mustBeDocumented!!)
+ assertEquals(Annotations.AnnotationScope.DIRECT, setterAnnotation.scope)
+ }
+ }
+ }
}
diff --git a/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt b/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt
new file mode 100644
index 00000000..f2fd518c
--- /dev/null
+++ b/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt
@@ -0,0 +1,111 @@
+package content.annotations
+
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.Annotations
+import org.jetbrains.dokka.model.StringValue
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
+import kotlin.test.assertEquals
+
+class FileLevelJvmNameTest : BaseAbstractTest() {
+ private val testConfiguration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ analysisPlatform = "jvm"
+ classpath += jvmStdlibPath!!
+ }
+ }
+ }
+
+ companion object {
+ private const val functionTest =
+ """
+ |/src/main/kotlin/test/source.kt
+ |@file:JvmName("CustomJvmName")
+ |package test
+ |
+ |fun function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """
+
+ private const val extensionFunctionTest =
+ """
+ |/src/main/kotlin/test/source.kt
+ |@file:JvmName("CustomJvmName")
+ |package test
+ |
+ |fun String.function(abc: String): String {
+ | return "Hello, " + abc
+ |}
+ """
+
+ private const val propertyTest =
+ """
+ |/src/main/kotlin/test/source.kt
+ |@file:JvmName("CustomJvmName")
+ |package test
+ |
+ |val property: String
+ | get() = ""
+ """
+
+ private const val extensionPropertyTest =
+ """
+ |/src/main/kotlin/test/source.kt
+ |@file:JvmName("CustomJvmName")
+ |package test
+ |
+ |val String.property: String
+ | get() = ""
+ """
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [functionTest, extensionFunctionTest])
+ fun `jvm name should be included in functions extra`(query: String) {
+ testInline(
+ query.trimIndent(), testConfiguration
+ ) {
+ documentablesCreationStage = { modules ->
+ val expectedAnnotation = Annotations.Annotation(
+ dri = DRI("kotlin.jvm", "JvmName"),
+ params = mapOf("name" to StringValue("CustomJvmName")),
+ scope = Annotations.AnnotationScope.FILE,
+ mustBeDocumented = false
+ )
+ val function = modules.flatMap { it.packages }.first().functions.first()
+ val annotation = function.extra[Annotations]?.fileLevelAnnotations?.entries?.first()?.value?.single()
+ assertEquals(emptyMap(), function.extra[Annotations]?.directAnnotations)
+ assertEquals(expectedAnnotation, annotation)
+ assertEquals(expectedAnnotation.scope, annotation?.scope)
+ assertEquals(expectedAnnotation.mustBeDocumented, annotation?.mustBeDocumented)
+ }
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = [propertyTest, extensionPropertyTest])
+ fun `jvm name should be included in properties extra`(query: String) {
+ testInline(
+ query.trimIndent(), testConfiguration
+ ) {
+ documentablesCreationStage = { modules ->
+ val expectedAnnotation = Annotations.Annotation(
+ dri = DRI("kotlin.jvm", "JvmName"),
+ params = mapOf("name" to StringValue("CustomJvmName")),
+ scope = Annotations.AnnotationScope.FILE,
+ mustBeDocumented = false
+ )
+ val properties = modules.flatMap { it.packages }.first().properties.first()
+ val annotation = properties.extra[Annotations]?.fileLevelAnnotations?.entries?.first()?.value?.single()
+ assertEquals(emptyMap(), properties.extra[Annotations]?.directAnnotations)
+ assertEquals(expectedAnnotation, annotation)
+ assertEquals(expectedAnnotation.scope, annotation?.scope)
+ assertEquals(expectedAnnotation.mustBeDocumented, annotation?.mustBeDocumented)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt
index b6787126..2260a46f 100644
--- a/plugins/base/src/test/kotlin/model/ClassesTest.kt
+++ b/plugins/base/src/test/kotlin/model/ClassesTest.kt
@@ -182,12 +182,12 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
"""
) {
with((this / "classes" / "Foo").cast<DClass>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "Deprecated"
params.entries counts 1
- (params["message"].assertNotNull("message") as StringValue).value equals "\"should no longer be used\""
+ (params["message"].assertNotNull("message") as StringValue).value equals "should no longer be used"
}
}
}
@@ -361,12 +361,12 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
"""
) {
with((this / "classes" / "C").cast<DClass>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "SinceKotlin"
params.entries counts 1
- (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ (params["version"].assertNotNull("version") as StringValue).value equals "1.1"
}
}
}
@@ -426,9 +426,9 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
"""@Suppress("abc") class Foo() {}"""
) {
with((this / "classes" / "Foo").cast<DClass>()) {
- with(extra[Annotations]?.content?.values?.firstOrNull()?.firstOrNull().assertNotNull("annotations")) {
+ with(extra[Annotations]?.directAnnotations?.values?.firstOrNull()?.firstOrNull().assertNotNull("annotations")) {
dri.toString() equals "kotlin/Suppress///PointingToDeclaration/"
- (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("\"abc\""))
+ (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("abc"))
}
}
}
@@ -446,7 +446,7 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
"""
) {
with((this / "classes" / "throws").cast<DAnnotation>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "Retention"
diff --git a/plugins/base/src/test/kotlin/model/FunctionsTest.kt b/plugins/base/src/test/kotlin/model/FunctionsTest.kt
index 9fffb4fc..ac9b6d7d 100644
--- a/plugins/base/src/test/kotlin/model/FunctionsTest.kt
+++ b/plugins/base/src/test/kotlin/model/FunctionsTest.kt
@@ -141,12 +141,12 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
"""
) {
with((this / "function" / "f").cast<DFunction>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "Suppress"
params.entries counts 1
- (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("\"FOO\""))
+ (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("FOO"))
}
}
}
@@ -226,7 +226,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
"""
) {
with((this / "function" / "Fancy").cast<DAnnotation>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 3
with(map { it.dri.classNames to it }.toMap()) {
with(this["Target"].assertNotNull("Target")) {
@@ -249,7 +249,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
}
with((this / "function" / "function" / "notInlined").cast<DParameter>()) {
- with(this.extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(this.extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "Fancy"
@@ -296,7 +296,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
}
}
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 3
with(map { it.dri.classNames to it }.toMap()) {
with(this["Target"].assertNotNull("Target")) {
@@ -319,7 +319,7 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
}
with((this / "function" / "f").cast<DFunction>()) {
- with(this.extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(this.extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(this.first()) {
dri.classNames equals "Fancy"
@@ -381,12 +381,12 @@ class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "fun
"""
) {
with((this / "function" / "f").cast<DFunction>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "SinceKotlin"
params.entries counts 1
- (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ (params["version"].assertNotNull("version") as StringValue).value equals "1.1"
}
}
}
diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt
index 18927218..beb7c8e4 100644
--- a/plugins/base/src/test/kotlin/model/JavaTest.kt
+++ b/plugins/base/src/test/kotlin/model/JavaTest.kt
@@ -274,7 +274,7 @@ class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
"""
) {
with((this / "java" / "Attribute").cast<DAnnotation>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
with(single()) {
dri.classNames equals "Target"
(params["value"].assertNotNull("value") as ArrayValue).value equals listOf(
diff --git a/plugins/base/src/test/kotlin/model/PropertyTest.kt b/plugins/base/src/test/kotlin/model/PropertyTest.kt
index af952b43..8474116f 100644
--- a/plugins/base/src/test/kotlin/model/PropertyTest.kt
+++ b/plugins/base/src/test/kotlin/model/PropertyTest.kt
@@ -150,12 +150,12 @@ class PropertyTest : AbstractModelTest("/src/main/kotlin/property/Test.kt", "pro
"""
) {
with((this / "property" / "prop").cast<DProperty>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "SinceKotlin"
params.entries counts 1
- (params["version"].assertNotNull("version") as StringValue).value equals "\"1.1\""
+ (params["version"].assertNotNull("version") as StringValue).value equals "1.1"
}
}
}
@@ -178,7 +178,7 @@ class PropertyTest : AbstractModelTest("/src/main/kotlin/property/Test.kt", "pro
}
) {
with((this / "property" / "property").cast<DProperty>()) {
- with(extra[Annotations]!!.content.entries.single().value.assertNotNull("Annotations")) {
+ with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) {
this counts 1
with(first()) {
dri.classNames equals "Strictfp"
diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt
index ba4b631f..f9d95f46 100644
--- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt
+++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt
@@ -1,11 +1,7 @@
package signatures
-import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaSourceSetID
-import org.jetbrains.dokka.jdk
import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Element
import org.junit.jupiter.api.Test
import utils.*
@@ -295,7 +291,7 @@ class SignatureTest : BaseAbstractTest() {
.firstSignature()
.match(
Div(
- Div("@", A("Marking"), "(", Span("msg = ", Span("\"Nenya\"")), Wbr, ")"),
+ Div("@", A("Marking"), "(", Span("msg = ", Span("Nenya")), Wbr, ")"),
Div("@", A("Marking2"), "(", Span("int = ", Span("1")), Wbr, ")")
),
"fun ", A("simpleFun"),
@@ -332,9 +328,9 @@ class SignatureTest : BaseAbstractTest() {
Div(
"@", A("Marking"), "(", Span(
"msg = [",
- Span(Span("\"Nenya\""), ", "), Wbr,
- Span(Span("\"Vilya\""), ", "), Wbr,
- Span(Span("\"Narya\"")), Wbr, "]"
+ Span(Span("Nenya"), ", "), Wbr,
+ Span(Span("Vilya"), ", "), Wbr,
+ Span(Span("Narya")), Wbr, "]"
), Wbr, ")"
)
),
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
index 2fb1ae0e..6535a22d 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocClasslikeTemplateMapTest.kt
@@ -149,13 +149,13 @@ internal class JavadocClasslikeTemplateMapTest : AbstractJavadocTemplateMapTest(
val map = allPagesOfType<JavadocClasslikePageNode>().first { it.name == "TestClass" }.templateMap
assertEquals("TestClass", map["name"])
val signature = assertIsInstance<Map<String, Any?>>(map["signature"])
- assertEquals("@<a href=Author.html>Author</a>(name = \"Benjamin Franklin\")", signature["annotations"])
+ assertEquals("@<a href=Author.html>Author</a>(name = Benjamin Franklin)", signature["annotations"])
val methods = assertIsInstance<Map<Any, Any?>>(map["methods"])
val ownMethods = assertIsInstance<List<*>>(methods["own"])
val method = assertIsInstance<Map<String, Any?>>(ownMethods.single())
val methodSignature = assertIsInstance<Map<String, Any?>>(method["signature"])
- assertEquals("@<a href=Author.html>Author</a>(name = \"Franklin D. Roosevelt\")", methodSignature["annotations"])
+ assertEquals("@<a href=Author.html>Author</a>(name = Franklin D. Roosevelt)", methodSignature["annotations"])
}
}
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
diff --git a/plugins/kotlin-as-java/src/test/kotlin/JvmNameTest.kt b/plugins/kotlin-as-java/src/test/kotlin/JvmNameTest.kt
new file mode 100644
index 00000000..4c7e2445
--- /dev/null
+++ b/plugins/kotlin-as-java/src/test/kotlin/JvmNameTest.kt
@@ -0,0 +1,158 @@
+package kotlinAsJavaPlugin
+
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.TypeConstructor
+import org.junit.jupiter.api.Test
+import kotlin.test.assertEquals
+
+class JvmNameTest : BaseAbstractTest() {
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/")
+ classpath += jvmStdlibPath!!
+ }
+ }
+ }
+
+ @Test
+ fun `should change name for class containing top level function`() {
+ testInline(
+ """
+ |/src/main/kotlin/kotlinAsJavaPlugin/sample.kt
+ |@file:JvmName("CustomJvmName")
+ |package kotlinAsJavaPlugin
+ |fun sample(): String = ""
+ """.trimMargin(),
+ configuration,
+ ) {
+ documentablesTransformationStage = { module ->
+ val expectedClassLikeDri = DRI(
+ packageName = "kotlinAsJavaPlugin",
+ classNames = "CustomJvmName",
+ )
+ val classLike = module.packages.flatMap { it.classlikes }.first()
+ assertEquals(expectedClassLikeDri, classLike.dri)
+ assertEquals("CustomJvmName", classLike.name)
+ }
+ }
+ }
+
+ @Test
+ fun `should change name for top level function`() {
+ testInline(
+ """
+ |/src/main/kotlin/kotlinAsJavaPlugin/sample.kt
+ |@file:JvmName("CustomJvmName")
+ |package kotlinAsJavaPlugin
+ |@JvmName("jvmSample")
+ |fun sample(): String = ""
+ """.trimMargin(),
+ configuration,
+ ) {
+ documentablesTransformationStage = { module ->
+ val expectedFunctionDri = DRI(
+ packageName = "kotlinAsJavaPlugin",
+ classNames = "CustomJvmName",
+ callable = Callable(
+ "jvmSample",
+ receiver = null,
+ params = emptyList()
+ )
+ )
+ val function = module.packages.flatMap { it.classlikes }.flatMap { it.functions }.first()
+ assertEquals(expectedFunctionDri, function.dri)
+ assertEquals("jvmSample", function.name)
+ }
+ }
+ }
+
+ @Test
+ fun `should change name of a setter for top level property`() {
+ testInline(
+ """
+ |/src/main/kotlin/kotlinAsJavaPlugin/sample.kt
+ |@file:JvmName("CustomJvmName")
+ |package kotlinAsJavaPlugin
+ |@get:JvmName("xd")
+ |@set:JvmName("asd")
+ |var property: String
+ | get() = ""
+ | set(value) {}
+ """.trimMargin(),
+ configuration,
+ ) {
+ documentablesTransformationStage = { module ->
+ val expectedSetterDri = DRI(
+ packageName = "kotlinAsJavaPlugin",
+ classNames = "CustomJvmName",
+ callable = Callable(
+ "asd",
+ receiver = null,
+ //Todo this is bad, this should be a type in java, look at the bytecode
+ params = listOf(TypeConstructor("kotlin.String", emptyList()))
+ )
+ )
+ val function = module.packages.flatMap { it.classlikes }.flatMap { it.functions }.first { it.name == "asd"}
+ assertEquals(expectedSetterDri, function.dri)
+ assertEquals("asd", function.name)
+ }
+ }
+ }
+
+ @Test
+ fun `should change name of a getter for top level property`() {
+ testInline(
+ """
+ |/src/main/kotlin/kotlinAsJavaPlugin/sample.kt
+ |@file:JvmName("CustomJvmName")
+ |package kotlinAsJavaPlugin
+ |@get:JvmName("xd")
+ |@set:JvmName("asd")
+ |var property: String
+ | get() = ""
+ | set(value) {}
+ """.trimMargin(),
+ configuration,
+ ) {
+ documentablesTransformationStage = { module ->
+ val expectedGetterDri = DRI(
+ packageName = "kotlinAsJavaPlugin",
+ classNames = "CustomJvmName",
+ callable = Callable(
+ "xd",
+ receiver = null,
+ params = emptyList()
+ )
+ )
+ val function = module.packages.flatMap { it.classlikes }.flatMap { it.functions }.first { it.name == "xd"}
+ assertEquals(expectedGetterDri, function.dri)
+ assertEquals("xd", function.name)
+ }
+ }
+ }
+
+ @Test
+ fun `should leave the name as default if annotation is not provided`() {
+ testInline(
+ """
+ |/src/main/kotlin/kotlinAsJavaPlugin/sample.kt
+ |package kotlinAsJavaPlugin
+ |fun sample(): String = ""
+ """.trimMargin(),
+ configuration,
+ ) {
+ documentablesTransformationStage = { module ->
+ val expectedClassLikeDri = DRI(
+ packageName = "kotlinAsJavaPlugin",
+ classNames = "SampleKt",
+ )
+ val classLike = module.packages.flatMap { it.classlikes }.first()
+ assertEquals(expectedClassLikeDri, classLike.dri)
+ assertEquals("SampleKt", classLike.name)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
index 5430ea88..8e7b798a 100644
--- a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
+++ b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
@@ -330,7 +330,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() {
) {
renderingStage = { _, _ ->
writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match(
- "final ", A("Integer"), A("someFun"), "(", A("Integer"), A("xd"), ")", Span()
+ "final ", A("Integer"), A("someFun"), "(", A("Integer"), "xd)", Span()
)
}
}
@@ -368,7 +368,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() {
renderingStage = { _, _ ->
writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match(
"final ", A("Integer"), A("someFun"), "(", A("Map"), "<", A("String"),
- ", ", A("Integer"), ">", A("xd"), ")", Span()
+ ", ", A("Integer"), "> xd)", Span()
)
}
}