Skip to content

Commit 9b07435

Browse files
authored
[K2] Support kotlin-as-java and javadoc plugins and update version of Analysis API (#3227)
* Implement InheritanceBuilder and for symbols * Enable tests for as-java and javadoc plugins and fix some * Update the version of Analysis API and enable test * Use assert from kotlin.test * Rename `descriptorInheritanceBuilder` * Fix after rebasing * Mute test `two classes from different packages`
1 parent 3be4dd9 commit 9b07435

File tree

20 files changed

+308
-60
lines changed

20 files changed

+308
-60
lines changed

examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ class Greeter(val name: String) {
1717

1818
fun main(args: Array<String>) {
1919
Greeter(args[0]).greet()
20-
}
20+
}

plugins/base/src/test/kotlin/model/ClassesTest.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
126126
type.name equals "Unit"
127127
}
128128
}
129+
130+
with((this.companion).cast<DObject>()) {
131+
name equals "Companion"
132+
children counts 5
133+
134+
with((this / "x").cast<DProperty>()) {
135+
name equals "x"
136+
}
137+
138+
with((this / "foo").cast<DFunction>()) {
139+
name equals "foo"
140+
parameters counts 0
141+
type.name equals "Unit"
142+
}
143+
}
129144
}
130145
}
131146
}

plugins/javadoc/build.gradle.kts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.jetbrains.registerDokkaArtifactPublication
77
plugins {
88
id("org.jetbrains.conventions.kotlin-jvm")
99
id("org.jetbrains.conventions.maven-publish")
10+
id("org.jetbrains.conventions.base-unit-test")
1011
}
1112

1213
dependencies {
@@ -22,7 +23,11 @@ dependencies {
2223
implementation(libs.kotlinx.coroutines.core)
2324

2425
testImplementation(kotlin("test"))
25-
testImplementation(projects.plugins.base.baseTestUtils)
26+
symbolsTestConfiguration(project(path = ":subprojects:analysis-kotlin-symbols", configuration = "shadow"))
27+
descriptorsTestConfiguration(project(path = ":subprojects:analysis-kotlin-descriptors", configuration = "shadow"))
28+
testImplementation(projects.plugins.base.baseTestUtils) {
29+
exclude(module = "analysis-kotlin-descriptors")
30+
}
2631
testImplementation(projects.core.testApi)
2732
testImplementation(libs.jsoup)
2833
}

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ internal abstract class AbstractJavadocTemplateMapTest : BaseAbstractTest() {
2828
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
2929
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
3030
)
31+
classpath = listOfNotNull(jvmStdlibPath)
3132
}
3233
}
3334
}

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.jsoup.Jsoup
88
import utils.TestOutputWriterPlugin
99
import kotlin.test.Test
1010
import kotlin.test.assertEquals
11+
import kotlin.test.assertTrue
1112

1213
internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
1314

@@ -16,6 +17,7 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
1617
sourceSets {
1718
sourceSet {
1819
sourceRoots = listOf("src/main/kotlin")
20+
classpath = listOfNotNull(jvmStdlibPath)
1921
}
2022
}
2123
}
@@ -54,13 +56,20 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
5456
.select("code")
5557
.map { it.text() }
5658
.toSet()
57-
58-
assertEquals(setOf(
59-
"getIssuesFetched()",
60-
"setIssuesFetched(Integer issuesFetched)",
61-
"isFoo()",
62-
"setFoo(String isFoo)",
63-
), props)
59+
// In K2 name of accessors parameter is `value`
60+
assertTrue(
61+
setOf(
62+
"getIssuesFetched()",
63+
"setIssuesFetched(Integer issuesFetched)",
64+
"isFoo()",
65+
"setFoo(String isFoo)",
66+
) == props || setOf(
67+
"getIssuesFetched()",
68+
"setIssuesFetched(Integer value)",
69+
"isFoo()",
70+
"setFoo(String value)",
71+
) == props
72+
)
6473

6574
val descriptionLinks = html
6675
.select("div.description")

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import org.jetbrains.dokka.javadoc.pages.AllClassesPage
88
import org.jetbrains.dokka.javadoc.pages.LinkJavadocListEntry
99
import org.jetbrains.dokka.links.DRI
1010
import org.jetbrains.dokka.pages.ContentKind
11+
import org.junit.jupiter.api.Tag
1112
import kotlin.test.Test
1213
import kotlin.test.assertEquals
1314

