aboutsummaryrefslogtreecommitdiff
path: root/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /dokka-subprojects/plugin-base/src/test/kotlin/model/annotations
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'dokka-subprojects/plugin-base/src/test/kotlin/model/annotations')
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt181
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt195
-rw-r--r--dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt105
3 files changed, 481 insertions, 0 deletions
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt
new file mode 100644
index 00000000..9800006b
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+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 utils.AbstractModelTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class JavaAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
+
+ @Test
+ fun `function with deprecated parameter`() {
+ inlineModelTest(
+ """
+ |public class Test {
+ | public void fn(@Deprecated String name) {}
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "fn").cast<DFunction>()) {
+ val dri =
+ parameters.first().extra[Annotations]?.directAnnotations?.flatMap { it.value }?.map { it.dri }
+ assertEquals(listOf(DRI("java.lang", "Deprecated")), dri)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with parameter that has custom annotation`() {
+ inlineModelTest(
+ """
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target(ElementType.PARAMETER)
+ |public @interface Hello {
+ | public String bar() default "";
+ |}
+ |public class Test {
+ | public void foo(@Hello(bar = "baz") String arg){ }
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "foo").cast<DFunction>()) {
+ val annotations =
+ parameters.first().extra[Annotations]?.directAnnotations?.flatMap { it.value }
+ val driOfHello = DRI("java", "Hello")
+ val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList()
+
+ assertEquals(listOf(driOfHello), annotations?.map { it.dri })
+ assertEquals(listOf("baz"), annotationsValues)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with annotated generic parameter`() {
+ inlineModelTest(
+ """
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target(ElementType.TYPE_PARAMETER)
+ |@interface Hello {
+ | public String bar() default "";
+ |}
+ |public class Test {
+ | public <@Hello(bar = "baz") T> List<T> foo() {
+ | return null;
+ | }
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "foo").cast<DFunction>()) {
+ val annotations = generics.first().extra[Annotations]?.directAnnotations?.flatMap { it.value }
+ val driOfHello = DRI("java", "Hello")
+ val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList()
+
+ assertEquals(listOf(driOfHello), annotations?.map { it.dri })
+ assertEquals(listOf("baz"), annotationsValues)
+ }
+ }
+ }
+ }
+
+ @Test
+ fun `function with generic parameter that has annotated bounds`() {
+ inlineModelTest(
+ """
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target({ElementType.TYPE_USE})
+ |@interface Hello {
+ | public String bar() default "";
+ |}
+ |public class Test {
+ | public <T extends @Hello(bar = "baz") String> List<T> foo() {
+ | return null;
+ | }
+ |}
+ """.trimIndent()
+ ) {
+ with((this / "java" / "Test").cast<DClass>()) {
+ with((this / "foo").cast<DFunction>()) {
+ val annotations = ((generics.first().bounds.first() as Nullable).inner as GenericTypeConstructor)
+ .extra[Annotations]?.directAnnotations?.flatMap { it.value }
+ val driOfHello = DRI("java", "Hello")
+ val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList()
+
+ assertEquals(listOf(driOfHello), annotations?.map { it.dri })
+ assertEquals(listOf("baz"), annotationsValues)
+ }
+ }
+ }
+ }
+
+ @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())
+ }
+ }
+ }
+ }
+}
+
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt
new file mode 100644
index 00000000..daab7dc9
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package model.annotations
+
+import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
+import org.jetbrains.dokka.model.*
+import translators.findClasslike
+import kotlin.test.*
+
+class JavaAnnotationsTest : BaseAbstractTest() {
+
+ val configuration = dokkaConfiguration {
+ sourceSets {
+ sourceSet {
+ sourceRoots = listOf("src/main/java")
+ }
+ }
+ }
+
+ @Test // see https://github.com/Kotlin/dokka/issues/2350
+ fun `should hande array used as annotation param value`() {
+ testInline(
+ """
+ |/src/main/java/annotation/TestClass.java
+ |package annotation;
+ |public class TestClass {
+ | @SimpleAnnotation(clazz = String[].class)
+ | public boolean simpleAnnotation() {
+ | return false;
+ | }
+ |}
+ |
+ |/src/main/java/annotation/SimpleAnnotation.java
+ |package annotation;
+ |@Retention(RetentionPolicy.RUNTIME)
+ |@Target(ElementType.METHOD)
+ |public @interface SimpleAnnotation {
+ | Class<?> clazz();
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesTransformationStage = { module ->
+ val testClass = module.findClasslike("annotation", "TestClass") as DClass
+ assertNotNull(testClass)
+
+ val annotatedFunction = testClass.functions.single { it.name == "simpleAnnotation" }
+ val annotation =
+ annotatedFunction.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single()
+ assertNotNull(annotation) { "Expected to find an annotation on simpleAnnotation function, found none" }
+ assertEquals("annotation", annotation.dri.packageName)
+ assertEquals("SimpleAnnotation", annotation.dri.classNames)
+ assertEquals(1, annotation.params.size)
+
+ val param = annotation.params.values.single()
+ assertTrue(param is ClassValue)
+ // should probably be Array instead
+ // String matches parsing of Kotlin sources as of now
+ assertEquals("String", param.className)
+ assertEquals("java.lang", param.classDRI.packageName)
+ assertEquals("String", param.classDRI.classNames)
+ }
+ }
+ }
+
+ @Test // see https://github.com/Kotlin/dokka/issues/2551
+ fun `should hande annotation used within annotation params with class param value`() {
+ testInline(
+ """
+ |/src/main/java/annotation/TestClass.java
+ |package annotation;
+ |public class TestClass {
+ | @XmlElementRefs({
+ | @XmlElementRef(name = "NotOffered", namespace = "http://www.gaeb.de/GAEB_DA_XML/DA86/3.3", type = JAXBElement.class, required = false)
+ | })
+ | public List<JAXBElement<Object>> content;
+ |}
+ |
+ |/src/main/java/annotation/XmlElementRefs.java
+ |package annotation;
+ |public @interface XmlElementRefs {
+ | XmlElementRef[] value();
+ |}
+ |
+ |/src/main/java/annotation/XmlElementRef.java
+ |package annotation;
+ |public @interface XmlElementRef {
+ | String name();
+ |
+ | String namespace();
+ |
+ | boolean required();
+ |
+ | Class<JAXBElement> type();
+ |}
+ |
+ |/src/main/java/annotation/JAXBElement.java
+ |package annotation;
+ |public class JAXBElement<T> {
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesTransformationStage = { module ->
+ val testClass = module.findClasslike("annotation", "TestClass") as DClass
+ assertNotNull(testClass)
+
+ val contentField = testClass.properties.find { it.name == "content" }
+ assertNotNull(contentField)
+
+ val annotation = contentField.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single()
+ assertNotNull(annotation) { "Expected to find an annotation on content field, found none" }
+ assertEquals("XmlElementRefs", annotation.dri.classNames)
+ assertEquals(1, annotation.params.size)
+
+ val arrayParam = annotation.params.values.single()
+ assertTrue(arrayParam is ArrayValue, "Expected single annotation param to be array")
+ assertEquals(1, arrayParam.value.size)
+
+ val arrayParamValue = arrayParam.value.single()
+ assertTrue(arrayParamValue is AnnotationValue)
+
+ val arrayParamAnnotationValue = arrayParamValue.annotation
+ assertEquals(4, arrayParamAnnotationValue.params.size)
+ assertEquals("XmlElementRef", arrayParamAnnotationValue.dri.classNames)
+
+ val annotationParams = arrayParamAnnotationValue.params.values.toList()
+
+ val nameParam = annotationParams[0]
+ assertTrue(nameParam is StringValue)
+ assertEquals("NotOffered", nameParam.value)
+
+ val namespaceParam = annotationParams[1]
+ assertTrue(namespaceParam is StringValue)
+ assertEquals("http://www.gaeb.de/GAEB_DA_XML/DA86/3.3", namespaceParam.value)
+
+ val typeParam = annotationParams[2]
+ assertTrue(typeParam is ClassValue)
+ assertEquals("JAXBElement", typeParam.className)
+ assertEquals("annotation", typeParam.classDRI.packageName)
+ assertEquals("JAXBElement", typeParam.classDRI.classNames)
+
+ val requiredParam = annotationParams[3]
+ assertTrue(requiredParam is BooleanValue)
+ assertFalse(requiredParam.value)
+ }
+ }
+ }
+
+ @Test // see https://github.com/Kotlin/dokka/issues/2509
+ fun `should handle generic class in annotation`() {
+ testInline(
+ """
+ |/src/main/java/annotation/Breaking.java
+ |package annotation;
+ |public class Breaking<Y> {
+ |}
+ |
+ |/src/main/java/annotation/TestAnnotate.java
+ |package annotation;
+ |public @interface TestAnnotate {
+ | Class<?> value();
+ |}
+ |
+ |/src/main/java/annotation/TestClass.java
+ |package annotation;
+ |@TestAnnotate(Breaking.class)
+ |public class TestClass {
+ |}
+ """.trimIndent(),
+ configuration
+ ) {
+ documentablesTransformationStage = { module ->
+ val testClass = module.findClasslike("annotation", "TestClass") as DClass
+ assertNotNull(testClass)
+
+ val annotation = testClass.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single()
+ assertNotNull(annotation) { "Expected to find an annotation on TestClass, found none" }
+
+ assertEquals("TestAnnotate", annotation.dri.classNames)
+ assertEquals(1, annotation.params.size)
+
+ val valueParameter = annotation.params.values.single()
+ assertTrue(valueParameter is ClassValue)
+
+ assertEquals("Breaking", valueParameter.className)
+
+ assertEquals("annotation", valueParameter.classDRI.packageName)
+ assertEquals("Breaking", valueParameter.classDRI.classNames)
+ }
+ }
+ }
+}
diff --git a/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt
new file mode 100644
index 00000000..e3b17818
--- /dev/null
+++ b/dokka-subprojects/plugin-base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+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 utils.AbstractModelTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+class KotlinAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/annotations/Test.kt", "annotations") {
+ @Test
+ fun `generic receiver with annotations`() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.TYPE_PARAMETER)
+ |annotation class Hello(val bar: String)
+ |fun <@Hello("abc") T> foo(arg: String): List<T> = TODO()
+ """.trimIndent()
+ ) {
+ with((this / "annotations" / "foo").cast<DFunction>()) {
+ val annotations = generics.first().extra[Annotations]?.directAnnotations?.flatMap { it.value }
+ val driOfHello = DRI("annotations", "Hello")
+ val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList()
+
+ assertEquals(listOf(driOfHello), annotations?.map { it.dri })
+ assertEquals(listOf("abc"), annotationsValues)
+ }
+ }
+ }
+
+ @Test
+ fun `generic receiver with annotated bounds`() {
+ inlineModelTest(
+ """
+ |@Target(AnnotationTarget.TYPE_PARAMETER)
+ |annotation class Hello(val bar: String)
+ |fun <T: @Hello("abc") String> foo(arg: String): List<T> = TODO()
+ """.trimIndent()
+ ) {
+ with((this / "annotations" / "foo").cast<DFunction>()) {
+ val annotations = (generics.first().bounds.first() as GenericTypeConstructor)
+ .extra[Annotations]?.directAnnotations?.flatMap { it.value }
+ val driOfHello = DRI("annotations", "Hello")
+ val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList()
+
+ assertEquals(listOf(driOfHello), annotations?.map { it.dri })
+ assertEquals(listOf("abc"), annotationsValues)
+ }
+ }
+ }
+
+ @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())
+ }
+ }
+ }
+}