aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/analysis
diff options
context:
space:
mode:
authorBłażej Kardyś <bkardys@virtuslab.com>2019-11-27 17:45:33 +0100
committerBłażej Kardyś <bkardys@virtuslab.com>2019-11-28 12:53:21 +0100
commitd37cf2f32840779706154a3cddbb2239cd80fd84 (patch)
tree97e2199624100550456e218a02d1e1590581b781 /core/src/main/kotlin/analysis
parent970bb62105af3828234eb871230ee9c1cd216af7 (diff)
downloaddokka-d37cf2f32840779706154a3cddbb2239cd80fd84.tar.gz
dokka-d37cf2f32840779706154a3cddbb2239cd80fd84.tar.bz2
dokka-d37cf2f32840779706154a3cddbb2239cd80fd84.zip
Cleaning package naming
Diffstat (limited to 'core/src/main/kotlin/analysis')
-rw-r--r--core/src/main/kotlin/analysis/AnalysisEnvironment.kt454
-rw-r--r--core/src/main/kotlin/analysis/CoreKotlinCacheService.kt30
-rw-r--r--core/src/main/kotlin/analysis/CoreProjectFileIndex.kt568
-rw-r--r--core/src/main/kotlin/analysis/DokkaAnalyzerFacades.kt164
-rw-r--r--core/src/main/kotlin/analysis/JavaResolveExtension.kt131
5 files changed, 1347 insertions, 0 deletions
diff --git a/core/src/main/kotlin/analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/analysis/AnalysisEnvironment.kt
new file mode 100644
index 00000000..30a51136
--- /dev/null
+++ b/core/src/main/kotlin/analysis/AnalysisEnvironment.kt
@@ -0,0 +1,454 @@
+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.search.GlobalSearchScope
+import com.intellij.util.io.URLUtil
+import org.jetbrains.dokka.Platform
+import org.jetbrains.kotlin.analyzer.*
+import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
+import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
+import org.jetbrains.kotlin.builtins.DefaultBuiltIns
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
+import org.jetbrains.kotlin.caches.project.LibraryModuleInfo
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+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.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.js.config.JSConfigurationKeys
+import org.jetbrains.kotlin.js.resolve.JsPlatform
+import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.*
+import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
+import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
+import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
+import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
+import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
+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
+
+/**
+ * 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.fallback", "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)
+
+ Extensions.registerAreaClass("IDEA_MODULE", null)
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(),
+ OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java)
+
+ projectComponentManager.registerService(ProjectFileIndex::class.java,
+ projectFileIndex)
+ projectComponentManager.registerService(ProjectRootManager::class.java,
+ CoreProjectRootManager(projectFileIndex))
+ return environment
+ }
+
+ 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)
+ val sourceFiles = environment.getSourceFiles()
+
+
+ val targetPlatform = when (analysisPlatform) {
+ Platform.js -> JsPlatform
+ Platform.common -> TargetPlatform.Common
+ Platform.native -> KonanPlatform
+ Platform.jvm -> JvmPlatform
+ }
+
+ val library = object : LibraryModuleInfo {
+ override val platform: TargetPlatform
+ get() = targetPlatform
+
+ override fun getLibraryRoots(): Collection<String> {
+ return classpath.map { it.absolutePath }
+ }
+
+ override val name: Name = Name.special("<library>")
+ override fun dependencies(): List<ModuleInfo> = listOf(this)
+ }
+ val module = object : ModuleInfo {
+ override val name: Name = Name.special("<module>")
+ override fun dependencies(): List<ModuleInfo> = listOf(this, library)
+ }
+
+ 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))
+ else -> throw IllegalArgumentException("Unexpected module info")
+ }
+ }
+
+ var builtIns: JvmBuiltIns? = null
+
+ val resolverForProject = when (analysisPlatform) {
+ Platform.jvm -> {
+ builtIns = JvmBuiltIns(projectContext.storageManager)
+ 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 resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly
+ val resolverForModule = resolverForProject.resolverForModule(module)
+ val libraryModuleDescriptor = resolverForProject.descriptorForModule(library)
+ val moduleDescriptor = resolverForProject.descriptorForModule(module)
+ builtIns?.initialize(moduleDescriptor, true)
+ 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 createCommonResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>,
+ environment: KotlinCoreEnvironment
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { MultiTargetPlatform.Common },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade },
+ platformParameters = { _ ->
+ CommonAnalysisParameters { content ->
+ environment.createPackagePartProvider(content.moduleContentScope)
+ }
+ },
+ targetEnvironment = CompilerEnvironment,
+ builtIns = DefaultBuiltIns.Instance
+ )
+ }
+
+ private fun createJsResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { JsPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { DokkaJsAnalyzerFacade },
+ platformParameters = { _ -> PlatformAnalysisParameters.Empty },
+ targetEnvironment = CompilerEnvironment,
+ builtIns = JsPlatform.builtIns
+ )
+ }
+
+ private fun createNativeResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { KonanPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { DokkaNativeAnalyzerFacade },
+ platformParameters = { _ -> PlatformAnalysisParameters.Empty },
+ targetEnvironment = CompilerEnvironment
+ )
+
+ }
+
+ private fun createJvmResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>,
+ sourcesScope: GlobalSearchScope,
+ builtIns: KotlinBuiltIns
+ ): ResolverForProjectImpl<ModuleInfo> {
+ val javaRoots = classpath
+ .mapNotNull {
+ val rootFile = when {
+ it.extension == "jar" ->
+ StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}")
+ else ->
+ StandardFileSystems.local().findFileByPath(it.absolutePath)
+ }
+
+ rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) }
+ }
+
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(library, module),
+ modulesContent = {
+ when (it) {
+ library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope))
+ module -> ModuleContent(it, emptyList(), sourcesScope)
+ else -> throw IllegalArgumentException("Unexpected module info")
+ }
+ },
+ modulePlatforms = { JvmPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade },
+ platformParameters = {
+ JvmPlatformParameters ({ content ->
+ JvmPackagePartProvider(
+ configuration.languageVersionSettings,
+ content.moduleContentScope)
+ .apply {
+ addRoots(javaRoots, messageCollector)
+ }
+ }, {
+ val file = (it as JavaClassImpl).psi.containingFile.virtualFile
+ if (file in sourcesScope)
+ module
+ else
+ library
+ })
+ },
+ targetEnvironment = CompilerEnvironment,
+ builtIns = builtIns
+ )
+ }
+
+ 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)
+ }
+}
+
+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()
+ }
+
+}
diff --git a/core/src/main/kotlin/analysis/CoreKotlinCacheService.kt b/core/src/main/kotlin/analysis/CoreKotlinCacheService.kt
new file mode 100644
index 00000000..509c4e10
--- /dev/null
+++ b/core/src/main/kotlin/analysis/CoreKotlinCacheService.kt
@@ -0,0 +1,30 @@
+package org.jetbrains.dokka.analysis
+
+import com.intellij.psi.PsiFile
+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.TargetPlatform
+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 getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade {
+ return resolutionFacade
+ }
+
+ override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? {
+ return resolutionFacade
+ }
+
+ override fun getSuppressionCache(): KotlinSuppressCache {
+ throw UnsupportedOperationException()
+ }
+
+}
+
diff --git a/core/src/main/kotlin/analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/analysis/CoreProjectFileIndex.kt
new file mode 100644
index 00000000..6863a266
--- /dev/null
+++ b/core/src/main/kotlin/analysis/CoreProjectFileIndex.kt
@@ -0,0 +1,568 @@
+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.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 getOptionValue(p0: String): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun clearOption(p0: String) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getName(): String = "<Dokka module>"
+
+ override fun getModuleWithLibrariesScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependentsScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleContentScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isLoaded(): Boolean {
+ throw UnsupportedOperationException()
+ }
+
+ override fun setOption(p0: String, p1: String?) {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependenciesScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleWithDependenciesAndLibrariesScope(p0: Boolean): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getProject(): Project = this@CoreProjectFileIndex.project
+
+ override fun getModuleContentWithDependenciesScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleFilePath(): String {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleTestsWithDependentsScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleScope(): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleScope(p0: Boolean): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleRuntimeScope(p0: Boolean): GlobalSearchScope {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getModuleFile(): VirtualFile? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> getExtensions(p0: ExtensionPointName<T>): Array<out T> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getComponent(p0: String): BaseComponent? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any?> getComponent(p0: Class<T>, p1: T): 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 <T : Any?> getComponents(p0: Class<T>): Array<out T> {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getPicoContainer(): PicoContainer {
+ throw UnsupportedOperationException()
+ }
+
+ override fun hasComponent(p0: Class<*>): Boolean {
+ 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)
+ StandardFileSystems.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/core/src/main/kotlin/analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/analysis/DokkaAnalyzerFacades.kt
new file mode 100644
index 00000000..c69ff645
--- /dev/null
+++ b/core/src/main/kotlin/analysis/DokkaAnalyzerFacades.kt
@@ -0,0 +1,164 @@
+package org.jetbrains.dokka.analysis
+
+import org.jetbrains.kotlin.analyzer.*
+import org.jetbrains.kotlin.caches.project.LibraryModuleInfo
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.config.TargetPlatformVersion
+import org.jetbrains.kotlin.container.StorageComponentContainer
+import org.jetbrains.kotlin.container.get
+import org.jetbrains.kotlin.container.useImpl
+import org.jetbrains.kotlin.container.useInstance
+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.configureModule
+import org.jetbrains.kotlin.ide.konan.KOTLIN_NATIVE_CURRENT_ABI_VERSION
+import org.jetbrains.kotlin.ide.konan.createPackageFragmentProvider
+import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.js.resolve.JsPlatform
+import org.jetbrains.kotlin.konan.file.File
+import org.jetbrains.kotlin.konan.library.createKonanLibrary
+import org.jetbrains.kotlin.resolve.*
+import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
+import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
+import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
+import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider
+import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
+
+fun createContainerForLazyResolve(
+ moduleContext: ModuleContext,
+ declarationProviderFactory: DeclarationProviderFactory,
+ bindingTrace: BindingTrace,
+ platform: TargetPlatform,
+ targetPlatformVersion: TargetPlatformVersion,
+ targetEnvironment: TargetEnvironment,
+ languageVersionSettings: LanguageVersionSettings
+): StorageComponentContainer = createContainer("LazyResolve", platform) {
+ configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
+
+ useInstance(declarationProviderFactory)
+ useInstance(languageVersionSettings)
+
+ useImpl<AnnotationResolverImpl>()
+ useImpl<CompilerDeserializationConfiguration>()
+ targetEnvironment.configure(this)
+
+ useImpl<ResolveSession>()
+ useImpl<LazyTopDownAnalyzer>()
+}
+
+
+object DokkaJsAnalyzerFacade : ResolverForModuleFactory() {
+ override fun <M : ModuleInfo> createResolverForModule(
+ moduleDescriptor: ModuleDescriptorImpl,
+ moduleContext: ModuleContext,
+ moduleContent: ModuleContent<M>,
+ platformParameters: PlatformAnalysisParameters,
+ targetEnvironment: TargetEnvironment,
+ resolverForProject: ResolverForProject<M>,
+ languageVersionSettings: LanguageVersionSettings,
+ targetPlatformVersion: TargetPlatformVersion
+ ): ResolverForModule {
+ val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
+ val project = moduleContext.project
+ val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
+ project,
+ moduleContext.storageManager,
+ syntheticFiles,
+ moduleContentScope,
+ moduleInfo
+ )
+
+ val container = createContainerForLazyResolve(
+ moduleContext,
+ declarationProviderFactory,
+ BindingTraceContext(),
+ JsPlatform,
+ TargetPlatformVersion.NoVersion,
+ targetEnvironment,
+ languageVersionSettings
+ )
+ var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
+
+ if (moduleInfo is LibraryModuleInfo && moduleInfo.platform == JsPlatform) {
+ val providers = moduleInfo.getLibraryRoots()
+ .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) }
+ .filter { it.version.isCompatible() }
+ .map { metadata ->
+ val (header, packageFragmentProtos) =
+ KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version)
+ createKotlinJavascriptPackageFragmentProvider(
+ moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version,
+ container.get(), LookupTracker.DO_NOTHING
+ )
+ }
+
+ if (providers.isNotEmpty()) {
+ packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers)
+ }
+ }
+
+ return ResolverForModule(packageFragmentProvider, container)
+ }
+
+ override val targetPlatform: TargetPlatform
+ get() = JsPlatform
+}
+
+object DokkaNativeAnalyzerFacade : ResolverForModuleFactory() {
+ override val targetPlatform: TargetPlatform
+ get() = KonanPlatform
+
+ override fun <M : ModuleInfo> createResolverForModule(
+ moduleDescriptor: ModuleDescriptorImpl,
+ moduleContext: ModuleContext,
+ moduleContent: ModuleContent<M>,
+ platformParameters: PlatformAnalysisParameters,
+ targetEnvironment: TargetEnvironment,
+ resolverForProject: ResolverForProject<M>,
+ languageVersionSettings: LanguageVersionSettings,
+ targetPlatformVersion: TargetPlatformVersion
+ ): ResolverForModule {
+
+ val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
+ moduleContext.project,
+ moduleContext.storageManager,
+ moduleContent.syntheticFiles,
+ moduleContent.moduleContentScope,
+ moduleContent.moduleInfo
+ )
+
+ val container = createContainerForLazyResolve(
+ moduleContext,
+ declarationProviderFactory,
+ BindingTraceContext(),
+ targetPlatform,
+ TargetPlatformVersion.NoVersion,
+ targetEnvironment,
+ languageVersionSettings
+ )
+
+ val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
+ val fragmentProviders = mutableListOf(packageFragmentProvider)
+
+ val moduleInfo = moduleContent.moduleInfo
+
+ if (moduleInfo is LibraryModuleInfo) {
+ moduleInfo.getLibraryRoots()
+ .filter { File(it).extension != "jar" }
+ .map { createKonanLibrary(File(it), KOTLIN_NATIVE_CURRENT_ABI_VERSION) }
+ .mapTo(fragmentProviders) {
+ it.createPackageFragmentProvider(
+ moduleContext.storageManager,
+ languageVersionSettings,
+ moduleDescriptor
+ )
+ }
+
+ }
+
+ return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)
+ }
+}
diff --git a/core/src/main/kotlin/analysis/JavaResolveExtension.kt b/core/src/main/kotlin/analysis/JavaResolveExtension.kt
new file mode 100644
index 00000000..2b60a639
--- /dev/null
+++ b/core/src/main/kotlin/analysis/JavaResolveExtension.kt
@@ -0,0 +1,131 @@
+/*
+ * 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.classes.KtLightClass
+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.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
+import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
+import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
+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, JvmPlatform)!!