aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
blob: 0ae72109e8eb1586ee2753c230c05a7805f9edf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package org.jetbrains.dokka.base.signatures

import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.properties.WithExtraProperties

interface JvmSignatureUtils {

    fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: Documentable)

    fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: Documentable)

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

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

    fun <T : Documentable> WithExtraProperties<T>.annotations(): List<Annotations.Annotation> =
        extra[Annotations]?.content ?: emptyList()

    private fun Annotations.Annotation.toSignatureString(): String =
        "@" + this.dri.classNames + "(" + this.params.entries.joinToString { it.key + "=" + it.value } + ")"

    private fun PageContentBuilder.DocumentableContentBuilder.annotations(
        d: Documentable,
        ignored: Set<Annotations.Annotation>,
        operation: (Annotations.Annotation) -> Unit
    ): Unit = when (d) {
        is DFunction -> d.annotations()
        is DProperty -> d.annotations()
        is DClass -> d.annotations()
        is DInterface -> d.annotations()
        is DObject -> d.annotations()
        is DEnum -> d.annotations()
        is DAnnotation -> d.annotations()
        is DTypeParameter -> d.annotations()
        is DEnumEntry -> d.annotations()
        is DTypeAlias -> d.annotations()
        is DParameter -> d.annotations()
        else -> null
    }?.let {
        it.filter { it !in ignored }.forEach {
            operation(it)
        }
    } ?: Unit

    fun PageContentBuilder.DocumentableContentBuilder.toSignatureString(
        a: Annotations.Annotation,
        renderAtStrategy: AtStrategy,
        listBrackets: Pair<Char, Char>,
        classExtension: String
    ) {
        when (renderAtStrategy) {
            is All, is OnlyOnce -> text("@")
            is Never -> Unit
        }
        link(a.dri.classNames!!, a.dri)
        text("(")
        a.params.entries.forEachIndexed { i, it ->
            text(it.key + " = ")
            when (renderAtStrategy) {
                is All -> All
                is Never, is OnlyOnce -> Never
            }.let { strategy ->
                valueToSignature(it.value, strategy, listBrackets, classExtension)
            }
            if (i != a.params.entries.size - 1) text(", ")
        }
        text(")")
    }

    private fun PageContentBuilder.DocumentableContentBuilder.valueToSignature(
        a: AnnotationParameterValue,
        renderAtStrategy: AtStrategy,
        listBrackets: Pair<Char, Char>,
        classExtension: String
    ): Unit = when (a) {
        is AnnotationValue -> toSignatureString(a.annotation, renderAtStrategy, listBrackets, classExtension)
        is ArrayValue -> {
            text(listBrackets.first.toString())
            a.value.forEachIndexed { i, it ->
                valueToSignature(it, renderAtStrategy, listBrackets, classExtension)
                if (i != a.value.size - 1) text(", ")
            }
            text(listBrackets.second.toString())
        }
        is EnumValue -> link(a.enumName, a.enumDri)
        is ClassValue -> link(a.className + classExtension, a.classDRI)
        is StringValue -> text(a.value)
    }

    fun PageContentBuilder.DocumentableContentBuilder.annotationsBlockWithIgnored(
        d: Documentable,
        ignored: Set<Annotations.Annotation>,
        renderAtStrategy: AtStrategy,
        listBrackets: Pair<Char, Char>,
        classExtension: String
    ) {
        annotations(d, ignored) {
            group {
                toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
            }
        }
    }

    fun PageContentBuilder.DocumentableContentBuilder.annotationsInlineWithIgnored(
        d: Documentable,
        ignored: Set<Annotations.Annotation>,
        renderAtStrategy: AtStrategy,
        listBrackets: Pair<Char, Char>,
        classExtension: String
    ) {
        annotations(d, ignored) {
            toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
            text(Typography.nbsp.toString())
        }
    }
}

sealed class AtStrategy
object All : AtStrategy()
object OnlyOnce : AtStrategy()
object Never : AtStrategy()