aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/core.api16
-rw-r--r--core/src/main/kotlin/model/additionalExtras.kt2
-rw-r--r--core/src/main/kotlin/model/ancestryNode.kt14
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt85
-rw-r--r--plugins/base/src/main/kotlin/translators/isException.kt9
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt134
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/parsers/PsiCommentsUtils.kt4
7 files changed, 137 insertions, 127 deletions
diff --git a/core/api/core.api b/core/api/core.api
index 8b76c00e..d3b4817b 100644
--- a/core/api/core.api
+++ b/core/api/core.api
@@ -671,6 +671,22 @@ public final class org/jetbrains/dokka/model/AdditionalModifiers$Companion : org
public fun mergeStrategyFor (Lorg/jetbrains/dokka/model/AdditionalModifiers;Lorg/jetbrains/dokka/model/AdditionalModifiers;)Lorg/jetbrains/dokka/model/properties/MergeStrategy;
}
+public final class org/jetbrains/dokka/model/AncestryNode {
+ public fun <init> (Lorg/jetbrains/dokka/model/TypeConstructor;Lorg/jetbrains/dokka/model/AncestryNode;Ljava/util/List;)V
+ public final fun allImplementedInterfaces ()Ljava/util/List;
+ public final fun component1 ()Lorg/jetbrains/dokka/model/TypeConstructor;
+ public final fun component2 ()Lorg/jetbrains/dokka/model/AncestryNode;
+ public final fun component3 ()Ljava/util/List;
+ public final fun copy (Lorg/jetbrains/dokka/model/TypeConstructor;Lorg/jetbrains/dokka/model/AncestryNode;Ljava/util/List;)Lorg/jetbrains/dokka/model/AncestryNode;
+ public static synthetic fun copy$default (Lorg/jetbrains/dokka/model/AncestryNode;Lorg/jetbrains/dokka/model/TypeConstructor;Lorg/jetbrains/dokka/model/AncestryNode;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/dokka/model/AncestryNode;
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getInterfaces ()Ljava/util/List;
+ public final fun getSuperclass ()Lorg/jetbrains/dokka/model/AncestryNode;
+ public final fun getTypeConstructor ()Lorg/jetbrains/dokka/model/TypeConstructor;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
public abstract class org/jetbrains/dokka/model/AnnotationParameterValue {
}
diff --git a/core/src/main/kotlin/model/additionalExtras.kt b/core/src/main/kotlin/model/additionalExtras.kt
index bc9135dd..d708d137 100644
--- a/core/src/main/kotlin/model/additionalExtras.kt
+++ b/core/src/main/kotlin/model/additionalExtras.kt
@@ -123,4 +123,4 @@ data class ConstructorValues(val values: SourceSetDependent<List<Expression>>) :
}
override val key: ExtraProperty.Key<DEnumEntry, ConstructorValues> = ConstructorValues
-} \ No newline at end of file
+}
diff --git a/core/src/main/kotlin/model/ancestryNode.kt b/core/src/main/kotlin/model/ancestryNode.kt
new file mode 100644
index 00000000..5c3c077b
--- /dev/null
+++ b/core/src/main/kotlin/model/ancestryNode.kt
@@ -0,0 +1,14 @@
+package org.jetbrains.dokka.model
+
+data class AncestryNode(
+ val typeConstructor: TypeConstructor,
+ val superclass: AncestryNode?,
+ val interfaces: List<AncestryNode>,
+) {
+ fun allImplementedInterfaces(): List<TypeConstructor> {
+ fun traverseInterfaces(ancestry: AncestryNode): List<TypeConstructor> =
+ ancestry.interfaces.flatMap { listOf(it.typeConstructor) + traverseInterfaces(it) } +
+ (ancestry.superclass?.let(::traverseInterfaces) ?: emptyList())
+ return traverseInterfaces(this).distinct()
+ }
+}
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index 6078b54d..96bd2fc0 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -13,7 +13,7 @@ import org.jetbrains.dokka.analysis.KotlinAnalysis
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.typeConstructorsBeingExceptions
import org.jetbrains.dokka.base.translators.psi.parsers.JavadocParser
import org.jetbrains.dokka.base.translators.unquotedValue
import org.jetbrains.dokka.links.*
@@ -21,7 +21,6 @@ import org.jetbrains.dokka.links.Callable
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.AnnotationTarget
import org.jetbrains.dokka.model.Nullable
-import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.doc.*
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.plugability.DokkaContext
@@ -215,8 +214,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
- info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
+ ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()),
+ info.ancestry.exceptionInSupertypesOrNull()
)
)
}
@@ -253,8 +252,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
- info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
+ ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()),
+ info.ancestry.exceptionInSupertypesOrNull()
)
)
}
@@ -298,7 +297,7 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent())
)
)
}
@@ -420,8 +419,8 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll<DClass>(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent()),
- info.exceptionsInSupertypes?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
+ ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()),
+ info.ancestry.exceptionInSupertypesOrNull()
)
)
}
@@ -664,8 +663,10 @@ private class DokkaDescriptorVisitor(
with(descriptor) {
coroutineScope {
val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
- val info = buildAncestryInformation(listOf(underlyingType)).sortedBy { it.level }
-
+ val info = buildAncestryInformation(defaultType).copy(
+ superclass = buildAncestryInformation(underlyingType),
+ interfaces = emptyList()
+ )
DTypeAlias(
dri = DRI.from(this@with),
name = name.asString(),
@@ -678,8 +679,7 @@ private class DokkaDescriptorVisitor(
generics = generics.await(),
extra = PropertyContainer.withAll(
descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- info.exceptionsInSupertypes()?.takeIf { it.isNotEmpty() }
- ?.let { ExceptionInSupertypes(it.toSourceSetDependent()) },
+ info.exceptionInSupertypesOrNull(),
)
)
}
@@ -759,15 +759,10 @@ private class DokkaDescriptorVisitor(
DRI.from(kt.constructor.declarationDescriptor as DeclarationDescriptor),
kt.arguments.map { it.toProjection() })
-
- private tailrec suspend fun buildAncestryInformation(
- supertypes: Collection<KotlinType>,
- level: Int = 0,
- ancestryInformation: Set<AncestryLevel> = emptySet()
- ): Set<AncestryLevel> {
- if (supertypes.isEmpty()) return ancestryInformation
-
- val (interfaces, superclass) = supertypes
+ private suspend fun buildAncestryInformation(
+ kotlinType: KotlinType
+ ): AncestryNode {
+ val (interfaces, superclass) = kotlinType.immediateSupertypes().filterNot { it.isAnyOrNullableAny() }
.partition {
val declaration = it.constructor.declarationDescriptor
val descriptor = declaration as? ClassDescriptor
@@ -775,25 +770,20 @@ private class DokkaDescriptorVisitor(
descriptor?.kind == ClassKind.INTERFACE
}
- val updated = coroutineScope {
- ancestryInformation + AncestryLevel(
- level,
- superclass.parallelMap(::toTypeConstructor).singleOrNull(),
- interfaces.parallelMap(::toTypeConstructor)
+ return coroutineScope {
+ AncestryNode(
+ typeConstructor = toTypeConstructor(kotlinType),
+ superclass = superclass.parallelMap(::buildAncestryInformation).singleOrNull(),
+ interfaces = interfaces.parallelMap(::buildAncestryInformation)
)
}
-
- return buildAncestryInformation(
- supertypes = supertypes.flatMap { it.immediateSupertypes() },
- level = level + 1,
- ancestryInformation = updated
- )
}
+
private suspend fun ClassDescriptor.resolveClassDescriptionData(): ClassInfo {
return coroutineScope {
ClassInfo(
- buildAncestryInformation(this@resolveClassDescriptionData.typeConstructor.supertypes.filterNot { it.isAnyOrNullableAny() }).sortedBy { it.level },
+ buildAncestryInformation(this@resolveClassDescriptionData.defaultType),
resolveDescriptorData()
)
}
@@ -1050,22 +1040,16 @@ private class DokkaDescriptorVisitor(
else -> node?.text?.let { ComplexExpression(it) }
}
- private data class ClassInfo(val ancestry: List<AncestryLevel>, val docs: SourceSetDependent<DocumentationNode>) {
+ private data class ClassInfo(val ancestry: AncestryNode, val docs: SourceSetDependent<DocumentationNode>) {
val supertypes: List<TypeConstructorWithKind>
- get() = ancestry.firstOrNull { it.level == 0 }?.let {
- listOfNotNull(it.superclass?.let {
+ get() = listOfNotNull(ancestry.superclass?.let {
+ it.typeConstructor.let {
TypeConstructorWithKind(
it,
KotlinClassKindTypes.CLASS
)
- }) + it.interfaces.map { TypeConstructorWithKind(it, KotlinClassKindTypes.INTERFACE) }
- }.orEmpty()
-
- val allImplementedInterfaces: List<TypeConstructor>
- get() = ancestry.flatMap { it.interfaces }.distinct()
-
- val exceptionsInSupertypes: List<TypeConstructor>?
- get() = ancestry.exceptionsInSupertypes()
+ }
+ }) + ancestry.interfaces.map { TypeConstructorWithKind(it.typeConstructor, KotlinClassKindTypes.INTERFACE) }
}
private fun DescriptorVisibility.toDokkaVisibility(): org.jetbrains.dokka.model.Visibility = when (this.delegate) {
@@ -1093,13 +1077,8 @@ private class DokkaDescriptorVisitor(
kind == CallableMemberDescriptor.Kind.SYNTHESIZED ||
containingDeclaration.fqNameOrNull()?.asString()
?.let { it == "kotlin.Any" || it == "kotlin.Enum" || it == "java.lang.Enum" || it == "java.lang.Object" } == true
-}
-private data class AncestryLevel(
- val level: Int,
- val superclass: TypeConstructor?,
- val interfaces: List<TypeConstructor>
-)
+ private fun AncestryNode.exceptionInSupertypesOrNull(): ExceptionInSupertypes? =
+ typeConstructorsBeingExceptions().takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }
+}
-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
index d5b58445..d148cd34 100644
--- a/plugins/base/src/main/kotlin/translators/isException.kt
+++ b/plugins/base/src/main/kotlin/translators/isException.kt
@@ -1,6 +1,15 @@
package org.jetbrains.dokka.base.translators
import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.model.AncestryNode
+import org.jetbrains.dokka.model.TypeConstructor
+
+internal fun AncestryNode.typeConstructorsBeingExceptions(): List<TypeConstructor> {
+ fun traverseSupertypes(ancestry: AncestryNode): List<TypeConstructor> =
+ listOf(ancestry.typeConstructor) + (ancestry.superclass?.let(::traverseSupertypes) ?: emptyList())
+
+ return superclass?.let(::traverseSupertypes)?.filter { type -> type.dri.isDirectlyAnException() } ?: emptyList()
+}
internal fun DRI.isDirectlyAnException(): Boolean =
toString().let { stringed ->
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index d912d65f..88c51b02 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -17,7 +17,7 @@ import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.analysis.PsiDocumentableSource
import org.jetbrains.dokka.analysis.from
import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.translators.isDirectlyAnException
+import org.jetbrains.dokka.base.translators.typeConstructorsBeingExceptions
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
@@ -29,25 +29,18 @@ import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.doc.Param
import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.model.properties.WithExtraProperties
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
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.dokka.utilities.parallelForEach
import org.jetbrains.dokka.utilities.parallelMap
import org.jetbrains.dokka.utilities.parallelMapNotNull
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
-import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
-import org.jetbrains.kotlin.descriptors.Visibilities
-import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
-import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
-import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName
import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName
@@ -55,8 +48,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
-import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.io.File
@@ -178,28 +169,15 @@ class DefaultPsiToDocumentableTranslator(
private suspend fun parseClasslike(psi: PsiClass, parent: DRI): DClasslike = coroutineScope {
with(psi) {
val dri = parent.withClass(name.toString())
- val ancestryTree = mutableListOf<AncestryLevel>()
val superMethodsKeys = hashSetOf<Int>()
val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
methods.asIterable().parallelForEach { superMethodsKeys.add(it.hash) }
- fun parseSupertypes(superTypes: Array<PsiClassType>, level: Int = 0) { // TODO: Rewrite it
- if (superTypes.isEmpty()) return
- val parsedClasses = superTypes.filter { !it.shouldBeIgnored }.mapNotNull { supertypePsi ->
- supertypePsi.resolve()?.let { supertypePsiClass ->
- val (supertypeDri, javaClassKind) = when {
- supertypePsiClass.isInterface -> DRI.from(supertypePsiClass) to JavaClassKindTypes.INTERFACE
- else -> DRI.from(supertypePsiClass) to JavaClassKindTypes.CLASS
- }
- GenericTypeConstructor(
- supertypeDri,
- supertypePsi.parameters.map(::getProjection)
- ) to javaClassKind
- }
- }
- val (classes, interfaces) = parsedClasses.partition { it.second == JavaClassKindTypes.CLASS }
- ancestryTree.add(AncestryLevel(level, classes.firstOrNull()?.first, interfaces.map { it.first }))
- superTypes.forEach { type ->
+ /**
+ * Caution! This method mutates superMethodsKeys and superMethods
+ */
+ fun Array<PsiClassType>.getSuperTypesPsiClasses(): List<Pair<PsiClass, JavaClassKindTypes>> {
+ forEach { type ->
(type as? PsiClassType)?.resolve()?.let {
val definedAt = DRI.from(it)
it.methods.forEach { method ->
@@ -211,13 +189,36 @@ class DefaultPsiToDocumentableTranslator(
superMethods.add(Pair(method, definedAt))
}
}
- parseSupertypes(it.superTypes, level + 1)
}
}
+ return filter { !it.shouldBeIgnored }.mapNotNull { supertypePsi ->
+ supertypePsi.resolve()?.let { supertypePsiClass ->
+ val javaClassKind = when {
+ supertypePsiClass.isInterface -> JavaClassKindTypes.INTERFACE
+ else -> JavaClassKindTypes.CLASS
+ }
+ supertypePsiClass to javaClassKind
+ }
+ }
+ }
+
+ fun traversePsiClassForAncestorsAndInheritedMembers(psiClass: PsiClass): AncestryNode {
+ val (classes, interfaces) = psiClass.superTypes.getSuperTypesPsiClasses()
+ .partition { it.second == JavaClassKindTypes.CLASS }
+
+ return AncestryNode(
+ typeConstructor = GenericTypeConstructor(
+ DRI.from(psiClass),
+ psiClass.typeParameters.map(::getProjection)
+ ),
+ superclass = classes.singleOrNull()?.first?.let(::traversePsiClassForAncestorsAndInheritedMembers),
+ interfaces = interfaces.map { traversePsiClassForAncestorsAndInheritedMembers(it.first) }
+ )
}
- parseSupertypes(superTypes)
+
+ val ancestry: AncestryNode = traversePsiClassForAncestorsAndInheritedMembers(this)
val (regularFunctions, accessors) = splitFunctionsAndAccessors()
- val overriden = regularFunctions.flatMap { it.findSuperMethods().toList() }
+ val overridden = regularFunctions.flatMap { it.findSuperMethods().toList() }
val documentation = javadocParser.parseDocumentation(this).toSourceSetDependent()
val allFunctions = async {
regularFunctions.parallelMapNotNull {
@@ -225,27 +226,22 @@ class DefaultPsiToDocumentableTranslator(
it,
parentDRI = dri
) else null
- } + superMethods.filter { it.first !in overriden }.parallelMap { parseFunction(it.first, inheritedFrom = it.second) }
+ } + superMethods.filter { it.first !in overridden }.parallelMap { parseFunction(it.first, inheritedFrom = it.second) }
}
val source = PsiDocumentableSource(this).toSourceSetDependent()
val classlikes = async { innerClasses.asIterable().parallelMap { parseClasslike(it, dri) } }
val visibility = getVisibility().toSourceSetDependent()
- val ancestors = ancestryTree.filter { it.level == 0 }.flatMap {
- listOfNotNull(it.superclass?.let {
- TypeConstructorWithKind(
- typeConstructor = it,
- kind = JavaClassKindTypes.CLASS
- )
- }) + it.interfaces.map {
+ val ancestors = (listOfNotNull(ancestry.superclass?.let {
+ it.typeConstructor.let {
TypeConstructorWithKind(
- typeConstructor = it,
- kind = JavaClassKindTypes.INTERFACE
+ it,
+ JavaClassKindTypes.CLASS
)
}
- }.toSourceSetDependent()
+ }) + ancestry.interfaces.map { TypeConstructorWithKind(it.typeConstructor, JavaClassKindTypes.INTERFACE) }).toSourceSetDependent()
val modifiers = getModifier().toSourceSetDependent()
val implementedInterfacesExtra =
- ImplementedInterfaces(ancestryTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
+ ImplementedInterfaces(ancestry.allImplementedInterfaces().toSourceSetDependent())
when {
isAnnotationType ->
DAnnotation(
@@ -349,16 +345,15 @@ class DefaultPsiToDocumentableTranslator(
implementedInterfacesExtra,
annotations.toList().toListOfAnnotations().toSourceSetDependent()
.toAnnotations(),
- isExceptionExtra(ancestryTree),
+ ancestry.exceptionInSupertypesOrNull()
)
)
}
}
}
- private fun isExceptionExtra(ancestryTree: List<AncestryLevel>): ExceptionInSupertypes? =
- ancestryTree.mapNotNull { it.superclass }.filter { it.dri.isDirectlyAnException() }
- .takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }
+ private fun AncestryNode.exceptionInSupertypesOrNull(): ExceptionInSupertypes? =
+ typeConstructorsBeingExceptions().takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }
private fun parseFunction(
psi: PsiMethod,
@@ -436,53 +431,56 @@ class DefaultPsiToDocumentableTranslator(
Annotations.Annotation(DRI("kotlin.jvm", "JvmStatic"), emptyMap())
}
- private fun getBound(type: PsiType): Bound {
- fun annotationsFromType(): List<Annotations.Annotation> = type.annotations.toList().toListOfAnnotations()
+ private fun <T : AnnotationTarget> PsiTypeParameter.annotations(): PropertyContainer<T> = this.annotations.toList().toListOfAnnotations().annotations()
+ private fun <T : AnnotationTarget> PsiType.annotations(): PropertyContainer<T> = this.annotations.toList().toListOfAnnotations().annotations()
- fun <T : AnnotationTarget> annotations(): PropertyContainer<T> =
- annotationsFromType().takeIf { it.isNotEmpty() }?.let { annotations ->
- PropertyContainer.withAll(annotations.toSourceSetDependent().toAnnotations())
- } ?: PropertyContainer.empty()
+ private fun <T : AnnotationTarget> List<Annotations.Annotation>.annotations(): PropertyContainer<T> =
+ this.takeIf { it.isNotEmpty() }?.let { annotations ->
+ 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(annotations())
- resolved is PsiTypeParameter ->
- TypeParameter(
- dri = DRI.from(resolved),
- name = resolved.name.orEmpty(),
- extra = annotations()
- )
+ resolved.qualifiedName == "java.lang.Object" -> JavaObject(type.annotations())
+ resolved is PsiTypeParameter -> getProjection(resolved)
Regex("kotlin\\.jvm\\.functions\\.Function.*").matches(resolved.qualifiedName ?: "") ||
Regex("java\\.util\\.function\\.Function.*").matches(
resolved.qualifiedName ?: ""
) -> FunctionalTypeConstructor(
DRI.from(resolved),
type.parameters.map { getProjection(it) },
- extra = annotations()
+ extra = type.annotations()
)
else -> GenericTypeConstructor(
DRI.from(resolved),
type.parameters.map { getProjection(it) },
- extra = annotations()
+ extra = type.annotations()
)
}
} ?: UnresolvedBound(type.presentableText)
is PsiArrayType -> GenericTypeConstructor(
DRI("kotlin", "Array"),
listOf(getProjection(type.componentType)),
- extra = annotations()
+ extra = type.annotations()
)
is PsiPrimitiveType -> if (type.name == "void") Void else PrimitiveJavaType(type.name)
- is PsiImmediateClassType -> JavaObject(annotations())
+ is PsiImmediateClassType -> JavaObject(type.annotations())
else -> throw IllegalStateException("${type.presentableText} is not supported by PSI parser")
}
//We would like to cache most of the bounds since it is not common to annotate them,
//but if this is the case, we treat them as 'one of'
- return if (annotationsFromType().isEmpty()) {
+ return if (type.annotations.toList().toListOfAnnotations().isEmpty()) {
cachedBounds.getOrPut(type.canonicalText) {
bound()
}
@@ -657,10 +655,4 @@ class DefaultPsiToDocumentableTranslator(
private val PsiElement.psiReference
get() = getChildOfType<PsiJavaCodeReferenceElement>()?.resolve()
}
-
- private data class AncestryLevel(
- val level: Int,
- val superclass: TypeConstructor?,
- val interfaces: List<TypeConstructor>
- )
}
diff --git a/plugins/base/src/main/kotlin/translators/psi/parsers/PsiCommentsUtils.kt b/plugins/base/src/main/kotlin/translators/psi/parsers/PsiCommentsUtils.kt
index 1771595a..1d905e2d 100644
--- a/plugins/base/src/main/kotlin/translators/psi/parsers/PsiCommentsUtils.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/parsers/PsiCommentsUtils.kt
@@ -98,7 +98,7 @@ internal fun findClosestDocComment(element: PsiNamedElement, logger: DokkaLogger
return findClosestDocComment(superMethods.single(), logger)
}
- val superMethodDocumentation = superMethods.map { method -> findClosestDocComment(method, logger) }
+ val superMethodDocumentation = superMethods.map { method -> findClosestDocComment(method, logger) }.distinct()
if (superMethodDocumentation.size == 1) {
return superMethodDocumentation.single()
}
@@ -143,4 +143,4 @@ internal fun PsiDocTag.contentElementsWithSiblingIfNeeded(): List<PsiElement> =
}
internal fun PsiDocTag.resolveToElement(): PsiElement? =
- dataElements.firstOrNull()?.firstChild?.referenceElementOrSelf()?.resolveToGetDri() \ No newline at end of file
+ dataElements.firstOrNull()?.firstChild?.referenceElementOrSelf()?.resolveToGetDri()