org.jetbrains.kotlin.analyzer.AnalyzerFacade.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* Copyright 2010-2015 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.
*/
package org.jetbrains.kotlin.analyzer
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.LazyModuleDependencies
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.utils.DescriptionAware
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
class ResolverForModule(
val packageFragmentProvider: PackageFragmentProvider,
val componentProvider: ComponentProvider
)
abstract class ResolverForProject {
fun resolverForModule(moduleInfo: M): ResolverForModule = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
abstract fun tryGetResolverForModule(moduleInfo: M): ResolverForModule?
abstract fun descriptorForModule(moduleInfo: M): ModuleDescriptor
abstract fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
abstract val name: String
abstract val allModules: Collection
override fun toString() = name
}
class EmptyResolverForProject : ResolverForProject() {
override val name: String
get() = "Empty resolver"
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? = null
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule = throw IllegalStateException("$descriptor is not contained in this resolver")
override fun descriptorForModule(moduleInfo: M) = throw IllegalStateException("Should not be called for $moduleInfo")
override val allModules: Collection = listOf()
}
class ResolverForProjectImpl(
private val debugName: String,
val descriptorByModule: Map,
val delegateResolver: ResolverForProject = EmptyResolverForProject()
) : ResolverForProject() {
override fun tryGetResolverForModule(moduleInfo: M): ResolverForModule? {
if (!isCorrectModuleInfo(moduleInfo)) {
return null
}
return resolverForModuleDescriptor(doGetDescriptorForModule(moduleInfo))
}
internal val resolverByModuleDescriptor: MutableMap ResolverForModule> = HashMap()
override val allModules: Collection by lazy {
(descriptorByModule.keys + delegateResolver.allModules).toSet()
}
override val name: String
get() = "Resolver for '$debugName'"
private fun isCorrectModuleInfo(moduleInfo: M) = moduleInfo in allModules
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule {
val computation = resolverByModuleDescriptor[descriptor] ?: run {
if (delegateResolver is EmptyResolverForProject<*>) {
throw IllegalStateException("$descriptor is not contained in resolver $name")
}
return delegateResolver.resolverForModuleDescriptor(descriptor)
}
return computation()
}
override fun descriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
if (!isCorrectModuleInfo(moduleInfo)) {
throw AssertionError("$name does not know how to resolve $moduleInfo")
}
return doGetDescriptorForModule(moduleInfo)
}
private fun doGetDescriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
return descriptorByModule[moduleInfo] ?: delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
}
}
data class ModuleContent(
val syntheticFiles: Collection,
val moduleContentScope: GlobalSearchScope
)
interface PlatformAnalysisParameters
interface ModuleInfo {
val isLibrary: Boolean
get() = false
val name: Name
fun dependencies(): List
fun modulesWhoseInternalsAreVisible(): Collection = listOf()
fun dependencyOnBuiltIns(): DependencyOnBuiltIns = DependenciesOnBuiltIns.LAST
val capabilities: Map, Any?>
get() = emptyMap()
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
interface DependencyOnBuiltIns {
fun adjustDependencies(builtinsModule: ModuleDescriptorImpl, dependencies: MutableList)
}
enum class DependenciesOnBuiltIns : DependencyOnBuiltIns {
NONE {
override fun adjustDependencies(builtinsModule: ModuleDescriptorImpl, dependencies: MutableList) {
//do nothing
}
},
LAST {
override fun adjustDependencies(builtinsModule: ModuleDescriptorImpl, dependencies: MutableList) {
dependencies.add(builtinsModule)
}
};
}
}
abstract class AnalyzerFacade {
fun setupResolverForProject(
debugName: String,
projectContext: ProjectContext,
modules: Collection,
modulesContent: (M) -> ModuleContent,
platformParameters: P,
targetEnvironment: TargetEnvironment = CompilerEnvironment,
builtIns: (M) -> KotlinBuiltIns = { DefaultBuiltIns.Instance },
delegateResolver: ResolverForProject = EmptyResolverForProject(),
packagePartProviderFactory: (M, ModuleContent) -> PackagePartProvider = { _, _ -> PackagePartProvider.Empty },
firstDependency: M? = null,
modulePlatforms: (M) -> MultiTargetPlatform?,
moduleSources: (M) -> SourceKind = { SourceKind.NONE }
): ResolverForProject {
val storageManager = projectContext.storageManager
fun createResolverForProject(): ResolverForProjectImpl {
val descriptorByModule = HashMap()
modules.forEach {
module ->
descriptorByModule[module] =
ModuleDescriptorImpl(module.name, storageManager, builtIns(module),
modulePlatforms(module), moduleSources(module), module.capabilities)
}
return ResolverForProjectImpl(debugName, descriptorByModule, delegateResolver)
}
val resolverForProject = createResolverForProject()
fun computeDependencyDescriptors(module: M): List {
val orderedDependencies = firstDependency.singletonOrEmptyList() + module.dependencies()
val dependenciesDescriptors = orderedDependencies.mapTo(ArrayList()) {
dependencyInfo ->
resolverForProject.descriptorForModule(dependencyInfo as M)
}
module.dependencyOnBuiltIns().adjustDependencies(
resolverForProject.descriptorForModule(module).builtIns.builtInsModule, dependenciesDescriptors)
return dependenciesDescriptors
}
fun computeModulesWhoseInternalsAreVisible(module: M): Set {
return module.modulesWhoseInternalsAreVisible().mapTo(LinkedHashSet()) { resolverForProject.descriptorForModule(it as M) }
}
fun setupModuleDependencies() {
modules.forEach {
module ->
resolverForProject.descriptorForModule(module).setDependencies(
LazyModuleDependencies(
storageManager,
{ computeDependencyDescriptors(module) },
{ computeModulesWhoseInternalsAreVisible(module) }
)
)
}
}
setupModuleDependencies()
fun initializeResolverForProject() {
modules.forEach {
module ->
val descriptor = resolverForProject.descriptorForModule(module)
val computeResolverForModule = storageManager.createLazyValue {
val content = modulesContent(module)
createResolverForModule(
module, descriptor, projectContext.withModule(descriptor), modulesContent(module),
platformParameters, targetEnvironment, resolverForProject,
packagePartProviderFactory(module, content)
)
}
descriptor.initialize(DelegatingPackageFragmentProvider { computeResolverForModule().packageFragmentProvider })
resolverForProject.resolverByModuleDescriptor[descriptor] = computeResolverForModule
}
}
initializeResolverForProject()
return resolverForProject
}
protected abstract fun createResolverForModule(
moduleInfo: M,
moduleDescriptor: ModuleDescriptorImpl,
moduleContext: ModuleContext,
moduleContent: ModuleContent,
platformParameters: P,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject,
packagePartProvider: PackagePartProvider
): ResolverForModule
abstract val targetPlatform: TargetPlatform
}
//NOTE: relies on delegate to be lazily computed and cached
private class DelegatingPackageFragmentProvider(
private val delegate: () -> PackageFragmentProvider
) : PackageFragmentProvider {
override fun getPackageFragments(fqName: FqName): List {
return delegate().getPackageFragments(fqName)
}
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection {
return delegate().getSubPackagesOf(fqName, nameFilter)
}
}
interface LanguageSettingsProvider {
fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project): LanguageVersionSettings
fun getTargetPlatform(moduleInfo: ModuleInfo): DescriptionAware
object Default : LanguageSettingsProvider {
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project) = LanguageVersionSettingsImpl.DEFAULT
override fun getTargetPlatform(moduleInfo: ModuleInfo): DescriptionAware = DescriptionAware.NoVersion
}
companion object {
fun getInstance(project: Project) = ServiceManager.getService(project, LanguageSettingsProvider::class.java) ?: Default
}
}