aboutsummaryrefslogtreecommitdiff
path: root/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt
blob: 91e5164d83633feadf6f8bb2580ca343d45add7d (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
package org.jetbrains.dokka.kotlinAsJava.signatures

import org.jetbrains.dokka.base.signatures.SignatureProvider
import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
import org.jetbrains.dokka.links.sureClassNames
import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.model.Annotation
import org.jetbrains.dokka.model.Enum
import org.jetbrains.dokka.model.Function
import org.jetbrains.dokka.pages.ContentKind
import org.jetbrains.dokka.pages.ContentNode
import org.jetbrains.dokka.pages.PlatformData
import org.jetbrains.dokka.utilities.DokkaLogger

class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider {
    private val contentBuilder = PageContentBuilder(ctcc, this, logger)

    private val ignoredVisibilities = setOf(JavaVisibility.Default, KotlinVisibility.Public)
    private val ignoredModifiers =
        setOf(KotlinModifier.Open, JavaModifier.Empty, KotlinModifier.Empty, KotlinModifier.Sealed)


    override fun signature(documentable: Documentable): ContentNode = when (documentable) {
        is Function -> signature(documentable)
        is Classlike -> signature(documentable)
        is TypeParameter -> signature(documentable)
        else -> throw NotImplementedError(
            "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}"
        )
    }

    private fun signature(c: Classlike) = contentBuilder.contentFor(c, ContentKind.Symbol) {
        platformText(c.visibility) { (it.takeIf { it !in ignoredVisibilities }?.name ?: "") + " " }

        if (c is Class) {
            text(c.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ")
        }

        when (c) {
            is Class -> text("class ")
            is Interface -> text("interface ")
            is Enum -> text("enum ")
            is Object -> text("class ")
            is Annotation -> text("@interface ")
        }
        text(c.name!!)
        if (c is WithGenerics) {
            list(c.generics, prefix = "<", suffix = ">") {
                +buildSignature(it)
            }
        }
        if (c is WithSupertypes) {
            c.supertypes.map { (p, dris) ->
                list(dris, prefix = " extends ", platformData = setOf(p)) {
                    link(it.sureClassNames, it, platformData = setOf(p))
                }
            }
        }
    }

    private fun signature(f: Function) = contentBuilder.contentFor(f, ContentKind.Symbol) {
        text(f.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ")
        val returnType = f.type
        if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) {
            type(returnType)
        }
        text("  ")
        link(f.name, f.dri)
        list(f.generics, prefix = "<", suffix = ">") {
            +buildSignature(it)
        }
        text("(")
        list(f.parameters) {
            type(it.type)
            text(" ")
            link(it.name!!, it.dri)
        }
        text(")")
    }

    private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) {
        text(t.name.substringAfterLast("."))
        list(t.bounds, prefix = " extends ") {
            signatureForProjection(it)
        }
    }


    private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(p: Projection): Unit = when (p) {
        is OtherParameter -> text(p.name)

        is TypeConstructor -> group {
            link(p.dri.classNames.orEmpty(), p.dri)
            list(p.projections, prefix = "<", suffix = ">") {
                signatureForProjection(it)
            }
        }

        is Variance -> group {
            text(p.kind.toString() + " ")
            signatureForProjection(p.inner)
        }

        is Star -> text("?")

        is Nullable -> signatureForProjection(p.inner)
    }
}