aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulia McClellan <juliamcclellan37@gmail.com>2023-08-04 06:22:54 -0400
committerGitHub <noreply@github.com>2023-08-04 12:22:54 +0200
commite7af2fd28ed46f02046ea329a8e6707a2e217bd6 (patch)
treef64ea2bb7ce0345f40cbcb032a49d2ad32e14c75
parent8fd4ed32275a7e2df38f5f62964093441c77065c (diff)
downloaddokka-e7af2fd28ed46f02046ea329a8e6707a2e217bd6.tar.gz
dokka-e7af2fd28ed46f02046ea329a8e6707a2e217bd6.tar.bz2
dokka-e7af2fd28ed46f02046ea329a8e6707a2e217bd6.zip
Fix handling of Java contravariance (#3092)
-rw-r--r--plugins/base/src/test/kotlin/model/JavaTest.kt45
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt4
2 files changed, 48 insertions, 1 deletions
diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt
index b3ee2726..f57c3c8c 100644
--- a/plugins/base/src/test/kotlin/model/JavaTest.kt
+++ b/plugins/base/src/test/kotlin/model/JavaTest.kt
@@ -10,6 +10,7 @@ import org.jetbrains.dokka.model.doc.Text
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import utils.AbstractModelTest
+import utils.assertContains
import utils.assertNotNull
import utils.name
import kotlin.test.assertEquals
@@ -439,4 +440,48 @@ class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
}
}
+ @Test
+ fun variances() {
+ inlineModelTest(
+ """
+ |public class Foo {
+ | public void superBound(java.util.List<? super String> param) {}
+ | public void extendsBound(java.util.List<? extends String> param) {}
+ | public void unbounded(java.util.List<?> param) {}
+ |}
+ """, configuration = configuration
+ ) {
+ with((this / "java" / "Foo").cast<DClass>()) {
+ val functionNames = functions.map { it.name }
+ assertContains(functionNames, "superBound")
+ assertContains(functionNames, "extendsBound")
+ assertContains(functionNames, "unbounded")
+
+ for (function in functions) {
+ val param = function.parameters.single()
+ val type = param.type as GenericTypeConstructor
+ val variance = type.projections.single()
+
+ when (function.name) {
+ "superBound" -> {
+ assertTrue(variance is Contravariance<*>)
+ val bound = (variance as Contravariance<*>).inner
+ assertEquals((bound as GenericTypeConstructor).dri.classNames, "String")
+ }
+ "extendsBound" -> {
+ assertTrue(variance is Covariance<*>)
+ val bound = (variance as Covariance<*>).inner
+ assertEquals((bound as GenericTypeConstructor).dri.classNames, "String")
+ }
+ "unbounded" -> {
+ assertTrue(variance is Covariance<*>)
+ val bound = (variance as Covariance<*>).inner
+ assertTrue(bound is JavaObject)
+ }
+ }
+ }
+ }
+ }
+ }
+
}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt
index 45f44338..a1f9cef0 100644
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt
+++ b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt
@@ -567,8 +567,10 @@ internal class DokkaPsiParser(
private fun getVariance(type: PsiWildcardType): Projection = when {
+ type.isExtends -> Covariance(getBound(type.extendsBound))
+ type.isSuper -> Contravariance(getBound(type.superBound))
+ // If the type isn't explicitly bounded, it still has an implicit `extends Object` bound
type.extendsBound != PsiType.NULL -> Covariance(getBound(type.extendsBound))
- type.superBound != PsiType.NULL -> Contravariance(getBound(type.superBound))
else -> throw IllegalStateException("${type.presentableText} has incorrect bounds")
}