Provide API to get frontend services from plugin code via resoltion facade

API to create ide-side services using frontend services (for now "ide services" cannot be injected into other ide services)
This commit is contained in:
Pavel V. Talanov
2015-07-27 16:44:20 +03:00
parent 84ebc7a0f8
commit 0c2650c86c
17 changed files with 183 additions and 276 deletions
@@ -28,12 +28,17 @@ public interface ComponentContainer {
fun createResolveContext(requestingDescriptor: ValueDescriptor): ValueResolveContext
}
public interface ComponentProvider {
public fun resolve(request: Type): ValueDescriptor?
public fun <T> create(request: Class<T>): T
}
object DynamicComponentDescriptor : ValueDescriptor {
override fun getValue(): Any = throw UnsupportedOperationException()
override fun toString(): String = "Dynamic"
}
public class StorageComponentContainer(id: String) : ComponentContainer, Closeable {
public class StorageComponentContainer(id: String) : ComponentContainer, ComponentProvider, Closeable {
public val unknownContext: ComponentResolveContext by lazy { ComponentResolveContext(this, DynamicComponentDescriptor) }
val componentStorage = ComponentStorage(id)
@@ -54,10 +59,14 @@ public class StorageComponentContainer(id: String) : ComponentContainer, Closeab
override fun close() = componentStorage.dispose()
jvmOverloads public fun resolve(request: Type, context: ValueResolveContext = unknownContext): ValueDescriptor? {
public fun resolve(request: Type, context: ValueResolveContext): ValueDescriptor? {
return componentStorage.resolve(request, context) ?: resolveIterable(request, context)
}
override fun resolve(request: Type): ValueDescriptor? {
return resolve(request, unknownContext)
}
private fun resolveIterable(request: Type, context: ValueResolveContext): ValueDescriptor? {
if (request !is ParameterizedType) return null
val rawType = request.getRawType()
@@ -86,6 +95,12 @@ public class StorageComponentContainer(id: String) : ComponentContainer, Closeab
componentStorage.registerDescriptors(unknownContext, descriptors)
return this
}
override fun <T> create(request: Class<T>): T {
val constructorBinding = request.bindToConstructor(unknownContext)
val args = constructorBinding.argumentDescriptors.map { it.getValue() }.toTypedArray()
return constructorBinding.constructor.newInstance(*args) as T
}
}
public fun StorageComponentContainer.registerSingleton(klass: Class<*>): StorageComponentContainer {
@@ -29,14 +29,14 @@ public inline fun <reified T> StorageComponentContainer.useImpl() {
registerSingleton(javaClass<T>())
}
public inline fun <reified T> StorageComponentContainer.get(): T {
return resolve(javaClass<T>(), unknownContext)!!.getValue() as T
public inline fun <reified T> ComponentProvider.get(): T {
return resolve(javaClass<T>())!!.getValue() as T
}
public fun StorageComponentContainer.useInstance(instance: Any) {
registerInstance(instance)
}
public inline fun <reified T> StorageComponentContainer.get(thisRef: Any?, desc: PropertyMetadata): T {
public inline fun <reified T> ComponentProvider.get(thisRef: Any?, desc: PropertyMetadata): T {
return resolve(javaClass<T>())!!.getValue() as T
}
@@ -70,7 +70,7 @@ public fun StorageComponentContainer.configureJavaTopDownAnalysis(moduleContentS
public fun createContainerForLazyResolveWithJava(
moduleContext: ModuleContext, bindingTrace: BindingTrace, declarationProviderFactory: DeclarationProviderFactory,
moduleContentScope: GlobalSearchScope, moduleClassResolver: ModuleClassResolver, targetEnvironment: TargetEnvironment = CompilerEnvironment
): Pair<ResolveSession, JavaDescriptorResolver> = createContainer("LazyResolveWithJava") {
): ComponentProvider = createContainer("LazyResolveWithJava") {
configureModule(moduleContext, JvmPlatform, bindingTrace)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, LookupTracker.DO_NOTHING)
@@ -82,10 +82,8 @@ public fun createContainerForLazyResolveWithJava(
useImpl<FileScopeProviderImpl>()
useImpl<LazyResolveToken>()
}.let {
it.javaAnalysisInit()
Pair(it.get<ResolveSession>(), it.get<JavaDescriptorResolver>())
}.apply {
javaAnalysisInit()
}
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.resolve.jvm
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.ModuleParameters
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
@@ -36,18 +36,12 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import java.util.ArrayList
import kotlin.platform.platformStatic
public class JvmResolverForModule(
override val lazyResolveSession: ResolveSession,
override val packageFragmentProvider: PackageFragmentProvider,
public val javaDescriptorResolver: JavaDescriptorResolver
) : ResolverForModule
public class JvmPlatformParameters(
public val moduleByJavaClass: (JavaClass) -> ModuleInfo
) : PlatformAnalysisParameters
public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatformParameters> {
public object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters> {
override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M,
moduleDescriptor: ModuleDescriptorImpl,
@@ -55,8 +49,8 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
moduleContent: ModuleContent,
platformParameters: JvmPlatformParameters,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, JvmResolverForModule>
): JvmResolverForModule {
resolverForProject: ResolverForProject<M>
): ResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project
val filesToAnalyze = getAllFilesToAnalyze(project, moduleInfo, syntheticFiles)
@@ -67,9 +61,9 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
val moduleInfo = platformParameters.moduleByJavaClass(javaClass)
resolverForProject.resolverForModule(moduleInfo as M).javaDescriptorResolver
resolverForProject.resolverForModule(moduleInfo as M).componentProvider.get<JavaDescriptorResolver>()
}
val (resolveSession, javaDescriptorResolver) = createContainerForLazyResolveWithJava(
val container = createContainerForLazyResolveWithJava(
moduleContext,
CodeAnalyzerInitializer.getInstance(project).createTrace(),
declarationProviderFactory,
@@ -77,9 +71,11 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
moduleClassResolver,
targetEnvironment
)
val resolveSession = container.get<ResolveSession>()
val javaDescriptorResolver = container.get<JavaDescriptorResolver>()
val providersForModule = listOf(resolveSession.getPackageFragmentProvider(), javaDescriptorResolver.packageFragmentProvider)
return JvmResolverForModule(resolveSession, CompositePackageFragmentProvider(providersForModule), javaDescriptorResolver)
return ResolverForModule(CompositePackageFragmentProvider(providersForModule), container)
}
override val moduleParameters: ModuleParameters
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.analyzer
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule
@@ -31,34 +32,33 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import java.util.ArrayList
import java.util.HashMap
public interface ResolverForModule {
public val lazyResolveSession: ResolveSession
public val packageFragmentProvider: PackageFragmentProvider
}
public class ResolverForModule(
public val packageFragmentProvider: PackageFragmentProvider,
public val componentProvider: ComponentProvider
)
public interface ResolverForProject<M : ModuleInfo,out R : ResolverForModule> {
public fun resolverForModule(moduleInfo: M): R = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
public interface ResolverForProject<M : ModuleInfo> {
public fun resolverForModule(moduleInfo: M): ResolverForModule = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
public fun descriptorForModule(moduleInfo: M): ModuleDescriptor
public fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R
public fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
val allModules: Collection<M>
}
public class EmptyResolverForProject<M : ModuleInfo, R : ResolverForModule> : ResolverForProject<M, R> {
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R = throw IllegalStateException("$descriptor is not contained in this resolver")
public class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M> {
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<M> = listOf()
}
public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
public class ResolverForProjectImpl<M : ModuleInfo>(
val descriptorByModule: Map<M, ModuleDescriptorImpl>,
val delegateResolver: ResolverForProject<M, R> = EmptyResolverForProject()
) : ResolverForProject<M, R> {
val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> R> = HashMap()
val delegateResolver: ResolverForProject<M> = EmptyResolverForProject()
) : ResolverForProject<M> {
val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> ResolverForModule> = HashMap()
override val allModules: Collection<M> by lazy {
(descriptorByModule.keySet() + delegateResolver.allModules).toSet()
@@ -70,7 +70,7 @@ public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>(
}
}
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R {
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule {
val computation = resolverByModuleDescriptor[descriptor] ?: return delegateResolver.resolverForModuleDescriptor(descriptor)
return computation()
}
@@ -121,18 +121,18 @@ public interface ModuleInfo {
}
}
public interface AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisParameters> {
public interface AnalyzerFacade<in P : PlatformAnalysisParameters> {
public fun <M : ModuleInfo> setupResolverForProject(
projectContext: ProjectContext,
modules: Collection<M>,
modulesContent: (M) -> ModuleContent,
platformParameters: P,
targetEnvironment: TargetEnvironment,
delegateResolver: ResolverForProject<M, A> = EmptyResolverForProject()
): ResolverForProject<M, A> {
delegateResolver: ResolverForProject<M> = EmptyResolverForProject()
): ResolverForProject<M> {
val storageManager = projectContext.storageManager
fun createResolverForProject(): ResolverForProjectImpl<M, A> {
fun createResolverForProject(): ResolverForProjectImpl<M> {
val descriptorByModule = HashMap<M, ModuleDescriptorImpl>()
modules.forEach {
module ->
@@ -204,8 +204,8 @@ public interface AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisPa
moduleContent: ModuleContent,
platformParameters: P,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, A>
): A
resolverForProject: ResolverForProject<M>
): ResolverForModule
public val moduleParameters: ModuleParameters
}
@@ -101,7 +101,7 @@ public fun createContainerForLazyLocalClassifierAnalyzer(
useImpl<LocalLazyDeclarationResolver>()
}
private fun createContainerForLazyResolve(
public fun createContainerForLazyResolve(
moduleContext: ModuleContext,
declarationProviderFactory: DeclarationProviderFactory,
bindingTrace: BindingTrace,
@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModule
import org.jetbrains.kotlin.test.JetTestUtils
import org.jetbrains.kotlin.types.ErrorUtils
import org.junit.Assert
@@ -64,7 +64,8 @@ public class MultiModuleJavaAnalysisCustomTest : UsefulTestCase() {
javaClass ->
val moduleName = javaClass.getName().asString().toLowerCase().first().toString()
modules.first { it._name == moduleName }
}
},
CompilerEnvironment
)
performChecks(resolverForProject, modules)
@@ -101,7 +102,7 @@ public class MultiModuleJavaAnalysisCustomTest : UsefulTestCase() {
return modules.values().toList()
}
private fun performChecks(resolverForProject: ResolverForProject<TestModule, JvmResolverForModule>, modules: List<TestModule>) {
private fun performChecks(resolverForProject: ResolverForProject<TestModule>, modules: List<TestModule>) {
modules.forEach {
module ->
val moduleDescriptor = resolverForProject.descriptorForModule(module)
@@ -20,9 +20,11 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.ModuleContent
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
@@ -36,9 +38,10 @@ public fun createResolveSessionForFiles(
val resolverForProject = JvmAnalyzerFacade.setupResolverForProject(
projectContext, listOf(testModule),
{ ModuleContent(syntheticFiles, GlobalSearchScope.allScope(project)) },
JvmPlatformParameters { testModule }
JvmPlatformParameters { testModule },
CompilerEnvironment
)
return resolverForProject.resolverForModule(testModule).lazyResolveSession
return resolverForProject.resolverForModule(testModule).componentProvider.get<ResolveSession>()
}
private class TestModule(val dependsOnBuiltins: Boolean) : ModuleInfo {
@@ -40,12 +40,8 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.*;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.idea.decompiler.navigation.JetSourceNavigationHelper;
import org.jetbrains.kotlin.idea.project.ResolveSessionForBodies;
import org.jetbrains.kotlin.idea.stubindex.JetFullClassNameIndex;
import org.jetbrains.kotlin.idea.stubindex.JetTopLevelClassByPackageIndex;
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil;
@@ -60,6 +56,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import java.io.IOException;
@@ -93,7 +90,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
Collections.sort(sortedFiles, scopeFileComparator);
JetFile file = sortedFiles.get(0);
ResolveSessionForBodies session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
ResolveSession session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
forceResolvePackageDeclarations(files, session);
return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor());
}
@@ -101,24 +98,26 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
@NotNull
@Override
public LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject) {
ResolveSessionForBodies session = KotlinCacheService.getInstance(classOrObject.getProject()).getLazyResolveSession(classOrObject);
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(classOrObject);
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(classOrObject);
BindingContext bindingContext = resolutionFacade.analyze(classOrObject, BodyResolveMode.FULL);
if (classOrObject.isLocal()) {
BindingContext bindingContext = session.resolveToElement(classOrObject, BodyResolveMode.FULL);
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject);
if (descriptor == null) {
LOG.warn("No class descriptor in context for class: " + PsiUtilPackage.getElementTextWithContext(classOrObject));
return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor());
return new LightClassConstructionContext(bindingContext, moduleDescriptor);
}
ForceResolveUtil.forceResolveAllContents(descriptor);
return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor());
return new LightClassConstructionContext(bindingContext, moduleDescriptor);
}
ForceResolveUtil.forceResolveAllContents(session.getClassDescriptor(classOrObject));
return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor());
ForceResolveUtil.forceResolveAllContents(resolutionFacade.resolveToDescriptor(classOrObject));
return new LightClassConstructionContext(bindingContext, moduleDescriptor);
}
private static void forceResolvePackageDeclarations(@NotNull Collection<JetFile> files, @NotNull KotlinCodeAnalyzer session) {
@@ -18,15 +18,16 @@ package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.descriptors.*
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.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModule
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.scopes.JetScope
@@ -35,8 +36,8 @@ public object JavaResolveExtension : CacheExtension<(PsiElement) -> Pair<JavaDes
override fun getData(resolverProvider: ModuleResolverProvider): (PsiElement) -> Pair<JavaDescriptorResolver, BindingContext> {
return {
val resolverForModule = resolverProvider.resolverByModule(it.getModuleInfo()) as JvmResolverForModule
Pair(resolverForModule.javaDescriptorResolver, resolverForModule.lazyResolveSession.getBindingContext())
val componentProvider = resolverProvider.resolverByModule(it.getModuleInfo()).componentProvider
Pair(componentProvider.get<JavaDescriptorResolver>(), componentProvider.get<BindingTrace>().getBindingContext())
}
}
@@ -20,12 +20,12 @@ import com.intellij.openapi.roots.OrderRootType
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.ModuleParameters
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.createLazyResolveSession
import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve
import org.jetbrains.kotlin.idea.framework.KotlinJavaScriptLibraryDetectionUtil
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.js.resolve.JsPlatform
@@ -34,15 +34,9 @@ import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.types.DynamicTypesAllowed
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
public class JsResolverForModule(
override val lazyResolveSession: ResolveSession,
override val packageFragmentProvider: PackageFragmentProvider
) : ResolverForModule
public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAnalysisParameters> {
public object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters> {
override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M,
@@ -51,16 +45,16 @@ public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAna
moduleContent: ModuleContent,
platformParameters: PlatformAnalysisParameters,
targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, JsResolverForModule>
): JsResolverForModule {
resolverForProject: ResolverForProject<M>
): ResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
project, moduleContext.storageManager, syntheticFiles, if (moduleInfo.isLibrary) GlobalSearchScope.EMPTY_SCOPE else moduleContentScope
)
val resolveSession = createLazyResolveSession(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment)
var packageFragmentProvider = resolveSession.getPackageFragmentProvider()
val container = createContainerForLazyResolve(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment)
var packageFragmentProvider = container.get<ResolveSession>().getPackageFragmentProvider()
if (moduleInfo is LibraryInfo && KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(moduleInfo.library)) {
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES)
@@ -74,7 +68,7 @@ public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAna
}
}
return JsResolverForModule(resolveSession, packageFragmentProvider)
return ResolverForModule(packageFragmentProvider, container)
}
override val moduleParameters: ModuleParameters
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider
import org.jetbrains.kotlin.idea.project.ResolveSessionForBodies
import org.jetbrains.kotlin.idea.project.ResolveElementCache
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.js.resolve.JsPlatform
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.utils.keysToMap
import kotlin.platform.platformStatic
@@ -150,7 +151,7 @@ public class KotlinCacheService(val project: Project) {
}
}
public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies {
public fun getLazyResolveSession(element: JetElement): ResolveSession {
val file = element.getContainingJetFile()
return getCacheToAnalyzeFiles(listOf(file)).getLazyResolveSession(file)
}
@@ -214,8 +215,17 @@ private fun globalResolveSessionProvider(
}
private class ResolutionFacadeImpl(private val project: Project, private val cache: KotlinResolveCache) : ResolutionFacade {
override fun <T> getIdeService(element: JetElement, serviceClass: Class<T>): T {
return cache.getIdeService(element, serviceClass)
}
override fun <T> getIdeService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
return cache.getIdeService(moduleDescriptor, serviceClass)
}
override fun analyze(element: JetElement, bodyResolveMode: BodyResolveMode): BindingContext {
return cache.getLazyResolveSession(element).resolveToElement(element, bodyResolveMode)
val resolveElementCache = cache.getService(element, javaClass<ResolveElementCache>())
return resolveElementCache.resolveToElement(element, bodyResolveMode)
}
override fun findModuleDescriptor(element: JetElement): ModuleDescriptor {
@@ -234,11 +244,18 @@ private class ResolutionFacadeImpl(private val project: Project, private val cac
return cache.getLazyResolveSession(file).getFileScopeProvider().getFileScope(file)
}
override fun <T> getFrontendService(element: JetElement, serviceClass: Class<T>): T {
return cache.getService(element, serviceClass)
}
override fun <T> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
return cache.getService(moduleDescriptor, serviceClass)
}
override fun resolveImportReference(moduleDescriptor: ModuleDescriptor, fqName: FqName): Collection<DeclarationDescriptor> {
val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false))
val resolveSession = cache.getLazyResolveSession(moduleDescriptor)
val resolver = resolveSession.getQualifiedExpressionResolver()
return resolver.processImportReference(
val qualifiedExpressionResolver = this.getService<QualifiedExpressionResolver>(moduleDescriptor)
return qualifiedExpressionResolver.processImportReference(
importDirective, moduleDescriptor, BindingTraceContext(), QualifiedExpressionResolver.LookupMode.EVERYTHING).getAllDescriptors()
}
@@ -29,19 +29,21 @@ import com.intellij.util.containers.SLRUCache
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.analyzer.analyzeInContext
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.SimpleGlobalContext
import org.jetbrains.kotlin.context.GlobalContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.frontend.di.createContainerForLazyBodyResolve
import org.jetbrains.kotlin.idea.project.ResolveSessionForBodies
import org.jetbrains.kotlin.idea.project.ResolveElementCache
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.util.getScopeAndDataFlowForAnalyzeFragment
import org.jetbrains.kotlin.types.TypeUtils
import java.util.HashMap
@@ -61,11 +63,31 @@ private class KotlinResolveCache(
val moduleResolverProvider: ModuleResolverProvider
get() = resolverCache.getValue()
public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies {
return moduleResolverProvider.resolveSessionForBodiesByModule(element.getModuleInfo())
public fun getLazyResolveSession(element: JetElement): ResolveSession {
return moduleResolverProvider.resolverByModule(element.getModuleInfo()).componentProvider.get<ResolveSession>()
}
public fun getLazyResolveSession(moduleDescriptor: ModuleDescriptor): ResolveSessionForBodies {
public fun <T> getService(element: JetElement, serviceClass: Class<T>): T {
//TODO_R:
return moduleResolverProvider.resolverForProject.resolverForModule(element.getModuleInfo()).componentProvider.resolve(serviceClass)?.getValue() as T
}
public fun <T> getService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
//TODO_R:
return moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor).componentProvider.resolve(serviceClass)?.getValue() as T
}
public fun <T> getIdeService(element: JetElement, serviceClass: Class<T>): T {
//TODO_R:
return moduleResolverProvider.resolverForProject.resolverForModule(element.getModuleInfo()).componentProvider.create(serviceClass)
}
public fun <T> getIdeService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
//TODO_R:
return moduleResolverProvider.resolverForProject.resolverForModuleDescriptor(moduleDescriptor).componentProvider.create(serviceClass)
}
public fun getLazyResolveSession(moduleDescriptor: ModuleDescriptor): ResolveSession {
return moduleResolverProvider.resolveSessionForBodiesByDescriptor(moduleDescriptor)
}
@@ -78,7 +100,7 @@ private class KotlinResolveCache(
val resolverProvider = moduleResolverProvider
val results = object : SLRUCache<JetFile, PerFileAnalysisCache>(2, 3) {
override fun createValue(file: JetFile?): PerFileAnalysisCache {
return PerFileAnalysisCache(file!!, resolverProvider.resolveSessionForBodiesByModule(file.getModuleInfo()))
return PerFileAnalysisCache(file!!, resolverProvider.resolverByModule(file.getModuleInfo()).componentProvider)
}
}
CachedValueProvider.Result(results, PsiModificationTracker.MODIFICATION_COUNT, resolverProvider.exceptionTracker)
@@ -105,7 +127,7 @@ private class KotlinResolveCache(
}
}
private class PerFileAnalysisCache(val file: JetFile, val resolveSession: ResolveSessionForBodies) {
private class PerFileAnalysisCache(val file: JetFile, val componentProvider: ComponentProvider) {
private val cache = HashMap<PsiElement, AnalysisResult>()
private fun lookUp(analyzableElement: JetElement): AnalysisResult? {
@@ -156,7 +178,7 @@ private class PerFileAnalysisCache(val file: JetFile, val resolveSession: Resolv
}
try {
return KotlinResolveDataProvider.analyze(project, resolveSession, analyzableElement)
return KotlinResolveDataProvider.analyze(project, componentProvider, analyzableElement)
}
catch (e: ProcessCanceledException) {
throw e
@@ -210,11 +232,11 @@ private object KotlinResolveDataProvider {
?: element.getContainingJetFile()
}
fun analyze(project: Project, resolveSession: ResolveSessionForBodies, analyzableElement: JetElement): AnalysisResult {
fun analyze(project: Project, componentProvider: ComponentProvider, analyzableElement: JetElement): AnalysisResult {
try {
val module = resolveSession.getModuleDescriptor()
val module = componentProvider.get<ModuleDescriptor>()
if (analyzableElement is JetCodeFragment) {
return AnalysisResult.success(analyzeExpressionCodeFragment(resolveSession, analyzableElement), module)
return AnalysisResult.success(analyzeExpressionCodeFragment(componentProvider, analyzableElement), module)
}
val file = analyzableElement.getContainingJetFile()
@@ -223,17 +245,18 @@ private object KotlinResolveDataProvider {
file.putUserData(LibrarySourceHacks.SKIP_TOP_LEVEL_MEMBERS, true)
}
val resolveSession = componentProvider.get<ResolveSession>()
val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + analyzableElement)
val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.getContainingJetFile())
val globalContext = SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker())
val moduleContext = globalContext.withProject(project).withModule(module)
val lazyTopDownAnalyzer = createContainerForLazyBodyResolve(
moduleContext,
//TODO: should get ModuleContext
componentProvider.get<GlobalContext>().withProject(project).withModule(module),
resolveSession,
trace,
targetPlatform,
resolveSession.getBodyResolveCache()
componentProvider.get<BodyResolveCache>()
).get<LazyTopDownAnalyzerForTopLevel>()
lazyTopDownAnalyzer.analyzeDeclarations(
@@ -259,12 +282,13 @@ private object KotlinResolveDataProvider {
}
}
private fun analyzeExpressionCodeFragment(resolveSession: ResolveSessionForBodies, codeFragment: JetCodeFragment): BindingContext {
private fun analyzeExpressionCodeFragment(componentProvider: ComponentProvider, codeFragment: JetCodeFragment): BindingContext {
val codeFragmentExpression = codeFragment.getContentElement()
if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY
val resolveSession = componentProvider.get<ResolveSession>()
val (scopeForContextElement, dataFlowInfo) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(resolveSession) {
resolveSession.resolveToElement(it, BodyResolveMode.PARTIAL_FOR_COMPLETION) //TODO: discuss it
componentProvider.get<ResolveElementCache>().resolveToElement(it, BodyResolveMode.PARTIAL_FOR_COMPLETION) //TODO: discuss it
} ?: return BindingContext.EMPTY
@@ -22,22 +22,22 @@ import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.project.IdeEnvironment
import org.jetbrains.kotlin.idea.project.ResolveSessionForBodies
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.utils.keysToMap
fun createModuleResolverProvider(
project: Project,
globalContext: GlobalContextImpl,
analyzerFacade: AnalyzerFacade<out ResolverForModule, JvmPlatformParameters>,
analyzerFacade: AnalyzerFacade<JvmPlatformParameters>,
syntheticFiles: Collection<JetFile>,
delegateProvider: ModuleResolverProvider,
moduleFilter: (IdeaModuleInfo) -> Boolean
@@ -51,7 +51,7 @@ fun createModuleResolverProvider(
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
fun createResolverForProject(): ResolverForProject<IdeaModuleInfo, ResolverForModule> {
fun createResolverForProject(): ResolverForProject<IdeaModuleInfo> {
val modulesContent = { module: IdeaModuleInfo ->
ModuleContent(syntheticFilesByModule[module] ?: listOf(), module.contentScope())
}
@@ -71,17 +71,8 @@ fun createModuleResolverProvider(
val resolverForProject = createResolverForProject()
val moduleDescriptors = modulesToCreateResolversFor.map { resolverForProject.descriptorForModule(it) }
val resolveSessionsForBodyByDescriptor = moduleDescriptors.keysToMap {
descriptor ->
globalContext.storageManager.createLazyValue {
val analyzer = resolverForProject.resolverForModuleDescriptor(descriptor)
ResolveSessionForBodies(project, analyzer.lazyResolveSession)
}
}
return ModuleResolverProviderImpl(
resolverForProject,
resolveSessionsForBodyByDescriptor,
globalContext,
delegateProvider
)
@@ -116,36 +107,34 @@ interface ModuleResolverProvider {
val exceptionTracker: ExceptionTracker
fun resolverByModule(module: IdeaModuleInfo): ResolverForModule = resolverForProject.resolverForModule(module)
fun resolveSessionForBodiesByModule(module: IdeaModuleInfo): ResolveSessionForBodies {
fun resolveSessionForBodiesByModule(module: IdeaModuleInfo): ResolveSession {
return resolveSessionForBodiesByDescriptor(resolverForProject.descriptorForModule(module))
}
fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSessionForBodies
val resolverForProject: ResolverForProject<IdeaModuleInfo, ResolverForModule>
fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSession
val resolverForProject: ResolverForProject<IdeaModuleInfo>
}
object EmptyModuleResolverProvider: ModuleResolverProvider {
override val exceptionTracker: ExceptionTracker
get() = throw IllegalStateException("Should not be called")
override val resolverForProject: ResolverForProject<IdeaModuleInfo, ResolverForModule> = EmptyResolverForProject()
override val resolverForProject: ResolverForProject<IdeaModuleInfo> = EmptyResolverForProject()
override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSessionForBodies {
override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSession {
throw IllegalStateException("Trying to obtain resolve session for $descriptor not present in this resolver")
}
}
class ModuleResolverProviderImpl(
override val resolverForProject: ResolverForProject<IdeaModuleInfo, ResolverForModule>,
private val bodiesResolveByDescriptor: Map<ModuleDescriptor, () -> ResolveSessionForBodies>,
override val resolverForProject: ResolverForProject<IdeaModuleInfo>,
val globalContext: GlobalContextImpl,
val delegateProvider: ModuleResolverProvider = EmptyModuleResolverProvider
): ModuleResolverProvider {
override val exceptionTracker: ExceptionTracker = globalContext.exceptionTracker
override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSessionForBodies {
val computation = bodiesResolveByDescriptor[descriptor] ?: return delegateProvider.resolveSessionForBodiesByDescriptor(descriptor)
return computation()
override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSession {
return resolverForProject.resolverForModuleDescriptor(descriptor).componentProvider.get<ResolveSession>()
}
}
@@ -44,6 +44,14 @@ public interface ResolutionFacade {
public fun <T> get(extension: CacheExtension<T>): T
public fun <T> getFrontendService(element: JetElement, serviceClass: Class<T>): T
public fun <T> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
public fun <T> getIdeService(element: JetElement, serviceClass: Class<T>): T
public fun <T> getIdeService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T
companion object {
//NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data )
// this scope can't be used to search for kotlin declarations in index in order to resolve in that case
@@ -56,3 +64,15 @@ public interface ResolutionFacade {
}
}
}
public inline fun <reified T> ResolutionFacade.getService(element: JetElement): T
= this.getFrontendService(element, javaClass<T>())
public inline fun <reified T> ResolutionFacade.getService(moduleDescriptor: ModuleDescriptor): T
= this.getFrontendService(moduleDescriptor, javaClass<T>())
public inline fun <reified T> ResolutionFacade.ideService(element: JetElement): T
= this.getIdeService(element, javaClass<T>())
public inline fun <reified T> ResolutionFacade.ideService(moduleDescriptor: ModuleDescriptor): T
= this.getIdeService(moduleDescriptor, javaClass<T>())
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.idea.project
import org.jetbrains.kotlin.analyzer.AnalyzerFacade
import org.jetbrains.kotlin.analyzer.ResolverForModule
import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -28,7 +27,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
public object AnalyzerFacadeProvider {
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now)
// otherwise we would be forced to add casts on the call site of setupResolverForProject
public fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade<out ResolverForModule, JvmPlatformParameters> {
public fun getAnalyzerFacade(targetPlatform: TargetPlatform): AnalyzerFacade<JvmPlatformParameters> {
return when (targetPlatform) {
JvmPlatform -> JvmAnalyzerFacade
JsPlatform -> JsAnalyzerFacade
@@ -1,149 +0,0 @@
/*
* 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.idea.project;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
import org.jetbrains.kotlin.resolve.BodyResolveCache;
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver;
import org.jetbrains.kotlin.resolve.lazy.*;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.storage.ExceptionTracker;
import org.jetbrains.kotlin.storage.StorageManager;
import java.util.Collection;
public class ResolveSessionForBodies implements KotlinCodeAnalyzer {
private final Object createdForObject;
private final ResolveSession resolveSession;
private final ResolveElementCache resolveElementCache;
public ResolveSessionForBodies(@NotNull Project project, @NotNull ResolveSession resolveSession) {
this(project, project, resolveSession);
}
private ResolveSessionForBodies(Object createdForObject, Project project, ResolveSession resolveSession) {
this.createdForObject = createdForObject;
this.resolveSession = resolveSession;
this.resolveElementCache = new ResolveElementCache(resolveSession, project);
}
@NotNull
public BindingContext resolveToElement(JetElement element, BodyResolveMode bodyResolveMode) {
return resolveElementCache.resolveToElement(element, bodyResolveMode);
}
@NotNull
@Override
public ModuleDescriptor getModuleDescriptor() {
return resolveSession.getModuleDescriptor();
}
@NotNull
@Override
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
return resolveSession.getClassDescriptor(classOrObject);
}
@NotNull
@Override
public BindingContext getBindingContext() {
return resolveSession.getBindingContext();
}
@NotNull
@Override
public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) {
return resolveSession.resolveToDescriptor(declaration);
}
@Override
public void forceResolveAll() {
resolveSession.forceResolveAll();
}
@Override
public String toString() {
return "ResolveSessionForBodies: " + resolveSession.getExceptionTracker().getModificationCount()
+ " " + createdForObject + " " + createdForObject.hashCode();
}
@Override
@Nullable
public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
return resolveSession.getPackageFragment(fqName);
}
@Override
@NotNull
@ReadOnly
public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName) {
return resolveSession.getTopLevelClassDescriptors(fqName);
}
@Override
@NotNull
public ScriptDescriptor getScriptDescriptor(@NotNull JetScript script) {
return resolveSession.getScriptDescriptor(script);
}
@NotNull
@Override
public DeclarationScopeProvider getDeclarationScopeProvider() {
return resolveSession.getDeclarationScopeProvider();
}
@NotNull
@Override
public FileScopeProvider getFileScopeProvider() {
return resolveSession.getFileScopeProvider();
}
@NotNull
public StorageManager getStorageManager() {
return resolveSession.getStorageManager();
}
@NotNull
public ExceptionTracker getExceptionTracker() {
return resolveSession.getExceptionTracker();
}
@NotNull
public BodyResolveCache getBodyResolveCache() {
return resolveElementCache;
}
@NotNull
@Override
public PackageFragmentProvider getPackageFragmentProvider() {
return resolveSession.getPackageFragmentProvider();
}
@NotNull
public QualifiedExpressionResolver getQualifiedExpressionResolver() {
return resolveSession.getQualifiedExpressionResolver();
}
}