Skip to content

Commit

Permalink
[K2] Support kotlin-as-java and javadoc plugins and update version of…
Browse files Browse the repository at this point in the history
… 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`
  • Loading branch information
vmishenev committed Oct 26, 2023
1 parent 3be4dd9 commit 9b07435
Show file tree
Hide file tree
Showing 20 changed files with 308 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ class Greeter(val name: String) {

fun main(args: Array<String>) {
Greeter(args[0]).greet()
}
}
15 changes: 15 additions & 0 deletions plugins/base/src/test/kotlin/model/ClassesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion plugins/javadoc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ internal abstract class AbstractJavadocTemplateMapTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
)
classpath = listOfNotNull(jvmStdlibPath)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {

Expand All @@ -16,6 +17,7 @@ internal class JavadocAccessorNamingTest : AbstractJavadocTemplateMapTest() {
sourceSets {
sourceSet {
sourceRoots = listOf("src/main/kotlin")
classpath = listOfNotNull(jvmStdlibPath)
}
}
}
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 })
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class JavadocLocationTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.kotlinStdlib()
)
analysisPlatform = "jvm"
classpath = listOfNotNull(jvmStdlibPath)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ 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/"),
ExternalDocumentationLink("https://kotlinlang.org/api/latest/jvm/stdlib/")
)
}
sourceSet {
sourceRoots = listOf("src")
sourceRoots = listOf("src/js")
analysisPlatform = "js"
externalDocumentationLinks = listOf(
ExternalDocumentationLink("https://docs.oracle.com/javase/8/docs/api/"),
Expand Down Expand Up @@ -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
) {
Expand Down
7 changes: 6 additions & 1 deletion plugins/kotlin-as-java/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
stdlibExternalDocumentationLink
)
classpath = listOfNotNull(jvmStdlibPath)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class KotlinAsJavaSignatureTest : BaseAbstractTest() {
DokkaConfiguration.ExternalDocumentationLink.jdk(8),
stdlibExternalDocumentationLink
)
classpath = listOfNotNull(jvmStdlibPath)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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?
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -17,14 +18,16 @@ 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
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 {
Expand All @@ -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) }
}
Expand Down Expand Up @@ -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) }
}
}
}

0 comments on commit 9b07435

Please sign in to comment.