aboutsummaryrefslogtreecommitdiff
path: root/plugins/base
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base')
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt23
-rw-r--r--plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt61
-rw-r--r--plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt56
3 files changed, 126 insertions, 14 deletions
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 7acf735a..4b2d7720 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -209,7 +209,13 @@ class DefaultPsiToDocumentableTranslator(
return AncestryNode(
typeConstructor = GenericTypeConstructor(
DRI.from(psiClass),
- psiClass.typeParameters.map(::getProjection)
+ psiClass.typeParameters.map { typeParameter ->
+ TypeParameter(
+ dri = DRI.from(typeParameter),
+ name = typeParameter.name.orEmpty(),
+ extra = typeParameter.annotations()
+ )
+ }
),
superclass = classes.singleOrNull()?.first?.let(::traversePsiClassForAncestorsAndInheritedMembers),
interfaces = interfaces.map { traversePsiClassForAncestorsAndInheritedMembers(it.first) }
@@ -439,20 +445,19 @@ class DefaultPsiToDocumentableTranslator(
PropertyContainer.withAll(annotations.toSourceSetDependent().toAnnotations())
} ?: PropertyContainer.empty()
- private fun getProjection(type: PsiTypeParameter) =
- TypeParameter(
- dri = DRI.from(type),
- name = type.name.orEmpty(),
- extra = type.annotations()
- )
-
private fun getBound(type: PsiType): Bound {
fun bound() = when (type) {
is PsiClassReferenceType ->
type.resolve()?.let { resolved ->
when {
resolved.qualifiedName == "java.lang.Object" -> JavaObject(type.annotations())
- resolved is PsiTypeParameter -> getProjection(resolved)
+ resolved is PsiTypeParameter -> {
+ TypeParameter(
+ dri = DRI.from(resolved),
+ name = resolved.name.orEmpty(),
+ extra = type.annotations()
+ )
+ }
Regex("kotlin\\.jvm\\.functions\\.Function.*").matches(resolved.qualifiedName ?: "") ||
Regex("java\\.util\\.function\\.Function.*").matches(
resolved.qualifiedName ?: ""
diff --git a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt b/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt
index 3e5c8176..d6564343 100644
--- a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt
+++ b/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt
@@ -1,11 +1,13 @@
package model.annotations
+import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.utilities.cast
import org.junit.jupiter.api.Test
import utils.AbstractModelTest
-import kotlin.test.Ignore
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
class JavaAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
@@ -114,4 +116,61 @@ class JavaAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/jav
}
}
}
+
+ @Test
+ fun `type parameter annotations should be visible even if type declaration has none`() {
+ inlineModelTest(
+ """
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target(ElementType.PARAMETER)
+ |public @interface Hello {
+ | public String bar() default "";
+ |}
+ |public class Test {
+ | public <T> void foo(java.util.List<@Hello T> param) {}
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "foo").cast<DFunction>()) {
+ val paramAnnotations = parameters.first()
+ .type.cast<GenericTypeConstructor>()
+ .projections.first().cast<TypeParameter>()
+ .annotations()
+ .values
+ .flatten()
+
+ assertEquals(1, paramAnnotations.size)
+ assertEquals(DRI("java", "Hello"), paramAnnotations[0].dri)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `type parameter annotations should not be propagated from resolved type`() {
+ inlineModelTest(
+ """
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target(ElementType.PARAMETER)
+ |public @interface Hello {
+ | public String bar() default "";
+ |}
+ |public class Test {
+ | public <@Hello T> void foo(java.util.List<T> param) {}
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "foo").cast<DFunction>()) {
+ val paramAnnotations = parameters.first()
+ .type.cast<GenericTypeConstructor>()
+ .projections.first().cast<TypeParameter>()
+ .annotations()
+
+ assertTrue(paramAnnotations.isEmpty())
+ }
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt b/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt
index e88d7353..c459cc34 100644
--- a/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt
+++ b/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt
@@ -1,13 +1,13 @@
package model.annotations
+import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations
import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.Annotations
-import org.jetbrains.dokka.model.DFunction
-import org.jetbrains.dokka.model.DProperty
-import org.jetbrains.dokka.model.GenericTypeConstructor
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.utilities.cast
import org.junit.jupiter.api.Test
import utils.AbstractModelTest
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
class KotlinAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/annotations/Test.kt", "annotations") {
@Test
@@ -50,4 +50,52 @@ class KotlinAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/a
}
}
}
+
+ @Test
+ fun `type parameter annotations should be visible even if type declaration has none`() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE)
+ |annotation class Hello
+ |
+ |fun <T> foo(param: List<@Hello T>) {}
+ """.trimIndent()
+ ) {
+ with((this / "annotations" / "foo").cast<DFunction>()) {
+ val paramAnnotations = parameters.first()
+ .type.cast<GenericTypeConstructor>()
+ .projections
+ .first().cast<Invariance<TypeParameter>>()
+ .inner.cast<TypeParameter>()
+ .annotations()
+ .values
+ .flatten()
+
+ assertEquals(1, paramAnnotations.size)
+ assertEquals(DRI("annotations", "Hello"), paramAnnotations[0].dri)
+ }
+ }
+ }
+
+ @Test
+ fun `type parameter annotations should not be propagated from resolved type`() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE)
+ |annotation class Hello
+ |
+ |fun <@Hello T> foo(param: List<T>) {}
+ """.trimIndent()
+ ) {
+ with((this / "annotations" / "foo").cast<DFunction>()) {
+ val paramAnnotations = parameters.first()
+ .type.cast<GenericTypeConstructor>()
+ .projections.first().cast<Invariance<TypeParameter>>()
+ .inner.cast<TypeParameter>()
+ .annotations()
+
+ assertTrue(paramAnnotations.isEmpty())
+ }
+ }
+ }
} \ No newline at end of file