1415
internal class JavadocAllClassesTemplateMapTest : AbstractJavadocTemplateMapTest() {
1516
@Test
17+
@Tag("onlyDescriptors") // https://github.com/Kotlin/dokka/issues/3250
1618
fun `two classes from different packages`() {
1719
dualTestTemplateMapInline(
1820
"""

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package org.jetbrains.dokka.javadoc
77
import org.jetbrains.dokka.javadoc.pages.IndexPage
88
import org.jetbrains.dokka.javadoc.renderer.TemplateMap
99
import org.jetbrains.dokka.links.DRI
10+
import org.junit.jupiter.api.Tag
1011
import kotlin.test.Test
1112
import kotlin.test.assertEquals
1213
import kotlin.test.assertNotNull
@@ -76,7 +77,21 @@ internal class JavadocIndexTest : AbstractJavadocTemplateMapTest() {
7677
AnnotationTarget.ANNOTATION_CLASS::class.java.methods.any { it.name == "describeConstable" }
7778

7879
testIndexPages(commonTestQuery) { indexPages ->
79-
assertEquals(if (hasAdditionalFunction()) 33 else 32, indexPages.sumBy { it.elements.size })
80+
assertEquals("A-index: a, A\n" +
81+
"B-index: b\n" +
82+
"C-index: c, ClassA, ClassB, ClassC, ClassC.InnerClass, ClassCEnum, compareTo\n" +
83+
"D-index: d, D\n" +
84+
"E-index: e, E, equals, equals\n" +
85+
"F-index: f\n" +
86+
"G-index: g, getDeclaringClass, getEntries, getName, getOrdinal\n" +
87+
"H-index: h, hashCode, hashCode\n" +
88+
"J-index: j\n" +
89+
"K-index: k\n" +
90+
"P-index: package0, package1\n" +
91+
"T-index: toString, toString\n" +
92+
"V-index: valueOf, values",
93+
indexPages.joinToString("\n") { it.title + ": " + it.elements.joinToString { it.getId() } })
94+
assertEquals(if (hasAdditionalFunction()) 34 else 33, indexPages.sumBy { it.elements.size })
8095
}
8196
}
8297

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ class JavadocLocationTest : BaseAbstractTest() {
247247
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
248248
)
249249
analysisPlatform = "jvm"
250+
classpath = listOfNotNull(jvmStdlibPath)
250251
}
251252
}
252253
}

plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
1818
format = "javadoc"
1919
sourceSets {
2020
sourceSet {
21-
sourceRoots = listOf("src")
21+
sourceRoots = listOf("src/jvm")
2222
analysisPlatform = "jvm"
2323
externalDocumentationLinks = listOf(
2424
ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
2525
ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
2626
)
2727
}
2828
sourceSet {
29-
sourceRoots = listOf("src")
29+
sourceRoots = listOf("src/js")
3030
analysisPlatform = "js"
3131
externalDocumentationLinks = listOf(
3232
ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
@@ -54,7 +54,9 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
5454
fun `mpp config should fail for javadoc`() {
5555
testInline(
5656
"""
57-
|/src/main/kotlin/example/Test.kt
57+
|/src/jvm/kotlin/example/Test.kt
58+
|class Test
59+
|/src/js/kotlin/example/Test.kt
5860
|class Test
5961
""".trimMargin(), mppConfig
6062
) {

plugins/kotlin-as-java/build.gradle.kts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.jetbrains.registerDokkaArtifactPublication
77
plugins {
88
id("org.jetbrains.conventions.kotlin-jvm")
99
id("org.jetbrains.conventions.maven-publish")
10+
id("org.jetbrains.conventions.base-unit-test")
1011
}
1112

1213
dependencies {
@@ -20,7 +21,11 @@ dependencies {
2021
testImplementation(kotlin("test"))
2122
testImplementation(libs.jsoup)
2223
testImplementation(projects.plugins.base)
23-
testImplementation(projects.plugins.base.baseTestUtils)
24+
symbolsTestConfiguration(project(path = ":subprojects:analysis-kotlin-symbols", configuration = "shadow"))
25+
descriptorsTestConfiguration(project(path = ":subprojects:analysis-kotlin-descriptors", configuration = "shadow"))
26+
testImplementation(projects.plugins.base.baseTestUtils) {
27+
exclude(module = "analysis-kotlin-descriptors")
28+
}
2429
testImplementation(projects.core.contentMatcherTestUtils)
2530
testImplementation(projects.core.testApi)
2631
}

plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() {
377377
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
378378
stdlibExternalDocumentationLink
379379
)
380+
classpath = listOfNotNull(jvmStdlibPath)
380381
}
381382
}
382383
}

plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class KotlinAsJavaSignatureTest : BaseAbstractTest() {
2323
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
2424
stdlibExternalDocumentationLink
2525
)
26+
classpath = listOfNotNull(jvmStdlibPath)
2627
}
2728
}
2829
}

subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,21 @@ import org.jetbrains.dokka.links.DRI
99

1010
@InternalDokkaApi
1111
public interface KotlinToJavaService {
12+
/**
13+
* E.g.
14+
* kotlin.Throwable -> java.lang.Throwable
15+
* kotlin.Int -> java.lang.Integer
16+
* kotlin.Int.Companion -> kotlin.jvm.internal.IntCompanionObject
17+
* kotlin.Nothing -> java.lang.Void
18+
* kotlin.IntArray -> null
19+
* kotlin.Function3 -> kotlin.jvm.functions.Function3
20+
* kotlin.coroutines.SuspendFunction3 -> kotlin.jvm.functions.Function4
21+
* kotlin.Function42 -> kotlin.jvm.functions.FunctionN
22+
* kotlin.coroutines.SuspendFunction42 -> kotlin.jvm.functions.FunctionN
23+
* kotlin.reflect.KFunction3 -> kotlin.reflect.KFunction
24+
* kotlin.reflect.KSuspendFunction3 -> kotlin.reflect.KFunction
25+
* kotlin.reflect.KFunction42 -> kotlin.reflect.KFunction
26+
* kotlin.reflect.KSuspendFunction42 -> kotlin.reflect.KFunction
27+
*/
1228
public fun findAsJava(kotlinDri: DRI): DRI?
1329
}

subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public class SymbolsAnalysisPlugin : DokkaPlugin() {
9292
internal val symbolAnalyzerImpl by extending {
9393
plugin<InternalKotlinAnalysisPlugin>().documentableSourceLanguageParser providing { KotlinDocumentableSourceLanguageParser() }
9494
}
95+
9596
internal val symbolFullClassHierarchyBuilder by extending {
9697
plugin<InternalKotlinAnalysisPlugin>().fullClassHierarchyBuilder providing ::SymbolFullClassHierarchyBuilder
9798
}
@@ -104,14 +105,14 @@ public class SymbolsAnalysisPlugin : DokkaPlugin() {
104105
plugin<InternalKotlinAnalysisPlugin>().moduleAndPackageDocumentationReader providing ::ModuleAndPackageDocumentationReader
105106
}
106107

107-
/* internal val kotlinToJavaMapper by extending {
108-
plugin<InternalKotlinAnalysisPlugin>().kotlinToJavaService providing { DescriptorKotlinToJavaMapper() }
108+
internal val kotlinToJavaMapper by extending {
109+
plugin<InternalKotlinAnalysisPlugin>().kotlinToJavaService providing { SymbolKotlinToJavaMapper() }
109110
}
110111

111-
intern val descriptorInheritanceBuilder by extending {
112-
plugin<InternalKotlinAnalysisPlugin>().inheritanceBuilder providing { DescriptorInheritanceBuilder() }
112+
internal val symbolInheritanceBuilder by extending {
113+
plugin<InternalKotlinAnalysisPlugin>().inheritanceBuilder providing ::SymbolInheritanceBuilder
113114
}
114-
*/
115+
115116
internal val symbolExternalDocumentablesProvider by extending {
116117
plugin<InternalKotlinAnalysisPlugin>().externalDocumentablesProvider providing ::SymbolExternalDocumentablesProvider
117118
}

subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package org.jetbrains.dokka.analysis.kotlin.symbols.services
66

77
import com.intellij.psi.PsiClass
8+
import org.jetbrains.dokka.DokkaConfiguration
89
import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource
910
import org.jetbrains.dokka.analysis.java.util.from
1011
import org.jetbrains.dokka.analysis.kotlin.symbols.translators.getDRIFromClassLike
@@ -17,14 +18,16 @@ import org.jetbrains.dokka.analysis.kotlin.internal.ClassHierarchy
1718
import org.jetbrains.dokka.analysis.kotlin.internal.FullClassHierarchyBuilder
1819
import org.jetbrains.dokka.analysis.kotlin.internal.Supertypes
1920
import org.jetbrains.dokka.analysis.kotlin.symbols.plugin.SymbolsAnalysisPlugin
21+
import org.jetbrains.dokka.analysis.kotlin.symbols.translators.AnnotationTranslator
22+
import org.jetbrains.dokka.analysis.kotlin.symbols.translators.TypeTranslator
2023
import org.jetbrains.dokka.plugability.DokkaContext
2124
import org.jetbrains.dokka.plugability.plugin
2225
import org.jetbrains.dokka.plugability.querySingle
2326
import org.jetbrains.kotlin.psi.KtClassOrObject
2427
import java.util.concurrent.ConcurrentHashMap
2528

2629

27-
internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : FullClassHierarchyBuilder {
30+
internal class SymbolFullClassHierarchyBuilder(context: DokkaContext) : FullClassHierarchyBuilder {
2831
private val kotlinAnalysis = context.plugin<SymbolsAnalysisPlugin>().querySingle { kotlinAnalysis }
2932

3033
override suspend fun build(module: DModule): ClassHierarchy {
@@ -38,14 +41,13 @@ internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : Full
3841
supersMap: MutableMap<DRI, Supertypes>
3942
) {
4043
val (dri, kotlinType) = driWithKType
41-
val supertypes = kotlinType.getDirectSuperTypes().filterNot { it.isAny }
42-
val supertypesDriWithKType = supertypes.mapNotNull { supertype ->
43-
supertype.expandedClassSymbol?.let {
44-
getDRIFromClassLike(it) to supertype
45-
}
46-
}
47-
4844
if (supersMap[dri] == null) {
45+
val supertypes = kotlinType.getDirectSuperTypes(shouldApproximate = true).filterNot { it.isAny }
46+
val supertypesDriWithKType = supertypes.mapNotNull { supertype ->
47+
supertype.expandedClassSymbol?.let {
48+
getDRIFromClassLike(it) to supertype
49+
}
50+
}
4951
supersMap[dri] = supertypesDriWithKType.map { it.first }
5052
supertypesDriWithKType.forEach { collectSupertypesFromKtType(it, supersMap) }
5153
}
@@ -92,4 +94,55 @@ internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : Full
9294
}
9395
}
9496

97+
internal class SuperclassesWithKind(
98+
val typeConstructorWithKind: TypeConstructorWithKind,
99+
val superclasses: List<TypeConstructorWithKind>
100+
)
101+
102+
/**
103+
* Currently, it works only for Symbols
104+
*/
105+
internal fun collectKotlinSupertypesWithKind(
106+
documentable: Iterable<Documentable>,
107+
sourceSet: DokkaConfiguration.DokkaSourceSet
108+
): Map<DRI, SuperclassesWithKind> {
109+
val typeTranslator = TypeTranslator(sourceSet, AnnotationTranslator())
110+
val hierarchy = mutableMapOf<DRI, SuperclassesWithKind>()
111+
112+
analyze(kotlinAnalysis.getModule(sourceSet)) {
113+
documentable.filterIsInstance<DClasslike>().forEach {
114+
val source = it.sources[sourceSet]
115+
if (source is KtPsiDocumentableSource) {
116+
(source.psi as? KtClassOrObject)?.let { psi ->
117+
val type = psi.getNamedClassOrObjectSymbol()?.buildSelfClassType() ?: return@analyze
118+
collectSupertypesWithKindFromKtType(typeTranslator, with(typeTranslator) {
119+
toTypeConstructorWithKindFrom(type)
120+
} to type, hierarchy)
121+
}
122+
} // else if (source is PsiDocumentableSource) TODO val psi = source.psi as? PsiClass
123+
}
124+
}
125+
return hierarchy
126+
}
127+
128+
private fun KtAnalysisSession.collectSupertypesWithKindFromKtType(
129+
typeTranslator: TypeTranslator,
130+
typeConstructorWithKindWithKType: Pair<TypeConstructorWithKind, KtType>,
131+
supersMap: MutableMap<DRI, SuperclassesWithKind>
132+
) {
133+
val (typeConstructorWithKind, kotlinType) = typeConstructorWithKindWithKType
134+
135+
if (supersMap[typeConstructorWithKind.typeConstructor.dri] == null) {
136+
val supertypes = kotlinType.getDirectSuperTypes(shouldApproximate = true).filterNot { it.isAny }
137+
138+
val supertypesDriWithKType = supertypes.map { supertype ->
139+
with(typeTranslator) {
140+
toTypeConstructorWithKindFrom(supertype)
141+
} to supertype
142+
}
143+
supersMap[typeConstructorWithKind.typeConstructor.dri] =
144+
SuperclassesWithKind(typeConstructorWithKind, supertypesDriWithKType.map { it.first })
145+
supertypesDriWithKType.forEach { collectSupertypesWithKindFromKtType(typeTranslator, it, supersMap) }
146+
}
147+
}
95148
}

0 commit comments

Comments
 (0)