aboutsummaryrefslogtreecommitdiff
path: root/subprojects/analysis-kotlin-descriptors
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/analysis-kotlin-descriptors')
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api1
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt10
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DefaultSamplesTransformer.kt35
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/SamplesTransformerImpl.kt153
4 files changed, 7 insertions, 192 deletions
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api b/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
index 470def08..7a85bc7a 100644
--- a/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
+++ b/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
@@ -10,6 +10,7 @@ public final class org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/Comp
public final fun getKdocFinder ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getKlibService ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getKotlinAnalysis ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
+ public final fun getKotlinSampleProviderFactory ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getMockApplicationHack ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
}
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt
index 2d79affa..805cfe86 100644
--- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt
+++ b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt
@@ -56,15 +56,17 @@ class CompilerDescriptorAnalysisPlugin : DokkaPlugin() {
CoreExtensions.sourceToDocumentableTranslator providing ::DefaultDescriptorToDocumentableTranslator
}
- internal val defaultSamplesTransformer by extending {
- CoreExtensions.pageTransformer providing ::DefaultSamplesTransformer
- }
internal val descriptorFullClassHierarchyBuilder by extending {
plugin<InternalKotlinAnalysisPlugin>().fullClassHierarchyBuilder providing { DescriptorFullClassHierarchyBuilder() }
}
- internal val kotlinSampleProviderFactory by extending {
+ /**
+ * StdLib has its own a sample provider
+ * So it should have a possibility to override this extension
+ */
+ @InternalDokkaApi
+ val kotlinSampleProviderFactory by extending {
plugin<InternalKotlinAnalysisPlugin>().sampleProviderFactory providing ::KotlinSampleProviderFactory
}
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DefaultSamplesTransformer.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DefaultSamplesTransformer.kt
deleted file mode 100644
index 22fecdf8..00000000
--- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DefaultSamplesTransformer.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl
-
-import com.intellij.psi.PsiElement
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.kotlin.psi.KtBlockExpression
-import org.jetbrains.kotlin.psi.KtDeclarationWithBody
-import org.jetbrains.kotlin.psi.KtFile
-
-internal class DefaultSamplesTransformer(context: DokkaContext) : SamplesTransformerImpl(context) {
-
- override fun processBody(psiElement: PsiElement): String {
- val text = processSampleBody(psiElement).trim { it == '\n' || it == '\r' }.trimEnd()
- val lines = text.split("\n")
- val indent = lines.filter(String::isNotBlank).map { it.takeWhile(Char::isWhitespace).count() }.minOrNull() ?: 0
- return lines.joinToString("\n") { it.drop(indent) }
- }
-
- private fun processSampleBody(psiElement: PsiElement): String = when (psiElement) {
- is KtDeclarationWithBody -> {
- when (val bodyExpression = psiElement.bodyExpression) {
- is KtBlockExpression -> bodyExpression.text.removeSurrounding("{", "}")
- else -> bodyExpression!!.text
- }
- }
- else -> psiElement.text
- }
-
- override fun processImports(psiElement: PsiElement): String {
- val psiFile = psiElement.containingFile
- return when(val text = (psiFile as? KtFile)?.importList?.text) {
- is String -> text
- else -> ""
- }
- }
-}
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/SamplesTransformerImpl.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/SamplesTransformerImpl.kt
deleted file mode 100644
index f1924708..00000000
--- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/SamplesTransformerImpl.kt
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl
-
-import com.intellij.psi.PsiElement
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin
-import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KDocFinder
-import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.KotlinAnalysis
-import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.SamplesKotlinAnalysis
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.doc.Sample
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
-import org.jetbrains.kotlin.resolve.lazy.ResolveSession
-
-internal const val KOTLIN_PLAYGROUND_SCRIPT = "<script src=\"`https://unpkg.com/kotlin-playground@1`\"></script>"
-
-internal abstract class SamplesTransformerImpl(val context: DokkaContext) : PageTransformer {
-
- private val kDocFinder: KDocFinder = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kdocFinder }
-
- abstract fun processBody(psiElement: PsiElement): String
- abstract fun processImports(psiElement: PsiElement): String
-
- final override fun invoke(input: RootPageNode): RootPageNode =
- /**
- * Run from the thread of [Dispatchers.Default]. It can help to avoid a memory leaks in `ThreadLocal`s (that keep `URLCLassLoader`)
- * since we shut down Dispatchers. Default at the end of each task (see [org.jetbrains.dokka.DokkaConfiguration.finalizeCoroutines]).
- * Currently, all `ThreadLocal`s are in a compiler/IDE codebase.
- */
- runBlocking(Dispatchers.Default) {
- val analysis = SamplesKotlinAnalysis(
- sourceSets = context.configuration.sourceSets,
- context = context,
- projectKotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis }
- )
- analysis.use {
- input.transformContentPagesTree { page ->
- val samples = (page as? WithDocumentables)?.documentables?.flatMap {
- it.documentation.entries.flatMap { entry ->
- entry.value.children.filterIsInstance<Sample>().map { entry.key to it }
- }
- }
-
- samples?.fold(page as ContentPage) { acc, (sampleSourceSet, sample) ->
- acc.modified(
- content = acc.content.addSample(page, sampleSourceSet, sample.name, it),
- embeddedResources = acc.embeddedResources + KOTLIN_PLAYGROUND_SCRIPT
- )
- } ?: page
- }
- }
- }
-
- private fun ContentNode.addSample(
- contentPage: ContentPage,
- sourceSet: DokkaSourceSet,
- fqName: String,
- analysis: KotlinAnalysis
- ): ContentNode {
- val resolveSession = analysis[sourceSet].resolveSession
- val psiElement = fqNameToPsiElement(resolveSession, fqName, sourceSet)
- ?: return this.also { context.logger.warn("Cannot find PsiElement corresponding to $fqName") }
- val imports =
- processImports(psiElement)
- val body = processBody(psiElement)
- val node = contentCode(contentPage.content.sourceSets, contentPage.dri, createSampleBody(imports, body), "kotlin")
-
- return dfs(fqName, node)
- }
-
- protected open fun createSampleBody(imports: String, body: String) =
- """ |$imports
- |fun main() {
- | //sampleStart
- | $body
- | //sampleEnd
- |}""".trimMargin()
-
- private fun ContentNode.dfs(fqName: String, node: ContentCodeBlock): ContentNode {
- return when (this) {
- is ContentHeader -> copy(children.map { it.dfs(fqName, node) })
- is ContentDivergentGroup -> @Suppress("UNCHECKED_CAST") copy(children.map {
- it.dfs(fqName, node)
- } as List<ContentDivergentInstance>)
- is ContentDivergentInstance -> copy(
- before.let { it?.dfs(fqName, node) },
- divergent.dfs(fqName, node),
- after.let { it?.dfs(fqName, node) })
- is ContentCodeBlock -> copy(children.map { it.dfs(fqName, node) })
- is ContentCodeInline -> copy(children.map { it.dfs(fqName, node) })
- is ContentDRILink -> copy(children.map { it.dfs(fqName, node) })
- is ContentResolvedLink -> copy(children.map { it.dfs(fqName, node) })
- is ContentEmbeddedResource -> copy(children.map { it.dfs(fqName, node) })
- is ContentTable -> copy(children = children.map { it.dfs(fqName, node) as ContentGroup })
- is ContentList -> copy(children.map { it.dfs(fqName, node) })
- is ContentGroup -> copy(children.map { it.dfs(fqName, node) })
- is PlatformHintedContent -> copy(inner.dfs(fqName, node))
- is ContentText -> if (text == fqName) node else this
- is ContentBreakLine -> this
- else -> this.also { context.logger.error("Could not recognize $this ContentNode in SamplesTransformer") }
- }
- }
-
- private fun fqNameToPsiElement(resolveSession: ResolveSession, functionName: String, dokkaSourceSet: DokkaSourceSet): PsiElement? {
- val packageName = functionName.takeWhile { it != '.' }
- val descriptor = resolveSession.getPackageFragment(FqName(packageName))
- ?: return null.also { context.logger.warn("Cannot find descriptor for package $packageName") }
-
- with (kDocFinder) {
- val symbol = resolveKDocLink(
- descriptor,
- functionName,
- dokkaSourceSet,
- emptyBindingContext = true
- ).firstOrNull() ?: return null.also { context.logger.warn("Unresolved function $functionName in @sample") }
- return DescriptorToSourceUtils.descriptorToDeclaration(symbol)
- }
- }
-
- private fun contentCode(
- sourceSets: Set<DisplaySourceSet>,
- dri: Set<DRI>,
- content: String,
- language: String,
- styles: Set<Style> = emptySet(),
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty()
- ) =
- ContentCodeBlock(
- children = listOf(
- ContentText(
- text = content,
- dci = DCI(dri, ContentKind.Sample),
- sourceSets = sourceSets,
- style = emptySet(),
- extra = PropertyContainer.empty()
- )
- ),
- language = language,
- dci = DCI(dri, ContentKind.Sample),
- sourceSets = sourceSets,
- style = styles + ContentStyle.RunnableSample + TextStyle.Monospace,
- extra = extra
- )
-}