aboutsummaryrefslogtreecommitdiff
path: root/subprojects
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/analysis-kotlin-api/api/analysis-kotlin-api.api15
-rw-r--r--subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAnalysisPlugin.kt2
-rw-r--r--subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider.kt30
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api15
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt9
-rw-r--r--subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider.kt109
6 files changed, 178 insertions, 2 deletions
diff --git a/subprojects/analysis-kotlin-api/api/analysis-kotlin-api.api b/subprojects/analysis-kotlin-api/api/analysis-kotlin-api.api
index a057470e..c65dfe5a 100644
--- a/subprojects/analysis-kotlin-api/api/analysis-kotlin-api.api
+++ b/subprojects/analysis-kotlin-api/api/analysis-kotlin-api.api
@@ -51,6 +51,7 @@ public final class org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAn
public final fun getInheritanceBuilder ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getKotlinToJavaService ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getModuleAndPackageDocumentationReader ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
+ public final fun getSampleProviderFactory ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getSyntheticDocumentableDetector ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
}
@@ -64,6 +65,20 @@ public abstract interface class org/jetbrains/dokka/analysis/kotlin/internal/Mod
public abstract fun read (Lorg/jetbrains/dokka/model/DPackage;)Ljava/util/Map;
}
+public abstract interface class org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider : java/lang/AutoCloseable {
+ public abstract fun getSample (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/lang/String;)Lorg/jetbrains/dokka/analysis/kotlin/internal/SampleProvider$SampleSnippet;
+}
+
+public final class org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider$SampleSnippet {
+ public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
+ public final fun getBody ()Ljava/lang/String;
+ public final fun getImports ()Ljava/lang/String;
+}
+
+public abstract interface class org/jetbrains/dokka/analysis/kotlin/internal/SampleProviderFactory {
+ public abstract fun build ()Lorg/jetbrains/dokka/analysis/kotlin/internal/SampleProvider;
+}
+
public abstract interface class org/jetbrains/dokka/analysis/kotlin/internal/SyntheticDocumentableDetector {
public abstract fun isSynthetic (Lorg/jetbrains/dokka/model/Documentable;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Z
}
diff --git a/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAnalysisPlugin.kt b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAnalysisPlugin.kt
index 330522f3..30c2c2f8 100644
--- a/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAnalysisPlugin.kt
+++ b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/InternalKotlinAnalysisPlugin.kt
@@ -26,6 +26,8 @@ class InternalKotlinAnalysisPlugin : DokkaPlugin() {
val documentableSourceLanguageParser by extensionPoint<DocumentableSourceLanguageParser>()
+ val sampleProviderFactory by extensionPoint<SampleProviderFactory>()
+
@OptIn(DokkaPluginApiPreview::class)
override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement
}
diff --git a/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider.kt b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider.kt
new file mode 100644
index 00000000..195f3c35
--- /dev/null
+++ b/subprojects/analysis-kotlin-api/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka.analysis.kotlin.internal
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.InternalDokkaApi
+
+@InternalDokkaApi
+interface SampleProviderFactory {
+ /**
+ * [SampleProvider] is a short-lived closeable instance.
+ * It assumes that [SampleProvider] scope of use is not big.
+ * Otherwise, it can lead to high memory consumption / leaks during Dokka running.
+ */
+ fun build(): SampleProvider
+}
+
+/**
+ * It is closeable.
+ * Otherwise, there is a chance of high memory consumption / leak.
+ * In general case, it creates a separate project to analysis samples directories.
+ */
+@InternalDokkaApi
+interface SampleProvider: AutoCloseable {
+ class SampleSnippet(val imports: String, val body:String)
+
+
+ /**
+ * @return [SampleSnippet] or null if it has not found by [fqLink]
+ */
+ fun getSample(sourceSet: DokkaConfiguration.DokkaSourceSet, fqLink: String): SampleSnippet?
+} \ No newline at end of file
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api b/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
index 7d53418f..470def08 100644
--- a/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
+++ b/subprojects/analysis-kotlin-descriptors/compiler/api/compiler.api
@@ -66,3 +66,18 @@ public abstract class org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/c
public final fun get (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Lorg/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisContext;
}
+public class org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider : org/jetbrains/dokka/analysis/kotlin/internal/SampleProvider {
+ public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
+ public fun close ()V
+ public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
+ public fun getSample (Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Ljava/lang/String;)Lorg/jetbrains/dokka/analysis/kotlin/internal/SampleProvider$SampleSnippet;
+ protected fun processBody (Lcom/intellij/psi/PsiElement;)Ljava/lang/String;
+ protected fun processImports (Lcom/intellij/psi/PsiElement;)Ljava/lang/String;
+}
+
+public final class org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProviderFactory : org/jetbrains/dokka/analysis/kotlin/internal/SampleProviderFactory {
+ public fun <init> (Lorg/jetbrains/dokka/plugability/DokkaContext;)V
+ public fun build ()Lorg/jetbrains/dokka/analysis/kotlin/internal/SampleProvider;
+ public final fun getContext ()Lorg/jetbrains/dokka/plugability/DokkaContext;
+}
+
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 6d63fe14..2d79affa 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
@@ -21,6 +21,7 @@ import org.jetbrains.dokka.renderers.PostAction
import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
+@Suppress("unused")
@InternalDokkaApi
class CompilerDescriptorAnalysisPlugin : DokkaPlugin() {
@@ -42,7 +43,7 @@ class CompilerDescriptorAnalysisPlugin : DokkaPlugin() {
plugin<InternalKotlinAnalysisPlugin>().documentableSourceLanguageParser providing { CompilerDocumentableSourceLanguageParser() }
}
- internal val defaultKotlinAnalysis by extending {
+ internal val defaultKotlinAnalysis by extending {
kotlinAnalysis providing { ctx ->
ProjectKotlinAnalysis(
sourceSets = ctx.configuration.sourceSets,
@@ -51,7 +52,7 @@ class CompilerDescriptorAnalysisPlugin : DokkaPlugin() {
}
}
- internal val descriptorToDocumentableTranslator by extending {
+ internal val descriptorToDocumentableTranslator by extending {
CoreExtensions.sourceToDocumentableTranslator providing ::DefaultDescriptorToDocumentableTranslator
}
@@ -63,6 +64,10 @@ class CompilerDescriptorAnalysisPlugin : DokkaPlugin() {
plugin<InternalKotlinAnalysisPlugin>().fullClassHierarchyBuilder providing { DescriptorFullClassHierarchyBuilder() }
}
+ internal val kotlinSampleProviderFactory by extending {
+ plugin<InternalKotlinAnalysisPlugin>().sampleProviderFactory providing ::KotlinSampleProviderFactory
+ }
+
internal val descriptorSyntheticDocumentableDetector by extending {
plugin<InternalKotlinAnalysisPlugin>().syntheticDocumentableDetector providing { DescriptorSyntheticDocumentableDetector() }
}
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider.kt
new file mode 100644
index 00000000..73f70b9c
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider.kt
@@ -0,0 +1,109 @@
+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
+import org.jetbrains.dokka.InternalDokkaApi
+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.SamplesKotlinAnalysis
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+import org.jetbrains.dokka.analysis.kotlin.internal.SampleProvider
+import org.jetbrains.dokka.analysis.kotlin.internal.SampleProviderFactory
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtBlockExpression
+import org.jetbrains.kotlin.psi.KtDeclarationWithBody
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+
+class KotlinSampleProviderFactory(val context: DokkaContext): SampleProviderFactory {
+ override fun build(): SampleProvider {
+ return KotlinSampleProvider(context)
+ }
+
+}
+/**
+ * It's declared as open since StdLib has its own sample transformer
+ * with [processBody] and [processImports]
+ */
+@InternalDokkaApi
+open class KotlinSampleProvider(val context: DokkaContext): SampleProvider {
+ private val kDocFinder: KDocFinder = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kdocFinder }
+ private val analysis = lazy {
+ /**
+ * 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) {
+ SamplesKotlinAnalysis(
+ sourceSets = context.configuration.sourceSets,
+ context = context,
+ projectKotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>()
+ .querySingle { kotlinAnalysis }
+ )
+ }
+ }
+ protected open 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
+ }
+
+ protected open fun processImports(psiElement: PsiElement): String {
+ val psiFile = psiElement.containingFile
+ return when(val text = (psiFile as? KtFile)?.importList?.text) {
+ is String -> text
+ else -> ""
+ }
+ }
+
+ /**
+ * @return [SampleProvider.SampleSnippet] or null if it has not found by [fqLink]
+ */
+ override fun getSample(sourceSet: DokkaConfiguration.DokkaSourceSet, fqLink: String): SampleProvider.SampleSnippet? {
+ return runBlocking(Dispatchers.Default) {
+ val resolveSession = analysis.value[sourceSet].resolveSession
+ val psiElement = fqNameToPsiElement(resolveSession, fqLink, sourceSet)
+ ?: return@runBlocking null.also { context.logger.warn("Cannot find PsiElement corresponding to $fqLink") }
+ val imports =
+ processImports(psiElement)
+ val body = processBody(psiElement)
+ return@runBlocking SampleProvider.SampleSnippet(imports, body)
+ }
+ }
+ override fun close() {
+ if(analysis.isInitialized())
+ analysis.value.close()
+ }
+
+ private fun fqNameToPsiElement(resolveSession: ResolveSession, functionName: String, dokkaSourceSet: DokkaConfiguration.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 org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration(symbol)
+ }
+ }
+} \ No newline at end of file