aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/kotlin/model/documentableProperties.kt9
-rw-r--r--core/src/main/kotlin/model/properties/PropertyContainer.kt2
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/utils.kt9
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt39
-rw-r--r--plugins/base/src/main/kotlin/translators/isException.kt9
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt9
-rw-r--r--plugins/base/src/test/kotlin/transformers/isExceptionTest.kt142
-rw-r--r--plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt2
8 files changed, 197 insertions, 24 deletions
diff --git a/core/src/main/kotlin/model/documentableProperties.kt b/core/src/main/kotlin/model/documentableProperties.kt
index 2845c7fc..991f5311 100644
--- a/core/src/main/kotlin/model/documentableProperties.kt
+++ b/core/src/main/kotlin/model/documentableProperties.kt
@@ -25,3 +25,12 @@ data class ImplementedInterfaces(val interfaces: SourceSetDependent<List<TypeCon
override val key: ExtraProperty.Key<Documentable, *> = ImplementedInterfaces
}
+
+data class ExceptionInSupertypes(val exceptions: SourceSetDependent<List<TypeConstructor>>): ExtraProperty<Documentable> {
+ companion object : ExtraProperty.Key<Documentable, ExceptionInSupertypes> {
+ override fun mergeStrategyFor(left: ExceptionInSupertypes, right: ExceptionInSupertypes) =
+ MergeStrategy.Replace(ExceptionInSupertypes(left.exceptions + right.exceptions))
+ }
+
+ override val key: ExtraProperty.Key<Documentable, *> = ExceptionInSupertypes
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/model/properties/PropertyContainer.kt b/core/src/main/kotlin/model/properties/PropertyContainer.kt
index 19189b39..162f1bc8 100644
--- a/core/src/main/kotlin/model/properties/PropertyContainer.kt
+++ b/core/src/main/kotlin/model/properties/PropertyContainer.kt
@@ -18,7 +18,7 @@ data class PropertyContainer<C : Any> internal constructor(
companion object {
fun <T : Any> empty(): PropertyContainer<T> = PropertyContainer(emptyMap())
- fun <T : Any> withAll(vararg extras: ExtraProperty<T>) = empty<T>().addAll(extras.toList())
+ fun <T : Any> withAll(vararg extras: ExtraProperty<T>?) = empty<T>().addAll(extras.filterNotNull())
fun <T : Any> withAll(extras: Collection<ExtraProperty<T>>) = empty<T>().addAll(extras)
}
}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt b/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
index 6b87fe39..ecf75a1f 100644
--- a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
+++ b/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
@@ -2,6 +2,7 @@ package org.jetbrains.dokka.base.transformers.documentables
import org.jetbrains.dokka.model.Annotations
import org.jetbrains.dokka.model.Documentable
+import org.jetbrains.dokka.model.ExceptionInSupertypes
import org.jetbrains.dokka.model.WithSupertypes
import org.jetbrains.dokka.model.properties.WithExtraProperties
@@ -16,9 +17,5 @@ val <T> T.deprecatedAnnotation where T : WithExtraProperties<out Documentable>
}
}
-val WithSupertypes.isException: Boolean
- get() = supertypes.values.flatten().any {
- val dri = it.typeConstructor.dri.toString()
- dri == "kotlin/Exception///PointingToDeclaration/" ||
- dri == "java.lang/Exception///PointingToDeclaration/"
- } \ No newline at end of file
+val <T : WithExtraProperties<out Documentable>> T.isException: Boolean
+ get() = extra[ExceptionInSupertypes] != null \ 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 fe0c090b..1a643624 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -1,15 +1,14 @@
package org.jetbrains.dokka.base.translators.descriptors
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.withContext
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
import org.jetbrains.dokka.analysis.DokkaResolutionFacade
import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.analysis.from
import org.jetbrains.dokka.base.parsers.MarkdownParser
+import org.jetbrains.dokka.base.translators.isDirectlyAnException
import org.jetbrains.dokka.links.*
import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.model.*
@@ -48,8 +47,9 @@ 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.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.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.lang.IllegalStateException
@@ -181,7 +181,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
+ info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
)
)
}
@@ -218,7 +219,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
+ info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
)
)
}
@@ -382,7 +384,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll<DClass>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
+ info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
)
)
}
@@ -613,6 +616,7 @@ private class DokkaDescriptorVisitor(
with(descriptor) {
coroutineScope {
val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
+ val info = buildAncestryInformation(listOf(underlyingType)).sortedBy { it.level }
DTypeAlias(
dri = DRI.from(this@with),
@@ -625,7 +629,8 @@ private class DokkaDescriptorVisitor(
sourceSets = setOf(sourceSet),
generics = generics.await(),
extra = PropertyContainer.withAll(
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ info.exceptionsInSupertypes()?.takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
)
)
}
@@ -724,7 +729,7 @@ private class DokkaDescriptorVisitor(
}
return buildAncestryInformation(
- supertypes = supertypes.flatMap { it.supertypes() },
+ supertypes = supertypes.flatMap { it.immediateSupertypes() },
level = level + 1,
ancestryInformation = updated
)
@@ -946,12 +951,6 @@ private class DokkaDescriptorVisitor(
private fun ValueArgument.childrenAsText() =
this.safeAs<KtValueArgument>()?.children?.map { it.text }.orEmpty()
- private data class AncestryLevel(
- val level: Int,
- val superclass: TypeConstructor?,
- val interfaces: List<TypeConstructor>
- )
-
private data class ClassInfo(val ancestry: List<AncestryLevel>, val docs: SourceSetDependent<DocumentationNode>) {
val supertypes: List<TypeConstructorWithKind>
get() = ancestry.firstOrNull { it.level == 0 }?.let {
@@ -965,6 +964,9 @@ private class DokkaDescriptorVisitor(
val allImplementedInterfaces: List<TypeConstructor>
get() = ancestry.flatMap { it.interfaces }.distinct()
+
+ val exceptionsInSupertypes: List<TypeConstructor>?
+ get() = ancestry.exceptionsInSupertypes()
}
private fun Visibility.toDokkaVisibility(): org.jetbrains.dokka.model.Visibility = when (this) {
@@ -978,3 +980,12 @@ private class DokkaDescriptorVisitor(
private fun ConstantsEnumValue.fullEnumEntryName() =
"${this.enumClassId.relativeClassName.asString()}.${this.enumEntryName.identifier}"
}
+
+private data class AncestryLevel(
+ val level: Int,
+ val superclass: TypeConstructor?,
+ val interfaces: List<TypeConstructor>
+)
+
+private fun List<AncestryLevel>.exceptionsInSupertypes(): List<TypeConstructor>? =
+ mapNotNull { it.superclass }.filter { type -> type.dri.isDirectlyAnException() }.takeIf { it.isNotEmpty() }
diff --git a/plugins/base/src/main/kotlin/translators/isException.kt b/plugins/base/src/main/kotlin/translators/isException.kt
new file mode 100644
index 00000000..d5b58445
--- /dev/null
+++ b/plugins/base/src/main/kotlin/translators/isException.kt
@@ -0,0 +1,9 @@
+package org.jetbrains.dokka.base.translators
+
+import org.jetbrains.dokka.links.DRI
+
+internal fun DRI.isDirectlyAnException(): Boolean =
+ toString().let { stringed ->
+ stringed == "kotlin/Exception///PointingToDeclaration/" ||
+ stringed == "java.lang/Exception///PointingToDeclaration/"
+ }
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index cbd02158..f46f11c9 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -7,13 +7,13 @@ import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.impl.source.PsiImmediateClassType
-import com.intellij.psi.javadoc.PsiDocComment
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.analysis.PsiDocumentableSource
import org.jetbrains.dokka.analysis.from
+import org.jetbrains.dokka.base.translators.isDirectlyAnException
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.nextTarget
import org.jetbrains.dokka.links.withClass
@@ -313,13 +313,18 @@ class DefaultPsiToDocumentableTranslator(
PropertyContainer.withAll(
implementedInterfacesExtra,
annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
+ .toAnnotations(),
+ isExceptionExtra(ancestryTree),
)
)
}
}
}
+ private fun isExceptionExtra(ancestryTree: List<AncestryLevel>): ExceptionInSupertypes? =
+ ancestryTree.mapNotNull { it.superclass }.filter { it.dri.isDirectlyAnException() }
+ .takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }
+
private fun parseFunction(
psi: PsiMethod,
isConstructor: Boolean = false,
diff --git a/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt b/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt
new file mode 100644
index 00000000..131c7b77
--- /dev/null
+++ b/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt
@@ -0,0 +1,142 @@
+package transformers
+
+import org.jetbrains.dokka.base.transformers.documentables.isException
+import org.jetbrains.dokka.model.DClass
+import org.jetbrains.dokka.model.DTypeAlias
+import org.junit.jupiter.api.Test
+import utils.AbstractModelTest
+
+class IsExceptionKotlinTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") {
+ @Test
+ fun `isException should work for kotlin exception`(){
+ inlineModelTest(
+ """
+ |class ExampleException(): Exception()"""
+ ) {
+ with((this / "classes" / "ExampleException").cast<DClass>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should work for java exceptions`(){
+ inlineModelTest(
+ """
+ |class ExampleException(): java.lang.Exception()"""
+ ) {
+ with((this / "classes" / "ExampleException").cast<DClass>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should work for RuntimeException`(){
+ inlineModelTest(
+ """
+ |class ExampleException(reason: String): RuntimeException(reason)"""
+ ) {
+ with((this / "classes" / "ExampleException").cast<DClass>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should work if exception is typealiased`(){
+ inlineModelTest(
+ """
+ |typealias ExampleException = java.lang.Exception"""
+ ) {
+ with((this / "classes" / "ExampleException").cast<DTypeAlias>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should work if exception is extending a typaliased class`(){
+ inlineModelTest(
+ """
+ |class ExampleException(): Exception()
+ |typealias ExampleExceptionAlias = ExampleException"""
+ ) {
+ with((this / "classes" / "ExampleExceptionAlias").cast<DTypeAlias>()) {
+ name equals "ExampleExceptionAlias"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should return false for a basic class`(){
+ inlineModelTest(
+ """
+ |class NotAnException(): Serializable"""
+ ) {
+ with((this / "classes" / "NotAnException").cast<DClass>()) {
+ name equals "NotAnException"
+ isException equals false
+ }
+ }
+ }
+
+ @Test
+ fun `isException should return false for a typealias`(){
+ inlineModelTest(
+ """
+ |typealias NotAnException = Serializable"""
+ ) {
+ with((this / "classes" / "NotAnException").cast<DTypeAlias>()) {
+ name equals "NotAnException"
+ isException equals false
+ }
+ }
+ }
+}
+
+class IsExceptionJavaTest: AbstractModelTest("/src/main/kotlin/java/Test.java", "java") {
+ @Test
+ fun `isException should work for java exceptions`(){
+ inlineModelTest(
+ """
+ |class ExampleException extends java.lang.Exception { }"""
+ ) {
+ with((this / "java" / "ExampleException").cast<DClass>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should work for RuntimeException`(){
+ inlineModelTest(
+ """
+ |class ExampleException extends java.lang.RuntimeException"""
+ ) {
+ with((this / "java" / "ExampleException").cast<DClass>()) {
+ name equals "ExampleException"
+ isException equals true
+ }
+ }
+ }
+
+ @Test
+ fun `isException should return false for a basic class`(){
+ inlineModelTest(
+ """
+ |class NotAnException extends Serializable"""
+ ) {
+ with((this / "java" / "NotAnException").cast<DClass>()) {
+ name equals "NotAnException"
+ isException equals false
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
index a7e10bd5..d6a15865 100644
--- a/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
+++ b/plugins/javadoc/src/main/kotlin/org/jetbrains/dokka/javadoc/pages/htmlPreprocessors.kt
@@ -141,7 +141,7 @@ object DeprecatedPageCreator : PageTransformer {
it.takeIf { it.isDeprecated() }?.putAs(DeprecatedPageSection.DeprecatedEnumConstants)
}
node.takeIf { it.isDeprecated() }?.putAs(
- if ((node.documentable as? WithSupertypes)?.isException == true) DeprecatedPageSection.DeprecatedExceptions
+ if ((node as? WithJavadocExtra<out Documentable>)?.isException == true) DeprecatedPageSection.DeprecatedExceptions
else when (node.kind) {
"enum" -> DeprecatedPageSection.DeprecatedEnums
"interface" -> DeprecatedPageSection.DeprecatedInterfaces