aboutsummaryrefslogtreecommitdiff
path: root/subprojects/analysis-kotlin-descriptors/ide
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-07-05 10:04:55 +0200
committerGitHub <noreply@github.com>2023-07-05 10:04:55 +0200
commit9559158bfeeb274e9ccf1b4563f1b23b42afc493 (patch)
tree3ece0887623cfe2b7148af23001867a1dd5e6597 /subprojects/analysis-kotlin-descriptors/ide
parentcbd9733d3dd2f52992e98e7cebd072091a572529 (diff)
downloaddokka-9559158bfeeb274e9ccf1b4563f1b23b42afc493.tar.gz
dokka-9559158bfeeb274e9ccf1b4563f1b23b42afc493.tar.bz2
dokka-9559158bfeeb274e9ccf1b4563f1b23b42afc493.zip
Decompose Kotlin/Java analysis (#3034)
* Extract analysis into separate modules
Diffstat (limited to 'subprojects/analysis-kotlin-descriptors/ide')
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/README.md11
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/api/ide.api4
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/build.gradle.kts21
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/CoreKotlinCacheService.kt54
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/DokkaResolutionFacade.kt123
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeAnalysisContextCreator.kt29
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeCompilerExtensionPointProvider.kt46
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorAnalysisPlugin.kt38
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorFinder.kt12
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeKLibService.kt30
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeMockApplicationHack.kt12
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdePluginKDocFinder.kt48
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/ResolutionFacadeAnalysisContext.kt30
-rw-r--r--subprojects/analysis-kotlin-descriptors/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin1
14 files changed, 459 insertions, 0 deletions
diff --git a/subprojects/analysis-kotlin-descriptors/ide/README.md b/subprojects/analysis-kotlin-descriptors/ide/README.md
new file mode 100644
index 00000000..14ed5baa
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/README.md
@@ -0,0 +1,11 @@
+# Descriptors: IDE
+
+An internal module that encapsulates external IDE (`org.jetbrains.kotlin:idea`) dependencies.
+
+IDE artifacts are reused for things that are not possible to do with the Kotlin compiler API, such
+as KDoc or KLib parsing/processing, because Dokka is very similar to an IDE when it comes to analyzing
+source code and docs.
+
+Exists primarily to make sure that unreliable and coupled external dependencies are somewhat abstracted away,
+otherwise everything gets tangled together and breaking changes in such dependencies become very
+difficult to resolve.
diff --git a/subprojects/analysis-kotlin-descriptors/ide/api/ide.api b/subprojects/analysis-kotlin-descriptors/ide/api/ide.api
new file mode 100644
index 00000000..a59658a3
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/api/ide.api
@@ -0,0 +1,4 @@
+public final class org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorAnalysisPlugin : org/jetbrains/dokka/plugability/DokkaPlugin {
+ public fun <init> ()V
+}
+
diff --git a/subprojects/analysis-kotlin-descriptors/ide/build.gradle.kts b/subprojects/analysis-kotlin-descriptors/ide/build.gradle.kts
new file mode 100644
index 00000000..79777256
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/build.gradle.kts
@@ -0,0 +1,21 @@
+plugins {
+ id("org.jetbrains.conventions.kotlin-jvm")
+}
+
+dependencies {
+ compileOnly(projects.core)
+ compileOnly(projects.subprojects.analysisKotlinApi)
+
+ implementation(projects.subprojects.analysisKotlinDescriptors.compiler)
+
+ api(libs.kotlin.idePlugin.common)
+ api(libs.kotlin.idePlugin.idea)
+ api(libs.kotlin.idePlugin.core)
+ api(libs.kotlin.idePlugin.native)
+
+ // TODO [beresnev] needed for CommonIdePlatformKind, describe
+ implementation(libs.kotlin.jps.common)
+
+ // TODO [beresnev] get rid of it
+ compileOnly(libs.kotlinx.coroutines.core)
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/CoreKotlinCacheService.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/CoreKotlinCacheService.kt
new file mode 100644
index 00000000..d7069656
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/CoreKotlinCacheService.kt
@@ -0,0 +1,54 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.intellij.psi.PsiFile
+import org.jetbrains.kotlin.analyzer.ModuleInfo
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.platform.TargetPlatform
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
+
+
+internal class CoreKotlinCacheService(private val resolutionFacade: DokkaResolutionFacade) : KotlinCacheService {
+ override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacade(element: KtElement): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByFile(
+ file: PsiFile,
+ platform: org.jetbrains.kotlin.platform.TargetPlatform
+ ): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByModuleInfo(
+ moduleInfo: ModuleInfo,
+ settings: PlatformAnalysisSettings
+ ): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByModuleInfo(
+ moduleInfo: ModuleInfo,
+ platform: org.jetbrains.kotlin.platform.TargetPlatform
+ ): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeWithForcedPlatform(
+ elements: List<KtElement>,
+ platform: TargetPlatform
+ ): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getSuppressionCache(): KotlinSuppressCache {
+ throw UnsupportedOperationException()
+ }
+
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/DokkaResolutionFacade.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/DokkaResolutionFacade.kt
new file mode 100644
index 00000000..e2253b99
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/DokkaResolutionFacade.kt
@@ -0,0 +1,123 @@
+@file:OptIn(FrontendInternals::class)
+
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.google.common.collect.ImmutableMap
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.analyzer.ModuleInfo
+import org.jetbrains.kotlin.analyzer.ResolverForModule
+import org.jetbrains.kotlin.analyzer.ResolverForProject
+import org.jetbrains.kotlin.container.getService
+import org.jetbrains.kotlin.container.tryGetService
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.diagnostics.DiagnosticSink
+import org.jetbrains.kotlin.idea.FrontendInternals
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
+import org.jetbrains.kotlin.util.slicedMap.WritableSlice
+
+internal class DokkaResolutionFacade(
+ override val project: Project,
+ override val moduleDescriptor: ModuleDescriptor,
+ val resolverForModule: ResolverForModule
+) : ResolutionFacade {
+ override fun analyzeWithAllCompilerChecks(
+ elements: Collection<KtElement>,
+ callback: DiagnosticSink.DiagnosticsCallback?
+ ): AnalysisResult {
+ throw UnsupportedOperationException()
+ }
+
+ @OptIn(FrontendInternals::class)
+ override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? {
+ return resolverForModule.componentProvider.tryGetService(serviceClass)
+ }
+
+ override fun resolveToDescriptor(
+ declaration: KtDeclaration,
+ bodyResolveMode: BodyResolveMode
+ ): DeclarationDescriptor {
+ return resolveSession.resolveToDescriptor(declaration)
+ }
+
+ override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext {
+ throw UnsupportedOperationException()
+ }
+
+ val resolveSession: ResolveSession get() = getFrontendService(ResolveSession::class.java)
+
+ override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext {
+ if (element is KtDeclaration) {
+ val descriptor = resolveToDescriptor(element)
+ return object : BindingContext {
+ override fun <K : Any?, V : Any?> getKeys(p0: WritableSlice<K, V>?): Collection<K> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getType(p0: KtExpression): KotlinType? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <K : Any?, V : Any?> get(slice: ReadOnlySlice<K, V>?, key: K): V? {
+ if (key != element) {
+ throw UnsupportedOperationException()
+ }
+ @Suppress("UNCHECKED_CAST")
+ return when {
+ slice == BindingContext.DECLARATION_TO_DESCRIPTOR -> descriptor as V
+ slice == BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER && (element as KtParameter).hasValOrVar() -> descriptor as V
+ else -> null
+ }
+ }
+
+ override fun getDiagnostics(): Diagnostics {
+ throw UnsupportedOperationException()
+ }
+
+ override fun addOwnDataTo(p0: BindingTrace, p1: Boolean) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <K : Any?, V : Any?> getSliceContents(p0: ReadOnlySlice<K, V>): ImmutableMap<K, V> {
+ throw UnsupportedOperationException()
+ }
+
+ }
+ }
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(serviceClass: Class<T>): T {
+ return resolverForModule.componentProvider.getService(serviceClass)
+ }
+
+ override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
+ return resolverForModule.componentProvider.getService(serviceClass)
+ }
+
+ override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getResolverForProject(): ResolverForProject<out ModuleInfo> {
+ throw UnsupportedOperationException()
+ }
+
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeAnalysisContextCreator.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeAnalysisContextCreator.kt
new file mode 100644
index 00000000..166e25fa
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeAnalysisContextCreator.kt
@@ -0,0 +1,29 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.intellij.mock.MockComponentManager
+import com.intellij.mock.MockProject
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.AnalysisContextCreator
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.AnalysisContext
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.AnalysisEnvironment
+import org.jetbrains.kotlin.analyzer.ResolverForModule
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+
+internal class IdeAnalysisContextCreator : AnalysisContextCreator {
+ override fun create(
+ project: MockProject,
+ moduleDescriptor: ModuleDescriptor,
+ moduleResolver: ResolverForModule,
+ kotlinEnvironment: KotlinCoreEnvironment,
+ analysisEnvironment: AnalysisEnvironment,
+ ): AnalysisContext {
+ val facade = DokkaResolutionFacade(project, moduleDescriptor, moduleResolver)
+ val projectComponentManager = project as MockComponentManager
+ projectComponentManager.registerService(
+ KotlinCacheService::class.java,
+ CoreKotlinCacheService(facade)
+ )
+ return ResolutionFacadeAnalysisContext(facade, kotlinEnvironment, analysisEnvironment)
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeCompilerExtensionPointProvider.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeCompilerExtensionPointProvider.kt
new file mode 100644
index 00000000..73d908e9
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeCompilerExtensionPointProvider.kt
@@ -0,0 +1,46 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerExtensionPointProvider
+import org.jetbrains.kotlin.caches.resolve.CommonPlatformKindResolution
+import org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution
+import org.jetbrains.kotlin.caches.resolve.JsPlatformKindResolution
+import org.jetbrains.kotlin.caches.resolve.JvmPlatformKindResolution
+import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor
+import org.jetbrains.kotlin.ide.konan.NativePlatformKindResolution
+import org.jetbrains.kotlin.platform.IdePlatformKind
+import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
+
+internal class IdeCompilerExtensionPointProvider : CompilerExtensionPointProvider {
+ override fun get(): List<CompilerExtensionPointProvider.CompilerExtensionPoint> {
+
+ @Suppress("UNCHECKED_CAST")
+ val idePlatformKind = CompilerExtensionPointProvider.CompilerExtensionPoint(
+ ApplicationExtensionDescriptor(
+ "org.jetbrains.kotlin.idePlatformKind",
+ IdePlatformKind::class.java
+ ) as ApplicationExtensionDescriptor<Any>,
+ listOf(
+ CommonIdePlatformKind,
+ JvmIdePlatformKind,
+ JsIdePlatformKind,
+ NativeIdePlatformKind
+ )
+ )
+
+ @Suppress("UNCHECKED_CAST")
+ val resolution = CompilerExtensionPointProvider.CompilerExtensionPoint(
+ IdePlatformKindResolution as ApplicationExtensionDescriptor<Any>,
+ listOf(
+ CommonPlatformKindResolution(),
+ JvmPlatformKindResolution(),
+ JsPlatformKindResolution(),
+ NativePlatformKindResolution()
+ )
+ )
+
+ return listOf(idePlatformKind, resolution)
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorAnalysisPlugin.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorAnalysisPlugin.kt
new file mode 100644
index 00000000..930e4a3f
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorAnalysisPlugin.kt
@@ -0,0 +1,38 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import org.jetbrains.dokka.InternalDokkaApi
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin
+import org.jetbrains.dokka.plugability.DokkaPlugin
+import org.jetbrains.dokka.plugability.DokkaPluginApiPreview
+import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement
+
+@InternalDokkaApi
+class IdeDescriptorAnalysisPlugin : DokkaPlugin() {
+
+ internal val ideKdocFinder by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().kdocFinder providing ::IdePluginKDocFinder
+ }
+
+ internal val ideDescriptorFinder by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().descriptorFinder providing { IdeDescriptorFinder() }
+ }
+
+ internal val ideKlibService by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().klibService providing { IdeKLibService() }
+ }
+
+ internal val ideCompilerExtensionPointProvider by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().compilerExtensionPointProvider providing { IdeCompilerExtensionPointProvider() }
+ }
+
+ internal val ideApplicationHack by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().mockApplicationHack providing { IdeMockApplicationHack() }
+ }
+
+ internal val ideAnalysisContextCreator by extending {
+ plugin<CompilerDescriptorAnalysisPlugin>().analysisContextCreator providing { IdeAnalysisContextCreator() }
+ }
+
+ @OptIn(DokkaPluginApiPreview::class)
+ override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorFinder.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorFinder.kt
new file mode 100644
index 00000000..bc591151
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeDescriptorFinder.kt
@@ -0,0 +1,12 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.DescriptorFinder
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
+import org.jetbrains.kotlin.psi.KtDeclaration
+
+internal class IdeDescriptorFinder : DescriptorFinder {
+ override fun KtDeclaration.findDescriptor(): DeclarationDescriptor? {
+ return this.descriptor
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeKLibService.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeKLibService.kt
new file mode 100644
index 00000000..c3422f56
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeKLibService.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KLibService
+import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataModuleDescriptorFactory
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
+import org.jetbrains.kotlin.idea.klib.createKlibPackageFragmentProvider
+import org.jetbrains.kotlin.idea.klib.getCompatibilityInfo
+import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.library.KotlinLibrary
+import org.jetbrains.kotlin.storage.StorageManager
+
+internal class IdeKLibService : KLibService {
+ override fun KotlinLibrary.createPackageFragmentProvider(
+ storageManager: StorageManager,
+ metadataModuleDescriptorFactory: KlibMetadataModuleDescriptorFactory,
+ languageVersionSettings: LanguageVersionSettings,
+ moduleDescriptor: ModuleDescriptor,
+ lookupTracker: LookupTracker,
+ ): PackageFragmentProvider? {
+ return this.createKlibPackageFragmentProvider(
+ storageManager, metadataModuleDescriptorFactory, languageVersionSettings, moduleDescriptor, lookupTracker
+ )
+ }
+
+ override fun isAnalysisCompatible(kotlinLibrary: KotlinLibrary): Boolean {
+ return kotlinLibrary.getCompatibilityInfo().isCompatible
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeMockApplicationHack.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeMockApplicationHack.kt
new file mode 100644
index 00000000..a582572d
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdeMockApplicationHack.kt
@@ -0,0 +1,12 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.intellij.mock.MockApplication
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.MockApplicationHack
+import org.jetbrains.kotlin.idea.klib.KlibLoadingMetadataCache
+
+internal class IdeMockApplicationHack : MockApplicationHack {
+ override fun hack(mockApplication: MockApplication) {
+ if (mockApplication.getService(KlibLoadingMetadataCache::class.java) == null)
+ mockApplication.registerService(KlibLoadingMetadataCache::class.java, KlibLoadingMetadataCache())
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdePluginKDocFinder.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdePluginKDocFinder.kt
new file mode 100644
index 00000000..d0d217f6
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/IdePluginKDocFinder.kt
@@ -0,0 +1,48 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KDocFinder
+import org.jetbrains.dokka.plugability.DokkaContext
+import org.jetbrains.dokka.plugability.plugin
+import org.jetbrains.dokka.plugability.querySingle
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
+import org.jetbrains.kotlin.idea.kdoc.findKDoc
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
+
+internal class IdePluginKDocFinder(
+ private val context: DokkaContext
+) : KDocFinder {
+
+ override fun KtElement.findKDoc(): KDocTag? {
+ return this.findKDoc { DescriptorToSourceUtils.descriptorToDeclaration(it) }
+ }
+
+ override fun DeclarationDescriptor.find(descriptorToPsi: (DeclarationDescriptorWithSource) -> PsiElement?): KDocTag? {
+ return this.findKDoc(descriptorToPsi)
+ }
+
+ override fun resolveKDocLink(
+ fromDescriptor: DeclarationDescriptor,
+ qualifiedName: String,
+ sourceSet: DokkaConfiguration.DokkaSourceSet,
+ emptyBindingContext: Boolean
+ ): Collection<DeclarationDescriptor> {
+ val facadeAnalysisContext = context
+ .plugin<CompilerDescriptorAnalysisPlugin>()
+ .querySingle { kotlinAnalysis }[sourceSet] as ResolutionFacadeAnalysisContext
+
+ return org.jetbrains.kotlin.idea.kdoc.resolveKDocLink(
+ context = if (emptyBindingContext) BindingContext.EMPTY else facadeAnalysisContext.resolveSession.bindingContext,
+ resolutionFacade = facadeAnalysisContext.facade,
+ fromDescriptor = fromDescriptor,
+ fromSubjectOfTag = null,
+ qualifiedName = qualifiedName.split('.')
+ )
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/ResolutionFacadeAnalysisContext.kt b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/ResolutionFacadeAnalysisContext.kt
new file mode 100644
index 00000000..d16ee7d2
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/ide/ResolutionFacadeAnalysisContext.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka.analysis.kotlin.descriptors.ide
+
+import com.intellij.openapi.project.Project
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.AnalysisContext
+import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.AnalysisEnvironment
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+
+internal class ResolutionFacadeAnalysisContext(
+ val facade: DokkaResolutionFacade,
+
+ private val kotlinEnvironment: KotlinCoreEnvironment,
+ private val analysisEnvironment: AnalysisEnvironment
+) : AnalysisContext {
+ private var isClosed: Boolean = false
+
+ override val environment: KotlinCoreEnvironment
+ get() = kotlinEnvironment.takeUnless { isClosed }
+ ?: throw IllegalStateException("AnalysisEnvironment is already closed")
+
+ override val resolveSession: ResolveSession = facade.resolveSession
+ override val moduleDescriptor: ModuleDescriptor = facade.moduleDescriptor
+ override val project: Project = facade.project
+
+ override fun close() {
+ isClosed = true
+ analysisEnvironment.dispose()
+ }
+}
diff --git a/subprojects/analysis-kotlin-descriptors/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/subprojects/analysis-kotlin-descriptors/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
new file mode 100644
index 00000000..f993dcb1
--- /dev/null
+++ b/subprojects/analysis-kotlin-descriptors/ide/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
@@ -0,0 +1 @@
+org.jetbrains.dokka.analysis.kotlin.descriptors.ide.IdeDescriptorAnalysisPlugin