diff options
Diffstat (limited to 'subprojects/analysis-kotlin-descriptors/compiler/src/main')
57 files changed, 0 insertions, 5136 deletions
diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/AnalysisContextCreator.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/AnalysisContextCreator.kt deleted file mode 100644 index 67476a50..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/AnalysisContextCreator.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import com.intellij.mock.MockProject -import org.jetbrains.dokka.InternalDokkaApi -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.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.descriptors.ModuleDescriptor - -@InternalDokkaApi -public interface AnalysisContextCreator { - public fun create( - project: MockProject, - moduleDescriptor: ModuleDescriptor, - moduleResolver: ResolverForModule, - kotlinEnvironment: KotlinCoreEnvironment, - analysisEnvironment: AnalysisEnvironment, - ): AnalysisContext -} 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 deleted file mode 100644 index c59a43b2..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDescriptorAnalysisPlugin.kt +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute -import com.intellij.psi.PsiAnnotation -import org.jetbrains.dokka.CoreExtensions -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.dokka.analysis.java.BreakingAbstractionKotlinLightMethodChecker -import org.jetbrains.dokka.analysis.java.JavaAnalysisPlugin -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DokkaAnalysisConfiguration -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.KotlinAnalysis -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.ProjectKotlinAnalysis -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.* -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentationReader -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java.* -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DefaultDescriptorToDocumentableTranslator -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.DefaultExternalDocumentablesProvider -import org.jetbrains.dokka.renderers.PostAction -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.analysis.kotlin.internal.SampleProviderFactory -import org.jetbrains.dokka.plugability.* -import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation - -@Suppress("unused") -@InternalDokkaApi -public class CompilerDescriptorAnalysisPlugin : DokkaPlugin() { - - @InternalDokkaApi - public val kdocFinder: ExtensionPoint<KDocFinder> by extensionPoint() - - @InternalDokkaApi - public val descriptorFinder: ExtensionPoint<DescriptorFinder> by extensionPoint() - - @InternalDokkaApi - public val klibService: ExtensionPoint<KLibService> by extensionPoint() - - @InternalDokkaApi - public val compilerExtensionPointProvider: ExtensionPoint<CompilerExtensionPointProvider> by extensionPoint() - - @InternalDokkaApi - public val mockApplicationHack: ExtensionPoint<MockApplicationHack> by extensionPoint() - - @InternalDokkaApi - public val analysisContextCreator: ExtensionPoint<AnalysisContextCreator> by extensionPoint() - - @InternalDokkaApi - public val kotlinAnalysis: ExtensionPoint<KotlinAnalysis> by extensionPoint() - - internal val documentableAnalyzerImpl by extending { - plugin<InternalKotlinAnalysisPlugin>().documentableSourceLanguageParser providing { CompilerDocumentableSourceLanguageParser() } - } - - internal val defaultKotlinAnalysis by extending { - @OptIn(DokkaPluginApiPreview::class) - kotlinAnalysis providing { ctx -> - val configuration = configuration<CompilerDescriptorAnalysisPlugin, DokkaAnalysisConfiguration>(ctx) - ?: DokkaAnalysisConfiguration() - ProjectKotlinAnalysis( - sourceSets = ctx.configuration.sourceSets, - context = ctx, - analysisConfiguration = configuration - ) - } - } - - internal val descriptorToDocumentableTranslator by extending { - CoreExtensions.sourceToDocumentableTranslator providing ::DefaultDescriptorToDocumentableTranslator - } - - - internal val descriptorFullClassHierarchyBuilder by extending { - plugin<InternalKotlinAnalysisPlugin>().fullClassHierarchyBuilder providing { DescriptorFullClassHierarchyBuilder() } - } - - /** - * StdLib has its own a sample provider - * So it should have a possibility to override this extension - */ - @InternalDokkaApi - public val kotlinSampleProviderFactory: Extension<SampleProviderFactory, *, *> by extending { - plugin<InternalKotlinAnalysisPlugin>().sampleProviderFactory providing ::KotlinSampleProviderFactory - } - - internal val descriptorSyntheticDocumentableDetector by extending { - plugin<InternalKotlinAnalysisPlugin>().syntheticDocumentableDetector providing { DescriptorSyntheticDocumentableDetector() } - } - - internal val moduleAndPackageDocumentationReader by extending { - plugin<InternalKotlinAnalysisPlugin>().moduleAndPackageDocumentationReader providing ::ModuleAndPackageDocumentationReader - } - - internal val kotlinToJavaMapper by extending { - plugin<InternalKotlinAnalysisPlugin>().kotlinToJavaService providing { DescriptorKotlinToJavaMapper() } - } - - internal val descriptorInheritanceBuilder by extending { - plugin<InternalKotlinAnalysisPlugin>().inheritanceBuilder providing { DescriptorInheritanceBuilder() } - } - - internal val defaultExternalDocumentablesProvider by extending { - plugin<InternalKotlinAnalysisPlugin>().externalDocumentablesProvider providing ::DefaultExternalDocumentablesProvider - } - - private val javaAnalysisPlugin by lazy { plugin<JavaAnalysisPlugin>() } - - internal val projectProvider by extending { - javaAnalysisPlugin.projectProvider providing { KotlinAnalysisProjectProvider() } - } - - internal val sourceRootsExtractor by extending { - javaAnalysisPlugin.sourceRootsExtractor providing { KotlinAnalysisSourceRootsExtractor() } - } - - internal val kotlinDocCommentCreator by extending { - javaAnalysisPlugin.docCommentCreators providing { - DescriptorKotlinDocCommentCreator(querySingle { kdocFinder }, querySingle { descriptorFinder }) - } - } - - internal val kotlinDocCommentParser by extending { - javaAnalysisPlugin.docCommentParsers providing { context -> - DescriptorKotlinDocCommentParser( - context, - context.logger - ) - } - } - - internal val inheritDocTagProvider by extending { - javaAnalysisPlugin.inheritDocTagContentProviders providing ::KotlinInheritDocTagContentProvider - } - - internal val kotlinLightMethodChecker by extending { - javaAnalysisPlugin.kotlinLightMethodChecker providing { - object : BreakingAbstractionKotlinLightMethodChecker { - override fun isLightAnnotation(annotation: PsiAnnotation): Boolean { - return annotation is KtLightAbstractAnnotation - } - - override fun isLightAnnotationAttribute(attribute: JvmAnnotationAttribute): Boolean { - return attribute is KtLightAbstractAnnotation - } - } - } - } - - internal val disposeKotlinAnalysisPostAction by extending { - CoreExtensions.postActions with PostAction { querySingle { kotlinAnalysis }.close() } - } - - @OptIn(DokkaPluginApiPreview::class) - override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDocumentableSourceLanguageParser.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDocumentableSourceLanguageParser.kt deleted file mode 100644 index 2dbc242a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerDocumentableSourceLanguageParser.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DescriptorDocumentableSource -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.WithSources -import org.jetbrains.dokka.analysis.kotlin.internal.DocumentableLanguage -import org.jetbrains.dokka.analysis.kotlin.internal.DocumentableSourceLanguageParser - -internal class CompilerDocumentableSourceLanguageParser : DocumentableSourceLanguageParser { - override fun getLanguage( - documentable: Documentable, - sourceSet: DokkaConfiguration.DokkaSourceSet, - ): DocumentableLanguage? { - val documentableSource = (documentable as? WithSources)?.sources?.get(sourceSet) ?: return null - return when (documentableSource) { - is PsiDocumentableSource -> DocumentableLanguage.JAVA - is DescriptorDocumentableSource -> DocumentableLanguage.KOTLIN - else -> error("Unknown language sources: ${documentableSource::class}") - } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerExtensionPointProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerExtensionPointProvider.kt deleted file mode 100644 index e42efe41..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/CompilerExtensionPointProvider.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor - -@InternalDokkaApi -public interface CompilerExtensionPointProvider { - public fun get(): List<CompilerExtensionPoint> - - public class CompilerExtensionPoint( - public val extensionDescriptor: ApplicationExtensionDescriptor<Any>, - public val extensions: List<Any> - ) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/DescriptorFinder.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/DescriptorFinder.kt deleted file mode 100644 index db06647d..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/DescriptorFinder.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.psi.KtDeclaration - -@InternalDokkaApi -public interface DescriptorFinder { - public fun KtDeclaration.findDescriptor(): DeclarationDescriptor? -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KDocFinder.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KDocFinder.kt deleted file mode 100644 index e5367211..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KDocFinder.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import com.intellij.psi.PsiElement -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils - -@InternalDokkaApi -public interface KDocFinder { - public fun KtElement.findKDoc(): KDocTag? - - public fun DeclarationDescriptor.find( - descriptorToPsi: (DeclarationDescriptorWithSource) -> PsiElement? = { - DescriptorToSourceUtils.descriptorToDeclaration( - it - ) - } - ): KDocTag? - - public fun resolveKDocLink( - fromDescriptor: DeclarationDescriptor, - qualifiedName: String, - sourceSet: DokkaConfiguration.DokkaSourceSet, - emptyBindingContext: Boolean = false - ): Collection<DeclarationDescriptor> -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KLibService.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KLibService.kt deleted file mode 100644 index fc173298..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/KLibService.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.kotlin.library.metadata.KlibMetadataModuleDescriptorFactory -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.storage.StorageManager - -@InternalDokkaApi -public interface KLibService { - public fun KotlinLibrary.createPackageFragmentProvider( - storageManager: StorageManager, - metadataModuleDescriptorFactory: KlibMetadataModuleDescriptorFactory, - languageVersionSettings: LanguageVersionSettings, - moduleDescriptor: ModuleDescriptor, - lookupTracker: LookupTracker - ): PackageFragmentProvider? - - public fun isAnalysisCompatible(kotlinLibrary: KotlinLibrary): Boolean -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/MockApplicationHack.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/MockApplicationHack.kt deleted file mode 100644 index 39ca666b..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/MockApplicationHack.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler - -import com.intellij.mock.MockApplication -import org.jetbrains.dokka.InternalDokkaApi - -@InternalDokkaApi -public interface MockApplicationHack { // ¯\_(ツ)_/¯ - public fun hack(mockApplication: MockApplication) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AbsolutePathString.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AbsolutePathString.kt deleted file mode 100644 index 8cf05053..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AbsolutePathString.kt +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -internal typealias AbsolutePathString = String diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisContext.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisContext.kt deleted file mode 100644 index 917a86e7..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisContext.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.openapi.project.Project -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.AnalysisContextCreator -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.DokkaPluginApiPreview -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.common.messages.MessageRenderer -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import java.io.Closeable -import java.io.File - -@OptIn(DokkaPluginApiPreview::class) -internal fun createAnalysisContext( - context: DokkaContext, - sourceSets: List<DokkaConfiguration.DokkaSourceSet>, - sourceSet: DokkaConfiguration.DokkaSourceSet, - analysisConfiguration: DokkaAnalysisConfiguration -): AnalysisContext { - val parentSourceSets = sourceSets.filter { it.sourceSetID in sourceSet.dependentSourceSets } - val classpath = sourceSet.classpath + parentSourceSets.flatMap { it.classpath } - val sources = sourceSet.sourceRoots + parentSourceSets.flatMap { it.sourceRoots } - - return createAnalysisContext( - context = context, - classpath = classpath, - sourceRoots = sources, - sourceSet = sourceSet, - analysisConfiguration = analysisConfiguration - ) -} - -@OptIn(DokkaPluginApiPreview::class) -internal fun createAnalysisContext( - context: DokkaContext, - classpath: List<File>, - sourceRoots: Set<File>, - sourceSet: DokkaConfiguration.DokkaSourceSet, - analysisConfiguration: DokkaAnalysisConfiguration -): AnalysisContext { - val analysisEnvironment = AnalysisEnvironment( - DokkaMessageCollector(context.logger), - sourceSet.analysisPlatform, - context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { mockApplicationHack }, - context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { klibService }, - ).apply { - if (analysisPlatform == Platform.jvm) { - configureJdkClasspathRoots() - } - addClasspath(classpath) - addSources(sourceRoots) - - loadLanguageVersionSettings(sourceSet.languageVersion, sourceSet.apiVersion) - } - - val environment = analysisEnvironment.createCoreEnvironment() - return analysisEnvironment.createResolutionFacade( - environment, - context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle<CompilerDescriptorAnalysisPlugin, AnalysisContextCreator> { analysisContextCreator }, - analysisConfiguration.ignoreCommonBuiltIns - ) -} - -internal class DokkaMessageCollector(private val logger: DokkaLogger) : MessageCollector { - override fun clear() { - seenErrors = false - } - - private var seenErrors = false - - override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) { - if (severity == CompilerMessageSeverity.ERROR) { - seenErrors = true - } - logger.info(MessageRenderer.PLAIN_FULL_PATHS.render(severity, message, location)) - } - - override fun hasErrors() = seenErrors -} - -@InternalDokkaApi -public interface AnalysisContext : Closeable { - public val environment: KotlinCoreEnvironment - public val resolveSession: ResolveSession - public val moduleDescriptor: ModuleDescriptor - public val project: Project -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisEnvironment.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisEnvironment.kt deleted file mode 100644 index 5a0fc396..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/AnalysisEnvironment.kt +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.core.CoreApplicationEnvironment -import com.intellij.mock.MockApplication -import com.intellij.mock.MockComponentManager -import com.intellij.mock.MockProject -import com.intellij.openapi.Disposable -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.extensions.Extensions -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.psi.PsiNameHelper -import com.intellij.psi.impl.PsiNameHelperImpl -import com.intellij.psi.impl.source.javadoc.JavadocManagerImpl -import com.intellij.psi.javadoc.CustomJavadocTagProvider -import com.intellij.psi.javadoc.JavadocManager -import com.intellij.psi.javadoc.JavadocTagInfo -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.AnalysisContextCreator -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KLibService -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.MockApplicationHack -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve.* -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters -import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer -import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices -import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory -import org.jetbrains.kotlin.builtins.DefaultBuiltIns -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.config.ContentRoot -import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot -import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM -import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.cli.jvm.index.JavaRoot -import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.context.withModule -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.js.config.JSConfigurationKeys -import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices -import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy -import org.jetbrains.kotlin.library.resolveSingleFileKlib -import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.CommonPlatforms -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.platform.js.JsPlatforms -import org.jetbrains.kotlin.platform.jvm.JvmPlatforms -import org.jetbrains.kotlin.platform.jvm.JvmPlatforms.unspecifiedJvmPlatform -import org.jetbrains.kotlin.platform.konan.NativePlatforms -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.CliSealedClassInheritorsProvider -import org.jetbrains.kotlin.resolve.CompilerEnvironment -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices -import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters -import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices -import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import java.io.File -import org.jetbrains.kotlin.konan.file.File as KFile - -internal const val JAR_SEPARATOR = "!/" - -/** - * Kotlin as a service entry point - * - * Configures environment, analyses files and provides facilities to perform code processing without emitting bytecode - * - * $messageCollector: required by compiler infrastructure and will receive all compiler messages - * $body: optional and can be used to configure environment without creating local variable - */ -@InternalDokkaApi -public class AnalysisEnvironment( - private val messageCollector: MessageCollector, - internal val analysisPlatform: Platform, - private val mockApplicationHack: MockApplicationHack, - private val kLibService: KLibService, -) : Disposable { - private val configuration = CompilerConfiguration() - - init { - configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) - } - - internal fun createCoreEnvironment(): KotlinCoreEnvironment { - System.setProperty("idea.io.use.nio2", "true") - System.setProperty("idea.ignore.disabled.plugins", "true") - - val configFiles = when (analysisPlatform) { - Platform.jvm, Platform.common -> EnvironmentConfigFiles.JVM_CONFIG_FILES - Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES - Platform.js, Platform.wasm -> EnvironmentConfigFiles.JS_CONFIG_FILES - } - - val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) - val projectComponentManager = environment.project as MockComponentManager - - CoreApplicationEnvironment.registerExtensionPoint( - environment.project.extensionArea, - JavadocTagInfo.EP_NAME, JavadocTagInfo::class.java - ) - - @Suppress("DEPRECATION") - val extensionArea = Extensions.getRootArea() - - CoreApplicationEnvironment.registerExtensionPoint( - extensionArea, - CustomJavadocTagProvider.EP_NAME, CustomJavadocTagProvider::class.java - ) - - // TODO: figure out why compilation fails with unresolved `CoreApplicationEnvironment.registerApplicationService(...)` - // call, fix it appropriately - with(ApplicationManager.getApplication() as MockApplication) { - mockApplicationHack.hack(this) - } - - projectComponentManager.registerService( - JavadocManager::class.java, - JavadocManagerImpl(environment.project) - ) - - projectComponentManager.registerService( - PsiNameHelper::class.java, - PsiNameHelperImpl(environment.project) - ) - - projectComponentManager.registerService( - CustomJavadocTagProvider::class.java, - CustomJavadocTagProvider { emptyList() } - ) - - return environment - } - - private fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = - when (analysisPlatform) { - Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - Platform.js, Platform.common, Platform.native, Platform.wasm -> GlobalSearchScope.filesScope( - project, - sourceFiles.map { it.virtualFile }.toSet() - ) - } - - internal fun createResolutionFacade( - environment: KotlinCoreEnvironment, - analysisContextCreator: AnalysisContextCreator, - ignoreCommonBuiltIns: Boolean = false - ): AnalysisContext { - val projectContext = ProjectContext(environment.project, "Dokka") - val sourceFiles = environment.getSourceFiles() - - val targetPlatform = when (analysisPlatform) { - Platform.js, Platform.wasm -> JsPlatforms.defaultJsPlatform - Platform.common -> CommonPlatforms.defaultCommonPlatform - Platform.native -> NativePlatforms.unspecifiedNativePlatform - Platform.jvm -> JvmPlatforms.defaultJvmPlatform - } - - val kotlinLibraries: Map<AbsolutePathString, KotlinLibrary> = resolveKotlinLibraries() - - val commonDependencyContainer = if (analysisPlatform == Platform.common) DokkaKlibMetadataCommonDependencyContainer( - kotlinLibraries.values.toList(), - environment.configuration, - LockBasedStorageManager("DokkaKlibMetadata") - ) else null - - val extraModuleDependencies = kotlinLibraries.values.registerLibraries() + commonDependencyContainer?.moduleInfos.orEmpty() - - val library = object : LibraryModuleInfo { - override val analyzerServices: PlatformDependentAnalyzerServices = - analysisPlatform.analyzerServices() - override val name: Name = Name.special("<library>") - override val platform: TargetPlatform = targetPlatform - override fun dependencies(): List<ModuleInfo> = listOf(this) - override fun getLibraryRoots(): Collection<String> = classpath - .map { libraryFile -> libraryFile.absolutePath } - .filter { path -> path !in kotlinLibraries } - } - - val module = object : ModuleInfo { - override val analyzerServices: PlatformDependentAnalyzerServices = - analysisPlatform.analyzerServices() - override val name: Name = Name.special("<module>") - override val platform: TargetPlatform = targetPlatform - override fun dependencies(): List<ModuleInfo> = - listOf(this, library) + extraModuleDependencies - - /** - * Only for common platform ignore BuiltIns for StdLib since it can cause a conflict - * between BuiltIns from a compiler and ones from source code. - */ - override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns { - return if (analysisPlatform == Platform.common && ignoreCommonBuiltIns) ModuleInfo.DependencyOnBuiltIns.NONE - else super.dependencyOnBuiltIns() - } - } - - val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) - val modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) - is DokkaKlibLibraryInfo -> { - if (it.libraryRoot in kotlinLibraries) - ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - else null - } - is CommonKlibModuleInfo -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - else -> null - } ?: throw IllegalArgumentException("Unexpected module info") - } - - var builtIns: JvmBuiltIns? = null - - val resolverForProject = when (analysisPlatform) { - Platform.jvm -> { - builtIns = JvmBuiltIns( - projectContext.storageManager, - JvmBuiltIns.Kind.FROM_CLASS_LOADER - ) // TODO we should use FROM_DEPENDENCIES - createJvmResolverForProject( - projectContext, - module, - library, - modulesContent, - sourcesScope, - builtIns - ) - } - Platform.common -> createCommonResolverForProject( - projectContext, - module, - modulesContent, - environment, - commonDependencyContainer - ) - Platform.js, Platform.wasm -> createJsResolverForProject(projectContext, module, modulesContent) - Platform.native -> createNativeResolverForProject(projectContext, module, modulesContent) - - } - @Suppress("UNUSED_VARIABLE") // BEWARE!!!! IT's UNUSED, but without it some things don't work - val libraryModuleDescriptor = resolverForProject.descriptorForModule(library) - - val moduleDescriptor = resolverForProject.descriptorForModule(module) - builtIns?.initialize(moduleDescriptor, true) - - @Suppress("UNUSED_VARIABLE") // BEWARE!!!! IT's UNUSED, but without it some things don't work - val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly - - val resolverForModule = resolverForProject.resolverForModule(module) - - return analysisContextCreator.create( - environment.project as MockProject, - moduleDescriptor, - resolverForModule, - environment, - this - ) - } - - private fun Platform.analyzerServices() = when (this) { - Platform.js, Platform.wasm -> JsPlatformAnalyzerServices - Platform.common -> CommonPlatformAnalyzerServices - Platform.native -> NativePlatformAnalyzerServices - Platform.jvm -> JvmPlatformAnalyzerServices - } - - private fun Collection<KotlinLibrary>.registerLibraries(): List<DokkaKlibLibraryInfo> { - if (analysisPlatform != Platform.native && analysisPlatform != Platform.js && analysisPlatform != Platform.wasm) return emptyList() - val dependencyResolver = DokkaKlibLibraryDependencyResolver() - val analyzerServices = analysisPlatform.analyzerServices() - - return map { kotlinLibrary -> - if (analysisPlatform == org.jetbrains.dokka.Platform.native) DokkaNativeKlibLibraryInfo( - kotlinLibrary, - analyzerServices, - dependencyResolver - ) - else DokkaJsKlibLibraryInfo(kotlinLibrary, analyzerServices, dependencyResolver) - } - } - - @OptIn(ExperimentalStdlibApi::class) - private fun resolveKotlinLibraries(): Map<AbsolutePathString, KotlinLibrary> { - return if (analysisPlatform == Platform.jvm) emptyMap() else buildMap { - classpath - .filter { it.isDirectory || it.extension == KLIB_FILE_EXTENSION } - .forEach { libraryFile -> - try { - val kotlinLibrary = resolveSingleFileKlib( - libraryFile = KFile(libraryFile.absolutePath), - strategy = ToolingSingleFileKlibResolveStrategy - ) - if (kLibService.isAnalysisCompatible(kotlinLibrary)) { - // exists, is KLIB, has compatible format - put( - libraryFile.absolutePath, - kotlinLibrary - ) - } - } catch (e: Throwable) { - configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - .report(CompilerMessageSeverity.WARNING, "Can not resolve KLIB. " + e.message) - } - } - } - } - - private fun createCommonResolverForProject( - projectContext: ProjectContext, - module: ModuleInfo, - modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, - environment: KotlinCoreEnvironment, - dependencyContainer: CommonDependenciesContainer? - ): ResolverForProject<ModuleInfo> { - return object : AbstractResolverForProject<ModuleInfo>( - "Dokka", - projectContext, - modules = module.dependencies() - ) { - override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) - - override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance - - override fun createResolverForModule( - descriptor: ModuleDescriptor, - moduleInfo: ModuleInfo - ): ResolverForModule = - CommonResolverForModuleFactory( - CommonAnalysisParameters( - metadataPartProviderFactory = { content -> - environment.createPackagePartProvider(content.moduleContentScope) - } - ), - CompilerEnvironment, - unspecifiedJvmPlatform, - true, - dependencyContainer - ).createResolverForModule( - moduleDescriptor = descriptor as ModuleDescriptorImpl, - moduleContext = projectContext.withModule(descriptor), - moduleContent = modulesContent(moduleInfo), - resolverForProject = this, - languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, - sealedInheritorsProvider = CliSealedClassInheritorsProvider, - resolveOptimizingOptions = null, - absentDescriptorHandlerClass = null - ) - - override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null - } - } - - private fun createJsResolverForProject( - projectContext: ProjectContext, - module: ModuleInfo, - modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProject<ModuleInfo> { - return object : AbstractResolverForProject<ModuleInfo>( - "Dokka", - projectContext, - modules = module.dependencies() - ) { - override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) - override fun createResolverForModule( - descriptor: ModuleDescriptor, - moduleInfo: ModuleInfo - ): ResolverForModule = DokkaJsResolverForModuleFactory(CompilerEnvironment, kLibService).createResolverForModule( - moduleDescriptor = descriptor as ModuleDescriptorImpl, - moduleContext = projectContext.withModule(descriptor), - moduleContent = modulesContent(moduleInfo), - resolverForProject = this, - languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, - sealedInheritorsProvider = CliSealedClassInheritorsProvider, - resolveOptimizingOptions = null, - absentDescriptorHandlerClass = null - ) - - override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance - - override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null - } - } - - private fun createNativeResolverForProject( - projectContext: ProjectContext, - module: ModuleInfo, - modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProject<ModuleInfo> { - return object : AbstractResolverForProject<ModuleInfo>( - "Dokka", - projectContext, - modules = module.dependencies() - ) { - override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) - override fun createResolverForModule( - descriptor: ModuleDescriptor, - moduleInfo: ModuleInfo - ): ResolverForModule { - - return DokkaNativeResolverForModuleFactory(CompilerEnvironment, kLibService).createResolverForModule( - moduleDescriptor = descriptor as ModuleDescriptorImpl, - moduleContext = projectContext.withModule(descriptor), - moduleContent = modulesContent(moduleInfo), - resolverForProject = this, - languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, - sealedInheritorsProvider = CliSealedClassInheritorsProvider, - resolveOptimizingOptions = null, - absentDescriptorHandlerClass = null - ) - } - - override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance - - override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null - } - } - - private fun createJvmResolverForProject( - projectContext: ProjectContext, - module: ModuleInfo, - library: LibraryModuleInfo, - modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, - sourcesScope: GlobalSearchScope, - builtIns: KotlinBuiltIns - ): ResolverForProject<ModuleInfo> { - val javaRoots = classpath - .mapNotNull { file -> - val rootFile = when (file.extension) { - "jar" -> StandardFileSystems.jar().findFileByPath("${file.absolutePath}$JAR_SEPARATOR") - else -> StandardFileSystems.local().findFileByPath(file.absolutePath) - } - rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } - } - - return object : AbstractResolverForProject<ModuleInfo>( - "Dokka", - projectContext, - modules = listOf(module, library) - ) { - override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = - when (module) { - library -> ModuleContent(module, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(module, emptyList(), sourcesScope) - else -> throw IllegalArgumentException("Unexpected module info") - } - - override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = builtIns - - override fun createResolverForModule( - descriptor: ModuleDescriptor, - moduleInfo: ModuleInfo - ): ResolverForModule = JvmResolverForModuleFactory( - JvmPlatformParameters(packagePartProviderFactory = { content -> - JvmPackagePartProvider( - configuration.languageVersionSettings, - content.moduleContentScope - ) - .apply { - addRoots(javaRoots, messageCollector) - } - }, moduleByJavaClass = { - val file = - (it as? BinaryJavaClass)?.virtualFile ?: (it as JavaClassImpl).psi.containingFile.virtualFile - if (file in sourcesScope) - module - else - library - }, resolverForReferencedModule = null, - useBuiltinsProviderForModule = { false }), - CompilerEnvironment, - unspecifiedJvmPlatform - ).createResolverForModule( - moduleDescriptor = descriptor as ModuleDescriptorImpl, - moduleContext = projectContext.withModule(descriptor), - moduleContent = modulesContent(moduleInfo), - resolverForProject = this, - languageVersionSettings = configuration.languageVersionSettings, - sealedInheritorsProvider = CliSealedClassInheritorsProvider, - resolveOptimizingOptions = null, - absentDescriptorHandlerClass = null - ) - - override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null - } - } - - internal fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { - val languageVersion = LanguageVersion.fromVersionString(languageVersionString) ?: LanguageVersion.LATEST_STABLE - val apiVersion = - apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) - configuration.languageVersionSettings = LanguageVersionSettingsImpl( - languageVersion = languageVersion, - apiVersion = apiVersion, analysisFlags = hashMapOf( - // force to resolve light classes (lazily by default) - AnalysisFlags.eagerResolveOfLightClasses to true - ) - ) - } - - /** - * Classpath for this environment. - */ - private val classpath: List<File> - get() = configuration.jvmClasspathRoots + configuration.getList(JSConfigurationKeys.LIBRARIES) - .mapNotNull { File(it) } - - /** - * Adds list of paths to classpath. - * $paths: collection of files to add - */ - internal fun addClasspath(paths: List<File>) { - if (analysisPlatform == Platform.js || analysisPlatform == Platform.wasm) { - configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) - } else { - configuration.addJvmClasspathRoots(paths) - } - } - - // Set up JDK classpath roots explicitly because of https://github.com/JetBrains/kotlin/commit/f89765eb33dd95c8de33a919cca83651b326b246 - internal fun configureJdkClasspathRoots() { - val jdkHome = File(System.getProperty("java.home")) - if (!jdkHome.exists()) { - messageCollector.report(CompilerMessageSeverity.WARNING, "Set existed java.home to use JDK") - } - configuration.put(JVMConfigurationKeys.JDK_HOME, jdkHome) - configuration.configureJdkClasspathRoots() // only non-nodular JDK - } - /** - * Adds path to classpath. - * $path: path to add - */ - internal fun addClasspath(path: File) { - if (analysisPlatform == Platform.js || analysisPlatform == Platform.wasm) { - configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) - } else { - configuration.addJvmClasspathRoot(path) - } - } - - /** - * List of source roots for this environment. - */ - internal val sources: List<String> - get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) - ?.filterIsInstance<KotlinSourceRoot>() - ?.map { it.path } ?: emptyList() - - /** - * Adds list of paths to source roots. - * $list: collection of files to add - */ - internal fun addSources(sourceDirectories: Iterable<File>) { - sourceDirectories.forEach { directory -> - configuration.addKotlinSourceRoot(directory.path) - if (directory.isDirectory || directory.extension == "java") { - configuration.addJavaSourceRoot(directory) - } - } - } - - internal fun addRoots(list: List<ContentRoot>) { - configuration.addAll(CLIConfigurationKeys.CONTENT_ROOTS, list) - } - - /** - * Disposes the environment and frees all associated resources. - */ - override fun dispose() { - Disposer.dispose(this) - } - -} - - diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/CallableFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/CallableFactory.kt deleted file mode 100644 index 068b4730..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/CallableFactory.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.psi.PsiField -import com.intellij.psi.PsiMethod -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.JavaClassReference -import org.jetbrains.dokka.links.TypeReference -import org.jetbrains.kotlin.descriptors.CallableDescriptor - -internal fun Callable.Companion.from(descriptor: CallableDescriptor, name: String? = null) = with(descriptor) { - Callable( - name ?: descriptor.name.asString(), - extensionReceiverParameter?.let { TypeReference.from(it) }, - valueParameters.mapNotNull { TypeReference.from(it) } - ) -} - -internal fun Callable.Companion.from(psi: PsiMethod) = with(psi) { - Callable( - name, - null, - parameterList.parameters.map { param -> JavaClassReference(param.type.canonicalText) }) -} - -internal fun Callable.Companion.from(psi: PsiField): Callable { - return Callable( - name = psi.name, - receiver = null, - params = emptyList() - ) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRIFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRIFactory.kt deleted file mode 100644 index e2deaa8c..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRIFactory.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.psi.* -import org.jetbrains.dokka.links.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor -import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull - -internal fun DRI.Companion.from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run { - val parameter = firstIsInstanceOrNull<ValueParameterDescriptor>() - val callable = parameter?.containingDeclaration ?: firstIsInstanceOrNull<CallableDescriptor>() - - DRI( - packageName = firstIsInstanceOrNull<PackageFragmentDescriptor>()?.fqName?.asString() ?: "", - classNames = (filterIsInstance<ClassDescriptor>() + filterIsInstance<TypeAliasDescriptor>()).toList() - .takeIf { it.isNotEmpty() } - ?.asReversed() - ?.joinToString(separator = ".") { it.name.asString() }, - callable = callable?.let { Callable.from(it) }, - target = DriTarget.from(parameter ?: descriptor), - extra = if (descriptor is EnumEntrySyntheticClassDescriptor || (descriptor as? ClassDescriptor)?.kind == ClassKind.ENUM_ENTRY) - DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode() - else null - ) -} - -internal 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 } - .toList() // We only want exact PsiClass types, not PsiTypeParameter subtype - val additionalClasses = if (psi is PsiEnumConstant) listOfNotNull(psiField?.name) else emptyList() - DRI( - packageName = classes.lastOrNull()?.qualifiedName?.substringBeforeLast('.', "") ?: "", - classNames = (additionalClasses + classes.mapNotNull { it.name }).takeIf { it.isNotEmpty() } - ?.asReversed()?.joinToString("."), - // The fallback strategy test whether psi is not `PsiEnumConstant`. The reason behind this is that - // we need unified DRI for both Java and Kotlin enums, so we can link them properly and treat them alike. - // To achieve that, we append enum name to classNames list and leave the callable part set to null. For Kotlin enums - // it is by default, while for Java enums we have to explicitly test for that in this `takeUnless` condition. - callable = psiMethod?.let { Callable.from(it) } ?: psiField?.takeUnless { psi is PsiEnumConstant }?.let { Callable.from(it) }, - target = DriTarget.from(psi), - extra = if (psi is PsiEnumConstant) - DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode() - else null - ) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRITargetFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRITargetFactory.kt deleted file mode 100644 index f9d01ceb..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/DRITargetFactory.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiParameter -import com.intellij.psi.PsiTypeParameter -import org.jetbrains.dokka.links.DriTarget -import org.jetbrains.dokka.links.PointingToCallableParameters -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.links.PointingToGenericParameters -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf -import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull - -internal fun DriTarget.Companion.from(descriptor: DeclarationDescriptor): DriTarget = descriptor.parentsWithSelf.run { - return when (descriptor) { - is TypeParameterDescriptor -> PointingToGenericParameters(descriptor.index) - is ValueParameterDescriptor -> PointingToCallableParameters(descriptor.index) - else -> { - val callable = firstIsInstanceOrNull<CallableDescriptor>() - val params = - callable?.let { listOfNotNull(it.extensionReceiverParameter) + it.valueParameters }.orEmpty() - val parameterDescriptor = firstIsInstanceOrNull<ParameterDescriptor>() - - parameterDescriptor?.let { PointingToCallableParameters(params.indexOf(it)) } - ?: PointingToDeclaration - } - } -} - - -internal fun DriTarget.Companion.from(psi: PsiElement): DriTarget = psi.parentsWithSelf.run { - return when (psi) { - is PsiTypeParameter -> PointingToGenericParameters(psi.index) - else -> firstIsInstanceOrNull<PsiParameter>()?.let { - val callable = firstIsInstanceOrNull<PsiMethod>() - val params = (callable?.parameterList?.parameters).orEmpty() - PointingToCallableParameters(params.indexOf(it)) - } ?: PointingToDeclaration - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/Documentable.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/Documentable.kt deleted file mode 100644 index ad5eb048..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/Documentable.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.psi.PsiDocumentManager -import org.jetbrains.dokka.model.DocumentableSource -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.kotlin.toSourceElement -import org.jetbrains.kotlin.resolve.source.getPsi - -internal class DescriptorDocumentableSource(val descriptor: DeclarationDescriptor) : DocumentableSource { - override val path = descriptor.toSourceElement.containingFile.toString() - - override fun computeLineNumber(): Int? { - return (this.descriptor as DeclarationDescriptorWithSource) - .source.getPsi() - ?.let { - val range = it.node?.findChildByType(KtTokens.IDENTIFIER)?.textRange ?: it.textRange - val doc = PsiDocumentManager.getInstance(it.project).getDocument(it.containingFile) - // IJ uses 0-based line-numbers; external source browsers use 1-based - doc?.getLineNumber(range.startOffset)?.plus(1) - } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/JvmDependenciesIndexImpl.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/JvmDependenciesIndexImpl.kt deleted file mode 100644 index da18a952..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/JvmDependenciesIndexImpl.kt +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/** - * DO NOT MOVE IT - * This is a hack for https://github.com/Kotlin/dokka/issues/1599 - * - * Copy-pasted from 1.9.20-Beta-1 - * Can be removed for Kotlin compiler 1.9.20 and later - * - * It makes this class threadsafe for Dokka - */ -@file:Suppress("PackageDirectoryMismatch") -package org.jetbrains.kotlin.cli.jvm.index - -import com.intellij.ide.highlighter.JavaClassFileType -import com.intellij.ide.highlighter.JavaFileType -import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.openapi.vfs.VirtualFile -import gnu.trove.THashMap -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import java.util.* -import java.util.concurrent.locks.ReentrantLock -import kotlin.concurrent.withLock - -// speeds up finding files/classes in classpath/java source roots -// TODO: KT-58327 needs to be adapted/removed if we want compiler to be multithreaded -// the main idea of this class is for each package to store roots which contains it to avoid excessive file system traversal -public class JvmDependenciesIndexImpl(_roots: List<JavaRoot>) : JvmDependenciesIndex { - private val lock = ReentrantLock() - - //these fields are computed based on _roots passed to constructor which are filled in later - private val roots: List<JavaRoot> by lazy { _roots.toList() } - - private val maxIndex: Int - get() = roots.size - - // each "Cache" object corresponds to a package - private class Cache { - private val innerPackageCaches = HashMap<String, Cache>() - - operator fun get(name: String) = innerPackageCaches.getOrPut(name, ::Cache) - - // indices of roots that are known to contain this package - // if this list contains [1, 3, 5] then roots with indices 1, 3 and 5 are known to contain this package, 2 and 4 are known not to (no information about roots 6 or higher) - // if this list contains maxIndex that means that all roots containing this package are known - @Suppress("DEPRECATION") // TODO: fix deprecation - val rootIndices = com.intellij.util.containers.IntArrayList(2) - } - - // root "Cache" object corresponds to DefaultPackage which exists in every root. Roots with non-default fqname are also listed here but - // they will be ignored on requests with invalid fqname prefix. - private val rootCache: Cache by lazy { - Cache().apply { - roots.indices.forEach(rootIndices::add) - rootIndices.add(maxIndex) - rootIndices.trimToSize() - } - } - - // holds the request and the result last time we searched for class - // helps improve several scenarios, LazyJavaResolverContext.findClassInJava being the most important - private var lastClassSearch: Pair<FindClassRequest, SearchResult>? = null - - override val indexedRoots: Sequence<JavaRoot> by lazy { roots.asSequence() } - - private val packageCache: Array<out MutableMap<String, VirtualFile?>> by lazy { - Array(roots.size) { THashMap<String, VirtualFile?>() } - } - - override fun traverseDirectoriesInPackage( - packageFqName: FqName, - acceptedRootTypes: Set<JavaRoot.RootType>, - continueSearch: (VirtualFile, JavaRoot.RootType) -> Boolean - ) { - lock.withLock { - search(TraverseRequest(packageFqName, acceptedRootTypes)) { dir, rootType -> - if (continueSearch(dir, rootType)) null else Unit - } - } - } - - // findClassGivenDirectory MUST check whether the class with this classId exists in given package - override fun <T : Any> findClass( - classId: ClassId, - acceptedRootTypes: Set<JavaRoot.RootType>, - findClassGivenDirectory: (VirtualFile, JavaRoot.RootType) -> T? - ): T? { - lock.withLock { - // TODO: KT-58327 probably should be changed to thread local to fix fast-path - // make a decision based on information saved from last class search - if (lastClassSearch?.first?.classId != classId) { - return search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory) - } - - val (cachedRequest, cachedResult) = lastClassSearch!! - return when (cachedResult) { - is SearchResult.NotFound -> { - val limitedRootTypes = acceptedRootTypes - cachedRequest.acceptedRootTypes - if (limitedRootTypes.isEmpty()) { - null - } else { - search(FindClassRequest(classId, limitedRootTypes), findClassGivenDirectory) - } - } - is SearchResult.Found -> { - if (cachedRequest.acceptedRootTypes == acceptedRootTypes) { - findClassGivenDirectory(cachedResult.packageDirectory, cachedResult.root.type) - } else { - search(FindClassRequest(classId, acceptedRootTypes), findClassGivenDirectory) - } - } - } - } - } - - private fun <T : Any> search(request: SearchRequest, handler: (VirtualFile, JavaRoot.RootType) -> T?): T? { - // a list of package sub names, ["org", "jb", "kotlin"] - val packagesPath = request.packageFqName.pathSegments().map { it.identifierOrNullIfSpecial ?: return null } - // a list of caches corresponding to packages, [default, "org", "org.jb", "org.jb.kotlin"] - val caches = cachesPath(packagesPath) - - var processedRootsUpTo = -1 - // traverse caches starting from last, which contains most specific information - - // NOTE: indices manipulation instead of using caches.reversed() is here for performance reasons - for (cacheIndex in caches.lastIndex downTo 0) { - val cacheRootIndices = caches[cacheIndex].rootIndices - for (i in 0 until cacheRootIndices.size()) { - val rootIndex = cacheRootIndices[i] - if (rootIndex <= processedRootsUpTo) continue // roots with those indices have been processed by now - - val directoryInRoot = travelPath(rootIndex, request.packageFqName, packagesPath, cacheIndex, caches) ?: continue - val root = roots[rootIndex] - if (root.type in request.acceptedRootTypes) { - val result = handler(directoryInRoot, root.type) - if (result != null) { - if (request is FindClassRequest) { - lastClassSearch = Pair(request, SearchResult.Found(directoryInRoot, root)) - } - return result - } - } - } - processedRootsUpTo = if (cacheRootIndices.isEmpty) processedRootsUpTo else cacheRootIndices[cacheRootIndices.size() - 1] - } - - if (request is FindClassRequest) { - lastClassSearch = Pair(request, SearchResult.NotFound) - } - return null - } - - // try to find a target directory corresponding to package represented by packagesPath in a given root represented by index - // possibly filling "Cache" objects with new information - private fun travelPath( - rootIndex: Int, - packageFqName: FqName, - packagesPath: List<String>, - fillCachesAfter: Int, - cachesPath: List<Cache> - ): VirtualFile? { - if (rootIndex >= maxIndex) { - for (i in (fillCachesAfter + 1) until cachesPath.size) { - // we all know roots that contain this package by now - cachesPath[i].rootIndices.add(maxIndex) - cachesPath[i].rootIndices.trimToSize() - } - return null - } - - return packageCache[rootIndex].getOrPut(packageFqName.asString()) { - doTravelPath(rootIndex, packagesPath, fillCachesAfter, cachesPath) - } - } - - private fun doTravelPath(rootIndex: Int, packagesPath: List<String>, fillCachesAfter: Int, cachesPath: List<Cache>): VirtualFile? { - val pathRoot = roots[rootIndex] - val prefixPathSegments = pathRoot.prefixFqName?.pathSegments() - - var currentFile = pathRoot.file - - for (pathIndex in packagesPath.indices) { - val subPackageName = packagesPath[pathIndex] - if (prefixPathSegments != null && pathIndex < prefixPathSegments.size) { - // Traverse prefix first instead of traversing real directories - if (prefixPathSegments[pathIndex].identifier != subPackageName) { - return null - } - } else { - currentFile = currentFile.findChildPackage(subPackageName, pathRoot.type) ?: return null - } - - val correspondingCacheIndex = pathIndex + 1 - if (correspondingCacheIndex > fillCachesAfter) { - // subPackageName exists in this root - cachesPath[correspondingCacheIndex].rootIndices.add(rootIndex) - } - } - - return currentFile - } - - private fun VirtualFile.findChildPackage(subPackageName: String, rootType: JavaRoot.RootType): VirtualFile? { - val childDirectory = findChild(subPackageName) ?: return null - - val fileExtension = when (rootType) { - JavaRoot.RootType.BINARY -> JavaClassFileType.INSTANCE.defaultExtension - JavaRoot.RootType.BINARY_SIG -> "sig" - JavaRoot.RootType.SOURCE -> JavaFileType.INSTANCE.defaultExtension - } - - // If in addition to a directory "foo" there's a class file "foo.class" AND there are no classes anywhere in the directory "foo", - // then we ignore the directory and let the resolution choose the class "foo" instead. - if (findChild("$subPackageName.$fileExtension")?.isDirectory == false) { - if (VfsUtilCore.processFilesRecursively(childDirectory) { file -> file.extension != fileExtension }) { - return null - } - } - - return childDirectory - } - - private fun cachesPath(path: List<String>): List<Cache> { - val caches = ArrayList<Cache>(path.size + 1) - caches.add(rootCache) - var currentCache = rootCache - for (subPackageName in path) { - currentCache = currentCache[subPackageName] - caches.add(currentCache) - } - return caches - } - - private data class FindClassRequest(val classId: ClassId, override val acceptedRootTypes: Set<JavaRoot.RootType>) : SearchRequest { - override val packageFqName: FqName - get() = classId.packageFqName - } - - private data class TraverseRequest( - override val packageFqName: FqName, - override val acceptedRootTypes: Set<JavaRoot.RootType> - ) : SearchRequest - - private interface SearchRequest { - val packageFqName: FqName - val acceptedRootTypes: Set<JavaRoot.RootType> - } - - private sealed class SearchResult { - class Found(val packageDirectory: VirtualFile, val root: JavaRoot) : SearchResult() - - object NotFound : SearchResult() - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinAnalysis.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinAnalysis.kt deleted file mode 100644 index 4e6f42c9..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinAnalysis.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet -import org.jetbrains.dokka.DokkaSourceSetID -import org.jetbrains.dokka.InternalDokkaApi -import org.jetbrains.dokka.model.SourceSetDependent -import org.jetbrains.dokka.plugability.ConfigurableBlock -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.DokkaPluginApiPreview -import java.io.Closeable - -@OptIn(DokkaPluginApiPreview::class) -@Suppress("FunctionName") -internal fun ProjectKotlinAnalysis( - sourceSets: List<DokkaSourceSet>, - context: DokkaContext, - analysisConfiguration: DokkaAnalysisConfiguration = DokkaAnalysisConfiguration() -): KotlinAnalysis { - val environments = sourceSets.associateWith { sourceSet -> - createAnalysisContext( - context = context, - sourceSets = sourceSets, - sourceSet = sourceSet, - analysisConfiguration = analysisConfiguration - ) - } - return EnvironmentKotlinAnalysis(environments) -} - -/** - * [projectKotlinAnalysis] needs to be closed separately - * Usually the analysis created for samples is short-lived and can be closed right after - * it's been used, there's no need to wait for [projectKotlinAnalysis] to be closed as it must be handled separately. - */ -@OptIn(DokkaPluginApiPreview::class) -@Suppress("FunctionName") -internal fun SamplesKotlinAnalysis( - sourceSets: List<DokkaSourceSet>, - context: DokkaContext, - projectKotlinAnalysis: KotlinAnalysis, - analysisConfiguration: DokkaAnalysisConfiguration = DokkaAnalysisConfiguration() -): KotlinAnalysis { - val environments = sourceSets - .filter { it.samples.isNotEmpty() } - .associateWith { sourceSet -> - createAnalysisContext( - context = context, - classpath = sourceSet.classpath, - sourceRoots = sourceSet.samples, - sourceSet = sourceSet, - analysisConfiguration = analysisConfiguration - ) - } - - return EnvironmentKotlinAnalysis(environments, projectKotlinAnalysis) -} -@DokkaPluginApiPreview -public data class DokkaAnalysisConfiguration( - /** - * Only for common platform ignore BuiltIns for StdLib since it can cause a conflict - * between BuiltIns from a compiler and ones from source code. - */ - val ignoreCommonBuiltIns: Boolean = DEFAULT_IGNORE_COMMON_BUILT_INS -): ConfigurableBlock { - public companion object { - public const val DEFAULT_IGNORE_COMMON_BUILT_INS: Boolean = false - } -} - -/** - * First child delegation. It does not close [parent]. - */ -@InternalDokkaApi -public abstract class KotlinAnalysis( - private val parent: KotlinAnalysis? = null -) : Closeable { - - public operator fun get(key: DokkaSourceSet): AnalysisContext { - return get(key.sourceSetID) - } - - internal operator fun get(key: DokkaSourceSetID): AnalysisContext { - return find(key) - ?: parent?.get(key) - ?: throw IllegalStateException("Missing EnvironmentAndFacade for sourceSet $key") - } - - internal abstract fun find(sourceSetID: DokkaSourceSetID): AnalysisContext? -} - -internal open class EnvironmentKotlinAnalysis( - private val environments: SourceSetDependent<AnalysisContext>, - parent: KotlinAnalysis? = null, -) : KotlinAnalysis(parent = parent) { - - override fun find(sourceSetID: DokkaSourceSetID): AnalysisContext? = - environments.entries.firstOrNull { (sourceSet, _) -> sourceSet.sourceSetID == sourceSetID }?.value - - override fun close() { - environments.values.forEach(AnalysisContext::close) - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinCliJavaFileManagerImpl.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinCliJavaFileManagerImpl.kt deleted file mode 100644 index 3d340672..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/KotlinCliJavaFileManagerImpl.kt +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/** - * DO NOT MOVE IT - * This is a hack for https://github.com/Kotlin/dokka/issues/1599 - * - * Copy-pasted from Kotlin compiler - * - * It makes this class threadsafe (`topLevelClassesCache` and `binaryCache`) for Dokka - * - */ -@file:Suppress("PackageDirectoryMismatch") -package org.jetbrains.kotlin.cli.jvm.compiler - -import com.intellij.core.CoreJavaFileManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.* -import com.intellij.psi.impl.file.PsiPackageImpl -import com.intellij.psi.search.GlobalSearchScope -import gnu.trove.THashMap -import gnu.trove.THashSet -import org.jetbrains.kotlin.cli.jvm.index.JavaRoot -import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex -import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex -import org.jetbrains.kotlin.load.java.JavaClassFinder -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext -import org.jetbrains.kotlin.load.java.structure.impl.classFiles.isNotTopLevelClass -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager -import org.jetbrains.kotlin.util.PerformanceCounter - -// TODO: do not inherit from CoreJavaFileManager to avoid accidental usage of its methods which do not use caches/indices -// Currently, the only relevant usage of this class as CoreJavaFileManager is at CoreJavaDirectoryService.getPackage, -// which is indirectly invoked from PsiPackage.getSubPackages -public class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJavaFileManager(myPsiManager), KotlinCliJavaFileManager { - private val perfCounter = PerformanceCounter.create("Find Java class") - private lateinit var index: JvmDependenciesIndex - private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex - private lateinit var packagePartProviders: List<JvmPackagePartProvider> - private val topLevelClassesCache: MutableMap<FqName, VirtualFile?> = THashMap() - private val allScope = GlobalSearchScope.allScope(myPsiManager.project) - private var usePsiClassFilesReading = false - - public fun initialize( - index: JvmDependenciesIndex, - packagePartProviders: List<JvmPackagePartProvider>, - singleJavaFileRootsIndex: SingleJavaFileRootsIndex, - usePsiClassFilesReading: Boolean - ) { - this.index = index - this.packagePartProviders = packagePartProviders - this.singleJavaFileRootsIndex = singleJavaFileRootsIndex - this.usePsiClassFilesReading = usePsiClassFilesReading - } - - private fun findPsiClass(classId: ClassId, searchScope: GlobalSearchScope): PsiClass? = perfCounter.time { - findVirtualFileForTopLevelClass(classId, searchScope)?.findPsiClassInVirtualFile(classId.relativeClassName.asString()) - } - - private fun findVirtualFileForTopLevelClass(classId: ClassId, searchScope: GlobalSearchScope): VirtualFile? { - val relativeClassName = classId.relativeClassName.asString() - synchronized(topLevelClassesCache) { - return topLevelClassesCache.getOrPut(classId.packageFqName.child(classId.relativeClassName.pathSegments().first())) { - index.findClass(classId) { dir, type -> - findVirtualFileGivenPackage(dir, relativeClassName, type) - } ?: singleJavaFileRootsIndex.findJavaSourceClass(classId) - }?.takeIf { it in searchScope } - } - } - - private val binaryCache: MutableMap<ClassId, JavaClass?> = THashMap() - private val signatureParsingComponent = BinaryClassSignatureParser() - - public fun findClass(classId: ClassId, searchScope: GlobalSearchScope): JavaClass? = findClass(JavaClassFinder.Request(classId), searchScope) - - override fun findClass(request: JavaClassFinder.Request, searchScope: GlobalSearchScope): JavaClass? { - val (classId, classFileContentFromRequest, outerClassFromRequest) = request - val virtualFile = findVirtualFileForTopLevelClass(classId, searchScope) ?: return null - - if (!usePsiClassFilesReading && (virtualFile.extension == "class" || virtualFile.extension == "sig")) { - synchronized(binaryCache){ - // We return all class files' names in the directory in knownClassNamesInPackage method, so one may request an inner class - return binaryCache.getOrPut(classId) { - // Note that currently we implicitly suppose that searchScope for binary classes is constant and we do not use it - // as a key in cache - // This is a true assumption by now since there are two search scopes in compiler: one for sources and another one for binary - // When it become wrong because we introduce the modules into CLI, it's worth to consider - // having different KotlinCliJavaFileManagerImpl's for different modules - - classId.outerClassId?.let { outerClassId -> - val outerClass = outerClassFromRequest ?: findClass(outerClassId, searchScope) - - return if (outerClass is BinaryJavaClass) - outerClass.findInnerClass(classId.shortClassName, classFileContentFromRequest) - else - outerClass?.findInnerClass(classId.shortClassName) - } - - // Here, we assume the class is top-level - val classContent = classFileContentFromRequest ?: virtualFile.contentsToByteArray() - if (virtualFile.nameWithoutExtension.contains("$") && isNotTopLevelClass(classContent)) return@getOrPut null - - val resolver = ClassifierResolutionContext { findClass(it, allScope) } - - BinaryJavaClass( - virtualFile, classId.asSingleFqName(), resolver, signatureParsingComponent, - outerClass = null, classContent = classContent - ) - } - } - } - - return virtualFile.findPsiClassInVirtualFile(classId.relativeClassName.asString())?.let(::JavaClassImpl) - } - - // this method is called from IDEA to resolve dependencies in Java code - // which supposedly shouldn't have errors so the dependencies exist in general - override fun findClass(qName: String, scope: GlobalSearchScope): PsiClass? { - // String cannot be reliably converted to ClassId because we don't know where the package name ends and class names begin. - // For example, if qName is "a.b.c.d.e", we should either look for a top level class "e" in the package "a.b.c.d", - // or, for example, for a nested class with the relative qualified name "c.d.e" in the package "a.b". - // Below, we start by looking for the top level class "e" in the package "a.b.c.d" first, then for the class "d.e" in the package - // "a.b.c", and so on, until we find something. Most classes are top level, so most of the times the search ends quickly - - forEachClassId(qName) { classId -> - findPsiClass(classId, scope)?.let { return it } - } - - return null - } - - private inline fun forEachClassId(fqName: String, block: (ClassId) -> Unit) { - var classId = fqName.toSafeTopLevelClassId() ?: return - - while (true) { - block(classId) - - val packageFqName = classId.packageFqName - if (packageFqName.isRoot) break - - classId = ClassId( - packageFqName.parent(), - FqName(packageFqName.shortName().asString() + "." + classId.relativeClassName.asString()), - false - ) - } - } - - override fun findClasses(qName: String, scope: GlobalSearchScope): Array<PsiClass> = perfCounter.time { - val result = ArrayList<PsiClass>(1) - forEachClassId(qName) { classId -> - val relativeClassName = classId.relativeClassName.asString() - index.traverseDirectoriesInPackage(classId.packageFqName) { dir, rootType -> - val psiClass = - findVirtualFileGivenPackage(dir, relativeClassName, rootType) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - if (psiClass != null) { - result.add(psiClass) - } - // traverse all - true - } - - singleJavaFileRootsIndex.findJavaSourceClass(classId) - ?.takeIf { it in scope } - ?.findPsiClassInVirtualFile(relativeClassName) - ?.let { result.add(it) } - - if (result.isNotEmpty()) { - return@time result.toTypedArray() - } - } - - PsiClass.EMPTY_ARRAY - } - - override fun findPackage(packageName: String): PsiPackage? { - var found = false - val packageFqName = packageName.toSafeFqName() ?: return null - index.traverseDirectoriesInPackage(packageFqName) { _, _ -> - found = true - //abort on first found - false - } - if (!found) { - found = packagePartProviders.any { it.findPackageParts(packageName).isNotEmpty() } - } - if (!found) { - found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty() - } - return if (found) PsiPackageImpl(myPsiManager, packageName) else null - } - - private fun findVirtualFileGivenPackage( - packageDir: VirtualFile, - classNameWithInnerClasses: String, - rootType: JavaRoot.RootType - ): VirtualFile? { - val topLevelClassName = classNameWithInnerClasses.substringBefore('.') - - val vFile = when (rootType) { - JavaRoot.RootType.BINARY -> packageDir.findChild("$topLevelClassName.class") - JavaRoot.RootType.BINARY_SIG -> packageDir.findChild("$topLevelClassName.sig") - JavaRoot.RootType.SOURCE -> packageDir.findChild("$topLevelClassName.java") - } ?: return null - - if (!vFile.isValid) { - LOG.error("Invalid child of valid parent: ${vFile.path}; ${packageDir.isValid} path=${packageDir.path}") - return null - } - - return vFile - } - - private fun VirtualFile.findPsiClassInVirtualFile(classNameWithInnerClasses: String): PsiClass? { - val file = myPsiManager.findFile(this) as? PsiClassOwner ?: return null - return findClassInPsiFile(classNameWithInnerClasses, file) - } - - override fun knownClassNamesInPackage(packageFqName: FqName): Set<String> { - val result = THashSet<String>() - index.traverseDirectoriesInPackage(packageFqName, continueSearch = { dir, _ -> - for (child in dir.children) { - if (child.extension == "class" || child.extension == "java" || child.extension == "sig") { - result.add(child.nameWithoutExtension) - } - } - - true - }) - - for (classId in singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName)) { - assert(!classId.isNestedClass) { "ClassId of a single .java source class should not be nested: $classId" } - result.add(classId.shortClassName.asString()) - } - - return result - } - - override fun findModules(moduleName: String, scope: GlobalSearchScope): Collection<PsiJavaModule> { - // TODO - return emptySet() - } - - override fun getNonTrivialPackagePrefixes(): Collection<String> = emptyList() - - public companion object { - private val LOG = Logger.getInstance(KotlinCliJavaFileManagerImpl::class.java) - - private fun findClassInPsiFile(classNameWithInnerClassesDotSeparated: String, file: PsiClassOwner): PsiClass? { - for (topLevelClass in file.classes) { - val candidate = findClassByTopLevelClass(classNameWithInnerClassesDotSeparated, topLevelClass) - if (candidate != null) { - return candidate - } - } - return null - } - - private fun findClassByTopLevelClass(className: String, topLevelClass: PsiClass): PsiClass? { - if (className.indexOf('.') < 0) { - return if (className == topLevelClass.name) topLevelClass else null - } - - val segments = StringUtil.split(className, ".").iterator() - if (!segments.hasNext() || segments.next() != topLevelClass.name) { - return null - } - var curClass = topLevelClass - while (segments.hasNext()) { - val innerClassName = segments.next() - val innerClass = curClass.findInnerClassByName(innerClassName, false) ?: return null - curClass = innerClass - } - return curClass - } - } -} - -// a sad workaround to avoid throwing exception when called from inside IDEA code -private fun <T : Any> safely(compute: () -> T): T? = - try { - compute() - } catch (e: IllegalArgumentException) { - null - } catch (e: AssertionError) { - null - } - -private fun String.toSafeFqName(): FqName? = safely { FqName(this) } -private fun String.toSafeTopLevelClassId(): ClassId? = safely { ClassId.topLevel(FqName(this)) } diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/TypeReferenceFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/TypeReferenceFactory.kt deleted file mode 100644 index b6929cbb..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/TypeReferenceFactory.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration - -import com.intellij.psi.PsiClass -import org.jetbrains.dokka.links.* -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.error.ErrorType -import org.jetbrains.kotlin.types.error.ErrorTypeConstructor -import org.jetbrains.kotlin.types.error.ErrorTypeKind - -internal fun TypeReference.Companion.from(d: ReceiverParameterDescriptor): TypeReference? = - when (d.value) { - is ExtensionReceiver -> fromPossiblyNullable(d.type, emptyList()) - else -> run { - println("Unknown value type for $d") - null - } - } - -internal fun TypeReference.Companion.from(d: ValueParameterDescriptor): TypeReference = - fromPossiblyNullable(d.type, emptyList()) - -internal fun TypeReference.Companion.from(@Suppress("UNUSED_PARAMETER") p: PsiClass) = TypeReference - -private fun TypeReference.Companion.fromPossiblyNullable(t: KotlinType, paramTrace: List<KotlinType>): TypeReference = - fromPossiblyRecursive(t, paramTrace).let { if (t.isMarkedNullable) Nullable(it) else it } - -private fun TypeReference.Companion.fromPossiblyRecursive(t: KotlinType, paramTrace: List<KotlinType>): TypeReference = - paramTrace.indexOfFirst { it.constructor == t.constructor && it.arguments == t.arguments } - .takeIf { it >= 0 } - ?.let(::RecursiveType) - ?: from(t, paramTrace) - -private fun TypeReference.Companion.from(t: KotlinType, paramTrace: List<KotlinType>): TypeReference { - if (t is ErrorType) { - val errorConstructor = t.constructor as? ErrorTypeConstructor - val presentableName = - if (errorConstructor?.kind == ErrorTypeKind.UNRESOLVED_TYPE && errorConstructor.parameters.isNotEmpty()) - errorConstructor.getParam(0) - else - t.constructor.toString() - return TypeConstructor(presentableName, t.arguments.map { fromProjection(it, paramTrace) }) - } - return when (val d = t.constructor.declarationDescriptor) { - is TypeParameterDescriptor -> TypeParam( - d.upperBounds.map { fromPossiblyNullable(it, paramTrace + t) } - ) - else -> TypeConstructor( - t.constructorName.orEmpty(), - t.arguments.map { fromProjection(it, paramTrace) } - ) - } -} - -private fun TypeReference.Companion.fromProjection(t: TypeProjection, paramTrace: List<KotlinType>): TypeReference = - if (t.isStarProjection) { - StarProjection - } else { - fromPossiblyNullable(t.type, paramTrace) - } - -private val KotlinType.constructorName - get() = constructor.declarationDescriptor?.fqNameSafe?.asString() diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/CommonKlibModuleInfo.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/CommonKlibModuleInfo.kt deleted file mode 100644 index 9f5ecc40..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/CommonKlibModuleInfo.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.CommonPlatforms -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices - -internal class CommonKlibModuleInfo( - override val name: Name, - val kotlinLibrary: KotlinLibrary, - private val dependOnModules: List<ModuleInfo> -) : ModuleInfo { - override fun dependencies(): List<ModuleInfo> = dependOnModules - - override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = ModuleInfo.DependencyOnBuiltIns.LAST - - override val platform: TargetPlatform - get() = CommonPlatforms.defaultCommonPlatform - - override val analyzerServices: PlatformDependentAnalyzerServices - get() = CommonPlatformAnalyzerServices -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsKlibLibraryInfo.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsKlibLibraryInfo.kt deleted file mode 100644 index 480bc7cb..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsKlibLibraryInfo.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.library.shortName -import org.jetbrains.kotlin.library.uniqueName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.platform.js.JsPlatforms -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices - -/** TODO: replace by [org.jetbrains.kotlin.caches.resolve.JsKlibLibraryInfo] after fix of KT-40734 */ -internal class DokkaJsKlibLibraryInfo( - override val kotlinLibrary: KotlinLibrary, - override val analyzerServices: PlatformDependentAnalyzerServices, - private val dependencyResolver: DokkaKlibLibraryDependencyResolver -) : DokkaKlibLibraryInfo() { - init { - dependencyResolver.registerLibrary(this) - } - - override val name: Name by lazy { - val libraryName = kotlinLibrary.shortName ?: kotlinLibrary.uniqueName - Name.special("<$libraryName>") - } - - override val platform: TargetPlatform = JsPlatforms.defaultJsPlatform - override fun dependencies(): List<ModuleInfo> = listOf(this) + dependencyResolver.resolveDependencies(this) - override fun getLibraryRoots(): Collection<String> = listOf(libraryRoot) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsResolverForModuleFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsResolverForModuleFactory.kt deleted file mode 100644 index 98f9c64a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaJsResolverForModuleFactory.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KLibService -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.builtins.DefaultBuiltIns -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.container.StorageComponentContainer -import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.context.ModuleContext -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices -import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories -import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer -import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider -import org.jetbrains.kotlin.resolve.TargetEnvironment -import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.serialization.js.DynamicTypeDeserializer -import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil -import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider -import org.jetbrains.kotlin.library.metadata.impl.KlibMetadataModuleDescriptorFactoryImpl -import org.jetbrains.kotlin.resolve.lazy.AbsentDescriptorHandler -import org.jetbrains.kotlin.resolve.scopes.optimization.OptimizingOptions -import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils -import java.io.File - -/** TODO: replace by [org.jetbrains.kotlin.caches.resolve.JsResolverForModuleFactory] after fix of KT-40734 */ -internal class DokkaJsResolverForModuleFactory( - private val targetEnvironment: TargetEnvironment, - private val kLibService: KLibService -) : ResolverForModuleFactory() { - companion object { - private val metadataFactories = KlibMetadataFactories({ DefaultBuiltIns.Instance }, DynamicTypeDeserializer) - - private val metadataModuleDescriptorFactory = KlibMetadataModuleDescriptorFactoryImpl( - metadataFactories.DefaultDescriptorFactory, - metadataFactories.DefaultPackageFragmentsFactory, - metadataFactories.flexibleTypeDeserializer, - ) - } - - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - sealedInheritorsProvider: SealedClassInheritorsProvider, - resolveOptimizingOptions: OptimizingOptions?, - absentDescriptorHandlerClass: Class<out AbsentDescriptorHandler>? - ): ResolverForModule { - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - moduleContext.project, - moduleContext.storageManager, - moduleContent.syntheticFiles, - moduleContent.moduleContentScope, - moduleContent.moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext = moduleContext, - declarationProviderFactory = declarationProviderFactory, - bindingTrace = CodeAnalyzerInitializer.getInstance(moduleContext.project).createTrace(), // BindingTraceContext(/* allowSliceRewrite = */ true), - platform = moduleDescriptor.platform!!, - analyzerServices = JsPlatformAnalyzerServices, - targetEnvironment = targetEnvironment, - languageVersionSettings = languageVersionSettings, - absentDescriptorHandlerClass = absentDescriptorHandlerClass - ) - - var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - - val libraryProviders = createPackageFragmentProvider(moduleContent.moduleInfo, container, moduleContext, moduleDescriptor, languageVersionSettings) - - if (libraryProviders.isNotEmpty()) { - packageFragmentProvider = - CompositePackageFragmentProvider(listOf(packageFragmentProvider) + libraryProviders, "DokkaCompositePackageFragmentProvider") - } - return ResolverForModule(packageFragmentProvider, container) - } - - internal fun <M : ModuleInfo> createPackageFragmentProvider( - moduleInfo: M, - container: StorageComponentContainer, - moduleContext: ModuleContext, - moduleDescriptor: ModuleDescriptorImpl, - languageVersionSettings: LanguageVersionSettings - ): List<PackageFragmentProvider> = when (moduleInfo) { - is DokkaJsKlibLibraryInfo -> { - with(kLibService) { - listOfNotNull( - moduleInfo.kotlinLibrary - .createPackageFragmentProvider( - storageManager = moduleContext.storageManager, - metadataModuleDescriptorFactory = metadataModuleDescriptorFactory, - languageVersionSettings = languageVersionSettings, - moduleDescriptor = moduleDescriptor, - lookupTracker = LookupTracker.DO_NOTHING - ) - ) - } - } - is LibraryModuleInfo -> { - moduleInfo.getLibraryRoots() - .flatMap { - if (File(it).exists()) { - KotlinJavascriptMetadataUtils.loadMetadata(it) - } else { - // TODO can/should we warn a user about a problem in a library root? If so how? - emptyList() - } - } - .filter { it.version.isCompatibleWithCurrentCompilerVersion() } - .map { metadata -> - val (header, packageFragmentProtos) = - KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version) - createKotlinJavascriptPackageFragmentProvider( - moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version, - container.get(), LookupTracker.DO_NOTHING - ) - } - } - else -> emptyList() - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryDependencyResolver.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryDependencyResolver.kt deleted file mode 100644 index 8d275ad8..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryDependencyResolver.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.library.uniqueName -import org.jetbrains.kotlin.library.unresolvedDependencies - -/** TODO: replace by [NativeKlibLibraryInfo] after fix of KT-40734 */ -internal class DokkaKlibLibraryDependencyResolver { - private val cachedDependencies = mutableMapOf</* libraryName */String, DokkaKlibLibraryInfo>() - - fun registerLibrary(libraryInfo: DokkaKlibLibraryInfo) { - cachedDependencies[libraryInfo.kotlinLibrary.uniqueName] = libraryInfo - } - - fun resolveDependencies(libraryInfo: DokkaKlibLibraryInfo): List<DokkaKlibLibraryInfo> { - return libraryInfo.kotlinLibrary.unresolvedDependencies.mapNotNull { cachedDependencies[it.path] } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryInfo.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryInfo.kt deleted file mode 100644 index 28a674af..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibLibraryInfo.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.analyzer.LibraryModuleInfo -import org.jetbrains.kotlin.library.KotlinLibrary - -internal abstract class DokkaKlibLibraryInfo : LibraryModuleInfo { - abstract val kotlinLibrary: KotlinLibrary - internal val libraryRoot: String - get() = kotlinLibrary.libraryFile.path -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibMetadataCommonDependencyContainer.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibMetadataCommonDependencyContainer.kt deleted file mode 100644 index 09f4e48a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaKlibMetadataCommonDependencyContainer.kt +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer -import org.jetbrains.kotlin.builtins.DefaultBuiltIns -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.library.metadata.DeserializedKlibModuleOrigin -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer -import org.jetbrains.kotlin.library.metadata.parseModuleHeader -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration -import org.jetbrains.kotlin.library.metadata.impl.KlibMetadataModuleDescriptorFactoryImpl -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.storage.StorageManager - -/** - * Adapted from org.jetbrains.kotlin.cli.metadata.KlibMetadataDependencyContainer - */ -internal class DokkaKlibMetadataCommonDependencyContainer( - kotlinLibraries: List<KotlinLibrary>, - private val configuration: CompilerConfiguration, - private val storageManager: StorageManager -) : CommonDependenciesContainer { - - private val builtIns - get() = DefaultBuiltIns.Instance - - private val mutableDependenciesForAllModuleDescriptors = mutableListOf<ModuleDescriptorImpl>().apply { - add(builtIns.builtInsModule) - } - - private val mutableDependenciesForAllModules = mutableListOf<ModuleInfo>() - - private val moduleDescriptorsForKotlinLibraries: Map<KotlinLibrary, ModuleDescriptorImpl> = - kotlinLibraries.associateBy({ it }) { library -> - val moduleHeader = parseModuleHeader(library.moduleHeaderData) - val moduleName = Name.special(moduleHeader.moduleName) - val moduleOrigin = DeserializedKlibModuleOrigin(library) - MetadataFactories.DefaultDescriptorFactory.createDescriptor( - moduleName, storageManager, builtIns, moduleOrigin - ) - }.also { result -> - val resultValues = result.values - resultValues.forEach { module -> - module.setDependencies(mutableDependenciesForAllModuleDescriptors) - } - mutableDependenciesForAllModuleDescriptors.addAll(resultValues) - } - - private val moduleInfosImpl: List<CommonKlibModuleInfo> = mutableListOf<CommonKlibModuleInfo>().apply { - addAll( - moduleDescriptorsForKotlinLibraries.map { (kotlinLibrary, moduleDescriptor) -> - CommonKlibModuleInfo(moduleDescriptor.name, kotlinLibrary, mutableDependenciesForAllModules) - } - ) - mutableDependenciesForAllModules.addAll(this@apply) - } - - override val moduleInfos: List<ModuleInfo> get() = moduleInfosImpl - - /* not used in Dokka */ - override val friendModuleInfos: List<ModuleInfo> = emptyList() - - /* not used in Dokka */ - override val refinesModuleInfos: List<ModuleInfo> = emptyList() - - override fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor { - if (moduleInfo !in moduleInfos) - error("Unknown module info $moduleInfo") - - // Ensure that the package fragment provider has been created and the module descriptor has been - // initialized with the package fragment provider: - packageFragmentProviderForModuleInfo(moduleInfo) - - return moduleDescriptorsForKotlinLibraries.getValue((moduleInfo as CommonKlibModuleInfo).kotlinLibrary) - } - - override fun registerDependencyForAllModules( - moduleInfo: ModuleInfo, - descriptorForModule: ModuleDescriptorImpl - ) { - mutableDependenciesForAllModules.add(moduleInfo) - mutableDependenciesForAllModuleDescriptors.add(descriptorForModule) - } - - override fun packageFragmentProviderForModuleInfo( - moduleInfo: ModuleInfo - ): PackageFragmentProvider? { - if (moduleInfo !in moduleInfos) - return null - return packageFragmentProviderForKotlinLibrary((moduleInfo as CommonKlibModuleInfo).kotlinLibrary) - } - - private val klibMetadataModuleDescriptorFactory by lazy { - KlibMetadataModuleDescriptorFactoryImpl( - MetadataFactories.DefaultDescriptorFactory, - MetadataFactories.DefaultPackageFragmentsFactory, - MetadataFactories.flexibleTypeDeserializer - ) - } - - private fun packageFragmentProviderForKotlinLibrary( - library: KotlinLibrary - ): PackageFragmentProvider { - val languageVersionSettings = configuration.languageVersionSettings - - val libraryModuleDescriptor = moduleDescriptorsForKotlinLibraries.getValue(library) - val packageFragmentNames = parseModuleHeader(library.moduleHeaderData).packageFragmentNameList - - return klibMetadataModuleDescriptorFactory.createPackageFragmentProvider( - library, - packageAccessHandler = null, - packageFragmentNames = packageFragmentNames, - storageManager = LockBasedStorageManager("KlibMetadataPackageFragmentProvider"), - moduleDescriptor = libraryModuleDescriptor, - configuration = CompilerDeserializationConfiguration(languageVersionSettings), - compositePackageFragmentAddend = null, - lookupTracker = LookupTracker.DO_NOTHING - ).also { - libraryModuleDescriptor.initialize(it) - } - } -} - -private val MetadataFactories = - KlibMetadataFactories( - { DefaultBuiltIns.Instance }, - NullFlexibleTypeDeserializer - ) diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeKlibLibraryInfo.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeKlibLibraryInfo.kt deleted file mode 100644 index 25cfb406..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeKlibLibraryInfo.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.descriptors.ModuleCapability -import org.jetbrains.kotlin.library.metadata.DeserializedKlibModuleOrigin -import org.jetbrains.kotlin.library.metadata.KlibModuleOrigin -import org.jetbrains.kotlin.library.KotlinLibrary -import org.jetbrains.kotlin.library.isInterop -import org.jetbrains.kotlin.library.shortName -import org.jetbrains.kotlin.library.uniqueName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.platform.konan.NativePlatforms -import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices -import java.io.IOException - -/** TODO: replace by [NativeKlibLibraryInfo] after fix of KT-40734 */ -internal class DokkaNativeKlibLibraryInfo( - override val kotlinLibrary: KotlinLibrary, - override val analyzerServices: PlatformDependentAnalyzerServices, - private val dependencyResolver: DokkaKlibLibraryDependencyResolver -) : DokkaKlibLibraryInfo() { - init { - dependencyResolver.registerLibrary(this) - } - - override val name: Name by lazy { - val libraryName = kotlinLibrary.shortName ?: kotlinLibrary.uniqueName - Name.special("<$libraryName>") - } - - override val platform: TargetPlatform = NativePlatforms.unspecifiedNativePlatform - override fun dependencies(): List<ModuleInfo> = listOf(this) + dependencyResolver.resolveDependencies(this) - override fun getLibraryRoots(): Collection<String> = listOf(libraryRoot) - - override val capabilities: Map<ModuleCapability<*>, Any?> - get() { - val capabilities = super.capabilities.toMutableMap() - capabilities[KlibModuleOrigin.CAPABILITY] = DeserializedKlibModuleOrigin(kotlinLibrary) - capabilities[ImplicitIntegerCoercion.MODULE_CAPABILITY] = kotlinLibrary.safeRead(false) { isInterop } - return capabilities - } - - private fun <T> KotlinLibrary.safeRead(defaultValue: T, action: KotlinLibrary.() -> T) = try { - action() - } catch (_: IOException) { - defaultValue - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeResolverForModuleFactory.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeResolverForModuleFactory.kt deleted file mode 100644 index 6063ae1b..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/configuration/resolve/DokkaNativeResolverForModuleFactory.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.resolve - -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KLibService -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.context.ModuleContext -import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories -import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer -import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer -import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider -import org.jetbrains.kotlin.resolve.TargetEnvironment -import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices -import org.jetbrains.kotlin.resolve.lazy.AbsentDescriptorHandler -import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.resolve.scopes.optimization.OptimizingOptions - -/** TODO: replace by [NativeResolverForModuleFactory] after fix of KT-40734 */ -internal class DokkaNativeResolverForModuleFactory( - private val targetEnvironment: TargetEnvironment, - private val kLibService: KLibService, -) : ResolverForModuleFactory() { - companion object { - private val metadataFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer) - } - - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - sealedInheritorsProvider: SealedClassInheritorsProvider, - resolveOptimizingOptions: OptimizingOptions?, - absentDescriptorHandlerClass: Class<out AbsentDescriptorHandler>? - ): ResolverForModule { - - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - moduleContext.project, - moduleContext.storageManager, - moduleContent.syntheticFiles, - moduleContent.moduleContentScope, - moduleContent.moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext = moduleContext, - declarationProviderFactory = declarationProviderFactory, - bindingTrace = CodeAnalyzerInitializer.getInstance(moduleContext.project).createTrace(), - platform = moduleDescriptor.platform!!, - analyzerServices = NativePlatformAnalyzerServices, - targetEnvironment = targetEnvironment, - languageVersionSettings = languageVersionSettings, - absentDescriptorHandlerClass = absentDescriptorHandlerClass - ) - - var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - - val klibPackageFragmentProvider = with(kLibService) { - (moduleContent.moduleInfo as? DokkaNativeKlibLibraryInfo) - ?.kotlinLibrary - ?.createPackageFragmentProvider( - storageManager = moduleContext.storageManager, - metadataModuleDescriptorFactory = metadataFactories.DefaultDeserializedDescriptorFactory, - languageVersionSettings = languageVersionSettings, - moduleDescriptor = moduleDescriptor, - lookupTracker = LookupTracker.DO_NOTHING - ) - } - - if (klibPackageFragmentProvider != null) { - packageFragmentProvider = - CompositePackageFragmentProvider(listOf(packageFragmentProvider, klibPackageFragmentProvider), "DokkaCompositePackageFragmentProvider") - } - - return ResolverForModule(packageFragmentProvider, container) - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorFullClassHierarchyBuilder.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorFullClassHierarchyBuilder.kt deleted file mode 100644 index 95295cf1..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorFullClassHierarchyBuilder.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl - -import com.intellij.psi.PsiClass -import kotlinx.coroutines.coroutineScope -import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DescriptorDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.utilities.parallelForEach -import org.jetbrains.dokka.analysis.kotlin.internal.ClassHierarchy -import org.jetbrains.dokka.analysis.kotlin.internal.FullClassHierarchyBuilder -import org.jetbrains.dokka.analysis.kotlin.internal.Supertypes -import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes -import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny -import java.util.concurrent.ConcurrentHashMap - -internal class DescriptorFullClassHierarchyBuilder : FullClassHierarchyBuilder { - - override suspend fun build(module: DModule): ClassHierarchy = coroutineScope { - val map = module.sourceSets.associateWith { ConcurrentHashMap<DRI, List<DRI>>() } - module.packages.parallelForEach { visitDocumentable(it, map) } - map - } - - private suspend fun collectSupertypesFromKotlinType( - driWithKType: Pair<DRI, KotlinType>, - supersMap: MutableMap<DRI, Supertypes> - ): Unit = coroutineScope { - val (dri, kotlinType) = driWithKType - val supertypes = kotlinType.immediateSupertypes().filterNot { it.isAnyOrNullableAny() } - val supertypesDriWithKType = supertypes.mapNotNull { supertype -> - supertype.constructor.declarationDescriptor?.let { - DRI.from(it) to supertype - } - } - - if (supersMap[dri] == null) { - // another thread can rewrite the same value, but it isn't a problem - supersMap[dri] = supertypesDriWithKType.map { it.first } - supertypesDriWithKType.parallelForEach { collectSupertypesFromKotlinType(it, supersMap) } - } - } - - private suspend fun collectSupertypesFromPsiClass( - driWithPsiClass: Pair<DRI, PsiClass>, - supersMap: MutableMap<DRI, Supertypes> - ): Unit = coroutineScope { - val (dri, psiClass) = driWithPsiClass - val supertypes = psiClass.superTypes.mapNotNull { it.resolve() } - .filterNot { it.qualifiedName == "java.lang.Object" } - val supertypesDriWithPsiClass = supertypes.map { DRI.from(it) to it } - - if (supersMap[dri] == null) { - // another thread can rewrite the same value, but it isn't a problem - supersMap[dri] = supertypesDriWithPsiClass.map { it.first } - supertypesDriWithPsiClass.parallelForEach { collectSupertypesFromPsiClass(it, supersMap) } - } - } - - private suspend fun visitDocumentable( - documentable: Documentable, - hierarchy: SourceSetDependent<MutableMap<DRI, List<DRI>>> - ): Unit = coroutineScope { - if (documentable is WithScope) { - documentable.classlikes.parallelForEach { visitDocumentable(it, hierarchy) } - } - if (documentable is DClasslike) { - // to build a full class graph, using supertypes from Documentable - // is not enough since it keeps only one level of hierarchy - documentable.sources.forEach { (sourceSet, source) -> - if (source is DescriptorDocumentableSource) { - val descriptor = source.descriptor as? ClassifierDescriptorWithTypeParameters ?: return@forEach // it can be typealias as well - val type = descriptor.defaultType - hierarchy[sourceSet]?.let { collectSupertypesFromKotlinType(documentable.dri to type, it) } - } else if (source is PsiDocumentableSource) { - val psi = source.psi as PsiClass - hierarchy[sourceSet]?.let { collectSupertypesFromPsiClass(documentable.dri to psi, it) } - } - } - } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorInheritanceBuilder.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorInheritanceBuilder.kt deleted file mode 100644 index 46974dce..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorInheritanceBuilder.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl - -import com.intellij.psi.PsiClass -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.analysis.java.util.PsiDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DescriptorDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.WithSources -import org.jetbrains.dokka.analysis.kotlin.internal.InheritanceBuilder -import org.jetbrains.dokka.analysis.kotlin.internal.InheritanceNode -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.resolve.DescriptorUtils.getClassDescriptorForType - -internal class DescriptorInheritanceBuilder : InheritanceBuilder { - - override fun build(documentables: Map<DRI, Documentable>): List<InheritanceNode> { - val descriptorMap = getDescriptorMap(documentables) - - val psiInheritanceTree = - documentables.flatMap { (_, v) -> (v as? WithSources)?.sources?.values.orEmpty() } - .filterIsInstance<PsiDocumentableSource>().mapNotNull { it.psi as? PsiClass } - .flatMap(::gatherPsiClasses) - .flatMap { entry -> entry.second.map { it to entry.first } } - .let { - it + it.map { it.second to null } - } - .groupBy({ it.first }) { it.second } - .map { it.key to it.value.filterNotNull().distinct() } - .map { (k, v) -> - InheritanceNode( - DRI.from(k), - v.map { InheritanceNode(DRI.from(it)) }, - k.supers.filter { it.isInterface }.map { DRI.from(it) }, - k.isInterface - ) - - } - - val descriptorInheritanceTree = descriptorMap.flatMap { (_, v) -> - v.typeConstructor.supertypes - .map { getClassDescriptorForType(it) to v } - } - .let { - it + it.map { it.second to null } - } - .groupBy({ it.first }) { it.second } - .map { it.key to it.value.filterNotNull().distinct() } - .map { (k, v) -> - InheritanceNode( - DRI.from(k), - v.map { InheritanceNode(DRI.from(it)) }, - k.typeConstructor.supertypes.map { getClassDescriptorForType(it) } - .mapNotNull { cd -> cd.takeIf { it.kind == ClassKind.INTERFACE }?.let { DRI.from(it) } }, - isInterface = k.kind == ClassKind.INTERFACE - ) - } - - return psiInheritanceTree + descriptorInheritanceTree - } - - private fun gatherPsiClasses(psi: PsiClass): List<Pair<PsiClass, List<PsiClass>>> = psi.supers.toList().let { l -> - listOf(psi to l) + l.flatMap { gatherPsiClasses(it) } - } - - private fun getDescriptorMap(documentables: Map<DRI, Documentable>): Map<DRI, ClassDescriptor> { - val map: MutableMap<DRI, ClassDescriptor> = mutableMapOf() - documentables - .mapNotNull { (k, v) -> - v.descriptorForPlatform()?.let { k to it }?.also { (k, v) -> map[k] = v } - }.map { it.second }.forEach { gatherSupertypes(it, map) } - - return map.toMap() - } - - private fun gatherSupertypes(descriptor: ClassDescriptor, map: MutableMap<DRI, ClassDescriptor>) { - map.putIfAbsent(DRI.from(descriptor), descriptor) - descriptor.typeConstructor.supertypes.map { getClassDescriptorForType(it) } - .forEach { gatherSupertypes(it, map) } - } - - - private fun Documentable?.descriptorForPlatform(platform: Platform = Platform.jvm) = - (this as? WithSources).descriptorForPlatform(platform) - - private fun WithSources?.descriptorForPlatform(platform: Platform = Platform.jvm) = this?.let { - it.sources.entries.find { it.key.analysisPlatform == platform }?.value?.let { it as? DescriptorDocumentableSource }?.descriptor as? ClassDescriptor - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorKotlinToJavaMapper.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorKotlinToJavaMapper.kt deleted file mode 100644 index b022e0c3..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorKotlinToJavaMapper.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl - -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.analysis.kotlin.internal.KotlinToJavaService -import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName - -internal class DescriptorKotlinToJavaMapper : KotlinToJavaService { - - override fun findAsJava(kotlinDri: DRI): DRI? { - return kotlinDri.partialFqName().mapToJava()?.toDRI(kotlinDri) - } - - private fun DRI.partialFqName() = packageName?.let { "$it." } + classNames - - private fun String.mapToJava(): ClassId? = - JavaToKotlinClassMap.mapKotlinToJava(FqName(this).toUnsafe()) - - private fun ClassId.toDRI(dri: DRI?): DRI = DRI( - packageName = packageFqName.asString(), - classNames = classNames(), - callable = dri?.callable,//?.asJava(), TODO: check this - extra = null, - target = PointingToDeclaration - ) - - private fun ClassId.classNames(): String = - shortClassName.identifier + (outerClassId?.classNames()?.let { ".$it" } ?: "") -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorSyntheticDocumentableDetector.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorSyntheticDocumentableDetector.kt deleted file mode 100644 index d6768eca..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/DescriptorSyntheticDocumentableDetector.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DescriptorDocumentableSource -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.WithSources -import org.jetbrains.dokka.analysis.kotlin.internal.SyntheticDocumentableDetector -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor - -internal class DescriptorSyntheticDocumentableDetector : SyntheticDocumentableDetector { - override fun isSynthetic(documentable: Documentable, sourceSet: DokkaConfiguration.DokkaSourceSet): Boolean { - return isFakeOverride(documentable, sourceSet) || isSynthesized(documentable, sourceSet) - } - - private fun isFakeOverride(documentable: Documentable, sourceSet: DokkaConfiguration.DokkaSourceSet): Boolean { - return callableMemberDescriptorOrNull(documentable, sourceSet)?.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE - } - - private fun isSynthesized(documentable: Documentable, sourceSet: DokkaConfiguration.DokkaSourceSet): Boolean { - return callableMemberDescriptorOrNull(documentable, sourceSet)?.kind == CallableMemberDescriptor.Kind.SYNTHESIZED - } - - private fun callableMemberDescriptorOrNull( - documentable: Documentable, sourceSet: DokkaConfiguration.DokkaSourceSet - ): CallableMemberDescriptor? { - if (documentable is WithSources) { - return documentable.sources[sourceSet] - .let { it as? DescriptorDocumentableSource }?.descriptor as? CallableMemberDescriptor - } - - return null - } -} 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 deleted file mode 100644 index 5199abf5..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/KotlinSampleProvider.kt +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -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.dokka.plugability.DokkaPluginApiPreview -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 - -public class KotlinSampleProviderFactory( - public 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 -public open class KotlinSampleProvider( - public 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) { - @OptIn(DokkaPluginApiPreview::class) - 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) - } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/IllegalModuleAndPackageDocumentation.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/IllegalModuleAndPackageDocumentation.kt deleted file mode 100644 index 98eabf19..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/IllegalModuleAndPackageDocumentation.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -import org.jetbrains.dokka.DokkaException - -internal class IllegalModuleAndPackageDocumentation( - source: ModuleAndPackageDocumentationSource, message: String -) : DokkaException("[$source] $message") diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentation.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentation.kt deleted file mode 100644 index 9b352c1a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentation.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -import org.jetbrains.dokka.model.doc.DocumentationNode - -internal data class ModuleAndPackageDocumentation( - val name: String, - val classifier: Classifier, - val documentation: DocumentationNode -) { - enum class Classifier { Module, Package } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationFragment.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationFragment.kt deleted file mode 100644 index d1e729b2..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationFragment.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - - -internal data class ModuleAndPackageDocumentationFragment( - val name: String, - val classifier: ModuleAndPackageDocumentation.Classifier, - val documentation: String, - val source: ModuleAndPackageDocumentationSource -) diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationParsingContext.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationParsingContext.kt deleted file mode 100644 index 95701964..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationParsingContext.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KDocFinder -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentation.Classifier.Module -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentation.Classifier.Package -import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name - -internal fun interface ModuleAndPackageDocumentationParsingContext { - fun markdownParserFor(fragment: ModuleAndPackageDocumentationFragment, location: String): MarkdownParser -} - -internal fun ModuleAndPackageDocumentationParsingContext.parse( - fragment: ModuleAndPackageDocumentationFragment -): DocumentationNode { - return markdownParserFor(fragment, fragment.source.sourceDescription).parse(fragment.documentation) -} - -internal fun ModuleAndPackageDocumentationParsingContext( - logger: DokkaLogger, - moduleDescriptor: ModuleDescriptor? = null, - kDocFinder: KDocFinder? = null, - sourceSet: DokkaConfiguration.DokkaSourceSet? = null -) = ModuleAndPackageDocumentationParsingContext { fragment, sourceLocation -> - val descriptor = when (fragment.classifier) { - Module -> moduleDescriptor?.getPackage(FqName.topLevel(Name.identifier(""))) - Package -> moduleDescriptor?.getPackage(FqName(fragment.name)) - } - - val externalDri = { link: String -> - try { - if (kDocFinder != null && descriptor != null && sourceSet != null) { - with(kDocFinder) { - resolveKDocLink( - descriptor, - link, - sourceSet - ).sorted().firstOrNull()?.let { - DRI.from( - it - ) - } - } - } else null - } catch (e1: IllegalArgumentException) { - logger.warn("Couldn't resolve link for $link") - null - } - } - - MarkdownParser(externalDri = externalDri, sourceLocation) -} - -private fun Collection<DeclarationDescriptor>.sorted() = sortedWith( - compareBy( - { it is ClassDescriptor }, - { (it as? FunctionDescriptor)?.name }, - { (it as? FunctionDescriptor)?.valueParameters?.size }, - { (it as? FunctionDescriptor)?.valueParameters?.joinToString { it.type.toString() } } - ) -) diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationReader.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationReader.kt deleted file mode 100644 index e3697159..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationReader.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -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.analysis.kotlin.descriptors.compiler.configuration.KotlinAnalysis -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentation.Classifier -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.DPackage -import org.jetbrains.dokka.model.SourceSetDependent -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.doc.Deprecated -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.associateWithNotNull -import org.jetbrains.dokka.analysis.kotlin.internal.ModuleAndPackageDocumentationReader - -internal fun ModuleAndPackageDocumentationReader(context: DokkaContext): ModuleAndPackageDocumentationReader = - ContextModuleAndPackageDocumentationReader(context) - -private class ContextModuleAndPackageDocumentationReader( - private val context: DokkaContext -) : ModuleAndPackageDocumentationReader { - - private val kotlinAnalysis: KotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis } - private val kdocFinder: KDocFinder = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kdocFinder } - - private val documentationFragments: SourceSetDependent<List<ModuleAndPackageDocumentationFragment>> = - context.configuration.sourceSets.associateWith { sourceSet -> - sourceSet.includes.flatMap { include -> parseModuleAndPackageDocumentationFragments(include) } - } - - private fun findDocumentationNodes( - sourceSets: Set<DokkaConfiguration.DokkaSourceSet>, - predicate: (ModuleAndPackageDocumentationFragment) -> Boolean - ): SourceSetDependent<DocumentationNode> { - return sourceSets.associateWithNotNull { sourceSet -> - val fragments = documentationFragments[sourceSet].orEmpty().filter(predicate) - val moduleDescriptor = kotlinAnalysis[sourceSet].moduleDescriptor - val documentations = fragments.map { fragment -> - parseModuleAndPackageDocumentation( - context = ModuleAndPackageDocumentationParsingContext(context.logger, moduleDescriptor, kdocFinder, sourceSet), - fragment = fragment - ) - } - when (documentations.size) { - 0 -> null - 1 -> documentations.single().documentation - else -> DocumentationNode(documentations.flatMap { it.documentation.children } - .mergeDocumentationNodes()) - } - } - } - - private val ModuleAndPackageDocumentationFragment.canonicalPackageName: String - get() { - check(classifier == Classifier.Package) - if (name == "[root]") return "" - return name - } - - override fun read(module: DModule): SourceSetDependent<DocumentationNode> { - return findDocumentationNodes(module.sourceSets) { fragment -> - fragment.classifier == Classifier.Module && (fragment.name == module.name) - } - } - - override fun read(pkg: DPackage): SourceSetDependent<DocumentationNode> { - return findDocumentationNodes(pkg.sourceSets) { fragment -> - fragment.classifier == Classifier.Package && fragment.canonicalPackageName == pkg.dri.packageName - } - } - - override fun read(module: DokkaConfiguration.DokkaModuleDescription): DocumentationNode? { - val parsingContext = ModuleAndPackageDocumentationParsingContext(context.logger) - - val documentationFragment = module.includes - .flatMap { include -> parseModuleAndPackageDocumentationFragments(include) } - .firstOrNull { fragment -> fragment.classifier == Classifier.Module && fragment.name == module.name } - ?: return null - - val moduleDocumentation = parseModuleAndPackageDocumentation(parsingContext, documentationFragment) - return moduleDocumentation.documentation - } - - private fun List<TagWrapper>.mergeDocumentationNodes(): List<TagWrapper> = - groupBy { it::class }.values.map { - it.reduce { acc, tagWrapper -> - val newRoot = CustomDocTag( - acc.children + tagWrapper.children, - name = (tagWrapper as? NamedTagWrapper)?.name.orEmpty() - ) - when (acc) { - is See -> acc.copy(newRoot) - is Param -> acc.copy(newRoot) - is Throws -> acc.copy(newRoot) - is Sample -> acc.copy(newRoot) - is Property -> acc.copy(newRoot) - is CustomTagWrapper -> acc.copy(newRoot) - is Description -> acc.copy(newRoot) - is Author -> acc.copy(newRoot) - is Version -> acc.copy(newRoot) - is Since -> acc.copy(newRoot) - is Return -> acc.copy(newRoot) - is Receiver -> acc.copy(newRoot) - is Constructor -> acc.copy(newRoot) - is Deprecated -> acc.copy(newRoot) - is org.jetbrains.dokka.model.doc.Suppress -> acc.copy(newRoot) - } - } - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationSource.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationSource.kt deleted file mode 100644 index 7d717de6..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/ModuleAndPackageDocumentationSource.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -import java.io.File - -internal abstract class ModuleAndPackageDocumentationSource { - abstract val sourceDescription: String - abstract val documentation: String - override fun toString(): String = sourceDescription -} - -internal data class ModuleAndPackageDocumentationFile(private val file: File) : ModuleAndPackageDocumentationSource() { - override val sourceDescription: String = file.path - override val documentation: String by lazy(LazyThreadSafetyMode.PUBLICATION) { file.readText() } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentation.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentation.kt deleted file mode 100644 index 286d650a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentation.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -internal fun parseModuleAndPackageDocumentation( - context: ModuleAndPackageDocumentationParsingContext, - fragment: ModuleAndPackageDocumentationFragment -): ModuleAndPackageDocumentation { - return ModuleAndPackageDocumentation( - name = fragment.name, - classifier = fragment.classifier, - documentation = context.parse(fragment) - ) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentationFragments.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentationFragments.kt deleted file mode 100644 index 2b36225b..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/impl/moduledocs/parseModuleAndPackageDocumentationFragments.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs - -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentation.Classifier.Module -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.impl.moduledocs.ModuleAndPackageDocumentation.Classifier.Package -import java.io.File - -internal fun parseModuleAndPackageDocumentationFragments(source: File): List<ModuleAndPackageDocumentationFragment> { - return parseModuleAndPackageDocumentationFragments(ModuleAndPackageDocumentationFile(source)) -} - -internal fun parseModuleAndPackageDocumentationFragments( - source: ModuleAndPackageDocumentationSource -): List<ModuleAndPackageDocumentationFragment> { - val fragmentStrings = source.documentation.split(Regex("(|^)#\\s*(?=(Module|Package))")) - return fragmentStrings - .filter(String::isNotBlank) - .map { fragmentString -> parseModuleAndPackageDocFragment(source, fragmentString) } -} - -private fun parseModuleAndPackageDocFragment( - source: ModuleAndPackageDocumentationSource, - fragment: String -): ModuleAndPackageDocumentationFragment { - val firstLineAndDocumentation = fragment.split("\r\n", "\n", "\r", limit = 2) - val firstLine = firstLineAndDocumentation[0] - - val classifierAndName = firstLine.split(Regex("\\s+"), limit = 2) - - val classifier = when (classifierAndName[0].trim()) { - "Module" -> Module - "Package" -> Package - else -> throw IllegalStateException( - """Unexpected classifier: "${classifierAndName[0]}", expected either "Module" or "Package". - |For more information consult the specification: https://kotlinlang.org/docs/dokka-module-and-package-docs.html""".trimMargin() - ) - } - - if (classifierAndName.size != 2 && classifier == Module) { - throw IllegalModuleAndPackageDocumentation(source, "Missing Module name") - } - - val name = classifierAndName.getOrNull(1)?.trim().orEmpty() - if (classifier == Package && name.contains(Regex("\\s"))) { - throw IllegalModuleAndPackageDocumentation( - source, "Package name cannot contain whitespace in '$firstLine'" - ) - } - - return ModuleAndPackageDocumentationFragment( - name = name, - classifier = classifier, - documentation = firstLineAndDocumentation.getOrNull(1)?.trim().orEmpty(), - source = source - ) -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorDocumentationContent.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorDocumentationContent.kt deleted file mode 100644 index e8dcf63c..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorDocumentationContent.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import org.jetbrains.dokka.analysis.java.doccomment.DocumentationContent -import org.jetbrains.dokka.analysis.java.JavadocTag -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag - -internal data class DescriptorDocumentationContent( - val descriptor: DeclarationDescriptor, - val element: KDocTag, - override val tag: JavadocTag, -) : DocumentationContent { - override fun resolveSiblings(): List<DocumentationContent> { - return listOf(this) - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocComment.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocComment.kt deleted file mode 100644 index b6150ca5..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocComment.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import org.jetbrains.dokka.analysis.java.* -import org.jetbrains.dokka.analysis.java.doccomment.DocComment -import org.jetbrains.dokka.analysis.java.doccomment.DocumentationContent -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag - -internal class DescriptorKotlinDocComment( - val comment: KDocTag, - val descriptor: DeclarationDescriptor -) : DocComment { - - private val tagsWithContent: List<KDocTag> = comment.children.mapNotNull { (it as? KDocTag) } - - override fun hasTag(tag: JavadocTag): Boolean { - return when (tag) { - is DescriptionJavadocTag -> comment.getContent().isNotEmpty() - is ThrowingExceptionJavadocTag -> tagsWithContent.any { it.hasException(tag) } - else -> tagsWithContent.any { it.text.startsWith("@${tag.name}") } - } - } - - private fun KDocTag.hasException(tag: ThrowingExceptionJavadocTag) = - text.startsWith("@${tag.name}") && getSubjectName() == tag.exceptionQualifiedName - - override fun resolveTag(tag: JavadocTag): List<DocumentationContent> { - return when (tag) { - is DescriptionJavadocTag -> listOf(DescriptorDocumentationContent(descriptor, comment, tag)) - is ParamJavadocTag -> { - val resolvedContent = resolveGeneric(tag) - listOf(resolvedContent[tag.paramIndex]) - } - - is ThrowsJavadocTag -> resolveThrowingException(tag) - is ExceptionJavadocTag -> resolveThrowingException(tag) - else -> resolveGeneric(tag) - } - } - - private fun resolveThrowingException(tag: ThrowingExceptionJavadocTag): List<DescriptorDocumentationContent> { - val exceptionName = tag.exceptionQualifiedName ?: return resolveGeneric(tag) - - return comment.children - .filterIsInstance<KDocTag>() - .filter { it.name == tag.name && it.getSubjectName() == exceptionName } - .map { DescriptorDocumentationContent(descriptor, it, tag) } - } - - private fun resolveGeneric(tag: JavadocTag): List<DescriptorDocumentationContent> { - return comment.children.mapNotNull { element -> - if (element is KDocTag && element.name == tag.name) { - DescriptorDocumentationContent(descriptor, element, tag) - } else { - null - } - } - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as DescriptorKotlinDocComment - - if (comment != other.comment) return false - if (descriptor.name != other.descriptor.name) return false - if (tagsWithContent != other.tagsWithContent) return false - - return true - } - - override fun hashCode(): Int { - var result = comment.hashCode() - result = 31 * result + descriptor.name.hashCode() - result = 31 * result + tagsWithContent.hashCode() - return result - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentCreator.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentCreator.kt deleted file mode 100644 index 6beaac3f..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentCreator.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import com.intellij.psi.PsiNamedElement -import org.jetbrains.dokka.analysis.java.doccomment.DocComment -import org.jetbrains.dokka.analysis.java.doccomment.DocCommentCreator -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KDocFinder -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.DescriptorFinder -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtElement - -internal class DescriptorKotlinDocCommentCreator( - private val kdocFinder: KDocFinder, - private val descriptorFinder: DescriptorFinder -) : DocCommentCreator { - override fun create(element: PsiNamedElement): DocComment? { - val ktElement = element.navigationElement as? KtElement ?: return null - val kdoc = with (kdocFinder) { - ktElement.findKDoc() - } ?: return null - val descriptor = with (descriptorFinder) { - (element.navigationElement as? KtDeclaration)?.findDescriptor() - } ?: return null - - return DescriptorKotlinDocComment(kdoc, descriptor) - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentParser.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentParser.kt deleted file mode 100644 index 694ee5ac..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/DescriptorKotlinDocCommentParser.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import com.intellij.psi.PsiNamedElement -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.analysis.java.doccomment.DocComment -import org.jetbrains.dokka.analysis.java.parsers.DocCommentParser -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator.parseFromKDocTag -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.DokkaLogger - -internal class DescriptorKotlinDocCommentParser( - private val context: DokkaContext, - private val logger: DokkaLogger -) : DocCommentParser { - - override fun canParse(docComment: DocComment): Boolean { - return docComment is DescriptorKotlinDocComment - } - - override fun parse(docComment: DocComment, context: PsiNamedElement): DocumentationNode { - val kotlinDocComment = docComment as DescriptorKotlinDocComment - return parseDocumentation(kotlinDocComment) - } - - fun parseDocumentation(element: DescriptorKotlinDocComment, parseWithChildren: Boolean = true): DocumentationNode { - val sourceSet = context.configuration.sourceSets.let { sourceSets -> - sourceSets.firstOrNull { it.sourceSetID.sourceSetName == "jvmMain" } - ?: sourceSets.first { it.analysisPlatform == Platform.jvm } - } - val kdocFinder = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kdocFinder } - return parseFromKDocTag( - kDocTag = element.comment, - externalDri = { link: String -> - try { - kdocFinder.resolveKDocLink(element.descriptor, link, sourceSet) - .firstOrNull() - ?.let { DRI.from(it) } - } catch (e1: IllegalArgumentException) { - logger.warn("Couldn't resolve link for $link") - null - } - }, - kdocLocation = null, - parseWithChildren = parseWithChildren - ) - } -} - diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisProjectProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisProjectProvider.kt deleted file mode 100644 index 33ad025f..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisProjectProvider.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import com.intellij.openapi.project.Project -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.java.ProjectProvider -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle - -internal class KotlinAnalysisProjectProvider : ProjectProvider { - override fun getProject(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext): Project { - val kotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis } - return kotlinAnalysis[sourceSet].project - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisSourceRootsExtractor.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisSourceRootsExtractor.kt deleted file mode 100644 index 78b08f18..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinAnalysisSourceRootsExtractor.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.java.SourceRootsExtractor -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import java.io.File - -internal class KotlinAnalysisSourceRootsExtractor : SourceRootsExtractor { - - override fun extract(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext): List<File> { - val kotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis } - val environment = kotlinAnalysis[sourceSet].environment - return environment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) - ?.filterIsInstance<JavaSourceRoot>() - ?.mapNotNull { it.file.takeIf { isFileInSourceRoots(it, sourceSet) } } - ?: listOf() - } - - private fun isFileInSourceRoots(file: File, sourceSet: DokkaConfiguration.DokkaSourceSet): Boolean = - sourceSet.sourceRoots.any { root -> file.startsWith(root) } - -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinInheritDocTagContentProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinInheritDocTagContentProvider.kt deleted file mode 100644 index 40a12fe8..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/java/KotlinInheritDocTagContentProvider.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.java - -import org.jetbrains.dokka.analysis.java.doccomment.DocumentationContent -import org.jetbrains.dokka.analysis.java.JavaAnalysisPlugin -import org.jetbrains.dokka.analysis.java.parsers.doctag.DocTagParserContext -import org.jetbrains.dokka.analysis.java.parsers.doctag.InheritDocTagContentProvider -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.query - -internal class KotlinInheritDocTagContentProvider( - context: DokkaContext -) : InheritDocTagContentProvider { - - val parser: DescriptorKotlinDocCommentParser by lazy { - context.plugin<JavaAnalysisPlugin>().query { docCommentParsers } - .single { it is DescriptorKotlinDocCommentParser } as DescriptorKotlinDocCommentParser - } - - override fun canConvert(content: DocumentationContent): Boolean = content is DescriptorDocumentationContent - - override fun convertToHtml(content: DocumentationContent, docTagParserContext: DocTagParserContext): String { - val descriptorContent = content as DescriptorDocumentationContent - val inheritedDocNode = parser.parseDocumentation( - DescriptorKotlinDocComment(descriptorContent.element, descriptorContent.descriptor), - parseWithChildren = false - ) - val id = docTagParserContext.store(inheritedDocNode) - return """<inheritdoc id="$id"/>""" - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/CollectionExtensions.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/CollectionExtensions.kt deleted file mode 100644 index b08eecfc..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/CollectionExtensions.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5 -internal inline fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? { - for (element in this) { - val result = transform(element) - if (result != null) { - return result - } - } - return null -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt deleted file mode 100644 index 4d561189..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultDescriptorToDocumentableTranslator.kt +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiNamedElement -import com.intellij.psi.util.PsiLiteralUtil.* -import kotlinx.coroutines.* -import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet -import org.jetbrains.dokka.analysis.java.JavaAnalysisPlugin -import org.jetbrains.dokka.analysis.java.parsers.JavadocParser -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.AnalysisContext -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.DescriptorDocumentableSource -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.KotlinAnalysis -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.links.* -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.AnnotationTarget -import org.jetbrains.dokka.model.Nullable -import org.jetbrains.dokka.model.Visibility -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.properties.PropertyContainer -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.query -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator -import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.dokka.utilities.parallelMap -import org.jetbrains.dokka.utilities.parallelMapNotNull -import org.jetbrains.kotlin.KtNodeTypes -import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor -import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType -import org.jetbrains.kotlin.builtins.isExtensionFunctionType -import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype -import org.jetbrains.kotlin.codegen.isJvmStaticInObjectOrClassOrInterface -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.annotations.Annotated -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.descriptors.java.JavaVisibilities -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor -import org.jetbrains.kotlin.load.kotlin.toSourceElement -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.calls.components.isVararg -import org.jetbrains.kotlin.resolve.calls.util.getValueArgumentsInParentheses -import org.jetbrains.kotlin.resolve.constants.ConstantValue -import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.LocalClass -import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.NormalClass -import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull -import org.jetbrains.kotlin.resolve.descriptorUtil.parents -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinEnum -import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -import org.jetbrains.kotlin.resolve.source.PsiSourceElement -import org.jetbrains.kotlin.resolve.source.PsiSourceFile -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes -import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import java.nio.file.Paths -import org.jetbrains.kotlin.resolve.constants.AnnotationValue as ConstantsAnnotationValue -import org.jetbrains.kotlin.resolve.constants.ArrayValue as ConstantsArrayValue -import org.jetbrains.kotlin.resolve.constants.BooleanValue as ConstantsBooleanValue -import org.jetbrains.kotlin.resolve.constants.DoubleValue as ConstantsDoubleValue -import org.jetbrains.kotlin.resolve.constants.EnumValue as ConstantsEnumValue -import org.jetbrains.kotlin.resolve.constants.FloatValue as ConstantsFloatValue -import org.jetbrains.kotlin.resolve.constants.IntValue as ConstantsIntValue -import org.jetbrains.kotlin.resolve.constants.KClassValue as ConstantsKtClassValue -import org.jetbrains.kotlin.resolve.constants.LongValue as ConstantsLongValue -import org.jetbrains.kotlin.resolve.constants.NullValue as ConstantsNullValue -import org.jetbrains.kotlin.resolve.constants.UIntValue as ConstantsUIntValue -import org.jetbrains.kotlin.resolve.constants.ULongValue as ConstantsULongValue - -internal class DefaultDescriptorToDocumentableTranslator( - private val context: DokkaContext -) : AsyncSourceToDocumentableTranslator, ExternalClasslikesTranslator { - - private val kotlinAnalysis: KotlinAnalysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis } - private val kdocFinder: KDocFinder = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kdocFinder } - - override suspend fun invokeSuspending(sourceSet: DokkaSourceSet, context: DokkaContext): DModule { - val analysisContext = kotlinAnalysis[sourceSet] - val environment = analysisContext.environment - val packageFragments = environment.getSourceFiles().asSequence() - .map { it.packageFqName } - .distinct() - .mapNotNull { analysisContext.resolveSession.getPackageFragment(it) } - .toList() - - val javadocParser = JavadocParser( - docCommentParsers = context.plugin<JavaAnalysisPlugin>().query { docCommentParsers }, - docCommentFinder = context.plugin<JavaAnalysisPlugin>().docCommentFinder - ) - - - return DokkaDescriptorVisitor(sourceSet, kdocFinder, kotlinAnalysis[sourceSet], context.logger, javadocParser).run { - packageFragments.parallelMap { - visitPackageFragmentDescriptor( - it - ) - } - }.let { - DModule( - name = context.configuration.moduleName, - packages = it, - documentation = emptyMap(), - expectPresentInSet = null, - sourceSets = setOf(sourceSet) - ) - } - } - - /** - * Implementation note: it runs in a separated single thread due to existing support of coroutines (see #2936) - */ - @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) - override fun translateClassDescriptor(descriptor: ClassDescriptor, sourceSet: DokkaSourceSet): DClasslike { - val driInfo = DRI.from(descriptor.parents.first()).withEmptyInfo() - - val javadocParser = JavadocParser( - docCommentParsers = context.plugin<JavaAnalysisPlugin>().query { docCommentParsers }, - docCommentFinder = context.plugin<JavaAnalysisPlugin>().docCommentFinder - ) - - return newSingleThreadContext("Generating documentable model of classlike").use { coroutineContext -> // see https://github.com/Kotlin/dokka/issues/3151 - runBlocking(coroutineContext) { - DokkaDescriptorVisitor(sourceSet, kdocFinder, kotlinAnalysis[sourceSet], context.logger, javadocParser) - .visitClassDescriptor(descriptor, driInfo) - } - } - } -} - -internal data class DRIWithPlatformInfo( - val dri: DRI, - val actual: SourceSetDependent<DocumentableSource> -) - -internal fun DRI.withEmptyInfo() = DRIWithPlatformInfo(this, emptyMap()) - -private class DokkaDescriptorVisitor( - private val sourceSet: DokkaSourceSet, - private val kDocFinder: KDocFinder, - private val analysisContext: AnalysisContext, - private val logger: DokkaLogger, - private val javadocParser: JavadocParser -) { - private val syntheticDocProvider = SyntheticDescriptorDocumentationProvider(kDocFinder, sourceSet) - - private fun Collection<DeclarationDescriptor>.filterDescriptorsInSourceSet() = filter { - it.toSourceElement.containingFile.toString().let { path -> - path.isNotBlank() && sourceSet.sourceRoots.any { root -> - Paths.get(path).startsWith(root.toPath()) - } - } - } - - private fun <T> T.toSourceSetDependent() = if (this != null) mapOf(sourceSet to this) else emptyMap() - - suspend fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor): DPackage { - val name = descriptor.fqName.asString().takeUnless { it.isBlank() } ?: "" - val driWithPlatform = DRI(packageName = name).withEmptyInfo() - val scope = descriptor.getMemberScope() - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind(true) - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val typealiases = async { descriptorsWithKind.typealiases.visitTypealiases() } - - DPackage( - dri = driWithPlatform.dri, - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - typealiases = typealiases.await(), - documentation = descriptor.resolveDescriptorData(), - sourceSets = setOf(sourceSet) - ) - } - } - - suspend fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClasslike = - when (descriptor.kind) { - ClassKind.ENUM_CLASS -> enumDescriptor(descriptor, parent) - ClassKind.OBJECT -> objectDescriptor(descriptor, parent) - ClassKind.INTERFACE -> interfaceDescriptor(descriptor, parent) - ClassKind.ANNOTATION_CLASS -> annotationDescriptor(descriptor, parent) - else -> classDescriptor(descriptor, parent) - } - - private suspend fun interfaceDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DInterface { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val scope = descriptor.unsubstitutedMemberScope - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - val info = descriptor.resolveClassDescriptionData() - - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind() - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } } - - DInterface( - dri = driWithPlatform.dri, - name = descriptor.name.asString(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - sources = descriptor.createSources(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - supertypes = info.supertypes.toSourceSetDependent(), - documentation = info.docs, - generics = generics.await(), - companion = descriptor.companion(driWithPlatform), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()), - info.ancestry.exceptionInSupertypesOrNull() - ) - ) - } - } - - private suspend fun objectDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DObject { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val scope = descriptor.unsubstitutedMemberScope - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - val info = descriptor.resolveClassDescriptionData() - - - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind() - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - - DObject( - dri = driWithPlatform.dri, - name = descriptor.name.asString(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - sources = descriptor.createSources(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - supertypes = info.supertypes.toSourceSetDependent(), - documentation = info.docs, - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()), - info.ancestry.exceptionInSupertypesOrNull() - ) - ) - } - - - } - - private suspend fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnum { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - val info = descriptor.resolveClassDescriptionData() - - return coroutineScope { - val descriptorsWithKind = descriptor.getEnumDescriptorsWithKind() - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val constructors = - async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } - val entries = async { descriptorsWithKind.enumEntries.visitEnumEntries(driWithPlatform) } - - DEnum( - dri = driWithPlatform.dri, - name = descriptor.name.asString(), - entries = entries.await(), - constructors = constructors.await(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - sources = descriptor.createSources(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - supertypes = info.supertypes.toSourceSetDependent(), - documentation = info.docs, - companion = descriptor.companion(driWithPlatform), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()) - ) - ) - } - } - - private fun ClassDescriptor.getEnumDescriptorsWithKind(): DescriptorsWithKind { - val descriptorsWithKind = this.unsubstitutedMemberScope.getDescriptorsWithKind() - val staticScopeForKotlinEnum = (this.staticScope as? StaticScopeForKotlinEnum) ?: return descriptorsWithKind - - // synthetic declarations, such as `entries`, `values()` and `valueOf()`, - // are not present among real in-code declarationg - val contributedDescriptors = staticScopeForKotlinEnum.getContributedDescriptors { true } - return descriptorsWithKind.copy( - properties = descriptorsWithKind.properties + contributedDescriptors.filterIsInstance<PropertyDescriptor>(), - functions = descriptorsWithKind.functions + contributedDescriptors.filterIsInstance<FunctionDescriptor>() - ) - } - - private suspend fun visitEnumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnumEntry { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val scope = descriptor.unsubstitutedMemberScope - val isExpect = descriptor.isExpect - - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind() - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - - DEnumEntry( - dri = driWithPlatform.dri.withEnumEntryExtra(), - name = descriptor.name.asString(), - documentation = descriptor.resolveDescriptorData(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - sourceSets = setOf(sourceSet), - expectPresentInSet = sourceSet.takeIf { isExpect }, - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations() - ) - ) - } - } - - private suspend fun annotationDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DAnnotation { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val scope = descriptor.unsubstitutedMemberScope - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind() - - val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } } - val constructors = - async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } - - DAnnotation( - dri = driWithPlatform.dri, - name = descriptor.name.asString(), - documentation = descriptor.resolveDescriptorData(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations() - ), - companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - generics = generics.await(), - constructors = constructors.await(), - sources = descriptor.createSources() - ) - } - - - } - - private suspend fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClass { - val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() - val scope = descriptor.unsubstitutedMemberScope - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - val info = descriptor.resolveClassDescriptionData() - val actual = descriptor.createSources() - - return coroutineScope { - val descriptorsWithKind = scope.getDescriptorsWithKind() - - val (regularFunctions, accessors) = splitFunctionsAndInheritedAccessors( - properties = descriptorsWithKind.properties, - functions = descriptorsWithKind.functions - ) - - val functions = async { regularFunctions.visitFunctions(driWithPlatform) } - val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform, accessors) } - val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } } - val constructors = async { - descriptor.constructors.parallelMap { - visitConstructorDescriptor( - it, - if (it.isPrimary) DRIWithPlatformInfo(driWithPlatform.dri, actual) - else DRIWithPlatformInfo(driWithPlatform.dri, emptyMap()) - ) - } - } - - DClass( - dri = driWithPlatform.dri, - name = descriptor.name.asString(), - constructors = constructors.await(), - functions = functions.await(), - properties = properties.await(), - classlikes = classlikes.await(), - sources = actual, - expectPresentInSet = sourceSet.takeIf { isExpect }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - supertypes = info.supertypes.toSourceSetDependent(), - generics = generics.await(), - documentation = info.docs, - modifier = descriptor.modifier().toSourceSetDependent(), - companion = descriptor.companion(driWithPlatform), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - ImplementedInterfaces(info.ancestry.allImplementedInterfaces().toSourceSetDependent()), - info.ancestry.exceptionInSupertypesOrNull() - ) - ) - } - } - - /** - * @param implicitAccessors getters/setters that are not part of the property descriptor, for instance - * average methods inherited from java sources that access the property - */ - private suspend fun visitPropertyDescriptor( - originalDescriptor: PropertyDescriptor, - implicitAccessors: DescriptorAccessorHolder?, - parent: DRIWithPlatformInfo - ): DProperty { - val (dri, _) = originalDescriptor.createDRI() - val inheritedFrom = dri.getInheritedFromDRI(parent) - val descriptor = originalDescriptor.getConcreteDescriptor() - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - - val actual = originalDescriptor.createSources() - - // example - generated getter that comes with data classes - suspend fun getDescriptorGetter() = - descriptor.accessors - .firstIsInstanceOrNull<PropertyGetterDescriptor>() - ?.let { - visitPropertyAccessorDescriptor(it, descriptor, dri, inheritedFrom) - } - - suspend fun getImplicitAccessorGetter() = - implicitAccessors?.getter?.let { visitFunctionDescriptor(it, parent) } - - // example - generated setter that comes with data classes - suspend fun getDescriptorSetter() = - descriptor.accessors - .firstIsInstanceOrNull<PropertySetterDescriptor>() - ?.let { - visitPropertyAccessorDescriptor(it, descriptor, dri, inheritedFrom) - } - - suspend fun getImplicitAccessorSetter() = - implicitAccessors?.setter?.let { visitFunctionDescriptor(it, parent) } - - return coroutineScope { - val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } } - val getter = getDescriptorGetter() ?: getImplicitAccessorGetter() - val setter = getDescriptorSetter() ?: getImplicitAccessorSetter() - - DProperty( - dri = dri, - name = descriptor.name.asString(), - receiver = descriptor.extensionReceiverParameter?.let { - visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual)) - }, - sources = actual, - getter = getter, - setter = setter, - visibility = descriptor.getVisibility(implicitAccessors).toSourceSetDependent(), - documentation = descriptor.getDocumentation(), - modifier = descriptor.modifier().toSourceSetDependent(), - type = descriptor.returnType!!.toBound(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - sourceSets = setOf(sourceSet), - generics = generics.await(), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - listOfNotNull( - (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField() - .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(), - (descriptor.getAnnotationsWithBackingField() + descriptor.fileLevelAnnotations()).toSourceSetDependent() - .toAnnotations(), - descriptor.getDefaultValue()?.let { DefaultValue(it.toSourceSetDependent()) }, - inheritedFrom?.let { InheritedMember(it.toSourceSetDependent()) }, - takeIf { descriptor.isVar(getter, setter) }?.let { IsVar }, - takeIf { descriptor.findPsi() is KtParameter }?.let { IsAlsoParameter(listOf(sourceSet)) } - ) - ) - ) - } - } - - private fun PropertyDescriptor.isVar(getter: DFunction?, setter: DFunction?): Boolean { - return if (this is JavaPropertyDescriptor) { - // in Java, concepts of extensibility and mutability are mixed into a single `final` modifier - // in Kotlin, it's different - val/var controls mutability and open modifier controls extensibility - // so when inheriting Java properties, you can end up with a final var - non extensible mutable prop - val isMutable = this.isVar - // non-final java property should be var if it has no accessors at all or has a setter - (isMutable && getter == null && setter == null) || (getter != null && setter != null) - } else { - this.isVar - } - } - - private fun PropertyDescriptor.getVisibility(implicitAccessors: DescriptorAccessorHolder?): Visibility { - val isNonPublicJavaProperty = this is JavaPropertyDescriptor && !this.visibility.isPublicAPI - val visibility = - if (isNonPublicJavaProperty) { - // only try to take implicit getter's visibility if it's a java property - // because it's not guaranteed that implicit accessor will be used - // for the kotlin property, as it may have an explicit accessor of its own, - // i.e in data classes or with get() and set() are overridden - (implicitAccessors?.getter?.visibility ?: this.visibility) - } else { - this.visibility - } - - return visibility.toDokkaVisibility() - } - - private fun CallableMemberDescriptor.createDRI(wasOverridenBy: DRI? = null): Pair<DRI, DRI?> = - if (kind == CallableMemberDescriptor.Kind.DECLARATION || overriddenDescriptors.isEmpty()) - Pair(DRI.from(this), wasOverridenBy) - else - overriddenDescriptors.first().createDRI(DRI.from(this)) - - private suspend fun visitFunctionDescriptor( - originalDescriptor: FunctionDescriptor, - parent: DRIWithPlatformInfo - ): DFunction { - val (dri, _) = originalDescriptor.createDRI() - val inheritedFrom = dri.getInheritedFromDRI(parent) - val descriptor = originalDescriptor.getConcreteDescriptor() - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - - val actual = originalDescriptor.createSources() - return coroutineScope { - val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } } - - DFunction( - dri = dri, - name = descriptor.name.asString(), - isConstructor = false, - receiver = descriptor.extensionReceiverParameter?.let { - visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual)) - }, - parameters = descriptor.valueParameters.mapIndexed { index, desc -> - parameter(index, desc, DRIWithPlatformInfo(dri, actual)) - }, - expectPresentInSet = sourceSet.takeIf { isExpect }, - sources = actual, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - generics = generics.await(), - documentation = descriptor.getDocumentation(), - modifier = descriptor.modifier().toSourceSetDependent(), - type = descriptor.returnType!!.toBound(), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - inheritedFrom?.let { InheritedMember(it.toSourceSetDependent()) }, - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - (descriptor.getAnnotations() + descriptor.fileLevelAnnotations()).toSourceSetDependent() - .toAnnotations(), - ObviousMember.takeIf { descriptor.isObvious() }, - ) - ) - } - } - - private fun DeclarationDescriptor.getDocumentation(): SourceSetDependent<DocumentationNode> { - val isSynthesized = this is CallableMemberDescriptor && this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED - return if (isSynthesized) { - syntheticDocProvider.getDocumentation(this)?.toSourceSetDependent() ?: emptyMap() - } else { - this.resolveDescriptorData() - } - } - - /** - * `createDRI` returns the DRI of the exact element and potential DRI of an element that is overriding it - * (It can be also FAKE_OVERRIDE which is in fact just inheritance of the symbol) - * - * Looking at what PSIs do, they give the DRI of the element within the classnames where it is actually - * declared and inheritedFrom as the same DRI but truncated callable part. - * Therefore, we set callable to null and take the DRI only if it is indeed coming from different class. - */ - private fun DRI.getInheritedFromDRI(parent: DRIWithPlatformInfo): DRI? { - return this.copy(callable = null) - .takeIf { parent.dri.classNames != this.classNames || parent.dri.packageName != this.packageName } - } - - private fun FunctionDescriptor.isObvious(): Boolean { - return kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE - || (kind == CallableMemberDescriptor.Kind.SYNTHESIZED && !syntheticDocProvider.isDocumented(this)) - || containingDeclaration.fqNameOrNull()?.isObvious() == true - } - - private fun FqName.isObvious(): Boolean = with(this.asString()) { - return this == "kotlin.Any" || this == "kotlin.Enum" - || this == "java.lang.Object" || this == "java.lang.Enum" - } - - suspend fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): DFunction { - val name = descriptor.constructedClass.name.toString() - val dri = parent.dri.copy(callable = Callable.from(descriptor, name)) - val actual = descriptor.createSources() - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - - return coroutineScope { - val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } } - - DFunction( - dri = dri, - name = name, - isConstructor = true, - receiver = descriptor.extensionReceiverParameter?.let { - visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual)) - }, - parameters = descriptor.valueParameters.mapIndexed { index, desc -> - parameter(index, desc, DRIWithPlatformInfo(dri, actual)) - }, - sources = actual, - expectPresentInSet = sourceSet.takeIf { isExpect }, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - documentation = descriptor.resolveDescriptorData().let { sourceSetDependent -> - if (descriptor.isPrimary) { - sourceSetDependent.map { entry -> - Pair( - entry.key, - entry.value.copy(children = (entry.value.children.find { it is Constructor }?.root?.let { constructor -> - listOf(Description(constructor)) - } ?: emptyList<TagWrapper>()) + entry.value.children.filterIsInstance<Param>())) - }.toMap() - } else { - sourceSetDependent - } - }, - type = descriptor.returnType.toBound(), - modifier = descriptor.modifier().toSourceSetDependent(), - generics = generics.await(), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll<DFunction>( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations() - ).let { - if (descriptor.isPrimary) { - it + PrimaryConstructorExtra - } else it - } - ) - } - } - - private suspend fun visitReceiverParameterDescriptor( - descriptor: ReceiverParameterDescriptor, - parent: DRIWithPlatformInfo - ) = DParameter( - dri = parent.dri.copy(target = PointingToDeclaration), - name = null, - type = descriptor.type.toBound(), - expectPresentInSet = null, - documentation = descriptor.resolveDescriptorData(), - sourceSets = setOf(sourceSet), - extra = PropertyContainer.withAll(descriptor.getAnnotations().toSourceSetDependent().toAnnotations()) - ) - - private suspend fun visitPropertyAccessorDescriptor( - descriptor: PropertyAccessorDescriptor, - propertyDescriptor: PropertyDescriptor, - parent: DRI, - inheritedFrom: DRI? = null - ): DFunction { - val dri = parent.copy(callable = Callable.from(descriptor)) - val isGetter = descriptor is PropertyGetterDescriptor - val isExpect = descriptor.isExpect - val isActual = descriptor.isActual - - suspend fun PropertyDescriptor.asParameter(parent: DRI) = - DParameter( - parent.copy(target = PointingToCallableParameters(parameterIndex = 1)), - this.name.asString(), - type = this.type.toBound(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - documentation = descriptor.resolveDescriptorData(), - sourceSets = setOf(sourceSet), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations() - ) - ) - - val name = run { - val rawName = propertyDescriptor.name.asString() - /* - * Kotlin has special rules for conversion around properties that - * start with "is" For more info see: - * https://kotlinlang.org/docs/java-interop.html#getters-and-setters - * https://kotlinlang.org/docs/java-to-kotlin-interop.html#properties - * - * Based on our testing, this rule only applies when the letter after - * the "is" is *not* lowercase. This means that words like "issue" won't - * have the rule applied but "is_foobar" and "is1of" will have the rule applied. - */ - val specialCaseIs = rawName.startsWith("is") - && rawName.getOrNull(2)?.isLowerCase() == false - - if (specialCaseIs) { - if (isGetter) rawName else rawName.replaceFirst("is", "set") - } else { - if (isGetter) "get${rawName.capitalize()}" else "set${rawName.capitalize()}" - } - } - - val parameters = - if (isGetter) { - emptyList() - } else { - listOf(propertyDescriptor.asParameter(dri)) - } - - return coroutineScope { - val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } } - DFunction( - dri, - name, - isConstructor = false, - parameters = parameters, - visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), - documentation = descriptor.resolveDescriptorData().mapInheritedTagWrappers(), - type = descriptor.returnType!!.toBound(), - generics = generics.await(), - modifier = descriptor.modifier().toSourceSetDependent(), - expectPresentInSet = sourceSet.takeIf { isExpect }, - receiver = descriptor.extensionReceiverParameter?.let { - visitReceiverParameterDescriptor( - it, - DRIWithPlatformInfo(dri, descriptor.createSources()) - ) - }, - sources = descriptor.createSources(), - sourceSets = setOf(sourceSet), - isExpectActual = (isExpect || isActual), - extra = PropertyContainer.withAll( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - inheritedFrom?.let { InheritedMember(it.toSourceSetDependent()) } - ) - ) - } - } - - /** - * Workaround for a problem with inheriting parent TagWrappers of the wrong type. - * - * For instance, if you annotate a class with `@property`, kotlin compiler will propagate - * this tag to the property and its getters and setters. In case of getters and setters, - * it's more correct to display propagated docs as description instead of property - */ - private fun SourceSetDependent<DocumentationNode>.mapInheritedTagWrappers(): SourceSetDependent<DocumentationNode> { - return this.mapValues { (_, value) -> - val mappedChildren = value.children.map { - when (it) { - is Property -> Description(it.root) - else -> it - } - } - value.copy(children = mappedChildren) - } - } - - private suspend fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor) = - with(descriptor) { - coroutineScope { - val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } } - val info = buildAncestryInformation(defaultType).copy( - superclass = buildAncestryInformation(underlyingType), - interfaces = emptyList() - ) - DTypeAlias( - dri = DRI.from(this@with), - name = name.asString(), - type = defaultType.toBound(), - expectPresentInSet = null, - underlyingType = underlyingType.toBound().toSourceSetDependent(), - visibility = visibility.toDokkaVisibility().toSourceSetDependent(), - documentation = resolveDescriptorData(), - sourceSets = setOf(sourceSet), - generics = generics.await(), - sources = descriptor.createSources(), - extra = PropertyContainer.withAll( - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - info.exceptionInSupertypesOrNull(), - ) - ) - } - } - - private suspend fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) = - DParameter( - dri = parent.dri.copy(target = PointingToCallableParameters(index)), - name = descriptor.name.asString(), - type = descriptor.varargElementType?.toBound() ?: descriptor.type.toBound(), - expectPresentInSet = null, - documentation = descriptor.resolveDescriptorData(), - sourceSets = setOf(sourceSet), - extra = PropertyContainer.withAll(listOfNotNull( - descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - descriptor.getDefaultValue()?.let { DefaultValue(it.toSourceSetDependent()) } - )) - ) - - private data class DescriptorsWithKind( - val functions: List<FunctionDescriptor>, - val properties: List<PropertyDescriptor>, - val classlikes: List<ClassDescriptor>, - val typealiases: List<TypeAliasDescriptor>, - val enumEntries: List<ClassDescriptor> - ) - - private fun MemberScope.getDescriptorsWithKind(shouldFilter: Boolean = false): DescriptorsWithKind { - val descriptors = getContributedDescriptors { true }.let { - if (shouldFilter) it.filterDescriptorsInSourceSet() else it - } - - class EnumEntryDescriptor - - val groupedDescriptors = descriptors.groupBy { - when { - it is FunctionDescriptor -> FunctionDescriptor::class - it is PropertyDescriptor -> PropertyDescriptor::class - it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY -> ClassDescriptor::class - it is TypeAliasDescriptor -> TypeAliasDescriptor::class - it is ClassDescriptor && it.kind == ClassKind.ENUM_ENTRY -> EnumEntryDescriptor::class - else -> IllegalStateException::class - } - } - - @Suppress("UNCHECKED_CAST") - return DescriptorsWithKind( - (groupedDescriptors[FunctionDescriptor::class] ?: emptyList()) as List<FunctionDescriptor>, - (groupedDescriptors[PropertyDescriptor::class] ?: emptyList()) as List<PropertyDescriptor>, - (groupedDescriptors[ClassDescriptor::class] ?: emptyList()) as List<ClassDescriptor>, - (groupedDescriptors[TypeAliasDescriptor::class] ?: emptyList()) as List<TypeAliasDescriptor>, - (groupedDescriptors[EnumEntryDescriptor::class] ?: emptyList()) as List<ClassDescriptor> - ) - } - - private suspend fun List<FunctionDescriptor>.visitFunctions(parent: DRIWithPlatformInfo): List<DFunction> = - coroutineScope { parallelMap { visitFunctionDescriptor(it, parent) } } - - private suspend fun List<PropertyDescriptor>.visitProperties( - parent: DRIWithPlatformInfo, - implicitAccessors: Map<PropertyDescriptor, DescriptorAccessorHolder> = emptyMap(), - ): List<DProperty> { - return coroutineScope { - parallelMap { - visitPropertyDescriptor(it, implicitAccessors[it], parent) - } - } - } - - private suspend fun List<ClassDescriptor>.visitClasslikes(parent: DRIWithPlatformInfo): List<DClasslike> = - coroutineScope { parallelMap { visitClassDescriptor(it, parent) } } - - private suspend fun List<TypeAliasDescriptor>.visitTypealiases(): List<DTypeAlias> = - coroutineScope { parallelMap { visitTypeAliasDescriptor(it) } } - - private suspend fun List<ClassDescriptor>.visitEnumEntries(parent: DRIWithPlatformInfo): List<DEnumEntry> = - coroutineScope { parallelMap { visitEnumEntryDescriptor(it, parent) } } - - private fun DeclarationDescriptor.resolveDescriptorData(): SourceSetDependent<DocumentationNode> = - resolveDocumentation()?.toSourceSetDependent() ?: emptyMap() - - - private suspend fun toTypeConstructor(kt: KotlinType) = - GenericTypeConstructor( - DRI.from(kt.constructor.declarationDescriptor as DeclarationDescriptor), - kt.arguments.map { it.toProjection() }, - extra = PropertyContainer.withAll(kt.getAnnotations().toSourceSetDependent().toAnnotations()) - ) - - private suspend fun buildAncestryInformation( - kotlinType: KotlinType - ): AncestryNode { - val (interfaces, superclass) = kotlinType.immediateSupertypes().filterNot { it.isAnyOrNullableAny() } - .partition { - val declaration = it.constructor.declarationDescriptor - val descriptor = declaration as? ClassDescriptor - ?: (declaration as? TypeAliasDescriptor)?.underlyingType?.constructor?.declarationDescriptor as? ClassDescriptor - descriptor?.kind == ClassKind.INTERFACE - } - - return coroutineScope { - AncestryNode( - typeConstructor = toTypeConstructor(kotlinType), - superclass = superclass.parallelMap(::buildAncestryInformation).singleOrNull(), - interfaces = interfaces.parallelMap(::buildAncestryInformation) - ) - } - } - - - private suspend fun ClassDescriptor.resolveClassDescriptionData(): ClassInfo { - return coroutineScope { - ClassInfo( - buildAncestryInformation(this@resolveClassDescriptionData.defaultType), - resolveDescriptorData() - ) - } - } - - private suspend fun TypeParameterDescriptor.toVariantTypeParameter() = - DTypeParameter( - variantTypeParameter( - TypeParameter(DRI.from(this), name.identifier, annotations.getPresentableName()) - ), - resolveDescriptorData(), - null, - upperBounds.map { it.toBound() }, - setOf(sourceSet), - extra = PropertyContainer.withAll( - additionalExtras().toSourceSetDependent().toAdditionalModifiers(), - getAnnotations().toSourceSetDependent().toAnnotations() - ) - ) - - private fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? = - mapNotNull { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name") - .let { it as? StringValue }?.value?.let { unquotedValue(it) } - - private suspend fun KotlinType.toBound(): Bound { - suspend fun <T : AnnotationTarget> annotations(): PropertyContainer<T> = - getAnnotations().takeIf { it.isNotEmpty() }?.let { annotations -> - PropertyContainer.withAll(annotations.toSourceSetDependent().toAnnotations()) - } ?: PropertyContainer.empty() - - return when (this) { - is DynamicType -> Dynamic - is AbbreviatedType -> TypeAliased( - abbreviation.toBound(), - expandedType.toBound(), - annotations() - ) - is DefinitelyNotNullType -> DefinitelyNonNullable( - original.toBound() - ) - else -> when (val ctor = constructor.declarationDescriptor) { - is TypeParameterDescriptor -> TypeParameter( - dri = DRI.from(ctor), - name = ctor.name.asString(), - presentableName = annotations.getPresentableName(), - extra = annotations() - ) - is FunctionClassDescriptor -> FunctionalTypeConstructor( - DRI.from(ctor), - arguments.map { it.toProjection() }, - isExtensionFunction = isExtensionFunctionType || isBuiltinExtensionFunctionalType, - isSuspendable = isSuspendFunctionTypeOrSubtype, - presentableName = annotations.getPresentableName(), - extra = annotations() - ) - else -> GenericTypeConstructor( - DRI.from(ctor!!), // TODO: remove '!!' - arguments.map { it.toProjection() }, - annotations.getPresentableName(), - extra = annotations() - ) - }.let { - if (isMarkedNullable) Nullable(it) else it - } - } - } - - private suspend fun TypeProjection.toProjection(): Projection = - if (isStarProjection) Star else formPossiblyVariant() - - private suspend fun TypeProjection.formPossiblyVariant(): Projection = - type.toBound().wrapWithVariance(projectionKind) - - private fun TypeParameterDescriptor.variantTypeParameter(type: TypeParameter) = - type.wrapWithVariance(variance) - - private fun <T : Bound> T.wrapWithVariance(variance: org.jetbrains.kotlin.types.Variance) = - when (variance) { - org.jetbrains.kotlin.types.Variance.INVARIANT -> Invariance(this) - org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Contravariance(this) - org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Covariance(this) - } - - private fun descriptorToAnyDeclaration(descriptor: DeclarationDescriptor): PsiElement? { - val effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(descriptor) - //take any - return effectiveReferencedDescriptors.firstOrNull()?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) } - } - - private fun DeclarationDescriptor.resolveDocumentation(): DocumentationNode? { - val find = with(kDocFinder) { - find(::descriptorToAnyDeclaration) - } - - return (find?.let { - parseFromKDocTag( - kDocTag = it, - externalDri = { link: String -> - try { - val kdocLink = with(kDocFinder) { - resolveKDocLink( - fromDescriptor = this@resolveDocumentation, - qualifiedName = link, - sourceSet = sourceSet - ) - } - kdocLink.firstOrNull()?.let { - DRI.from( - it - ) - } - } catch (e1: IllegalArgumentException) { - logger.warn("Couldn't resolve link for $link") - null - } - }, - kdocLocation = toSourceElement.containingFile.name?.let { - val fqName = fqNameOrNull()?.asString() - if (fqName != null) "$it/$fqName" - else it - } - ) - } ?: getJavaDocs())?.takeIf { it.children.isNotEmpty() } - } - - private fun DeclarationDescriptor.getJavaDocs(): DocumentationNode? { - val overriddenDescriptors = (this as? CallableDescriptor)?.overriddenDescriptors ?: emptyList() - val allDescriptors = overriddenDescriptors + listOf(this) - return allDescriptors - .mapNotNull { it.findPsi() as? PsiNamedElement } - .firstOrNull() - ?.let { javadocParser.parseDocumentation(it) } - } - - private suspend fun ClassDescriptor.companion(dri: DRIWithPlatformInfo): DObject? = companionObjectDescriptor?.let { - objectDescriptor(it, dri) - } - - private fun MemberDescriptor.modifier() = when (modality) { - Modality.FINAL -> KotlinModifier.Final - Modality.SEALED -> KotlinModifier.Sealed - Modality.OPEN -> KotlinModifier.Open - Modality.ABSTRACT -> KotlinModifier.Abstract - else -> KotlinModifier.Empty - } - - private fun MemberDescriptor.createSources(): SourceSetDependent<DocumentableSource> = - DescriptorDocumentableSource(this).toSourceSetDependent() - - private fun FunctionDescriptor.additionalExtras() = listOfNotNull( - ExtraModifiers.KotlinOnlyModifiers.Infix.takeIf { isInfix }, - ExtraModifiers.KotlinOnlyModifiers.Inline.takeIf { isInline }, - ExtraModifiers.KotlinOnlyModifiers.Suspend.takeIf { isSuspend }, - ExtraModifiers.KotlinOnlyModifiers.Operator.takeIf { isOperator }, - ExtraModifiers.JavaOnlyModifiers.Static.takeIf { isJvmStaticInObjectOrClassOrInterface() }, - ExtraModifiers.KotlinOnlyModifiers.TailRec.takeIf { isTailrec }, - ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal }, - ExtraModifiers.KotlinOnlyModifiers.Override.takeIf { DescriptorUtils.isOverride(this) } - ).toSet() - - private fun ClassDescriptor.additionalExtras() = listOfNotNull( - ExtraModifiers.KotlinOnlyModifiers.Inline.takeIf { isInline }, - ExtraModifiers.KotlinOnlyModifiers.Value.takeIf { isValue }, - ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal }, - ExtraModifiers.KotlinOnlyModifiers.Inner.takeIf { isInner }, - ExtraModifiers.KotlinOnlyModifiers.Data.takeIf { isData }, - ExtraModifiers.KotlinOnlyModifiers.Fun.takeIf { isFun }, - ).toSet() - - private fun ValueParameterDescriptor.additionalExtras() = listOfNotNull( - ExtraModifiers.KotlinOnlyModifiers.NoInline.takeIf { isNoinline }, - ExtraModifiers.KotlinOnlyModifiers.CrossInline.takeIf { isCrossinline }, - ExtraModifiers.KotlinOnlyModifiers.Const.takeIf { isConst }, - ExtraModifiers.KotlinOnlyModifiers.LateInit.takeIf { isLateInit }, - ExtraModifiers.KotlinOnlyModifiers.VarArg.takeIf { isVararg } - ).toSet() - - private fun TypeParameterDescriptor.additionalExtras() = listOfNotNull( - ExtraModifiers.KotlinOnlyModifiers.Reified.takeIf { isReified } - ).toSet() - - private fun PropertyDescriptor.additionalExtras() = listOfNotNull( - ExtraModifiers.KotlinOnlyModifiers.Const.takeIf { isConst }, - ExtraModifiers.KotlinOnlyModifiers.LateInit.takeIf { isLateInit }, - ExtraModifiers.JavaOnlyModifiers.Static.takeIf { isJvmStaticInObjectOrClassOrInterface() }, - ExtraModifiers.KotlinOnlyModifiers.External.takeIf { isExternal }, - ExtraModifiers.KotlinOnlyModifiers.Override.takeIf { DescriptorUtils.isOverride(this) } - ) - - private suspend fun Annotated.getAnnotations() = annotations.parallelMapNotNull { it.toAnnotation() } - - private fun ConstantValue<*>.toValue(): AnnotationParameterValue = when (this) { - is ConstantsAnnotationValue -> AnnotationValue(value.toAnnotation()) - is ConstantsArrayValue -> ArrayValue(value.map { it.toValue() }) - is ConstantsEnumValue -> EnumValue( - fullEnumEntryName(), - DRI(enumClassId.packageFqName.asString(), fullEnumEntryName()) - ) - is ConstantsKtClassValue -> when (val value = value) { - is NormalClass -> value.classId.let { - ClassValue( - it.relativeClassName.asString(), - DRI(it.packageFqName.asString(), it.relativeClassName.asString()) - ) - } - is LocalClass -> value.type.let { - ClassValue( - it.toString(), - DRI.from(it.constructor.declarationDescriptor as DeclarationDescriptor) - ) - } - } - is ConstantsFloatValue -> FloatValue(value) - is ConstantsDoubleValue -> DoubleValue(value) - is ConstantsUIntValue -> IntValue(value) - is ConstantsULongValue -> LongValue(value) - is ConstantsIntValue -> IntValue(value) - is ConstantsLongValue -> LongValue(value) - is ConstantsBooleanValue -> BooleanValue(value) - is ConstantsNullValue -> NullValue - else -> StringValue(unquotedValue(toString())) - } - - private fun AnnotationDescriptor.toAnnotation(scope: Annotations.AnnotationScope = Annotations.AnnotationScope.DIRECT): Annotations.Annotation = - Annotations.Annotation( - DRI.from(annotationClass as DeclarationDescriptor), - allValueArguments.map { it.key.asString() to it.value.toValue() }.toMap(), - mustBeDocumented(), - scope - ) - - private fun AnnotationDescriptor.mustBeDocumented(): Boolean = - if (source.toString() == "NO_SOURCE") false - else annotationClass?.annotations?.hasAnnotation(FqName("kotlin.annotation.MustBeDocumented")) ?: false - - private suspend fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> = - getAnnotations() + (backingField?.getAnnotations() ?: emptyList()) - - private fun List<Annotations.Annotation>.toAdditionalExtras() = mapNotNull { - try { - ExtraModifiers.valueOf(it.dri.classNames?.toLowerCase() ?: "") - } catch (e: IllegalArgumentException) { - null - } - } - - private fun <T : CallableMemberDescriptor> T.getConcreteDescriptor(): T { - return if (kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - this - } else { - @Suppress("UNCHECKED_CAST") - overriddenDescriptors.first().getConcreteDescriptor() as T - } - } - - private fun ValueParameterDescriptor.getDefaultValue(): Expression? = - ((source as? KotlinSourceElement)?.psi as? KtParameter)?.defaultValue?.toDefaultValueExpression() - - private fun PropertyDescriptor.getDefaultValue(): Expression? = - (source as? KotlinSourceElement)?.psi?.children?.firstIsInstanceOrNull<KtConstantExpression>() - ?.toDefaultValueExpression() - - private fun ClassDescriptor.getAppliedConstructorParameters() = - (source as PsiSourceElement).psi?.children?.flatMap { - (it as? KtInitializerList)?.initializersAsExpression().orEmpty() - }.orEmpty() - - private fun KtInitializerList.initializersAsExpression() = - initializers.firstIsInstanceOrNull<KtCallElement>() - ?.getValueArgumentsInParentheses() - ?.map { it.getArgumentExpression()?.toDefaultValueExpression() ?: ComplexExpression("") } - .orEmpty() - - private fun KtExpression.toDefaultValueExpression(): Expression? = when (node?.elementType) { - KtNodeTypes.INTEGER_CONSTANT -> parseLong(node?.text)?.let { IntegerConstant(it) } - KtNodeTypes.FLOAT_CONSTANT -> if (node?.text?.toLowerCase()?.endsWith('f') == true) - parseFloat(node?.text)?.let { FloatConstant(it) } - else parseDouble(node?.text)?.let { DoubleConstant(it) } - KtNodeTypes.BOOLEAN_CONSTANT -> BooleanConstant(node?.text == "true") - KtNodeTypes.STRING_TEMPLATE -> StringConstant(node.findChildByType(KtNodeTypes.LITERAL_STRING_TEMPLATE_ENTRY)?.text.orEmpty()) - else -> node?.text?.let { ComplexExpression(it) } - } - - private data class ClassInfo(val ancestry: AncestryNode, val docs: SourceSetDependent<DocumentationNode>) { - val supertypes: List<TypeConstructorWithKind> - get() = listOfNotNull(ancestry.superclass?.let { - it.typeConstructor.let { - TypeConstructorWithKind( - it, - KotlinClassKindTypes.CLASS - ) - } - }) + ancestry.interfaces.map { TypeConstructorWithKind(it.typeConstructor, KotlinClassKindTypes.INTERFACE) } - } - - private fun DescriptorVisibility.toDokkaVisibility(): Visibility = when (this.delegate) { - Visibilities.Public -> KotlinVisibility.Public - Visibilities.Protected -> KotlinVisibility.Protected - Visibilities.Internal -> KotlinVisibility.Internal - Visibilities.Private, Visibilities.PrivateToThis -> KotlinVisibility.Private - JavaVisibilities.ProtectedAndPackage -> KotlinVisibility.Protected - JavaVisibilities.ProtectedStaticVisibility -> KotlinVisibility.Protected - JavaVisibilities.PackageVisibility -> JavaVisibility.Default - else -> KotlinVisibility.Public - } - - private fun ConstantsEnumValue.fullEnumEntryName() = - "${this.enumClassId.relativeClassName.asString()}.${this.enumEntryName.identifier}" - - private fun DeclarationDescriptorWithSource.ktFile(): KtFile? = - (source.containingFile as? PsiSourceFile)?.psiFile as? KtFile - - private suspend fun DeclarationDescriptorWithSource.fileLevelAnnotations() = ktFile() - ?.let { file -> - analysisContext.resolveSession.getFileAnnotations(file) - } - ?.toList() - ?.parallelMap { it.toAnnotation(scope = Annotations.AnnotationScope.FILE) } - .orEmpty() - - private fun AncestryNode.exceptionInSupertypesOrNull(): ExceptionInSupertypes? = - typeConstructorsBeingExceptions().takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) } -} - diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultExternalDocumentablesProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultExternalDocumentablesProvider.kt deleted file mode 100644 index 006a990b..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DefaultExternalDocumentablesProvider.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.DClasslike -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.ExternalDocumentablesProvider -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.PackageViewDescriptor -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered - -internal class DefaultExternalDocumentablesProvider(context: DokkaContext) : ExternalDocumentablesProvider { - private val analysis = context.plugin<CompilerDescriptorAnalysisPlugin>().querySingle { kotlinAnalysis } - - private val translator: ExternalClasslikesTranslator = DefaultDescriptorToDocumentableTranslator(context) - - override fun findClasslike(dri: DRI, sourceSet: DokkaSourceSet): DClasslike? { - val pkg = dri.packageName?.let { FqName(it) } ?: FqName.ROOT - val names = dri.classNames?.split('.') ?: return null - - val packageDsc = analysis[sourceSet].moduleDescriptor.getPackage(pkg) - val classDsc = names.fold<String, DeclarationDescriptor?>(packageDsc) { dsc, name -> - dsc?.scope?.getDescriptorsFiltered { it.identifier == name } - ?.filterIsInstance<ClassDescriptor>() - ?.firstOrNull() - } - - return (classDsc as? ClassDescriptor)?.let { translator.translateClassDescriptor(it, sourceSet) } - } - - private val DeclarationDescriptor.scope: MemberScope - get() = when (this) { - is PackageViewDescriptor -> memberScope - is ClassDescriptor -> unsubstitutedMemberScope - else -> throw IllegalArgumentException("Unexpected type of descriptor: ${this::class}") - } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DescriptorAccessorConventionUtil.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DescriptorAccessorConventionUtil.kt deleted file mode 100644 index b350e035..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/DescriptorAccessorConventionUtil.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor -import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName -import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName - -internal data class DescriptorFunctionsHolder( - val regularFunctions: List<FunctionDescriptor>, - val accessors: Map<PropertyDescriptor, DescriptorAccessorHolder> -) - -internal data class DescriptorAccessorHolder( - val getter: FunctionDescriptor? = null, - val setter: FunctionDescriptor? = null -) - -/** - * Separate regular Kotlin/Java functions and inherited Java accessors - * to properly display properties inherited from Java. - * - * Take this example: - * ``` - * // java - * public class JavaClass { - * private int a = 1; - * public int getA() { return a; } - * public void setA(int a) { this.a = a; } - * } - * - * // kotlin - * class Bar : JavaClass() { - * fun foo() {} - * } - * ``` - * - * It should result in: - * - 1 regular function `foo` - * - Map a=[`getA`, `setA`] - */ -internal fun splitFunctionsAndInheritedAccessors( - properties: List<PropertyDescriptor>, - functions: List<FunctionDescriptor> -): DescriptorFunctionsHolder { - val (javaMethods, kotlinFunctions) = functions.partition { it is JavaMethodDescriptor } - if (javaMethods.isEmpty()) { - return DescriptorFunctionsHolder(regularFunctions = kotlinFunctions, emptyMap()) - } - - val propertiesByName = properties.associateBy { it.name.asString() } - val regularFunctions = ArrayList<FunctionDescriptor>(kotlinFunctions) - - val accessors = mutableMapOf<PropertyDescriptor, DescriptorAccessorHolder>() - javaMethods.forEach { function -> - val possiblePropertyNamesForFunction = function.toPossiblePropertyNames() - val property = possiblePropertyNamesForFunction.firstNotNullOfOrNull { propertiesByName[it] } - if (property != null && function.isAccessorFor(property)) { - accessors.compute(property) { prop, accessorHolder -> - if (function.isGetterFor(prop)) - accessorHolder?.copy(getter = function) ?: DescriptorAccessorHolder(getter = function) - else - accessorHolder?.copy(setter = function) ?: DescriptorAccessorHolder(setter = function) - } - } else { - regularFunctions.add(function) - } - } - - val accessorLookalikes = removeNonAccessorsReturning(accessors) - regularFunctions.addAll(accessorLookalikes) - - return DescriptorFunctionsHolder(regularFunctions, accessors) -} - -/** - * If a field has no getter, it's not accessible as a property from Kotlin's perspective, - * but it still might have a setter lookalike. In this case, this "setter" should be just a regular function - * - * @return removed elements - */ -private fun removeNonAccessorsReturning( - propertyAccessors: MutableMap<PropertyDescriptor, DescriptorAccessorHolder> -): List<FunctionDescriptor> { - val nonAccessors = mutableListOf<FunctionDescriptor>() - propertyAccessors.entries.removeIf { (_, accessors) -> - if (accessors.getter == null && accessors.setter != null) { - nonAccessors.add(accessors.setter) - true - } else { - false - } - } - return nonAccessors -} - -private fun FunctionDescriptor.toPossiblePropertyNames(): List<String> { - val stringName = this.name.asString() - return when { - JvmAbi.isSetterName(stringName) -> propertyNamesBySetMethodName(this.name).map { it.asString() } - JvmAbi.isGetterName(stringName) -> propertyNamesByGetMethod(this) - else -> listOf() - } -} - -private fun propertyNamesByGetMethod(functionDescriptor: FunctionDescriptor): List<String> { - val stringName = functionDescriptor.name.asString() - // In java, the convention for boolean property accessors is as follows: - // - `private boolean active;` - // - `private boolean isActive();` - // - // Whereas in Kotlin, because there are no explicit accessors, the convention is - // - `val isActive: Boolean` - // - // This makes it difficult to guess the name of the accessor property in case of Java - val javaPropName = if (functionDescriptor is JavaMethodDescriptor && JvmAbi.startsWithIsPrefix(stringName)) { - val javaPropName = stringName.removePrefix("is").let { newName -> - newName.replaceFirst(newName[0], newName[0].toLowerCase()) - } - javaPropName - } else { - null - } - val kotlinPropName = propertyNameByGetMethodName(functionDescriptor.name)?.asString() - return listOfNotNull(javaPropName, kotlinPropName) -} - -private fun FunctionDescriptor.isAccessorFor(property: PropertyDescriptor): Boolean { - return (this.isGetterFor(property) || this.isSetterFor(property)) - && !property.visibility.isPublicAPI - && this.visibility.isPublicAPI -} - -private fun FunctionDescriptor.isGetterFor(property: PropertyDescriptor): Boolean { - return this.returnType == property.returnType - && this.valueParameters.isEmpty() -} - -private fun FunctionDescriptor.isSetterFor(property: PropertyDescriptor): Boolean { - return this.valueParameters.size == 1 - && this.valueParameters[0].type == property.returnType -} - diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/ExternalClasslikesTranslator.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/ExternalClasslikesTranslator.kt deleted file mode 100644 index 7a305bc1..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/ExternalClasslikesTranslator.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet -import org.jetbrains.dokka.model.DClasslike -import org.jetbrains.kotlin.descriptors.ClassDescriptor - -/** - * Service translating [ClassDescriptor]s of symbols defined outside of documented project to [DClasslike]s. - */ -internal fun interface ExternalClasslikesTranslator { - fun translateClassDescriptor(descriptor: ClassDescriptor, sourceSet: DokkaSourceSet): DClasslike -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/KdocMarkdownParser.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/KdocMarkdownParser.kt deleted file mode 100644 index 7c304e39..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/KdocMarkdownParser.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import com.intellij.psi.PsiElement -import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser -import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser.Companion.fqDeclarationName -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.doc.Suppress -import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag -import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag - -internal fun parseFromKDocTag( - kDocTag: KDocTag?, - externalDri: (String) -> DRI?, - kdocLocation: String?, - parseWithChildren: Boolean = true -): DocumentationNode { - return if (kDocTag == null) { - DocumentationNode(emptyList()) - } else { - fun parseStringToDocNode(text: String) = - MarkdownParser(externalDri, kdocLocation).parseStringToDocNode(text) - - fun pointedLink(tag: KDocTag): DRI? = (parseStringToDocNode("[${tag.getSubjectName()}]")).let { - val link = it.children[0].children[0] - if (link is DocumentationLink) link.dri else null - } - - val allTags = - listOf(kDocTag) + if (kDocTag.canHaveParent() && parseWithChildren) getAllKDocTags(findParent(kDocTag)) else emptyList() - DocumentationNode( - allTags.map { - when (it.knownTag) { - null -> if (it.name == null) Description(parseStringToDocNode(it.getContent())) else CustomTagWrapper( - parseStringToDocNode(it.getContent()), - it.name!! - ) - KDocKnownTag.AUTHOR -> Author(parseStringToDocNode(it.getContent())) - KDocKnownTag.THROWS -> { - val dri = pointedLink(it) - Throws( - parseStringToDocNode(it.getContent()), - dri?.fqDeclarationName() ?: it.getSubjectName().orEmpty(), - dri, - ) - } - KDocKnownTag.EXCEPTION -> { - val dri = pointedLink(it) - Throws( - parseStringToDocNode(it.getContent()), - dri?.fqDeclarationName() ?: it.getSubjectName().orEmpty(), - dri - ) - } - KDocKnownTag.PARAM -> Param( - parseStringToDocNode(it.getContent()), - it.getSubjectName().orEmpty() - ) - KDocKnownTag.RECEIVER -> Receiver(parseStringToDocNode(it.getContent())) - KDocKnownTag.RETURN -> Return(parseStringToDocNode(it.getContent())) - KDocKnownTag.SEE -> { - val dri = pointedLink(it) - See( - parseStringToDocNode(it.getContent()), - dri?.fqDeclarationName() ?: it.getSubjectName().orEmpty(), - dri, - ) - } - KDocKnownTag.SINCE -> Since(parseStringToDocNode(it.getContent())) - KDocKnownTag.CONSTRUCTOR -> Constructor(parseStringToDocNode(it.getContent())) - KDocKnownTag.PROPERTY -> Property( - parseStringToDocNode(it.getContent()), - it.getSubjectName().orEmpty() - ) - KDocKnownTag.SAMPLE -> Sample( - parseStringToDocNode(it.getContent()), - it.getSubjectName().orEmpty() - ) - KDocKnownTag.SUPPRESS -> Suppress(parseStringToDocNode(it.getContent())) - } - } - ) - } -} - -//Horrible hack but since link resolution is passed as a function i am not able to resolve them otherwise -@kotlin.Suppress("DeprecatedCallableAddReplaceWith") -@Deprecated("This function makes wrong assumptions and is missing a lot of corner cases related to generics, " + - "parameters and static members. This is not supposed to be public API and will not be supported in the future") -internal fun DRI.fqName(): String? = "$packageName.$classNames".takeIf { packageName != null && classNames != null } - -private fun findParent(kDoc: PsiElement): PsiElement = - if (kDoc.canHaveParent()) findParent(kDoc.parent) else kDoc - -private fun PsiElement.canHaveParent(): Boolean = this is KDocSection && knownTag != KDocKnownTag.PROPERTY - -private fun getAllKDocTags(kDocImpl: PsiElement): List<KDocTag> = - kDocImpl.children.filterIsInstance<KDocTag>().filterNot { it is KDocSection } + kDocImpl.children.flatMap { - getAllKDocTags(it) - } diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt deleted file mode 100644 index cff24590..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/SyntheticDescriptorDocumentationProvider.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.KDocFinder -import org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.configuration.from -import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.resolve.DescriptorFactory -import org.jetbrains.kotlin.resolve.DescriptorUtils - -private const val ENUM_ENTRIES_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumEntries.kt.template" -private const val ENUM_VALUEOF_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumValueOf.kt.template" -private const val ENUM_VALUES_TEMPLATE_PATH = "/dokka/docs/kdoc/EnumValues.kt.template" - -internal class SyntheticDescriptorDocumentationProvider( - private val kDocFinder: KDocFinder, - private val sourceSet: DokkaConfiguration.DokkaSourceSet -) { - fun isDocumented(descriptor: DeclarationDescriptor): Boolean { - return when(descriptor) { - is PropertyDescriptor -> descriptor.isEnumEntries() - is FunctionDescriptor -> { - DescriptorFactory.isEnumValuesMethod(descriptor) || DescriptorFactory.isEnumValueOfMethod(descriptor) - } - else -> false - } - } - - private fun PropertyDescriptor.isEnumEntries(): Boolean { - return this.name == StandardNames.ENUM_ENTRIES - && this.kind == CallableMemberDescriptor.Kind.SYNTHESIZED - && DescriptorUtils.isEnumClass(this.containingDeclaration) - } - - fun getDocumentation(descriptor: DeclarationDescriptor): DocumentationNode? { - return when(descriptor) { - is PropertyDescriptor -> descriptor.getDocumentation() - is FunctionDescriptor -> descriptor.getDocumentation() - else -> null - } - } - - private fun PropertyDescriptor.getDocumentation(): DocumentationNode? { - return when { - this.isEnumEntries() -> loadTemplate(this, ENUM_ENTRIES_TEMPLATE_PATH) - else -> null - } - } - - private fun FunctionDescriptor.getDocumentation(): DocumentationNode? { - return when { - DescriptorFactory.isEnumValuesMethod(this) -> loadTemplate(this, ENUM_VALUES_TEMPLATE_PATH) - DescriptorFactory.isEnumValueOfMethod(this) -> loadTemplate(this, ENUM_VALUEOF_TEMPLATE_PATH) - else -> null - } - } - - private fun loadTemplate(descriptor: DeclarationDescriptor, filePath: String): DocumentationNode? { - val kdoc = loadContent(filePath) ?: return null - val parser = MarkdownParser({ link -> resolveLink(descriptor, link)}, filePath) - return parser.parse(kdoc) - } - - private fun loadContent(filePath: String): String? = javaClass.getResource(filePath)?.readText() - - private fun resolveLink(descriptor: DeclarationDescriptor, link: String): DRI? = - kDocFinder.resolveKDocLink( - fromDescriptor = descriptor, - qualifiedName = link, - sourceSet = sourceSet - ).firstOrNull()?.let { DRI.from(it) } -} diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/annotationsValue.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/annotationsValue.kt deleted file mode 100644 index 6944ac1d..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/annotationsValue.kt +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -internal fun unquotedValue(value: String): String = value.removeSurrounding("\"") diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/isException.kt b/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/isException.kt deleted file mode 100644 index e484f37a..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/descriptors/compiler/translator/isException.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.translator - -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.AncestryNode -import org.jetbrains.dokka.model.TypeConstructor - -internal fun AncestryNode.typeConstructorsBeingExceptions(): List<TypeConstructor> { - fun traverseSupertypes(ancestry: AncestryNode): List<TypeConstructor> = - listOf(ancestry.typeConstructor) + (ancestry.superclass?.let(::traverseSupertypes) ?: emptyList()) - - return superclass?.let(::traverseSupertypes)?.filter { type -> type.dri.isDirectlyAnException() } ?: emptyList() -} - -internal fun DRI.isDirectlyAnException(): Boolean = - toString().let { stringed -> - stringed == "kotlin/Exception///PointingToDeclaration/" || - stringed == "java.lang/Exception///PointingToDeclaration/" - } diff --git a/subprojects/analysis-kotlin-descriptors/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/subprojects/analysis-kotlin-descriptors/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin deleted file mode 100644 index 0d7ee9f6..00000000 --- a/subprojects/analysis-kotlin-descriptors/compiler/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin +++ /dev/null @@ -1,5 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -org.jetbrains.dokka.analysis.kotlin.descriptors.compiler.CompilerDescriptorAnalysisPlugin |