aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2023-10-26 14:39:00 +0300
committerGitHub <noreply@github.com>2023-10-26 14:39:00 +0300
commit9b07435773831874d4d80066a2227596198af988 (patch)
tree45bdc3f88ac64ea934515a1f6b44e63e461f6ce1
parent3be4dd94e3af2e749969ba352482eae6957cac5a (diff)
downloaddokka-9b07435773831874d4d80066a2227596198af988.tar.gz
dokka-9b07435773831874d4d80066a2227596198af988.tar.bz2
dokka-9b07435773831874d4d80066a2227596198af988.zip
[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`
-rw-r--r--examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt2
-rw-r--r--plugins/base/src/test/kotlin/model/ClassesTest.kt15
-rw-r--r--plugins/javadoc/build.gradle.kts7
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt1
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt23
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt2
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt17
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt1
-rw-r--r--plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt8
-rw-r--r--plugins/kotlin-as-java/build.gradle.kts7
-rw-r--r--plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt1
-rw-r--r--plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt1
-rw-r--r--subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt16
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt11
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt69
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolInheritanceBuilder.kt89
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolKotlinToJavaMapper.kt38
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt11
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt47
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt2
20 files changed, 308 insertions, 60 deletions
diff --git a/examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt b/examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt
index 172e18f7..e37fcfb7 100644
--- a/examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt
+++ b/examples/gradle/dokka-gradle-example/src/main/kotlin/demo/HelloWorld.kt
@@ -17,4 +17,4 @@ class Greeter(val name: String) {
fun main(args: Array<String>) {
Greeter(args[0]).greet()
-}
+} \ No newline at end of file
diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt
index 763809e8..c18dfafb 100644
--- a/plugins/base/src/test/kotlin/model/ClassesTest.kt
+++ b/plugins/base/src/test/kotlin/model/ClassesTest.kt
@@ -126,6 +126,21 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class
type.name equals "Unit"
}
}
+
+ with((this.companion).cast<DObject>()) {
+ name equals "Companion"
+ children counts 5
+
+ with((this / "x").cast<DProperty>()) {
+ name equals "x"
+ }
+
+ with((this / "foo").cast<DFunction>()) {
+ name equals "foo"
+ parameters counts 0
+ type.name equals "Unit"
+ }
+ }
}
}
}
diff --git a/plugins/javadoc/build.gradle.kts b/plugins/javadoc/build.gradle.kts
index 2a04366b..ea882bb4 100644
--- a/plugins/javadoc/build.gradle.kts
+++ b/plugins/javadoc/build.gradle.kts
@@ -7,6 +7,7 @@ import org.jetbrains.registerDokkaArtifactPublication
plugins {
id("org.jetbrains.conventions.kotlin-jvm")
id("org.jetbrains.conventions.maven-publish")
+ id("org.jetbrains.conventions.base-unit-test")
}
dependencies {
@@ -22,7 +23,11 @@ dependencies {
implementation(libs.kotlinx.coroutines.core)
testImplementation(kotlin("test"))
- testImplementation(projects.plugins.base.baseTestUtils)
+ symbolsTestConfiguration(project(path = ":subprojects:analysis-kotlin-symbols", configuration = "shadow"))
+ descriptorsTestConfiguration(project(path = ":subprojects:analysis-kotlin-descriptors", configuration = "shadow"))
+ testImplementation(projects.plugins.base.baseTestUtils) {
+ exclude(module = "analysis-kotlin-descriptors")
+ }
testImplementation(projects.core.testApi)
testImplementation(libs.jsoup)
}
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt
index 070f1834..60265e33 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/AbstractJavadocTemplateMapTest.kt
@@ -28,6 +28,7 @@ internal abstract class AbstractJavadocTemplateMapTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
)
+ classpath = listOfNotNull(jvmStdlibPath)
}
}
}
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt
index 3f7e1610..95ce4d27 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAccessorNamingTest.kt
@@ -8,6 +8,7 @@ import org.jsoup.Jsoup
import utils.TestOutputWriterPlugin
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
@@ -16,6 +17,7 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
sourceSets {
sourceSet {
sourceRoots = listOf("src/main/kotlin")
+ classpath = listOfNotNull(jvmStdlibPath)
}
}
}
@@ -54,13 +56,20 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
.select("code")
.map { it.text() }
.toSet()
-
- assertEquals(setOf(
- "getIssuesFetched()",
- "setIssuesFetched(Integer issuesFetched)",
- "isFoo()",
- "setFoo(String isFoo)",
- ), props)
+ // In K2 name of accessors parameter is `value`
+ assertTrue(
+ setOf(
+ "getIssuesFetched()",
+ "setIssuesFetched(Integer issuesFetched)",
+ "isFoo()",
+ "setFoo(String isFoo)",
+ ) == props || setOf(
+ "getIssuesFetched()",
+ "setIssuesFetched(Integer value)",
+ "isFoo()",
+ "setFoo(String value)",
+ ) == props
+ )
val descriptionLinks = html
.select("div.description")
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt
index a399f523..8d7ff1ea 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocAllClassesTemplateMapTest.kt
@@ -8,11 +8,13 @@ import org.jetbrains.dokka.javadoc.pages.AllClassesPage
import org.jetbrains.dokka.javadoc.pages.LinkJavadocListEntry
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.pages.ContentKind
+import org.junit.jupiter.api.Tag
import kotlin.test.Test
import kotlin.test.assertEquals
internal class JavadocAllClassesTemplateMapTest : AbstractJavadocTemplateMapTest() {
@Test
+ @Tag("onlyDescriptors") // https://github.com/Kotlin/dokka/issues/3250
fun `two classes from different packages`() {
dualTestTemplateMapInline(
"""
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
index ec36d0e3..ba8f73cf 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/JavadocIndexTest.kt
@@ -7,6 +7,7 @@ package org.jetbrains.dokka.javadoc
import org.jetbrains.dokka.javadoc.pages.IndexPage
import org.jetbrains.dokka.javadoc.renderer.TemplateMap
import org.jetbrains.dokka.links.DRI
+import org.junit.jupiter.api.Tag
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
@@ -76,7 +77,21 @@ internal class JavadocIndexTest : AbstractJavadocTemplateMapTest() {
AnnotationTarget.ANNOTATION_CLASS::class.java.methods.any { it.name == "describeConstable" }
testIndexPages(commonTestQuery) { indexPages ->
- assertEquals(if (hasAdditionalFunction()) 33 else 32, indexPages.sumBy { it.elements.size })
+ assertEquals("A-index: a, A\n" +
+ "B-index: b\n" +
+ "C-index: c, ClassA, ClassB, ClassC, ClassC.InnerClass, ClassCEnum, compareTo\n" +
+ "D-index: d, D\n" +
+ "E-index: e, E, equals, equals\n" +
+ "F-index: f\n" +
+ "G-index: g, getDeclaringClass, getEntries, getName, getOrdinal\n" +
+ "H-index: h, hashCode, hashCode\n" +
+ "J-index: j\n" +
+ "K-index: k\n" +
+ "P-index: package0, package1\n" +
+ "T-index: toString, toString\n" +
+ "V-index: valueOf, values",
+ indexPages.joinToString("\n") { it.title + ": " + it.elements.joinToString { it.getId() } })
+ assertEquals(if (hasAdditionalFunction()) 34 else 33, indexPages.sumBy { it.elements.size })
}
}
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
index 60de0e3d..bef81372 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/location/JavadocLocationTest.kt
@@ -247,6 +247,7 @@ class JavadocLocationTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
)
analysisPlatform = "jvm"
+ classpath = listOfNotNull(jvmStdlibPath)
}
}
}
diff --git a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt
index 0bd6c4d5..cea32026 100644
--- a/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt
+++ b/plugins/javadoc/src/test/kotlin/org/jetbrains/dokka/javadoc/validity/MultiplatformConfiguredCheckerTest.kt
@@ -18,7 +18,7 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
format = "javadoc"
sourceSets {
sourceSet {
- sourceRoots = listOf("src")
+ sourceRoots = listOf("src/jvm")
analysisPlatform = "jvm"
externalDocumentationLinks = listOf(
ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
@@ -26,7 +26,7 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
)
}
sourceSet {
- sourceRoots = listOf("src")
+ sourceRoots = listOf("src/js")
analysisPlatform = "js"
externalDocumentationLinks = listOf(
ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
@@ -54,7 +54,9 @@ class MultiplatformConfiguredCheckerTest : BaseAbstractTest() {
fun `mpp config should fail for javadoc`() {
testInline(
"""
- |/src/main/kotlin/example/Test.kt
+ |/src/jvm/kotlin/example/Test.kt
+ |class Test
+ |/src/js/kotlin/example/Test.kt
|class Test
""".trimMargin(), mppConfig
) {
diff --git a/plugins/kotlin-as-java/build.gradle.kts b/plugins/kotlin-as-java/build.gradle.kts
index 19a7bf78..0b855895 100644
--- a/plugins/kotlin-as-java/build.gradle.kts
+++ b/plugins/kotlin-as-java/build.gradle.kts
@@ -7,6 +7,7 @@ import org.jetbrains.registerDokkaArtifactPublication
plugins {
id("org.jetbrains.conventions.kotlin-jvm")
id("org.jetbrains.conventions.maven-publish")
+ id("org.jetbrains.conventions.base-unit-test")
}
dependencies {
@@ -20,7 +21,11 @@ dependencies {
testImplementation(kotlin("test"))
testImplementation(libs.jsoup)
testImplementation(projects.plugins.base)
- testImplementation(projects.plugins.base.baseTestUtils)
+ symbolsTestConfiguration(project(path = ":subprojects:analysis-kotlin-symbols", configuration = "shadow"))
+ descriptorsTestConfiguration(project(path = ":subprojects:analysis-kotlin-descriptors", configuration = "shadow"))
+ testImplementation(projects.plugins.base.baseTestUtils) {
+ exclude(module = "analysis-kotlin-descriptors")
+ }
testImplementation(projects.core.contentMatcherTestUtils)
testImplementation(projects.core.testApi)
}
diff --git a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
index f6124f88..93d5c1b5 100644
--- a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
+++ b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt
@@ -377,6 +377,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
stdlibExternalDocumentationLink
)
+ classpath = listOfNotNull(jvmStdlibPath)
}
}
}
diff --git a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt
index c87fda5e..25312810 100644
--- a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt
+++ b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaSignatureTest.kt
@@ -23,6 +23,7 @@ class KotlinAsJavaSignatureTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
stdlibExternalDocumentationLink
)
+ classpath = listOfNotNull(jvmStdlibPath)
}
}
}
diff --git a/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt
index c8e99d10..1ce47031 100644
--- a/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt
+++ b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/KotlinToJavaService.kt
@@ -9,5 +9,21 @@ import org.jetbrains.dokka.links.DRI
@InternalDokkaApi
public interface KotlinToJavaService {
+ /**
+ * E.g.
+ * kotlin.Throwable -> java.lang.Throwable
+ * kotlin.Int -> java.lang.Integer
+ * kotlin.Int.Companion -> kotlin.jvm.internal.IntCompanionObject
+ * kotlin.Nothing -> java.lang.Void
+ * kotlin.IntArray -> null
+ * kotlin.Function3 -> kotlin.jvm.functions.Function3
+ * kotlin.coroutines.SuspendFunction3 -> kotlin.jvm.functions.Function4
+ * kotlin.Function42 -> kotlin.jvm.functions.FunctionN
+ * kotlin.coroutines.SuspendFunction42 -> kotlin.jvm.functions.FunctionN
+ * kotlin.reflect.KFunction3 -> kotlin.reflect.KFunction
+ * kotlin.reflect.KSuspendFunction3 -> kotlin.reflect.KFunction
+ * kotlin.reflect.KFunction42 -> kotlin.reflect.KFunction
+ * kotlin.reflect.KSuspendFunction42 -> kotlin.reflect.KFunction
+ */
public fun findAsJava(kotlinDri: DRI): DRI?
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt
index ef795145..122e0b10 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt
@@ -92,6 +92,7 @@ public class SymbolsAnalysisPlugin : DokkaPlugin() {
internal val symbolAnalyzerImpl by extending {
plugin<InternalKotlinAnalysisPlugin>().documentableSourceLanguageParser providing { KotlinDocumentableSourceLanguageParser() }
}
+
internal val symbolFullClassHierarchyBuilder by extending {
plugin<InternalKotlinAnalysisPlugin>().fullClassHierarchyBuilder providing ::SymbolFullClassHierarchyBuilder
}
@@ -104,14 +105,14 @@ public class SymbolsAnalysisPlugin : DokkaPlugin() {
plugin<InternalKotlinAnalysisPlugin>().moduleAndPackageDocumentationReader providing ::ModuleAndPackageDocumentationReader
}
- /* internal val kotlinToJavaMapper by extending {
- plugin<InternalKotlinAnalysisPlugin>().kotlinToJavaService providing { DescriptorKotlinToJavaMapper() }
+ internal val kotlinToJavaMapper by extending {
+ plugin<InternalKotlinAnalysisPlugin>().kotlinToJavaService providing { SymbolKotlinToJavaMapper() }
}
- intern val descriptorInheritanceBuilder by extending {
- plugin<InternalKotlinAnalysisPlugin>().inheritanceBuilder providing { DescriptorInheritanceBuilder() }
+ internal val symbolInheritanceBuilder by extending {
+ plugin<InternalKotlinAnalysisPlugin>().inheritanceBuilder providing ::SymbolInheritanceBuilder
}
- */
+
internal val symbolExternalDocumentablesProvider by extending {
plugin<InternalKotlinAnalysisPlugin>().externalDocumentablesProvider providing ::SymbolExternalDocumentablesProvider
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt
index 497d7946..0b68ac81 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt
@@ -5,6 +5,7 @@
package org.jetbrains.dokka.analysis.kotlin.symbols.services
import com.intellij.psi.PsiClass
+import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource
import org.jetbrains.dokka.analysis.java.util.from
import org.jetbrains.dokka.analysis.kotlin.symbols.translators.getDRIFromClassLike
@@ -17,6 +18,8 @@ import org.jetbrains.dokka.analysis.kotlin.internal.ClassHierarchy
import org.jetbrains.dokka.analysis.kotlin.internal.FullClassHierarchyBuilder
import org.jetbrains.dokka.analysis.kotlin.internal.Supertypes
import org.jetbrains.dokka.analysis.kotlin.symbols.plugin.SymbolsAnalysisPlugin
+import org.jetbrains.dokka.analysis.kotlin.symbols.translators.AnnotationTranslator
+import org.jetbrains.dokka.analysis.kotlin.symbols.translators.TypeTranslator
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
import org.jetbrains.dokka.plugability.querySingle
@@ -24,7 +27,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import java.util.concurrent.ConcurrentHashMap
-internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : FullClassHierarchyBuilder {
+internal class SymbolFullClassHierarchyBuilder(context: DokkaContext) : FullClassHierarchyBuilder {
private val kotlinAnalysis = context.plugin<SymbolsAnalysisPlugin>().querySingle { kotlinAnalysis }
override suspend fun build(module: DModule): ClassHierarchy {
@@ -38,14 +41,13 @@ internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : Full
supersMap: MutableMap<DRI, Supertypes>
) {
val (dri, kotlinType) = driWithKType
- val supertypes = kotlinType.getDirectSuperTypes().filterNot { it.isAny }
- val supertypesDriWithKType = supertypes.mapNotNull { supertype ->
- supertype.expandedClassSymbol?.let {
- getDRIFromClassLike(it) to supertype
- }
- }
-
if (supersMap[dri] == null) {
+ val supertypes = kotlinType.getDirectSuperTypes(shouldApproximate = true).filterNot { it.isAny }
+ val supertypesDriWithKType = supertypes.mapNotNull { supertype ->
+ supertype.expandedClassSymbol?.let {
+ getDRIFromClassLike(it) to supertype
+ }
+ }
supersMap[dri] = supertypesDriWithKType.map { it.first }
supertypesDriWithKType.forEach { collectSupertypesFromKtType(it, supersMap) }
}
@@ -92,4 +94,55 @@ internal class SymbolFullClassHierarchyBuilder(val context: DokkaContext) : Full
}
}
+ internal class SuperclassesWithKind(
+ val typeConstructorWithKind: TypeConstructorWithKind,
+ val superclasses: List<TypeConstructorWithKind>
+ )
+
+ /**
+ * Currently, it works only for Symbols
+ */
+ internal fun collectKotlinSupertypesWithKind(
+ documentable: Iterable<Documentable>,
+ sourceSet: DokkaConfiguration.DokkaSourceSet
+ ): Map<DRI, SuperclassesWithKind> {
+ val typeTranslator = TypeTranslator(sourceSet, AnnotationTranslator())
+ val hierarchy = mutableMapOf<DRI, SuperclassesWithKind>()
+
+ analyze(kotlinAnalysis.getModule(sourceSet)) {
+ documentable.filterIsInstance<DClasslike>().forEach {
+ val source = it.sources[sourceSet]
+ if (source is KtPsiDocumentableSource) {
+ (source.psi as? KtClassOrObject)?.let { psi ->
+ val type = psi.getNamedClassOrObjectSymbol()?.buildSelfClassType() ?: return@analyze
+ collectSupertypesWithKindFromKtType(typeTranslator, with(typeTranslator) {
+ toTypeConstructorWithKindFrom(type)
+ } to type, hierarchy)
+ }
+ } // else if (source is PsiDocumentableSource) TODO val psi = source.psi as? PsiClass
+ }
+ }
+ return hierarchy
+ }
+
+ private fun KtAnalysisSession.collectSupertypesWithKindFromKtType(
+ typeTranslator: TypeTranslator,
+ typeConstructorWithKindWithKType: Pair<TypeConstructorWithKind, KtType>,
+ supersMap: MutableMap<DRI, SuperclassesWithKind>
+ ) {
+ val (typeConstructorWithKind, kotlinType) = typeConstructorWithKindWithKType
+
+ if (supersMap[typeConstructorWithKind.typeConstructor.dri] == null) {
+ val supertypes = kotlinType.getDirectSuperTypes(shouldApproximate = true).filterNot { it.isAny }
+
+ val supertypesDriWithKType = supertypes.map { supertype ->
+ with(typeTranslator) {
+ toTypeConstructorWithKindFrom(supertype)
+ } to supertype
+ }
+ supersMap[typeConstructorWithKind.typeConstructor.dri] =
+ SuperclassesWithKind(typeConstructorWithKind, supertypesDriWithKType.map { it.first })
+ supertypesDriWithKType.forEach { collectSupertypesWithKindFromKtType(typeTranslator, it, supersMap) }
+ }
+ }
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolInheritanceBuilder.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolInheritanceBuilder.kt
new file mode 100644
index 00000000..540f08a7
--- /dev/null
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolInheritanceBuilder.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.analysis.kotlin.symbols.services
+
+import com.intellij.psi.PsiClass
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.analysis.java.util.from
+import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.analysis.kotlin.internal.InheritanceBuilder
+import org.jetbrains.dokka.analysis.kotlin.internal.InheritanceNode
+import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
+import org.jetbrains.dokka.model.*
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+
+/**
+ * This is copy-pasted from org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.DescriptorInheritanceBuilder and adapted for symbols
+ */
+internal class SymbolInheritanceBuilder(context: DokkaContext) : InheritanceBuilder {
+ private val symbolFullClassHierarchyBuilder =
+ context.plugin<InternalKotlinAnalysisPlugin>().querySingle { fullClassHierarchyBuilder }
+
+ override fun build(documentables: Map<DRI, Documentable>): List<InheritanceNode> {
+
+ // this statement is copy-pasted from the version for Descriptors
+ val psiInheritanceTree =
+ documentables.flatMap { (_, v) -> (v as? WithSources)?.sources?.values.orEmpty() }
+ .filterIsInstance<PsiDocumentableSource>().mapNotNull { it.psi as? PsiClass }
+ .flatMap(::gatherPsiClasses)
+ .flatMap { entry -> entry.second.map { it to entry.first } }
+ .let {
+ it + it.map { it.second to null }
+ }
+ .groupBy({ it.first }) { it.second }
+ .map { it.key to it.value.filterNotNull().distinct() }
+ .map { (k, v) ->
+ InheritanceNode(
+ DRI.from(k),
+ v.map { InheritanceNode(DRI.from(it)) },
+ k.supers.filter { it.isInterface }.map { DRI.from(it) },
+ k.isInterface
+ )
+
+ }
+
+ // copy-pasted from stdlib 1.5
+ fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? {
+ for (element in this) {
+ val result = transform(element)
+ if (result != null) {
+ return result
+ }
+ }
+ return null
+ }
+
+ val jvmSourceSet =
+ documentables.values.firstNotNullOfOrNull { it.sourceSets.find { it.analysisPlatform == Platform.jvm } }
+ if (jvmSourceSet == null)
+ return psiInheritanceTree
+
+ val typeConstructorsMap =
+ (symbolFullClassHierarchyBuilder as? SymbolFullClassHierarchyBuilder)?.collectKotlinSupertypesWithKind(
+ documentables.values,
+ jvmSourceSet
+ )
+ ?: throw IllegalStateException("Unexpected symbolFullClassHierarchyBuildertype") // TODO: https://github.com/Kotlin/dokka/issues/3225 Unify FullClassHierarchyBuilder and InheritanceBuilder into one builder
+
+ fun ClassKind.isInterface() = this == KotlinClassKindTypes.INTERFACE || this == JavaClassKindTypes.INTERFACE
+ val symbolsInheritanceTree = typeConstructorsMap.map { (dri, superclasses) ->
+ InheritanceNode(
+ dri,
+ superclasses.superclasses.map { InheritanceNode(it.typeConstructor.dri) },
+ superclasses.superclasses.filter { it.kind.isInterface() }.map { it.typeConstructor.dri },
+ isInterface = superclasses.typeConstructorWithKind.kind.isInterface()
+ )
+ }
+
+ return psiInheritanceTree + symbolsInheritanceTree
+ }
+
+ private fun gatherPsiClasses(psi: PsiClass): List<Pair<PsiClass, List<PsiClass>>> = psi.supers.toList().let { l ->
+ listOf(psi to l) + l.flatMap { gatherPsiClasses(it) }
+ }
+}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolKotlinToJavaMapper.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolKotlinToJavaMapper.kt
new file mode 100644
index 00000000..77ede87f
--- /dev/null
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolKotlinToJavaMapper.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package org.jetbrains.dokka.analysis.kotlin.symbols.services
+
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.PointingToDeclaration
+import org.jetbrains.dokka.analysis.kotlin.internal.KotlinToJavaService
+import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap // or import kotlin.reflect.jvm.internal.impl.builtins.jvm.JavaToKotlinClassMap see https://github.com/Kotlin/dokka/issues/3226
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+
+/**
+ * This is copy-pasted from org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.DescriptorKotlinToJavaMapper
+ */
+internal class SymbolKotlinToJavaMapper : KotlinToJavaService {
+
+ override fun findAsJava(kotlinDri: DRI): DRI? {
+ return kotlinDri.partialFqName().mapToJava()?.toDRI(kotlinDri)
+ }
+
+ private fun DRI.partialFqName() = packageName?.let { "$it." } + classNames
+
+ private fun String.mapToJava(): ClassId? =
+ JavaToKotlinClassMap.mapKotlinToJava(FqName(this).toUnsafe())
+
+ private fun ClassId.toDRI(dri: DRI?): DRI = DRI(
+ packageName = packageFqName.asString(),
+ classNames = classNames(),
+ callable = dri?.callable,//?.asJava(), TODO: check this
+ extra = null,
+ target = PointingToDeclaration
+ )
+
+ private fun ClassId.classNames(): String =
+ shortClassName.identifier + (outerClassId?.classNames()?.let { ".$it" } ?: "")
+}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
index faae08e2..c9882487 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
@@ -11,6 +11,7 @@ import org.jetbrains.dokka.model.ClassValue
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.base.KtConstantValue
+import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
@@ -34,12 +35,16 @@ internal class AnnotationTranslator {
annotated.annotations.map { toDokkaAnnotation(it) }
/**
- * @return direct annotations and file-level annotations
+ * The examples of annotations from backing field are [JvmField], [JvmSynthetic].
+ *
+ * @return direct annotations, annotations from backing field and file-level annotations
*/
fun KtAnalysisSession.getAllAnnotationsFrom(annotated: KtAnnotated): List<Annotations.Annotation> {
val directAnnotations = getDirectAnnotationsFrom(annotated)
- val fileLevelAnnotations = (annotated as? KtSymbol)?.let { getFileLevelAnnotationsFrom(it) } ?: emptyList()
- return directAnnotations + fileLevelAnnotations
+ val backingFieldAnnotations =
+ (annotated as? KtPropertySymbol)?.backingFieldSymbol?.let { getDirectAnnotationsFrom(it) }.orEmpty()
+ val fileLevelAnnotations = (annotated as? KtSymbol)?.let { getFileLevelAnnotationsFrom(it) }.orEmpty()
+ return directAnnotations + backingFieldAnnotations + fileLevelAnnotations
}
private fun KtAnnotationApplication.isNoExistedInSource() = psi == null
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt
index 6c7071f5..298d0182 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt
@@ -212,7 +212,15 @@ internal class DokkaSymbolVisitor(
val isActual = namedClassOrObjectSymbol.isActual
val documentation = getDocumentation(namedClassOrObjectSymbol)?.toSourceSetDependent() ?: emptyMap()
- val (constructors, functions, properties, classlikes) = getDokkaScopeFrom(namedClassOrObjectSymbol, dri)
+ val (constructors, functions, properties, classlikesWithoutCompanion) = getDokkaScopeFrom(namedClassOrObjectSymbol, dri)
+
+ val companionObject = namedClassOrObjectSymbol.companionObject?.let {
+ visitNamedClassOrObjectSymbol(
+ it,
+ dri
+ )
+ } as? DObject
+ val classlikes = if (companionObject == null) classlikesWithoutCompanion else classlikesWithoutCompanion + companionObject
val generics = namedClassOrObjectSymbol.typeParameters.mapIndexed { index, symbol ->
visitVariantTypeParameter(
@@ -229,7 +237,6 @@ internal class DokkaSymbolVisitor(
namedClassOrObjectSymbol.superTypes.filterNot { it.isAny }
.map { with(typeTranslator) { toTypeConstructorWithKindFrom(it) } }
.toSourceSetDependent()
-
return@withExceptionCatcher when (namedClassOrObjectSymbol.classKind) {
KtClassKind.OBJECT, KtClassKind.COMPANION_OBJECT ->
DObject(
@@ -268,12 +275,7 @@ internal class DokkaSymbolVisitor(
generics = generics,
documentation = documentation,
modifier = namedClassOrObjectSymbol.getDokkaModality().toSourceSetDependent(),
- companion = namedClassOrObjectSymbol.companionObject?.let {
- visitNamedClassOrObjectSymbol(
- it,
- dri
- )
- } as? DObject,
+ companion = companionObject,
sourceSets = setOf(sourceSet),
isExpectActual = (isExpect || isActual),
extra = PropertyContainer.withAll(
@@ -296,12 +298,7 @@ internal class DokkaSymbolVisitor(
supertypes = supertypes,
generics = generics,
documentation = documentation,
- companion = namedClassOrObjectSymbol.companionObject?.let {
- visitNamedClassOrObjectSymbol(
- it,
- dri
- )
- } as? DObject,
+ companion = companionObject,
sourceSets = setOf(sourceSet),
isExpectActual = (isExpect || isActual),
extra = PropertyContainer.withAll(
@@ -322,12 +319,7 @@ internal class DokkaSymbolVisitor(
expectPresentInSet = sourceSet.takeIf { isExpect },
sourceSets = setOf(sourceSet),
isExpectActual = (isExpect || isActual),
- companion = namedClassOrObjectSymbol.companionObject?.let {
- visitNamedClassOrObjectSymbol(
- it,
- dri
- )
- } as? DObject,
+ companion = companionObject,
visibility = namedClassOrObjectSymbol.getDokkaVisibility().toSourceSetDependent(),
generics = generics,
constructors = constructors,
@@ -401,7 +393,7 @@ internal class DokkaSymbolVisitor(
val constructors: List<DFunction>,
val functions: List<DFunction>,
val properties: List<DProperty>,
- val classlikes: List<DClasslike>
+ val classlikesWithoutCompanion: List<DClasslike>
)
/**
@@ -445,13 +437,10 @@ internal class DokkaSymbolVisitor(
javaFields.map { visitJavaFieldSymbol(it, dri) }
- // hack, by default, compiler adds an empty companion object for enum
- // TODO check if it is empty
- fun List<KtNamedClassOrObjectSymbol>.filterOutEnumCompanion() =
- if (namedClassOrObjectSymbol.classKind == KtClassKind.ENUM_CLASS)
+ fun List<KtNamedClassOrObjectSymbol>.filterOutCompanion() =
filterNot {
- it.name.asString() == "Companion" && it.classKind == KtClassKind.COMPANION_OBJECT
- } else this
+ it.classKind == KtClassKind.COMPANION_OBJECT
+ }
fun List<KtNamedClassOrObjectSymbol>.filterOutAndMarkAlreadyVisited() = filterNot { symbol ->
visitedNamedClassOrObjectSymbol.contains(symbol.classIdIfNonLocal)
@@ -465,7 +454,7 @@ internal class DokkaSymbolVisitor(
}
val classlikes = classifiers.filterIsInstance<KtNamedClassOrObjectSymbol>()
- .filterOutEnumCompanion() // hack to filter out companion for enum
+ .filterOutCompanion() // also, this is a hack to filter out companion for enum
.filterOutAndMarkAlreadyVisited()
.map { visitNamedClassOrObjectSymbol(it, dri) }
@@ -473,7 +462,7 @@ internal class DokkaSymbolVisitor(
constructors = constructors,
functions = functions,
properties = properties,
- classlikes = classlikes
+ classlikesWithoutCompanion = classlikes
)
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
index 7127cbdf..f7366294 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
@@ -44,7 +44,7 @@ internal class TypeTranslator(
typeAlias = GenericTypeConstructor(
dri = getDRIFromNonErrorClassType(classType),
projections = classType.ownTypeArguments.map { toProjection(it) }),
- inner = toBoundFrom(classSymbol.expandedType),
+ inner = toBoundFrom(classType.fullyExpandedType),
extra = PropertyContainer.withAll(
getDokkaAnnotationsFrom(classType)?.toSourceSetDependent()?.toAnnotations()
)