Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotations for parameters #1710

Merged
merged 2 commits into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions core/src/main/kotlin/model/Documentable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.model.properties.WithExtraProperties

interface Annotatable

abstract class Documentable : WithChildren<Documentable> {
abstract class Documentable : WithChildren<Documentable>, Annotatable {
abstract val name: String?
abstract val dri: DRI
abstract val documentation: SourceSetDependent<DocumentationNode>
Expand Down Expand Up @@ -346,7 +347,14 @@ data class DTypeParameter(
bounds: List<Bound>,
sourceSets: Set<DokkaSourceSet>,
extra: PropertyContainer<DTypeParameter> = PropertyContainer.empty()
) : this(Invariance(TypeParameter(dri, name, presentableName)), documentation, expectPresentInSet, bounds, sourceSets, extra)
) : this(
Invariance(TypeParameter(dri, name, presentableName)),
documentation,
expectPresentInSet,
bounds,
sourceSets,
extra
)

override val dri: DRI by variantTypeParameter.inner::dri
override val name: String by variantTypeParameter.inner::name
Expand Down Expand Up @@ -376,8 +384,17 @@ data class DTypeAlias(
}

sealed class Projection
sealed class Bound : Projection()
data class TypeParameter(val dri: DRI, val name: String, val presentableName: String? = null) : Bound()
sealed class Bound : Projection(), Annotatable
data class TypeParameter(
val dri: DRI,
val name: String,
val presentableName: String? = null,
override val extra: PropertyContainer<TypeParameter> = PropertyContainer.empty()
) : Bound(), WithExtraProperties<TypeParameter> {
override fun withNewExtras(newExtras: PropertyContainer<TypeParameter>): TypeParameter =
copy(extra = extra)
}

object Star : Projection()

sealed class TypeConstructor : Bound() {
Expand All @@ -389,49 +406,65 @@ sealed class TypeConstructor : Bound() {
data class GenericTypeConstructor(
override val dri: DRI,
override val projections: List<Projection>,
override val presentableName: String? = null
) : TypeConstructor()
override val presentableName: String? = null,
override val extra: PropertyContainer<GenericTypeConstructor> = PropertyContainer.empty()
) : TypeConstructor(), WithExtraProperties<GenericTypeConstructor> {
override fun withNewExtras(newExtras: PropertyContainer<GenericTypeConstructor>): GenericTypeConstructor =
copy(extra = newExtras)
}

data class FunctionalTypeConstructor(
override val dri: DRI,
override val projections: List<Projection>,
val isExtensionFunction: Boolean = false,
val isSuspendable: Boolean = false,
override val presentableName: String? = null
) : TypeConstructor()
override val presentableName: String? = null,
override val extra: PropertyContainer<FunctionalTypeConstructor> = PropertyContainer.empty(),
) : TypeConstructor(), WithExtraProperties<FunctionalTypeConstructor> {
override fun withNewExtras(newExtras: PropertyContainer<FunctionalTypeConstructor>): FunctionalTypeConstructor =
copy(extra = newExtras)
}

data class Nullable(val inner: Bound) : Bound()

sealed class Variance<out T : Bound> : Projection() {
abstract val inner: T
}

data class Covariance<out T : Bound>(override val inner: T) : Variance<T>() {
override fun toString() = "out"
}

data class Contravariance<out T : Bound>(override val inner: T) : Variance<T>() {
override fun toString() = "in"
}

data class Invariance<out T : Bound>(override val inner: T) : Variance<T>() {
override fun toString() = ""
}

data class TypeAliased(val typeAlias: Bound, val inner: Bound) : Bound()
data class PrimitiveJavaType(val name: String) : Bound()
data class PrimitiveJavaType(
val name: String,
) : Bound()
MarcinAman marked this conversation as resolved.
Show resolved Hide resolved

object Void : Bound()
object JavaObject : Bound()

data class JavaObject(override val extra: PropertyContainer<JavaObject> = PropertyContainer.empty()) : Bound(),
WithExtraProperties<JavaObject> {
override fun withNewExtras(newExtras: PropertyContainer<JavaObject>): JavaObject =
copy(extra = newExtras)
}

object Dynamic : Bound()
data class UnresolvedBound(val name: String) : Bound()

fun Variance<TypeParameter>.withDri(dri: DRI) = when(this) {
fun Variance<TypeParameter>.withDri(dri: DRI) = when (this) {
is Contravariance -> Contravariance(TypeParameter(dri, inner.name, inner.presentableName))
is Covariance -> Covariance(TypeParameter(dri, inner.name, inner.presentableName))
is Invariance -> Invariance(TypeParameter(dri, inner.name, inner.presentableName))
}

private fun String.shorten(maxLength: Int) = lineSequence().first().let {
if (it.length != length || it.length > maxLength) it.take(maxLength - 3) + "..." else it
}

fun Documentable.dfs(predicate: (Documentable) -> Boolean): Documentable? =
if (predicate(this)) {
this
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/kotlin/model/additionalExtras.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ fun SourceSetDependent<Set<ExtraModifiers>>.toAdditionalModifiers() = Additional

data class Annotations(
private val myContent: SourceSetDependent<List<Annotation>>
) : ExtraProperty<Documentable> {
companion object : ExtraProperty.Key<Documentable, Annotations> {
override fun mergeStrategyFor(left: Annotations, right: Annotations): MergeStrategy<Documentable> =
) : ExtraProperty<Annotatable> {
companion object : ExtraProperty.Key<Annotatable, Annotations> {
override fun mergeStrategyFor(left: Annotations, right: Annotations): MergeStrategy<Annotatable> =
MergeStrategy.Replace(Annotations(left.myContent + right.myContent))
}

override val key: ExtraProperty.Key<Documentable, *> = Annotations
override val key: ExtraProperty.Key<Annotatable, *> = Annotations

data class Annotation(
val dri: DRI,
Expand Down
16 changes: 10 additions & 6 deletions plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.drisOfAllNestedB

interface JvmSignatureUtils {

fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Documentable)
fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Annotatable)

fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Documentable)
fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Annotatable)

fun <T : Documentable> WithExtraProperties<T>.modifiers(): SourceSetDependent<Set<ExtraModifiers>>

fun Collection<ExtraModifiers>.toSignatureString(): String =
joinToString("") { it.name.toLowerCase() + " " }

fun <T : Documentable> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
fun <T : Annotatable> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
extra[Annotations]?.directAnnotations ?: emptyMap()

private fun PageContentBuilder.DocumentableContentBuilder.annotations(
d: Documentable,
d: Annotatable,
ignored: Set<Annotations.Annotation>,
styles: Set<Style>,
operation: PageContentBuilder.DocumentableContentBuilder.(Annotations.Annotation) -> Unit
Expand All @@ -40,6 +40,10 @@ interface JvmSignatureUtils {
is DEnumEntry -> d.annotations()
is DTypeAlias -> d.annotations()
is DParameter -> d.annotations()
is TypeParameter -> d.annotations()
is GenericTypeConstructor -> d.annotations()
is FunctionalTypeConstructor -> d.annotations()
is JavaObject -> d.annotations()
else -> null
}?.let {
it.entries.forEach {
Expand Down Expand Up @@ -104,7 +108,7 @@ interface JvmSignatureUtils {
}

fun PageContentBuilder.DocumentableContentBuilder.annotationsBlockWithIgnored(
d: Documentable,
d: Annotatable,
ignored: Set<Annotations.Annotation>,
renderAtStrategy: AtStrategy,
listBrackets: Pair<Char, Char>,
Expand All @@ -118,7 +122,7 @@ interface JvmSignatureUtils {
}

fun PageContentBuilder.DocumentableContentBuilder.annotationsInlineWithIgnored(
d: Documentable,
d: Annotatable,
ignored: Set<Annotations.Annotation>,
renderAtStrategy: AtStrategy,
listBrackets: Pair<Char, Char>,
Expand Down
25 changes: 18 additions & 7 deletions plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
link(c.name!!, c.dri)
if (c is WithGenerics) {
list(c.generics, prefix = "<", suffix = ">") {
annotationsInline(it)
+buildSignature(it)
}
}
Expand Down Expand Up @@ -219,6 +220,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
text(p.modifiers()[it]?.toSignatureString() ?: "")
p.setter?.let { text("var ") } ?: text("val ")
list(p.generics, prefix = "<", suffix = "> ") {
annotationsInline(it)
+buildSignature(it)
}
p.receiver?.also {
Expand Down Expand Up @@ -252,6 +254,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
text("fun ")
val usedGenerics = if (f.isConstructor) f.generics.filter { f uses it } else f.generics
list(usedGenerics, prefix = "<", suffix = "> ") {
annotationsInline(it)
+buildSignature(it)
}
f.receiver?.also {
Expand Down Expand Up @@ -328,19 +331,23 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog

private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(
p: Projection, showFullyQualifiedName: Boolean = false
): Unit =
when (p) {
is TypeParameter -> link(p.name, p.dri)

is FunctionalTypeConstructor ->
): Unit {
return when (p) {
is TypeParameter -> {
annotationsInline(p)
link(p.name, p.dri)
}
is FunctionalTypeConstructor -> {
annotationsInline(p)
+funType(mainDRI.single(), mainSourcesetData, p)

}
is GenericTypeConstructor ->
group(styles = emptySet()) {
val linkText = if (showFullyQualifiedName && p.dri.packageName != null) {
"${p.dri.packageName}.${p.dri.classNames.orEmpty()}"
} else p.dri.classNames.orEmpty()
if (p.presentableName != null) text(p.presentableName + ": ")
annotationsInline(p)
link(linkText, p.dri)
list(p.projections, prefix = "<", suffix = ">") {
signatureForProjection(it, showFullyQualifiedName)
Expand All @@ -360,12 +367,16 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog
}

is TypeAliased -> signatureForProjection(p.typeAlias)
is JavaObject -> link("Any", DriOfAny)
is JavaObject -> {
annotationsInline(p)
link("Any", DriOfAny)
}
is Void -> link("Unit", DriOfUnit)
is PrimitiveJavaType -> signatureForProjection(p.translateToKotlin(), showFullyQualifiedName)
is Dynamic -> text("dynamic")
is UnresolvedBound -> text(p.name)
}
}

private fun funType(dri: DRI, sourceSets: Set<DokkaSourceSet>, type: FunctionalTypeConstructor) =
contentBuilder.contentFor(dri, sourceSets, ContentKind.Main) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ object KotlinSignatureUtils : JvmSignatureUtils {
)


override fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Documentable) =
override fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Annotatable) =
annotationsBlockWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)

override fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Documentable) =
override fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Annotatable) =
annotationsInlineWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)

override fun <T : Documentable> WithExtraProperties<T>.modifiers() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -784,36 +784,45 @@ private class DokkaDescriptorVisitor(
)

private suspend fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? =
map { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name")
mapNotNull { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name")
.safeAs<StringValue>()?.value?.let { unquotedValue(it) }

private suspend fun KotlinType.toBound(): Bound = when (this) {

is DynamicType -> Dynamic
is AbbreviatedType -> TypeAliased(
abbreviation.toBound(),
expandedType.toBound()
)
else -> when (val ctor = constructor.declarationDescriptor) {
is TypeParameterDescriptor -> TypeParameter(
dri = DRI.from(ctor),
name = ctor.name.asString(),
presentableName = annotations.getPresentableName()
)
is FunctionClassDescriptor -> FunctionalTypeConstructor(
DRI.from(ctor),
arguments.map { it.toProjection() },
isExtensionFunction = isExtensionFunctionType || isBuiltinExtensionFunctionalType,
isSuspendable = isSuspendFunctionTypeOrSubtype,
presentableName = annotations.getPresentableName()
private suspend fun KotlinType.toBound(): Bound {
suspend fun <T : Annotatable> annotations(): PropertyContainer<T> =
getAnnotations().takeIf { it.isNotEmpty() }?.let { annotations ->
PropertyContainer.withAll(annotations.toSourceSetDependent().toAnnotations())
} ?: PropertyContainer.empty()

return when (this) {
is DynamicType -> Dynamic
is AbbreviatedType -> TypeAliased(
abbreviation.toBound(),
expandedType.toBound()
)
else -> GenericTypeConstructor(
DRI.from(ctor!!), // TODO: remove '!!'
arguments.map { it.toProjection() },
annotations.getPresentableName()
)
}.let {
if (isMarkedNullable) Nullable(it) else it
else -> when (val ctor = constructor.declarationDescriptor) {
is TypeParameterDescriptor -> TypeParameter(
dri = DRI.from(ctor),
name = ctor.name.asString(),
presentableName = annotations.getPresentableName(),
extra = annotations()
)
is FunctionClassDescriptor -> FunctionalTypeConstructor(
DRI.from(ctor),
arguments.map { it.toProjection() },
isExtensionFunction = isExtensionFunctionType || isBuiltinExtensionFunctionalType,
isSuspendable = isSuspendFunctionTypeOrSubtype,
presentableName = annotations.getPresentableName(),
extra = annotations()
)
else -> GenericTypeConstructor(
DRI.from(ctor!!), // TODO: remove '!!'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The !! can be removed here IMHO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think so since it is nullable and afaik we dont have a nullable constructor for DRI

arguments.map { it.toProjection() },
annotations.getPresentableName(),
extra = annotations()
)
}.let {
if (isMarkedNullable) Nullable(it) else it
}
}
}

Expand Down Expand Up @@ -909,7 +918,7 @@ private class DokkaDescriptorVisitor(

private suspend fun Annotated.getAnnotations() = annotations.parallelMapNotNull { it.toAnnotation() }

private suspend fun ConstantValue<*>.toValue(): AnnotationParameterValue? = when (this) {
private fun ConstantValue<*>.toValue(): AnnotationParameterValue? = when (this) {
is ConstantsAnnotationValue -> value.toAnnotation()?.let { AnnotationValue(it) }
is ConstantsArrayValue -> ArrayValue(value.mapNotNull { it.toValue() })
is ConstantsEnumValue -> EnumValue(
Expand All @@ -933,7 +942,7 @@ private class DokkaDescriptorVisitor(
else -> StringValue(unquotedValue(toString()))
}

private suspend fun AnnotationDescriptor.toAnnotation(scope: Annotations.AnnotationScope = Annotations.AnnotationScope.DIRECT): Annotations.Annotation =
private fun AnnotationDescriptor.toAnnotation(scope: Annotations.AnnotationScope = Annotations.AnnotationScope.DIRECT): Annotations.Annotation? =
MarcinAman marked this conversation as resolved.
Show resolved Hide resolved
Annotations.Annotation(
DRI.from(annotationClass as DeclarationDescriptor),
allValueArguments.map { it.key.asString() to it.value.toValue() }.filter {
Expand All @@ -944,7 +953,8 @@ private class DokkaDescriptorVisitor(
)

private fun AnnotationDescriptor.mustBeDocumented(): Boolean =
annotationClass?.annotations?.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented")) ?: false
if (source.toString() == "NO_SOURCE") false
else annotationClass?.annotations?.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented")) ?: false

private suspend fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> =
getAnnotations() + (backingField?.getAnnotations() ?: emptyList())
Expand Down Expand Up @@ -1015,8 +1025,8 @@ private class DokkaDescriptorVisitor(
private suspend fun DeclarationDescriptorWithSource.fileLevelAnnotations() = ktFile()
?.let { file -> resolutionFacade.resolveSession.getFileAnnotations(file) }
?.toList()
?.parallelMapNotNull { it.toAnnotation(scope = Annotations.AnnotationScope.FILE) }
.orEmpty()
.parallelMap { it.toAnnotation(scope = Annotations.AnnotationScope.FILE) }
}

private data class AncestryLevel(
Expand Down
Loading