aboutsummaryrefslogtreecommitdiff
path: root/subprojects
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2023-08-28 19:42:21 +0300
committerGitHub <noreply@github.com>2023-08-28 19:42:21 +0300
commit0e00edc6fcd406fcf38673ef6a2f8f59e8374de2 (patch)
tree697b0de0d44b421c922f1f5e6a7c1352f17c68a6 /subprojects
parentbec2cac91726e52884329e7997207e9777abaab7 (diff)
downloaddokka-0e00edc6fcd406fcf38673ef6a2f8f59e8374de2.tar.gz
dokka-0e00edc6fcd406fcf38673ef6a2f8f59e8374de2.tar.bz2
dokka-0e00edc6fcd406fcf38673ef6a2f8f59e8374de2.zip
Support Dokka K2 analysis (#3094)
Dokka has its own documentable model to represent analyzed code. The analysis is performed by a compiler frontend. In K1 the compiler frontend has descriptors that use the underlying Binding Context (global shared stateful structure). Dokka just maps descriptors to Documentable by DefaultDescriptorToDocumentableTranslator. K2 compiler has FIR tree, which means “Frontend Intermediate Representation”, instead of Binding Context. But we do not use FIR in Dokka directly, since it is too low-level for analysis. The Kotlin compiler provides high-level Analysis API for this case. The API is used by KSP too. Analysis API represent elements of FIR (declarations, parameters and so on) as Symbols. For more details see KtSymbolByFirBuilder, KtSymbol. For Dokka symbol is the replacement of descriptor in K2. Also, to set up the environment of project analysis in K1 we use idea dependencies (or copy-past from there). In K2 for these aims, there is a Standalone mode for Analysis API.
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/analysis-java-psi/api/analysis-java-psi.api4
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt3
-rw-r--r--subprojects/analysis-kotlin-symbols/api/analysis-kotlin-symbols.api19
-rw-r--r--subprojects/analysis-kotlin-symbols/build.gradle.kts71
-rw-r--r--subprojects/analysis-kotlin-symbols/compiler/api/compiler.api4
-rw-r--r--subprojects/analysis-kotlin-symbols/compiler/build.gradle.kts13
-rw-r--r--subprojects/analysis-kotlin-symbols/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/compiler/CompilerSymbolsAnalysisPlugin.kt11
-rw-r--r--subprojects/analysis-kotlin-symbols/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
-rw-r--r--subprojects/analysis-kotlin-symbols/ide/api/ide.api4
-rw-r--r--subprojects/analysis-kotlin-symbols/ide/build.gradle.kts13
-rw-r--r--subprojects/analysis-kotlin-symbols/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/ide/IdeSymbolsAnalysisPlugin.kt11
-rw-r--r--subprojects/analysis-kotlin-symbols/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt170
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KdocMarkdownParser.kt97
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt42
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/SyntheticKDocProvider.kt61
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/DescriptorDocumentationContent.kt15
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/DescriptorKotlinDocCommentCreator.kt16
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocComment.kt81
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt46
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinInheritDocTagContentProvider.kt31
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/IllegalModuleAndPackageDocumentation.kt7
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentation.kt11
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationFragment.kt9
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt47
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationReader.kt110
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationSource.kt14
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/parseModuleAndPackageDocumentation.kt12
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/parseModuleAndPackageDocumentationFragments.kt55
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/AnalysisContext.kt139
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/KotlinAnalysis.kt245
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin.kt121
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/KotlinAnalysisProjectProvider.kt16
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/KotlinAnalysisSourceRootsExtractor.kt12
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/KotlinDocumentableSourceLanguageParser.kt26
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/KotlinSampleProvider.kt85
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/KtPsiDocumentableSource.kt20
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolExternalDocumentablesProvider.kt34
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolFullClassHierarchyBuilder.kt85
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/services/SymbolSyntheticDocumentableDetector.kt41
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt134
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DRIFactory.kt140
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/DefaultSymbolToDocumentableTranslator.kt949
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TranslatorError.kt29
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeReferenceFactory.kt78
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt186
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/utils/isException.kt18
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
48 files changed, 3276 insertions, 62 deletions
diff --git a/subprojects/analysis-java-psi/api/analysis-java-psi.api b/subprojects/analysis-java-psi/api/analysis-java-psi.api
index 404249f8..6b4d444f 100644
--- a/subprojects/analysis-java-psi/api/analysis-java-psi.api
+++ b/subprojects/analysis-java-psi/api/analysis-java-psi.api
@@ -146,3 +146,7 @@ public final class org/jetbrains/dokka/analysis/java/util/PsiDocumentableSource
public final fun getPsi ()Lcom/intellij/psi/PsiNamedElement;
}
+public final class org/jetbrains/dokka/analysis/java/util/PsiUtilKt {
+ public static final fun from (Lorg/jetbrains/dokka/links/DRI$Companion;Lcom/intellij/psi/PsiElement;)Lorg/jetbrains/dokka/links/DRI;
+}
+
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt
index ed58eb56..eb2058d8 100644
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt
+++ b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt
@@ -12,7 +12,8 @@ import org.jetbrains.dokka.utilities.firstIsInstanceOrNull
internal val PsiElement.parentsWithSelf: Sequence<PsiElement>
get() = generateSequence(this) { if (it is PsiFile) null else it.parent }
-internal fun DRI.Companion.from(psi: PsiElement) = psi.parentsWithSelf.run {
+@InternalDokkaApi
+fun DRI.Companion.from(psi: PsiElement) = psi.parentsWithSelf.run {
val psiMethod = firstIsInstanceOrNull<PsiMethod>()
val psiField = firstIsInstanceOrNull<PsiField>()
val classes = filterIsInstance<PsiClass>().filterNot { it is PsiTypeParameter }
diff --git a/subprojects/analysis-kotlin-symbols/api/analysis-kotlin-symbols.api b/subprojects/analysis-kotlin-symbols/api/analysis-kotlin-symbols.api
index e69de29b..4bddfcf1 100644
--- a/subprojects/analysis-kotlin-symbols/api/analysis-kotlin-symbols.api
+++ b/subprojects/analysis-kotlin-symbols/api/analysis-kotlin-symbols.api
@@ -0,0 +1,19 @@
+public final class org/jetbrains/dokka/analysis/kotlin/symbols/plugin/SymbolsAnalysisPlugin : org/jetbrains/dokka/plugability/DokkaPlugin {
+ public fun <init> ()V
+}
+
+public class org/jetbrains/dokka/analysis/kotlin/symbols/services/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/symbols/services/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-symbols/build.gradle.kts b/subprojects/analysis-kotlin-symbols/build.gradle.kts
index c000df58..9fddcde1 100644
--- a/subprojects/analysis-kotlin-symbols/build.gradle.kts
+++ b/subprojects/analysis-kotlin-symbols/build.gradle.kts
@@ -8,9 +8,74 @@ plugins {
}
dependencies {
- implementation(projects.subprojects.analysisKotlinApi)
- implementation(projects.subprojects.analysisKotlinSymbols.compiler)
- implementation(projects.subprojects.analysisKotlinSymbols.ide)
+ compileOnly(projects.core)
+ compileOnly(projects.subprojects.analysisKotlinApi)
+
+ implementation(projects.subprojects.analysisMarkdownJb)
+ implementation(projects.subprojects.analysisJavaPsi)
+
+
+ // ----------- IDE dependencies ----------------------------------------------------------------------------
+
+ listOf(
+ libs.intellij.platform.util.rt,
+ libs.intellij.platform.util.api,
+ libs.intellij.java.psi.api,
+ libs.intellij.java.psi.impl
+ ).forEach {
+ runtimeOnly(it) { isTransitive = false }
+ }
+
+ implementation(libs.intellij.java.psi.api) { isTransitive = false }
+
+
+ // TODO move to toml
+ listOf(
+ "com.jetbrains.intellij.platform:util-class-loader",
+ "com.jetbrains.intellij.platform:util-text-matching",
+ "com.jetbrains.intellij.platform:util-base",
+ "com.jetbrains.intellij.platform:util-xml-dom",
+ "com.jetbrains.intellij.platform:core-impl",
+ "com.jetbrains.intellij.platform:extensions",
+ ).forEach {
+ runtimeOnly("$it:213.7172.25") { isTransitive = false }
+ }
+
+ implementation("com.jetbrains.intellij.platform:core:213.7172.25") {
+ isTransitive = false
+ } // for Standalone prototype
+
+ // ----------- Analysis dependencies ----------------------------------------------------------------------------
+
+ listOf(
+ libs.kotlin.high.level.api.api,
+ libs.kotlin.analysis.api.standalone,
+ libs.kotlin.high.level.api.impl // for Standalone prototype
+ ).forEach {
+ implementation(it) {
+ isTransitive = false // see KTIJ-19820
+ }
+ }
+ listOf(
+ libs.kotlin.high.level.api.impl,
+ libs.kotlin.high.level.api.fir,
+ libs.kotlin.high.level.api.fe10,
+ libs.kotlin.low.level.api.fir,
+ libs.kotlin.analysis.project.structure,
+ libs.kotlin.analysis.api.providers,
+ libs.kotlin.symbol.light.classes
+ ).forEach {
+ runtimeOnly(it) {
+ isTransitive = false // see KTIJ-19820
+ }
+ }
+ runtimeOnly(libs.kotlinx.collections.immutable)
+ implementation(libs.kotlin.compiler.k2) {
+ isTransitive = false
+ }
+
+ // TODO [beresnev] get rid of it
+ compileOnly(libs.kotlinx.coroutines.core)
}
tasks {
diff --git a/subprojects/analysis-kotlin-symbols/compiler/api/compiler.api b/subprojects/analysis-kotlin-symbols/compiler/api/compiler.api
deleted file mode 100644
index 39870f57..00000000
--- a/subprojects/analysis-kotlin-symbols/compiler/api/compiler.api
+++ /dev/null
@@ -1,4 +0,0 @@
-public final class org/jetbrains/dokka/analysis/kotlin/symbols/compiler/CompilerSymbolsAnalysisPlugin : org/jetbrains/dokka/plugability/DokkaPlugin {
- public fun <init> ()V
-}
-
diff --git a/subprojects/analysis-kotlin-symbols/compiler/build.gradle.kts b/subprojects/analysis-kotlin-symbols/compiler/build.gradle.kts
deleted file mode 100644
index 876d87ca..00000000
--- a/subprojects/analysis-kotlin-symbols/compiler/build.gradle.kts
+++ /dev/null
@@ -1,13 +0,0 @@
-plugins {
- id("org.jetbrains.conventions.kotlin-jvm")
-}
-
-dependencies {
- compileOnly(projects.core)
- compileOnly(projects.subprojects.analysisKotlinApi)
-
- // TODO
-
- // TODO [beresnev] get rid of it
- compileOnly(libs.kotlinx.coroutines.core)
-}
diff --git a/subprojects/analysis-kotlin-symbols/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/compiler/CompilerSymbolsAnalysisPlugin.kt b/subprojects/analysis-kotlin-symbols/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/compiler/CompilerSymbolsAnalysisPlugin.kt
deleted file mode 100644
index 4a39e0d8..00000000
--- a/subprojects/analysis-kotlin-symbols/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/compiler/CompilerSymbolsAnalysisPlugin.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.jetbrains.dokka.analysis.kotlin.symbols.compiler
-
-import org.jetbrains.dokka.plugability.DokkaPlugin
-import org.jetbrains.dokka.plugability.DokkaPluginApiPreview
-import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement
-
-class CompilerSymbolsAnalysisPlugin : DokkaPlugin() {
-
- @OptIn(DokkaPluginApiPreview::class)
- override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement
-}
diff --git a/subprojects/analysis-kotlin-symbols/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/subprojects/analysis-kotlin-symbols/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
deleted file mode 100644
index 47163f6e..00000000
--- a/subprojects/analysis-kotlin-symbols/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
+++ /dev/null
@@ -1 +0,0 @@
-org.jetbrains.dokka.analysis.kotlin.symbols.compiler.CompilerSymbolsAnalysisPlugin
diff --git a/subprojects/analysis-kotlin-symbols/ide/api/ide.api b/subprojects/analysis-kotlin-symbols/ide/api/ide.api
deleted file mode 100644
index 9be46c0b..00000000
--- a/subprojects/analysis-kotlin-symbols/ide/api/ide.api
+++ /dev/null
@@ -1,4 +0,0 @@
-public final class org/jetbrains/dokka/analysis/kotlin/symbols/ide/IdeSymbolsAnalysisPlugin : org/jetbrains/dokka/plugability/DokkaPlugin {
- public fun <init> ()V
-}
-
diff --git a/subprojects/analysis-kotlin-symbols/ide/build.gradle.kts b/subprojects/analysis-kotlin-symbols/ide/build.gradle.kts
deleted file mode 100644
index 876d87ca..00000000
--- a/subprojects/analysis-kotlin-symbols/ide/build.gradle.kts
+++ /dev/null
@@ -1,13 +0,0 @@
-plugins {
- id("org.jetbrains.conventions.kotlin-jvm")
-}
-
-dependencies {
- compileOnly(projects.core)
- compileOnly(projects.subprojects.analysisKotlinApi)
-
- // TODO
-
- // TODO [beresnev] get rid of it
- compileOnly(libs.kotlinx.coroutines.core)
-}
diff --git a/subprojects/analysis-kotlin-symbols/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/ide/IdeSymbolsAnalysisPlugin.kt b/subprojects/analysis-kotlin-symbols/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/ide/IdeSymbolsAnalysisPlugin.kt
deleted file mode 100644
index 33f555cb..00000000
--- a/subprojects/analysis-kotlin-symbols/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/ide/IdeSymbolsAnalysisPlugin.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.jetbrains.dokka.analysis.kotlin.symbols.ide
-
-import org.jetbrains.dokka.plugability.DokkaPlugin
-import org.jetbrains.dokka.plugability.DokkaPluginApiPreview
-import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement
-
-class IdeSymbolsAnalysisPlugin : DokkaPlugin() {
-
- @OptIn(DokkaPluginApiPreview::class)
- override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement
-}
diff --git a/subprojects/analysis-kotlin-symbols/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/subprojects/analysis-kotlin-symbols/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
deleted file mode 100644
index 59245578..00000000
--- a/subprojects/analysis-kotlin-symbols/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
+++ /dev/null
@@ -1 +0,0 @@
-org.jetbrains.dokka.analysis.kotlin.symbols.ide.IdeSymbolsAnalysisPlugin
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt
new file mode 100644
index 00000000..c1b8651a
--- /dev/null
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt
@@ -0,0 +1,170 @@
+package org.jetbrains.dokka.analysis.kotlin.symbols.kdoc
+
+import com.intellij.psi.PsiNamedElement
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.dokka.analysis.java.parsers.JavadocParser
+import org.jetbrains.dokka.model.doc.DocumentationNode
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
+import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
+import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
+import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
+import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
+import org.jetbrains.kotlin.kdoc.psi.api.KDoc
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
+import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
+import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
+import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
+import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
+
+internal fun KtAnalysisSession.getJavaDocDocumentationFrom(
+ symbol: KtSymbol,
+ javadocParser: JavadocParser
+): DocumentationNode? {
+ if (symbol.origin == KtSymbolOrigin.JAVA) {
+ return (symbol.psi as? PsiNamedElement)?.let {
+ javadocParser.parseDocumentation(it)
+ }
+ } else if (symbol.origin == KtSymbolOrigin.SOURCE && symbol is KtCallableSymbol) {
+ // Note: javadocParser searches in overridden JAVA declarations for JAVA method, not Kotlin
+ symbol.getAllOverriddenSymbols().forEach { overrider ->
+ if (overrider.origin == KtSymbolOrigin.JAVA)
+ return@getJavaDocDocumentationFrom (overrider.psi as? PsiNamedElement)?.let {
+ javadocParser.parseDocumentation(it)
+ }
+ }
+ }
+ return null
+}
+
+internal fun KtAnalysisSession.getKDocDocumentationFrom(symbol: KtSymbol, logger: DokkaLogger) = findKDoc(symbol)?.let { kDocContent ->
+
+ val ktElement = symbol.psi
+ val kdocLocation = ktElement?.containingFile?.name?.let {
+ val name = when(symbol) {
+ is KtCallableSymbol -> symbol.callableIdIfNonLocal?.toString()
+ is KtClassOrObjectSymbol -> symbol.classIdIfNonLocal?.toString()
+ is KtNamedSymbol -> symbol.name.asString()
+ else -> null
+ }?.replace('/', '.') // replace to be compatible with K1
+
+ if (name != null) "$it/$name"
+ else it
+ }
+
+
+ parseFromKDocTag(
+ kDocTag = kDocContent.contentTag,
+ externalDri = { link -> resolveKDocLink(link).logIfNotResolved(link.getLinkText(), logger) },
+ kdocLocation = kdocLocation
+ )
+}
+
+
+
+
+// ----------- copy-paste from IDE ----------------------------------------------------------------------------
+
+internal data class KDocContent(
+ val contentTag: KDocTag,
+ val sections: List<KDocSection>
+)
+
+internal fun KtAnalysisSession.findKDoc(symbol: KtSymbol): KDocContent? {
+ // for generated function (e.g. `copy`) psi returns class, see test `data class kdocs over generated methods`
+ if (symbol.origin != KtSymbolOrigin.SOURCE) return null
+ val ktElement = symbol.psi as? KtElement
+ ktElement?.findKDoc()?.let {
+ return it
+ }
+
+ if (symbol is KtCallableSymbol) {
+ symbol.getAllOverriddenSymbols().forEach { overrider ->
+ findKDoc(overrider)?.let {
+ return it
+ }
+ }
+ }
+ return null
+}
+
+
+internal fun KtElement.findKDoc(): KDocContent? = this.lookupOwnedKDoc()
+ ?: this.lookupKDocInContainer()
+
+
+
+private fun KtElement.lookupOwnedKDoc(): KDocContent? {
+ // KDoc for primary constructor is located inside of its class KDoc
+ val psiDeclaration = when (this) {
+ is KtPrimaryConstructor -> getContainingClassOrObject()
+ else -> this
+ }
+
+ if (psiDeclaration is KtDeclaration) {
+ val kdoc = psiDeclaration.docComment
+ if (kdoc != null) {
+ if (this is KtConstructor<*>) {
+ // ConstructorDescriptor resolves to the same JetDeclaration
+ val constructorSection = kdoc.findSectionByTag(KDocKnownTag.CONSTRUCTOR)
+ if (constructorSection != null) {
+ // if annotated with @constructor tag and the caret is on constructor definition,
+ // then show @constructor description as the main content, and additional sections
+ // that contain @param tags (if any), as the most relatable ones
+ // practical example: val foo = Fo<caret>o("argument") -- show @constructor and @param content
+ val paramSections = kdoc.findSectionsContainingTag(KDocKnownTag.PARAM)
+ return KDocContent(constructorSection, paramSections)
+ }
+ }
+ return KDocContent(kdoc.getDefaultSection(), kdoc.getAllSections())
+ }
+ }
+
+ return null
+}
+
+/**
+ * Looks for sections that have a deeply nested [tag],
+ * as opposed to [KDoc.findSectionByTag], which only looks among the top level
+ */
+private fun KDoc.findSectionsContainingTag(tag: KDocKnownTag): List<KDocSection> {
+ return getChildrenOfType<KDocSection>()
+ .filter { it.findTagByName(tag.name.toLowerCaseAsciiOnly()) != null }
+}
+
+private fun KtElement.lookupKDocInContainer(): KDocContent? {
+ val subjectName = name
+ val containingDeclaration =
+ PsiTreeUtil.findFirstParent(this, true) {
+ it is KtDeclarationWithBody && it !is KtPrimaryConstructor
+ || it is KtClassOrObject
+ }
+
+ val containerKDoc = containingDeclaration?.getChildOfType<KDoc>()
+ if (containerKDoc == null || subjectName == null) return null
+ val propertySection = containerKDoc.findSectionByTag(KDocKnownTag.PROPERTY, subjectName)
+ val paramTag =
+ containerKDoc.findDescendantOfType<KDocTag> {