Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add external documentable provider (#2307)
* Add external documentable provider * Update the api spec of base plugin * Hide mistakenly exposed fields * Add comments and fix naming
- Loading branch information
Showing
7 changed files
with
261 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
plugins/base/src/main/kotlin/translators/descriptors/DefaultExternalDocumentablesProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.jetbrains.dokka.base.translators.descriptors | ||
|
||
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet | ||
import org.jetbrains.dokka.base.DokkaBase | ||
import org.jetbrains.dokka.links.DRI | ||
import org.jetbrains.dokka.model.DClasslike | ||
import org.jetbrains.dokka.plugability.DokkaContext | ||
import org.jetbrains.dokka.plugability.querySingle | ||
import org.jetbrains.dokka.plugability.plugin | ||
import org.jetbrains.kotlin.descriptors.ClassDescriptor | ||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor | ||
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.resolve.scopes.MemberScope | ||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered | ||
|
||
class DefaultExternalDocumentablesProvider(context: DokkaContext) : ExternalDocumentablesProvider { | ||
private val analysis = context.plugin<DokkaBase>().querySingle { kotlinAnalysis } | ||
|
||
private val translator = context.plugin<DokkaBase>().querySingle { externalClasslikesTranslator } | ||
|
||
override fun findClasslike(dri: DRI, sourceSet: DokkaSourceSet): DClasslike? { | ||
val pkg = dri.packageName?.let { FqName(it) } ?: FqName.ROOT | ||
val names = dri.classNames?.split('.') ?: return null | ||
|
||
val packageDsc = analysis[sourceSet].facade.moduleDescriptor.getPackage(pkg) | ||
val classDsc = names.fold<String, DeclarationDescriptor?>(packageDsc) { dsc, name -> | ||
dsc?.scope?.getDescriptorsFiltered { it.identifier == name } | ||
?.filterIsInstance<ClassDescriptor>() | ||
?.firstOrNull() | ||
} | ||
|
||
return (classDsc as? ClassDescriptor)?.let { translator.translateClassDescriptor(it, sourceSet) } | ||
} | ||
|
||
private val DeclarationDescriptor.scope: MemberScope | ||
get() = when (this) { | ||
is PackageViewDescriptor -> memberScope | ||
is ClassDescriptor -> unsubstitutedMemberScope | ||
else -> throw IllegalArgumentException("Unexpected type of descriptor: ${this::class}") | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
plugins/base/src/main/kotlin/translators/descriptors/ExternalClasslikesTranslator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.jetbrains.dokka.base.translators.descriptors | ||
|
||
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet | ||
import org.jetbrains.dokka.model.DClasslike | ||
import org.jetbrains.kotlin.descriptors.ClassDescriptor | ||
|
||
/** | ||
* Service translating [ClassDescriptor]s of symbols defined outside of documented project to [DClasslike]s. | ||
*/ | ||
interface ExternalClasslikesTranslator { | ||
fun translateClassDescriptor(descriptor: ClassDescriptor, sourceSet: DokkaSourceSet): DClasslike | ||
} |
22 changes: 22 additions & 0 deletions
22
plugins/base/src/main/kotlin/translators/descriptors/ExternalDocumentablesProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.jetbrains.dokka.base.translators.descriptors | ||
|
||
import org.jetbrains.dokka.DokkaConfiguration | ||
import org.jetbrains.dokka.links.DRI | ||
import org.jetbrains.dokka.model.DClasslike | ||
|
||
/** | ||
* Service that can be queried with [DRI] and source set to obtain a documentable for classlike. | ||
* | ||
* There are some cases when there is a need to process documentables of classlikes that were not defined | ||
* in the project itself but are somehow related to the symbols defined in the documented project (e.g. are supertypes | ||
* of classes defined in project). | ||
*/ | ||
interface ExternalDocumentablesProvider { | ||
|
||
/** | ||
* Returns [DClasslike] matching provided [DRI] in specified source set. | ||
* | ||
* Result is null if compiler haven't generated matching class descriptor. | ||
*/ | ||
fun findClasslike(dri: DRI, sourceSet: DokkaConfiguration.DokkaSourceSet): DClasslike? | ||
} |
139 changes: 139 additions & 0 deletions
139
plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package translators | ||
|
||
import com.intellij.openapi.application.PathManager | ||
import kotlinx.coroutines.Job | ||
import org.jetbrains.dokka.base.DokkaBase | ||
import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest | ||
import org.jetbrains.dokka.base.translators.descriptors.ExternalDocumentablesProvider | ||
import org.jetbrains.dokka.model.DClass | ||
import org.jetbrains.dokka.model.DInterface | ||
import org.jetbrains.dokka.plugability.plugin | ||
import org.jetbrains.dokka.plugability.querySingle | ||
import org.jetbrains.dokka.utilities.cast | ||
import org.junit.jupiter.api.Assertions.assertEquals | ||
import org.junit.jupiter.api.Test | ||
|
||
class ExternalDocumentablesTest : BaseAbstractTest() { | ||
@Test | ||
fun `external documentable from java stdlib`() { | ||
val configuration = dokkaConfiguration { | ||
sourceSets { | ||
sourceSet { | ||
sourceRoots = listOf("src") | ||
analysisPlatform = "jvm" | ||
classpath += jvmStdlibPath!! | ||
} | ||
} | ||
} | ||
|
||
testInline( | ||
""" | ||
/src/com/sample/MyList.kt | ||
package com.sample | ||
class MyList: ArrayList<Int>() | ||
""".trimIndent(), | ||
configuration | ||
) { | ||
lateinit var provider: ExternalDocumentablesProvider | ||
pluginsSetupStage = { | ||
provider = it.plugin<DokkaBase>().querySingle { externalDocumentablesProvider } | ||
} | ||
documentablesTransformationStage = { mod -> | ||
val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() | ||
val res = provider.findClasslike( | ||
entry.value.single().typeConstructor.dri, | ||
entry.key) | ||
assertEquals("ArrayList", res?.name) | ||
assertEquals("java.util/ArrayList///PointingToDeclaration/", res?.dri?.toString()) | ||
|
||
val supertypes = res?.cast<DClass>()?.supertypes?.values?.single() | ||
?.map { it.typeConstructor.dri.classNames } | ||
assertEquals( | ||
listOf("AbstractList", "RandomAccess", "Cloneable", "Serializable", "MutableList"), | ||
supertypes | ||
) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `external documentable from dependency`() { | ||
val coroutinesPath = | ||
PathManager.getResourceRoot(Job::class.java, "/kotlinx/coroutines/Job.class") | ||
|
||
val configuration = dokkaConfiguration { | ||
sourceSets { | ||
sourceSet { | ||
sourceRoots = listOf("src") | ||
analysisPlatform = "jvm" | ||
classpath += listOf(jvmStdlibPath!!, coroutinesPath!!) | ||
} | ||
} | ||
} | ||
|
||
testInline( | ||
""" | ||
/src/com/sample/MyJob.kt | ||
package com.sample | ||
import kotlinx.coroutines.Job | ||
abstract class MyJob: Job | ||
""".trimIndent(), | ||
configuration | ||
) { | ||
lateinit var provider: ExternalDocumentablesProvider | ||
pluginsSetupStage = { | ||
provider = it.plugin<DokkaBase>().querySingle { externalDocumentablesProvider } | ||
} | ||
documentablesTransformationStage = { mod -> | ||
val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() | ||
val res = provider.findClasslike( | ||
entry.value.single().typeConstructor.dri, | ||
entry.key) | ||
assertEquals("Job", res?.name) | ||
assertEquals("kotlinx.coroutines/Job///PointingToDeclaration/", res?.dri?.toString()) | ||
|
||
val supertypes = res?.cast<DInterface>()?.supertypes?.values?.single() | ||
?.map { it.typeConstructor.dri.classNames } | ||
assertEquals( | ||
listOf("CoroutineContext.Element"), | ||
supertypes | ||
) | ||
} | ||
} | ||
} | ||
|
||
@Test | ||
fun `external documentable for nested class`() { | ||
val configuration = dokkaConfiguration { | ||
sourceSets { | ||
sourceSet { | ||
sourceRoots = listOf("src") | ||
analysisPlatform = "jvm" | ||
classpath += jvmStdlibPath!! | ||
} | ||
} | ||
} | ||
|
||
testInline( | ||
""" | ||
/src/com/sample/MyList.kt | ||
package com.sample | ||
abstract class MyEntry: Map.Entry<Int, String> | ||
""".trimIndent(), | ||
configuration | ||
) { | ||
lateinit var provider: ExternalDocumentablesProvider | ||
pluginsSetupStage = { | ||
provider = it.plugin<DokkaBase>().querySingle { externalDocumentablesProvider } | ||
} | ||
documentablesTransformationStage = { mod -> | ||
val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() | ||
val res = provider.findClasslike( | ||
entry.value.single().typeConstructor.dri, | ||
entry.key) | ||
assertEquals("Entry", res?.name) | ||
assertEquals("kotlin.collections/Map.Entry///PointingToDeclaration/", res?.dri?.toString()) | ||
} | ||
} | ||
} | ||
} |