aboutsummaryrefslogtreecommitdiff
path: root/kotlin-analysis/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'kotlin-analysis/src/main')
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt664
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CallableFactory.kt31
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreKotlinCacheService.kt42
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreProjectFileIndex.kt515
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt38
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRITargetFactory.kt44
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/Documentable.kt14
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt56
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/JavaResolveExtension.kt128
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/KotlinAnalysis.kt39
-rw-r--r--kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/TypeReferenceFactory.kt51
11 files changed, 1622 insertions, 0 deletions
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt
new file mode 100644
index 00000000..c39621f9
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/AnalysisEnvironment.kt
@@ -0,0 +1,664 @@
+package org.jetbrains.dokka.analysis
+
+import com.google.common.collect.ImmutableMap
+import com.intellij.core.CoreApplicationEnvironment
+import com.intellij.core.CoreModuleManager
+import com.intellij.mock.MockComponentManager
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.extensions.Extensions
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.module.ModuleManager
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.OrderEnumerationHandler
+import com.intellij.openapi.roots.ProjectFileIndex
+import com.intellij.openapi.roots.ProjectRootManager
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.vfs.StandardFileSystems
+import com.intellij.psi.PsiElement
+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.Platform
+import org.jetbrains.kotlin.analyzer.*
+import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
+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.caches.resolve.*
+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.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.container.getService
+import org.jetbrains.kotlin.container.tryGetService
+import org.jetbrains.kotlin.context.ProjectContext
+import org.jetbrains.kotlin.context.withModule
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
+import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
+import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor
+import org.jetbrains.kotlin.ide.konan.NativePlatformKindResolution
+import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.js.config.JSConfigurationKeys
+import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
+import org.jetbrains.kotlin.library.impl.createKotlinLibrary
+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.IdePlatformKind
+import org.jetbrains.kotlin.platform.TargetPlatform
+import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
+import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
+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.*
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.CompilerEnvironment
+import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
+import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
+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.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice
+import org.jetbrains.kotlin.util.slicedMap.WritableSlice
+import java.io.File
+
+const val JAR_SEPARATOR = "!/"
+const val KLIB_EXTENSION = "klib"
+
+/**
+ * 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
+ */
+class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPlatform: Platform) : Disposable {
+ val configuration = CompilerConfiguration()
+
+ init {
+ configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
+ }
+
+ fun createCoreEnvironment(): KotlinCoreEnvironment {
+ System.setProperty("idea.io.use.nio2", "true")
+
+ val configFiles = when (analysisPlatform) {
+ Platform.jvm, Platform.common -> EnvironmentConfigFiles.JVM_CONFIG_FILES
+ Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES
+ Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES
+ }
+
+ val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles)
+ val projectComponentManager = environment.project as MockComponentManager
+
+ val projectFileIndex = CoreProjectFileIndex(
+ environment.project,
+ environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)
+ )
+
+ val moduleManager = object : CoreModuleManager(environment.project, this) {
+ override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module)
+ }
+
+ CoreApplicationEnvironment.registerComponentInstance(
+ projectComponentManager.picoContainer,
+ ModuleManager::class.java, moduleManager
+ )
+
+ CoreApplicationEnvironment.registerExtensionPoint(
+ Extensions.getRootArea(),
+ OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java
+ )
+
+ CoreApplicationEnvironment.registerExtensionPoint(
+ environment.project.extensionArea,
+ JavadocTagInfo.EP_NAME, JavadocTagInfo::class.java
+ )
+
+ CoreApplicationEnvironment.registerExtensionPoint(
+ Extensions.getRootArea(),
+ CustomJavadocTagProvider.EP_NAME, CustomJavadocTagProvider::class.java
+ )
+
+ projectComponentManager.registerService(
+ ProjectFileIndex::class.java,
+ projectFileIndex
+ )
+
+ projectComponentManager.registerService(
+ ProjectRootManager::class.java,
+ CoreProjectRootManager(projectFileIndex)
+ )
+
+ projectComponentManager.registerService(
+ JavadocManager::class.java,
+ JavadocManagerImpl(environment.project)
+ )
+
+ projectComponentManager.registerService(
+ CustomJavadocTagProvider::class.java,
+ CustomJavadocTagProvider { emptyList() }
+ )
+
+ registerExtensionPoint(
+ ApplicationExtensionDescriptor("org.jetbrains.kotlin.idePlatformKind", IdePlatformKind::class.java),
+ listOf(
+ CommonIdePlatformKind,
+ JvmIdePlatformKind,
+ JsIdePlatformKind,
+ NativeIdePlatformKind
+ )
+ )
+
+ registerExtensionPoint(
+ IdePlatformKindResolution,
+ listOf(
+ CommonPlatformKindResolution(),
+ JvmPlatformKindResolution(),
+ JsPlatformKindResolution(),
+ NativePlatformKindResolution()
+ )
+ )
+
+ 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 -> GlobalSearchScope.filesScope(
+ project,
+ sourceFiles.map { it.virtualFile }.toSet()
+ )
+ }
+
+ fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> {
+ val projectContext = ProjectContext(environment.project, "Dokka")
+ val sourceFiles = environment.getSourceFiles()
+
+
+ val targetPlatform = when (analysisPlatform) {
+ Platform.js -> JsPlatforms.defaultJsPlatform
+ Platform.common -> CommonPlatforms.defaultCommonPlatform
+ Platform.native -> NativePlatforms.unspecifiedNativePlatform
+ Platform.jvm -> JvmPlatforms.defaultJvmPlatform
+ }
+
+ val nativeLibraries = classpath.filter { it.extension == KLIB_EXTENSION }
+ .map { createNativeLibraryModuleInfo(it) }
+
+ 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.filterNot { it.extension == KLIB_EXTENSION }.map { it.absolutePath }
+ }
+
+ 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) + nativeLibraries
+ }
+
+ 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))
+ in nativeLibraries -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope))
+ else -> 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,
+ library,
+ modulesContent,
+ environment
+ )
+ Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent)
+ Platform.native -> createNativeResolverForProject(projectContext, module, library, modulesContent)
+
+ }
+ val libraryModuleDescriptor = resolverForProject.descriptorForModule(library)
+ val moduleDescriptor = resolverForProject.descriptorForModule(module)
+ builtIns?.initialize(moduleDescriptor, true)
+
+ val resolverForLibrary =
+ resolverForProject.resolverForModule(library) // Required before module to initialize library properly
+ val resolverForModule = resolverForProject.resolverForModule(module)
+ val libraryResolutionFacade =
+ DokkaResolutionFacade(
+ environment.project,
+ libraryModuleDescriptor,
+ resolverForLibrary
+ )
+ val created =
+ DokkaResolutionFacade(
+ environment.project,
+ moduleDescriptor,
+ resolverForModule
+ )
+ val projectComponentManager = environment.project as MockComponentManager
+ projectComponentManager.registerService(KotlinCacheService::class.java,
+ CoreKotlinCacheService(created)
+ )
+
+ return created to libraryResolutionFacade
+ }
+
+ private fun Platform.analyzerServices() = when (this) {
+ Platform.js -> JsPlatformAnalyzerServices
+ Platform.common -> CommonPlatformAnalyzerServices
+ Platform.native -> NativePlatformAnalyzerServices
+ Platform.jvm -> JvmPlatformAnalyzerServices
+ }
+
+ private fun createNativeLibraryModuleInfo(libraryFile: File): LibraryModuleInfo {
+ val kotlinLibrary = createKotlinLibrary(org.jetbrains.kotlin.konan.file.File(libraryFile.absolutePath), "",false)
+ return object : LibraryModuleInfo {
+ override val analyzerServices: PlatformDependentAnalyzerServices =
+ analysisPlatform.analyzerServices()
+ override val name: Name = Name.special("<klib>")
+ override val platform: TargetPlatform = NativePlatforms.unspecifiedNativePlatform
+ override fun dependencies(): List<ModuleInfo> = listOf(this)
+ override fun getLibraryRoots(): Collection<String> = listOf(libraryFile.absolutePath)
+ override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
+ get() = super.capabilities + (KlibModuleOrigin.CAPABILITY to kotlinLibrary)
+ }
+ }
+
+ private fun createCommonResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>,
+ environment: KotlinCoreEnvironment
+ ): ResolverForProject<ModuleInfo> {
+ return object : AbstractResolverForProject<ModuleInfo>(
+ "Dokka",
+ projectContext,
+ modules = listOf(module, library)
+ ) {
+ override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null
+
+ 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 { content ->
+ environment.createPackagePartProvider(content.moduleContentScope)
+ },
+ CompilerEnvironment,
+ unspecifiedJvmPlatform,
+ true
+ ).createResolverForModule(
+ descriptor as ModuleDescriptorImpl,
+ projectContext.withModule(descriptor),
+ modulesContent(moduleInfo),
+ this,
+ LanguageVersionSettingsImpl.DEFAULT
+ )
+ }
+ }
+
+ private fun createJsResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>
+ ): ResolverForProject<ModuleInfo> {
+ return object : AbstractResolverForProject<ModuleInfo>(
+ "Dokka",
+ projectContext,
+ modules = listOf(module, library)
+ ) {
+ override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module)
+ override fun createResolverForModule(
+ descriptor: ModuleDescriptor,
+ moduleInfo: ModuleInfo
+ ): ResolverForModule = JsResolverForModuleFactory(
+ CompilerEnvironment
+ ).createResolverForModule(
+ descriptor as ModuleDescriptorImpl,
+ projectContext.withModule(descriptor),
+ modulesContent(moduleInfo),
+ this,
+ LanguageVersionSettingsImpl.DEFAULT
+ )
+
+ override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance
+
+ override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null
+ }
+ }
+
+ private fun createNativeResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ 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 NativeResolverForModuleFactory(
+ PlatformAnalysisParameters.Empty,
+ CompilerEnvironment,
+ NativePlatforms.unspecifiedNativePlatform
+ ).createResolverForModule(
+ descriptor as ModuleDescriptorImpl,
+ projectContext.withModule(descriptor),
+ modulesContent(moduleInfo),
+ this,
+ LanguageVersionSettingsImpl.DEFAULT
+ )
+ }
+
+ 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 {
+ val rootFile = when (it.extension) {
+ "jar" -> StandardFileSystems.jar().findFileByPath("${it.absolutePath}$JAR_SEPARATOR")
+ else -> StandardFileSystems.local().findFileByPath(it.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({ content ->
+ JvmPackagePartProvider(
+ configuration.languageVersionSettings,
+ content.moduleContentScope
+ )
+ .apply {
+ addRoots(javaRoots, messageCollector)
+ }
+ }, {
+ val file = (it as? BinaryJavaClass)?.virtualFile ?: (it as JavaClassImpl).psi.containingFile.virtualFile
+ if (file in sourcesScope)
+ module
+ else
+ library
+ }),
+ CompilerEnvironment,
+ unspecifiedJvmPlatform
+ ).createResolverForModule(
+ descriptor as ModuleDescriptorImpl,
+ projectContext.withModule(descriptor),
+ modulesContent(moduleInfo),
+ this,
+ LanguageVersionSettingsImpl.DEFAULT
+ )
+
+ override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null
+ }
+ }
+
+ 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, apiVersion)
+ }
+
+ /**
+ * Classpath for this environment.
+ */
+ val classpath: List<File>
+ get() = configuration.jvmClasspathRoots
+
+ /**
+ * Adds list of paths to classpath.
+ * $paths: collection of files to add
+ */
+ fun addClasspath(paths: List<File>) {
+ if (analysisPlatform == Platform.js) {
+ configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath })
+ }
+ configuration.addJvmClasspathRoots(paths)
+ }
+
+ /**
+ * Adds path to classpath.
+ * $path: path to add
+ */
+ fun addClasspath(path: File) {
+ if (analysisPlatform == Platform.js) {
+ configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath)
+ }
+ configuration.addJvmClasspathRoot(path)
+ }
+
+ /**
+ * List of source roots for this environment.
+ */
+ 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
+ */
+ fun addSources(list: List<String>) {
+ list.forEach {
+ configuration.addKotlinSourceRoot(it)
+ val file = File(it)
+ if (file.isDirectory || file.extension == ".java") {
+ configuration.addJavaSourceRoot(file)
+ }
+ }
+ }
+
+ 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)
+ }
+
+ companion object {
+ private fun <T : Any> registerExtensionPoint(
+ appExtension: ApplicationExtensionDescriptor<T>,
+ instances: List<T>
+ ) {
+ if (Extensions.getRootArea().hasExtensionPoint(appExtension.extensionPointName))
+ return
+
+ appExtension.registerExtensionPoint()
+ instances.forEach(appExtension::registerExtension)
+ }
+ }
+}
+
+fun contentRootFromPath(path: String): ContentRoot {
+ val file = File(path)
+ return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path, false)
+}
+
+
+class DokkaResolutionFacade(
+ override val project: Project,
+ override val moduleDescriptor: ModuleDescriptor,
+ val resolverForModule: ResolverForModule
+) : ResolutionFacade {
+ override fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>): AnalysisResult {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> tryGetFrontendService(element: PsiElement, serviceClass: Class<T>): T? {
+ return resolverForModule.componentProvider.tryGetService(serviceClass)
+ }
+
+ override fun resolveToDescriptor(
+ declaration: KtDeclaration,
+ bodyResolveMode: BodyResolveMode
+ ): DeclarationDescriptor {
+ return resolveSession.resolveToDescriptor(declaration)
+ }
+
+ override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext {
+ throw UnsupportedOperationException()
+ }
+
+ val resolveSession: ResolveSession get() = getFrontendService(ResolveSession::class.java)
+
+ override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext {
+ if (element is KtDeclaration) {
+ val descriptor = resolveToDescriptor(element)
+ return object : BindingContext {
+ override fun <K : Any?, V : Any?> getKeys(p0: WritableSlice<K, V>?): Collection<K> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getType(p0: KtExpression): KotlinType? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <K : Any?, V : Any?> get(slice: ReadOnlySlice<K, V>?, key: K): V? {
+ if (key != element) {
+ throw UnsupportedOperationException()
+ }
+ return when {
+ slice == BindingContext.DECLARATION_TO_DESCRIPTOR -> descriptor as V
+ slice == BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER && (element as KtParameter).hasValOrVar() -> descriptor as V
+ else -> null
+ }
+ }
+
+ override fun getDiagnostics(): Diagnostics {
+ throw UnsupportedOperationException()
+ }
+
+ override fun addOwnDataTo(p0: BindingTrace, p1: Boolean) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <K : Any?, V : Any?> getSliceContents(p0: ReadOnlySlice<K, V>): ImmutableMap<K, V> {
+ throw UnsupportedOperationException()
+ }
+
+ }
+ }
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(serviceClass: Class<T>): T {
+ return resolverForModule.componentProvider.getService(serviceClass)
+ }
+
+ override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
+ return resolverForModule.componentProvider.getService(serviceClass)
+ }
+
+ override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getResolverForProject(): ResolverForProject<out ModuleInfo> {
+ throw UnsupportedOperationException()
+ }
+
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CallableFactory.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CallableFactory.kt
new file mode 100644
index 00000000..ebfe20a5
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CallableFactory.kt
@@ -0,0 +1,31 @@
+package org.jetbrains.dokka.analysis
+
+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
+
+fun Callable.Companion.from(descriptor: CallableDescriptor) = with(descriptor) {
+ Callable(
+ name.asString(),
+ extensionReceiverParameter?.let { TypeReference.from(it) },
+ valueParameters.mapNotNull { TypeReference.from(it) }
+ )
+}
+
+fun Callable.Companion.from(psi: PsiMethod) = with(psi) {
+ Callable(
+ name,
+ null,
+ parameterList.parameters.map { param -> JavaClassReference(param.type.canonicalText) })
+}
+
+fun Callable.Companion.from(psi: PsiField): Callable {
+ return Callable(
+ name = psi.name,
+ receiver = null,
+ params = emptyList()
+ )
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreKotlinCacheService.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreKotlinCacheService.kt
new file mode 100644
index 00000000..68415875
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreKotlinCacheService.kt
@@ -0,0 +1,42 @@
+package org.jetbrains.dokka.analysis
+
+import com.intellij.psi.PsiFile
+import org.jetbrains.dokka.analysis.DokkaResolutionFacade
+import org.jetbrains.kotlin.analyzer.ModuleInfo
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
+
+
+class CoreKotlinCacheService(private val resolutionFacade: DokkaResolutionFacade) : KotlinCacheService {
+ override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacade(
+ elements: List<KtElement>,
+ platform: org.jetbrains.kotlin.platform.TargetPlatform
+ ): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByFile(
+ file: PsiFile,
+ platform: org.jetbrains.kotlin.platform.TargetPlatform
+ ): ResolutionFacade? {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByModuleInfo(
+ moduleInfo: ModuleInfo,
+ platform: org.jetbrains.kotlin.platform.TargetPlatform
+ ): ResolutionFacade? {
+ return resolutionFacade
+ }
+
+ override fun getSuppressionCache(): KotlinSuppressCache {
+ throw UnsupportedOperationException()
+ }
+
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreProjectFileIndex.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreProjectFileIndex.kt
new file mode 100644
index 00000000..d0e0bb4f
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/CoreProjectFileIndex.kt
@@ -0,0 +1,515 @@
+package org.jetbrains.dokka.analysis
+
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.components.BaseComponent
+import com.intellij.openapi.extensions.ExtensionPointName
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.projectRoots.Sdk
+import com.intellij.openapi.projectRoots.SdkAdditionalData
+import com.intellij.openapi.projectRoots.SdkModificator
+import com.intellij.openapi.projectRoots.SdkTypeId
+import com.intellij.openapi.roots.*
+import com.intellij.openapi.roots.impl.ProjectOrderEnumerator
+import com.intellij.openapi.util.Condition
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.UserDataHolderBase
+import com.intellij.openapi.vfs.StandardFileSystems
+import com.intellij.openapi.vfs.VfsUtilCore.getVirtualFileForJar
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.openapi.vfs.VirtualFileFilter
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.util.messages.MessageBus
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+import org.jetbrains.kotlin.cli.common.config.ContentRoot
+import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
+import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
+import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
+import org.picocontainer.PicoContainer
+import java.io.File
+
+/**
+ * Workaround for the lack of ability to create a ProjectFileIndex implementation using only
+ * classes from projectModel-{api,impl}.
+ */
+class CoreProjectFileIndex(private val project: Project, contentRoots: List<ContentRoot>) : ProjectFileIndex, ModuleFileIndex {
+ override fun iterateContent(p0: ContentIterator, p1: VirtualFileFilter?): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun iterateContentUnderDirectory(p0: VirtualFile, p1: ContentIterator, p2: VirtualFileFilter?): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInLibrary(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ val sourceRoots = contentRoots.filter { it !is JvmClasspathRoot }
+ val classpathRoots = contentRoots.filterIsInstance<JvmClasspathRoot>()
+
+ val module: Module = object : UserDataHolderBase(), Module {
+ override fun isDisposed(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getName(): String = "<Dokka module>"
+
+ override fun getModuleWithLibrariesScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependentsScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependenciesScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependenciesAndLibrariesScope(p0: Boolean): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleTestsWithDependentsScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleRuntimeScope(p0: Boolean): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> getExtensions(p0: ExtensionPointName<T>): Array<out T> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> getComponent(interfaceClass: Class<T>): T? {
+ if (interfaceClass == ModuleRootManager::class.java) {
+ return moduleRootManager as T
+ }
+ throw UnsupportedOperationException()
+ }
+
+ override fun getDisposed(): Condition<*> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getPicoContainer(): PicoContainer {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getMessageBus(): MessageBus {
+ throw UnsupportedOperationException()
+ }
+
+ override fun dispose() {
+ throw UnsupportedOperationException()
+ }
+ }
+
+ private val sdk: Sdk = object : Sdk, RootProvider {
+ override fun getFiles(rootType: OrderRootType): Array<out VirtualFile> = classpathRoots
+ .mapNotNull { StandardFileSystems.local().findFileByPath(it.file.path) }
+ .toTypedArray()
+
+ override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener, p1: Disposable) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getUrls(p0: OrderRootType): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun removeRootSetChangedListener(p0: RootProvider.RootSetChangedListener) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSdkModificator(): SdkModificator {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getName(): String = "<dokka SDK>"
+
+ override fun getRootProvider(): RootProvider = this
+
+ override fun getHomePath(): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getVersionString(): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSdkAdditionalData(): SdkAdditionalData? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun clone(): Any {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSdkType(): SdkTypeId {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getHomeDirectory(): VirtualFile? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> getUserData(p0: Key<T>): T? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> putUserData(p0: Key<T>, p1: T?) {
+ throw UnsupportedOperationException()
+ }
+ }
+
+ private val moduleSourceOrderEntry = object : ModuleSourceOrderEntry {
+ override fun getFiles(p0: OrderRootType): Array<VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getUrls(p0: OrderRootType): Array<String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <R : Any?> accept(p0: RootPolicy<R>, p1: R?): R {
+ throw UnsupportedOperationException()
+ }
+
+
+ override fun getPresentableName(): String {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getOwnerModule(): Module = module
+
+
+ override fun isValid(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun compareTo(other: OrderEntry?): Int {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getRootModel(): ModuleRootModel = moduleRootManager
+
+ override fun isSynthetic(): Boolean {
+ throw UnsupportedOperationException()
+ }
+ }
+
+ private val sdkOrderEntry = object : JdkOrderEntry {
+ override fun getFiles(p0: OrderRootType): Array<VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getUrls(p0: OrderRootType): Array<String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <R : Any?> accept(p0: RootPolicy<R>, p1: R?): R {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getJdkName(): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getJdk(): Sdk = sdk
+
+ override fun getPresentableName(): String {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getOwnerModule(): Module {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isValid(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getRootFiles(p0: OrderRootType): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getRootUrls(p0: OrderRootType): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun compareTo(other: OrderEntry?): Int {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isSynthetic(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ }
+
+ inner class MyModuleRootManager : ModuleRootManager() {
+ override fun getExternalSource(): ProjectModelExternalSource? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getExcludeRoots(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentEntries(): Array<out ContentEntry> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getExcludeRootUrls(): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <R : Any?> processOrder(p0: RootPolicy<R>, p1: R): R {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRoots(p0: Boolean): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRoots(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRoots(p0: JpsModuleSourceRootType<*>): MutableList<VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRoots(p0: MutableSet<out JpsModuleSourceRootType<*>>): MutableList<VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRoots(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun orderEntries(): OrderEnumerator =
+ ProjectOrderEnumerator(project, null).using(object : RootModelProvider {
+ override fun getModules(): Array<out Module> = arrayOf(module)
+
+ override fun getRootModel(p0: Module): ModuleRootModel = this@MyModuleRootManager
+ })
+
+ override fun <T : Any?> getModuleExtension(p0: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getDependencyModuleNames(): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModule(): Module = this@CoreProjectFileIndex.module
+
+ override fun isSdkInherited(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getOrderEntries(): Array<out OrderEntry> = arrayOf(moduleSourceOrderEntry, sdkOrderEntry)
+
+ override fun getSourceRootUrls(): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRootUrls(p0: Boolean): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSdk(): Sdk? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRootUrls(): Array<out String> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleDependencies(): Array<out Module> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleDependencies(p0: Boolean): Array<out Module> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModifiableModel(): ModifiableRootModel {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isDependsOn(p0: Module): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getFileIndex(): ModuleFileIndex {
+ return this@CoreProjectFileIndex
+ }
+
+ override fun getDependencies(): Array<out Module> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getDependencies(p0: Boolean): Array<out Module> {
+ throw UnsupportedOperationException()
+ }
+ }
+
+ val moduleRootManager = MyModuleRootManager()
+
+ override fun getContentRootForFile(p0: VirtualFile): VirtualFile? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRootForFile(p0: VirtualFile, p1: Boolean): VirtualFile? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getPackageNameByDirectory(p0: VirtualFile): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInLibrarySource(file: VirtualFile): Boolean = false
+
+ override fun getClassRootForFile(file: VirtualFile): VirtualFile? =
+ classpathRoots.firstOrNull { it.contains(file) }?.let { StandardFileSystems.local().findFileByPath(it.file.path) }
+
+ override fun getOrderEntriesForFile(file: VirtualFile): List<OrderEntry> =
+ if (classpathRoots.contains(file)) listOf(sdkOrderEntry) else emptyList()
+
+ override fun isInLibraryClasses(file: VirtualFile): Boolean = classpathRoots.contains(file)
+
+ override fun isExcluded(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSourceRootForFile(p0: VirtualFile): VirtualFile? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isUnderIgnored(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isLibraryClassFile(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleForFile(file: VirtualFile): Module? =
+ if (sourceRoots.contains(file)) module else null
+
+ private fun List<ContentRoot>.contains(file: VirtualFile): Boolean = any { it.contains(file) }
+
+ override fun getModuleForFile(p0: VirtualFile, p1: Boolean): Module? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInSource(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isIgnored(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isContentSourceFile(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInSourceContent(file: VirtualFile): Boolean = sourceRoots.contains(file)
+
+ override fun iterateContent(p0: ContentIterator): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInContent(p0: VirtualFile): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun iterateContentUnderDirectory(p0: VirtualFile, p1: ContentIterator): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isInTestSourceContent(file: VirtualFile): Boolean = false
+
+ override fun isUnderSourceRootOfType(p0: VirtualFile, p1: MutableSet<out JpsModuleSourceRootType<*>>): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getOrderEntryForFile(p0: VirtualFile): OrderEntry? {
+ throw UnsupportedOperationException()
+ }
+}
+
+class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : ProjectRootManager() {
+ override fun orderEntries(): OrderEnumerator {
+ throw UnsupportedOperationException()
+ }
+
+ override fun orderEntries(p0: MutableCollection<out Module>): OrderEnumerator {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRootsFromAllModules(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun setProjectSdk(p0: Sdk?) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun setProjectSdkName(p0: String) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleSourceRoots(p0: MutableSet<out JpsModuleSourceRootType<*>>): MutableList<VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentSourceRoots(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getFileIndex(): ProjectFileIndex = projectFileIndex
+
+ override fun getProjectSdkName(): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getProjectSdk(): Sdk? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRoots(): Array<out VirtualFile> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getContentRootUrls(): MutableList<String> {
+ throw UnsupportedOperationException()
+ }
+
+}
+
+fun ContentRoot.contains(file: VirtualFile) = when (this) {
+ is JvmContentRoot -> {
+ val path = if (file.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL)
+ getVirtualFileForJar(file)?.path ?: file.path
+ else
+ file.path
+ File(path).startsWith(this.file.absoluteFile)
+ }
+ is KotlinSourceRoot -> File(file.path).startsWith(File(this.path).absoluteFile)
+ else -> false
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt
new file mode 100644
index 00000000..513817f3
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRIFactory.kt
@@ -0,0 +1,38 @@
+package org.jetbrains.dokka.analysis
+
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+import org.jetbrains.dokka.links.Callable
+import org.jetbrains.dokka.links.DRI
+import org.jetbrains.dokka.links.DriTarget
+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
+
+fun DRI.Companion.from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run {
+ val callable = firstIsInstanceOrNull<CallableDescriptor>()
+ DRI(
+ firstIsInstanceOrNull<PackageFragmentDescriptor>()?.fqName?.asString(),
+ (filterIsInstance<ClassDescriptor>() + filterIsInstance<TypeAliasDescriptor>()).toList()
+ .takeIf { it.isNotEmpty() }
+ ?.asReversed()
+ ?.joinToString(separator = ".") { it.name.asString() },
+ callable?.let { Callable.from(it) },
+ DriTarget.from(descriptor)
+ )
+}
+
+fun DRI.Companion.from(psi: PsiElement) = psi.parentsWithSelf.run {
+ val psiMethod = firstIsInstanceOrNull<PsiMethod>()
+ val psiField = firstIsInstanceOrNull<PsiField>()
+ val classes = filterIsInstance<PsiClass>().toList()
+ DRI(
+ classes.lastOrNull()?.qualifiedName?.substringBeforeLast('.', ""),
+ classes.toList().takeIf { it.isNotEmpty() }?.asReversed()?.mapNotNull { it.name }?.joinToString("."),
+ psiMethod?.let { Callable.from(it) } ?: psiField?.let { Callable.from(it) },
+ DriTarget.from(psi)
+ )
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRITargetFactory.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRITargetFactory.kt
new file mode 100644
index 00000000..031a5a32
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/DRITargetFactory.kt
@@ -0,0 +1,44 @@
+package org.jetbrains.dokka.analysis
+
+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.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.ParameterDescriptor
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
+import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+
+fun DriTarget.Companion.from(descriptor: DeclarationDescriptor): DriTarget = descriptor.parentsWithSelf.run {
+ return when (descriptor) {
+ is TypeParameterDescriptor -> PointingToGenericParameters(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
+ }
+ }
+}
+
+
+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/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/Documentable.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/Documentable.kt
new file mode 100644
index 00000000..0c55fed4
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/Documentable.kt
@@ -0,0 +1,14 @@
+package org.jetbrains.dokka.analysis
+
+import com.intellij.psi.PsiNamedElement
+import org.jetbrains.dokka.model.DocumentableSource
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.load.kotlin.toSourceElement
+
+class DescriptorDocumentableSource(val descriptor: DeclarationDescriptor) : DocumentableSource {
+ override val path = descriptor.toSourceElement.containingFile.toString()
+}
+
+class PsiDocumentableSource(val psi: PsiNamedElement) : DocumentableSource {
+ override val path = psi.containingFile.virtualFile.path
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt
new file mode 100644
index 00000000..d9a89194
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/EnvironmentAndFacade.kt
@@ -0,0 +1,56 @@
+package org.jetbrains.dokka.analysis
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.kotlin.cli.common.messages.*
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.utils.PathUtil
+import java.io.File
+
+internal fun createEnvironmentAndFacade(
+ logger: DokkaLogger,
+ configuration: DokkaConfiguration,
+ sourceSet: DokkaConfiguration.DokkaSourceSet
+): EnvironmentAndFacade =
+ AnalysisEnvironment(DokkaMessageCollector(logger), sourceSet.analysisPlatform).run {
+ if (analysisPlatform == Platform.jvm) {
+ addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
+ }
+ sourceSet.classpath.forEach { addClasspath(File(it)) }
+
+ addSources(
+ (sourceSet.sourceRoots + configuration.sourceSets.filter { it.sourceSetID in sourceSet.dependentSourceSets }
+ .flatMap { it.sourceRoots })
+ .map { it.path }
+ )
+
+ loadLanguageVersionSettings(sourceSet.languageVersion, sourceSet.apiVersion)
+
+ val environment = createCoreEnvironment()
+ val (facade, _) = createResolutionFacade(environment)
+ EnvironmentAndFacade(environment, facade)
+ }
+
+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
+}
+
+// It is not data class due to ill-defined equals
+class EnvironmentAndFacade(val environment: KotlinCoreEnvironment, val facade: DokkaResolutionFacade) {
+ operator fun component1() = environment
+ operator fun component2() = facade
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/JavaResolveExtension.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/JavaResolveExtension.kt
new file mode 100644
index 00000000..ab6bec9c
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/JavaResolveExtension.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2010-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("JavaResolutionUtils")
+
+package org.jetbrains.dokka.analysis
+
+import com.intellij.psi.*
+import org.jetbrains.kotlin.asJava.unwrapped
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.incremental.components.NoLookupLocation
+import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
+import org.jetbrains.kotlin.load.java.structure.*
+import org.jetbrains.kotlin.load.java.structure.impl.*
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
+import org.jetbrains.kotlin.resolve.scopes.MemberScope
+
+// TODO: Remove that file
+
+@JvmOverloads
+fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? {
+ val method = originalElement as? PsiMethod ?: return null
+ if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null
+ val resolver = method.getJavaDescriptorResolver(resolutionFacade)
+ return when {
+ method.isConstructor -> resolver?.resolveConstructor(JavaConstructorImpl(method))
+ else -> resolver?.resolveMethod(JavaMethodImpl(method))
+ }
+}
+
+@JvmOverloads
+fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? {
+ val psiClass = originalElement as? PsiClass ?: return null
+ return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass))
+}
+
+@JvmOverloads
+fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? {
+ val field = originalElement as? PsiField ?: return null
+ return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field))
+}
+
+@JvmOverloads
+fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? {
+ return when (this) {
+ is PsiEnumConstant -> containingClass?.getJavaClassDescriptor(resolutionFacade)
+ is PsiClass -> getJavaClassDescriptor(resolutionFacade)
+ is PsiMethod -> getJavaMethodDescriptor(resolutionFacade)
+ is PsiField -> getJavaFieldDescriptor(resolutionFacade)
+ else -> null
+ }
+}
+
+@JvmOverloads
+fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? {
+ val callable = unwrapped
+ return when (callable) {
+ is PsiMember -> getJavaMemberDescriptor(resolutionFacade)
+ is KtDeclaration -> {
+ val descriptor = resolutionFacade.resolveToDescriptor(callable)
+ if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor
+ }
+ else -> null
+ }
+}
+
+private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? {
+ return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java)
+}
+
+private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): DeclarationDescriptor? {
+ return getContainingScope(method)
+ ?.getContributedDescriptors(nameFilter = { true }, kindFilter = DescriptorKindFilter.CALLABLES)
+ ?.filterIsInstance<DeclarationDescriptorWithSource>()
+ ?.findByJavaElement(method)
+}
+
+private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? {
+ return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor)
+}
+
+private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? {
+ return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field)
+}
+
+private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? {
+ val containingClass = resolveClass(member.containingClass)
+ return if (member.isStatic)
+ containingClass?.staticScope
+ else
+ containingClass?.defaultType?.memberScope
+}
+
+private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElement(javaElement: JavaElement): T? {
+ return firstOrNull { member ->
+ val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement
+ when {
+ memberJavaElement == javaElement ->
+ true
+ memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> ->
+ memberJavaElement.psi.isEquivalentTo(javaElement.psi)
+ else ->
+ false
+ }
+ }
+}
+
+fun PsiElement.javaResolutionFacade() =
+ KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatforms.defaultJvmPlatform)!!
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/KotlinAnalysis.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/KotlinAnalysis.kt
new file mode 100644
index 00000000..e723768c
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/KotlinAnalysis.kt
@@ -0,0 +1,39 @@
+@file:Suppress("FunctionName")
+
+package org.jetbrains.dokka.analysis
+
+import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
+import org.jetbrains.dokka.DokkaSourceSetID
+import org.jetbrains.dokka.model.SourceSetDependent
+import org.jetbrains.dokka.plugability.DokkaContext
+
+fun KotlinAnalysis(context: DokkaContext): KotlinAnalysis {
+ val environments = context.configuration.sourceSets
+ .associate { sourceSet ->
+ sourceSet to createEnvironmentAndFacade(
+ logger = context.logger,
+ configuration = context.configuration,
+ sourceSet = sourceSet
+ )
+ }
+
+ return KotlinAnalysisImpl(environments)
+}
+
+interface KotlinAnalysis : SourceSetDependent<EnvironmentAndFacade> {
+ override fun get(key: DokkaSourceSet): EnvironmentAndFacade
+ operator fun get(sourceSetID: DokkaSourceSetID): EnvironmentAndFacade
+}
+
+internal class KotlinAnalysisImpl(
+ private val environments: SourceSetDependent<EnvironmentAndFacade>
+) : KotlinAnalysis, SourceSetDependent<EnvironmentAndFacade> by environments {
+
+ override fun get(key: DokkaSourceSet): EnvironmentAndFacade {
+ return environments[key] ?: throw IllegalStateException("Missing EnvironmentAndFacade for sourceSet $key")
+ }
+
+ override fun get(sourceSetID: DokkaSourceSetID): EnvironmentAndFacade {
+ return environments.entries.first { (sourceSet, _) -> sourceSet.sourceSetID == sourceSetID }.value
+ }
+}
diff --git a/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/TypeReferenceFactory.kt b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/TypeReferenceFactory.kt
new file mode 100644
index 00000000..e07672d4
--- /dev/null
+++ b/kotlin-analysis/src/main/kotlin/org/jetbrains/dokka/analysis/TypeReferenceFactory.kt
@@ -0,0 +1,51 @@
+package org.jetbrains.dokka.analysis
+
+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
+
+fun TypeReference.Companion.from(d: ReceiverParameterDescriptor): TypeReference? =
+ when (d.value) {
+ is ExtensionReceiver -> fromPossiblyNullable(d.type)
+ else -> run {
+ println("Unknown value type for $d")
+ null
+ }
+ }
+
+fun TypeReference.Companion.from(d: ValueParameterDescriptor): TypeReference? =
+ fromPossiblyNullable(d.type)
+
+fun TypeReference.Companion.from(p: PsiClass) = TypeReference
+
+private fun TypeReference.Companion.fromPossiblyNullable(t: KotlinType, self: KotlinType? = null): TypeReference =
+ from(t, self).let { if (t.isMarkedNullable) Nullable(it) else it }
+
+private fun TypeReference.Companion.from(t: KotlinType, self: KotlinType? = null): TypeReference =
+ if (self is KotlinType && self.constructor == t.constructor && self.arguments == t.arguments)
+ SelfType
+ else when (val d = t.constructor.declarationDescriptor) {
+ is TypeParameterDescriptor -> TypeParam(
+ d.upperBounds.map { fromPossiblyNullable(it, self ?: t) }
+ )
+ else -> TypeConstructor(
+ t.constructorName.orEmpty(),
+ t.arguments.map { fromProjection(it, self) }
+ )
+ }
+
+private fun TypeReference.Companion.fromProjection(t: TypeProjection, r: KotlinType? = null): TypeReference =
+ if (t.isStarProjection) {
+ StarProjection
+ } else {
+ fromPossiblyNullable(t.type, r)
+ }
+
+private val KotlinType.constructorName
+ get() = constructor.declarationDescriptor?.fqNameSafe?.asString()