diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2023-07-05 10:04:55 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-05 10:04:55 +0200 |
commit | 9559158bfeeb274e9ccf1b4563f1b23b42afc493 (patch) | |
tree | 3ece0887623cfe2b7148af23001867a1dd5e6597 /subprojects/analysis-kotlin-descriptors/ide | |
parent | cbd9733d3dd2f52992e98e7cebd072091a572529 (diff) | |
download | dokka-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')
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 |