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 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 { object DynamicComponentDescriptor : ValueDescriptor {
override fun getValue(): Any = throw UnsupportedOperationException() override fun getValue(): Any = throw UnsupportedOperationException()
override fun toString(): String = "Dynamic" 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) } public val unknownContext: ComponentResolveContext by lazy { ComponentResolveContext(this, DynamicComponentDescriptor) }
val componentStorage = ComponentStorage(id) val componentStorage = ComponentStorage(id)
@@ -54,10 +59,14 @@ public class StorageComponentContainer(id: String) : ComponentContainer, Closeab
override fun close() = componentStorage.dispose() 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) 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? { private fun resolveIterable(request: Type, context: ValueResolveContext): ValueDescriptor? {
if (request !is ParameterizedType) return null if (request !is ParameterizedType) return null
val rawType = request.getRawType() val rawType = request.getRawType()
@@ -86,6 +95,12 @@ public class StorageComponentContainer(id: String) : ComponentContainer, Closeab
componentStorage.registerDescriptors(unknownContext, descriptors) componentStorage.registerDescriptors(unknownContext, descriptors)
return this 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 { public fun StorageComponentContainer.registerSingleton(klass: Class<*>): StorageComponentContainer {
@@ -29,14 +29,14 @@ public inline fun <reified T> StorageComponentContainer.useImpl() {
registerSingleton(javaClass<T>()) registerSingleton(javaClass<T>())
} }
public inline fun <reified T> StorageComponentContainer.get(): T { public inline fun <reified T> ComponentProvider.get(): T {
return resolve(javaClass<T>(), unknownContext)!!.getValue() as T return resolve(javaClass<T>())!!.getValue() as T
} }
public fun StorageComponentContainer.useInstance(instance: Any) { public fun StorageComponentContainer.useInstance(instance: Any) {
registerInstance(instance) 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 return resolve(javaClass<T>())!!.getValue() as T
} }
@@ -70,7 +70,7 @@ public fun StorageComponentContainer.configureJavaTopDownAnalysis(moduleContentS
public fun createContainerForLazyResolveWithJava( public fun createContainerForLazyResolveWithJava(
moduleContext: ModuleContext, bindingTrace: BindingTrace, declarationProviderFactory: DeclarationProviderFactory, moduleContext: ModuleContext, bindingTrace: BindingTrace, declarationProviderFactory: DeclarationProviderFactory,
moduleContentScope: GlobalSearchScope, moduleClassResolver: ModuleClassResolver, targetEnvironment: TargetEnvironment = CompilerEnvironment moduleContentScope: GlobalSearchScope, moduleClassResolver: ModuleClassResolver, targetEnvironment: TargetEnvironment = CompilerEnvironment
): Pair<ResolveSession, JavaDescriptorResolver> = createContainer("LazyResolveWithJava") { ): ComponentProvider = createContainer("LazyResolveWithJava") {
configureModule(moduleContext, JvmPlatform, bindingTrace) configureModule(moduleContext, JvmPlatform, bindingTrace)
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, LookupTracker.DO_NOTHING) configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, LookupTracker.DO_NOTHING)
@@ -82,10 +82,8 @@ public fun createContainerForLazyResolveWithJava(
useImpl<FileScopeProviderImpl>() useImpl<FileScopeProviderImpl>()
useImpl<LazyResolveToken>() useImpl<LazyResolveToken>()
}.let { }.apply {
it.javaAnalysisInit() javaAnalysisInit()
Pair(it.get<ResolveSession>(), it.get<JavaDescriptorResolver>())
} }
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.resolve.jvm
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.ModuleParameters 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.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider import org.jetbrains.kotlin.extensions.ExternalDeclarationsProvider
@@ -36,18 +36,12 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import java.util.ArrayList import java.util.ArrayList
import kotlin.platform.platformStatic import kotlin.platform.platformStatic
public class JvmResolverForModule(
override val lazyResolveSession: ResolveSession,
override val packageFragmentProvider: PackageFragmentProvider,
public val javaDescriptorResolver: JavaDescriptorResolver
) : ResolverForModule
public class JvmPlatformParameters( public class JvmPlatformParameters(
public val moduleByJavaClass: (JavaClass) -> ModuleInfo public val moduleByJavaClass: (JavaClass) -> ModuleInfo
) : PlatformAnalysisParameters ) : PlatformAnalysisParameters
public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatformParameters> { public object JvmAnalyzerFacade : AnalyzerFacade<JvmPlatformParameters> {
override fun <M : ModuleInfo> createResolverForModule( override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M, moduleInfo: M,
moduleDescriptor: ModuleDescriptorImpl, moduleDescriptor: ModuleDescriptorImpl,
@@ -55,8 +49,8 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
moduleContent: ModuleContent, moduleContent: ModuleContent,
platformParameters: JvmPlatformParameters, platformParameters: JvmPlatformParameters,
targetEnvironment: TargetEnvironment, targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, JvmResolverForModule> resolverForProject: ResolverForProject<M>
): JvmResolverForModule { ): ResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent val (syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project val project = moduleContext.project
val filesToAnalyze = getAllFilesToAnalyze(project, moduleInfo, syntheticFiles) val filesToAnalyze = getAllFilesToAnalyze(project, moduleInfo, syntheticFiles)
@@ -67,9 +61,9 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
val moduleClassResolver = ModuleClassResolverImpl { javaClass -> val moduleClassResolver = ModuleClassResolverImpl { javaClass ->
val moduleInfo = platformParameters.moduleByJavaClass(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, moduleContext,
CodeAnalyzerInitializer.getInstance(project).createTrace(), CodeAnalyzerInitializer.getInstance(project).createTrace(),
declarationProviderFactory, declarationProviderFactory,
@@ -77,9 +71,11 @@ public object JvmAnalyzerFacade : AnalyzerFacade<JvmResolverForModule, JvmPlatfo
moduleClassResolver, moduleClassResolver,
targetEnvironment targetEnvironment
) )
val resolveSession = container.get<ResolveSession>()
val javaDescriptorResolver = container.get<JavaDescriptorResolver>()
val providersForModule = listOf(resolveSession.getPackageFragmentProvider(), javaDescriptorResolver.packageFragmentProvider) val providersForModule = listOf(resolveSession.getPackageFragmentProvider(), javaDescriptorResolver.packageFragmentProvider)
return JvmResolverForModule(resolveSession, CompositePackageFragmentProvider(providersForModule), javaDescriptorResolver) return ResolverForModule(CompositePackageFragmentProvider(providersForModule), container)
} }
override val moduleParameters: ModuleParameters override val moduleParameters: ModuleParameters
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.analyzer
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.context.withModule 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.name.Name
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.TargetEnvironment import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import java.util.ArrayList import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
public interface ResolverForModule { public class ResolverForModule(
public val lazyResolveSession: ResolveSession public val packageFragmentProvider: PackageFragmentProvider,
public val packageFragmentProvider: PackageFragmentProvider public val componentProvider: ComponentProvider
} )
public interface ResolverForProject<M : ModuleInfo,out R : ResolverForModule> { public interface ResolverForProject<M : ModuleInfo> {
public fun resolverForModule(moduleInfo: M): R = resolverForModuleDescriptor(descriptorForModule(moduleInfo)) public fun resolverForModule(moduleInfo: M): ResolverForModule = resolverForModuleDescriptor(descriptorForModule(moduleInfo))
public fun descriptorForModule(moduleInfo: M): ModuleDescriptor public fun descriptorForModule(moduleInfo: M): ModuleDescriptor
public fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R public fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): ResolverForModule
val allModules: Collection<M> val allModules: Collection<M>
} }
public class EmptyResolverForProject<M : ModuleInfo, R : ResolverForModule> : ResolverForProject<M, R> { public class EmptyResolverForProject<M : ModuleInfo> : ResolverForProject<M> {
override fun resolverForModuleDescriptor(descriptor: ModuleDescriptor): R = throw IllegalStateException("$descriptor is not contained in this resolver") 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 fun descriptorForModule(moduleInfo: M) = throw IllegalStateException("Should not be called for $moduleInfo")
override val allModules: Collection<M> = listOf() override val allModules: Collection<M> = listOf()
} }
public class ResolverForProjectImpl<M : ModuleInfo, R : ResolverForModule>( public class ResolverForProjectImpl<M : ModuleInfo>(
val descriptorByModule: Map<M, ModuleDescriptorImpl>, val descriptorByModule: Map<M, ModuleDescriptorImpl>,
val delegateResolver: ResolverForProject<M, R> = EmptyResolverForProject() val delegateResolver: ResolverForProject<M> = EmptyResolverForProject()
) : ResolverForProject<M, R> { ) : ResolverForProject<M> {
val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> R> = HashMap() val resolverByModuleDescriptor: MutableMap<ModuleDescriptor, () -> ResolverForModule> = HashMap()
override val allModules: Collection<M> by lazy { override val allModules: Collection<M> by lazy {
(descriptorByModule.keySet() + delegateResolver.allModules).toSet() (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) val computation = resolverByModuleDescriptor[descriptor] ?: return delegateResolver.resolverForModuleDescriptor(descriptor)
return computation() 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( public fun <M : ModuleInfo> setupResolverForProject(
projectContext: ProjectContext, projectContext: ProjectContext,
modules: Collection<M>, modules: Collection<M>,
modulesContent: (M) -> ModuleContent, modulesContent: (M) -> ModuleContent,
platformParameters: P, platformParameters: P,
targetEnvironment: TargetEnvironment, targetEnvironment: TargetEnvironment,
delegateResolver: ResolverForProject<M, A> = EmptyResolverForProject() delegateResolver: ResolverForProject<M> = EmptyResolverForProject()
): ResolverForProject<M, A> { ): ResolverForProject<M> {
val storageManager = projectContext.storageManager val storageManager = projectContext.storageManager
fun createResolverForProject(): ResolverForProjectImpl<M, A> { fun createResolverForProject(): ResolverForProjectImpl<M> {
val descriptorByModule = HashMap<M, ModuleDescriptorImpl>() val descriptorByModule = HashMap<M, ModuleDescriptorImpl>()
modules.forEach { modules.forEach {
module -> module ->
@@ -204,8 +204,8 @@ public interface AnalyzerFacade<A : ResolverForModule, in P : PlatformAnalysisPa
moduleContent: ModuleContent, moduleContent: ModuleContent,
platformParameters: P, platformParameters: P,
targetEnvironment: TargetEnvironment, targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, A> resolverForProject: ResolverForProject<M>
): A ): ResolverForModule
public val moduleParameters: ModuleParameters public val moduleParameters: ModuleParameters
} }
@@ -101,7 +101,7 @@ public fun createContainerForLazyLocalClassifierAnalyzer(
useImpl<LocalLazyDeclarationResolver>() useImpl<LocalLazyDeclarationResolver>()
} }
private fun createContainerForLazyResolve( public fun createContainerForLazyResolve(
moduleContext: ModuleContext, moduleContext: ModuleContext,
declarationProviderFactory: DeclarationProviderFactory, declarationProviderFactory: DeclarationProviderFactory,
bindingTrace: BindingTrace, bindingTrace: BindingTrace,
@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModule
import org.jetbrains.kotlin.test.JetTestUtils import org.jetbrains.kotlin.test.JetTestUtils
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
import org.junit.Assert import org.junit.Assert
@@ -64,7 +64,8 @@ public class MultiModuleJavaAnalysisCustomTest : UsefulTestCase() {
javaClass -> javaClass ->
val moduleName = javaClass.getName().asString().toLowerCase().first().toString() val moduleName = javaClass.getName().asString().toLowerCase().first().toString()
modules.first { it._name == moduleName } modules.first { it._name == moduleName }
} },
CompilerEnvironment
) )
performChecks(resolverForProject, modules) performChecks(resolverForProject, modules)
@@ -101,7 +102,7 @@ public class MultiModuleJavaAnalysisCustomTest : UsefulTestCase() {
return modules.values().toList() 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 { modules.forEach {
module -> module ->
val moduleDescriptor = resolverForProject.descriptorForModule(module) val moduleDescriptor = resolverForProject.descriptorForModule(module)
@@ -20,9 +20,11 @@ import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.ModuleContent import org.jetbrains.kotlin.analyzer.ModuleContent
import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile 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.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
@@ -36,9 +38,10 @@ public fun createResolveSessionForFiles(
val resolverForProject = JvmAnalyzerFacade.setupResolverForProject( val resolverForProject = JvmAnalyzerFacade.setupResolverForProject(
projectContext, listOf(testModule), projectContext, listOf(testModule),
{ ModuleContent(syntheticFiles, GlobalSearchScope.allScope(project)) }, { 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 { 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.*; import org.jetbrains.kotlin.asJava.*;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
import org.jetbrains.kotlin.idea.decompiler.navigation.JetSourceNavigationHelper; 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.JetFullClassNameIndex;
import org.jetbrains.kotlin.idea.stubindex.JetTopLevelClassByPackageIndex; import org.jetbrains.kotlin.idea.stubindex.JetTopLevelClassByPackageIndex;
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil; 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.BodyResolveMode;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.JetScope;
import java.io.IOException; import java.io.IOException;
@@ -93,7 +90,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
Collections.sort(sortedFiles, scopeFileComparator); Collections.sort(sortedFiles, scopeFileComparator);
JetFile file = sortedFiles.get(0); JetFile file = sortedFiles.get(0);
ResolveSessionForBodies session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file); ResolveSession session = KotlinCacheService.getInstance(file.getProject()).getLazyResolveSession(file);
forceResolvePackageDeclarations(files, session); forceResolvePackageDeclarations(files, session);
return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor()); return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor());
} }
@@ -101,24 +98,26 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
@NotNull @NotNull
@Override @Override
public LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject) { 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()) { if (classOrObject.isLocal()) {
BindingContext bindingContext = session.resolveToElement(classOrObject, BodyResolveMode.FULL);
ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject); ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject);
if (descriptor == null) { if (descriptor == null) {
LOG.warn("No class descriptor in context for class: " + PsiUtilPackage.getElementTextWithContext(classOrObject)); 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); ForceResolveUtil.forceResolveAllContents(descriptor);
return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor()); return new LightClassConstructionContext(bindingContext, moduleDescriptor);
} }
ForceResolveUtil.forceResolveAllContents(session.getClassDescriptor(classOrObject)); ForceResolveUtil.forceResolveAllContents(resolutionFacade.resolveToDescriptor(classOrObject));
return new LightClassConstructionContext(session.getBindingContext(), session.getModuleDescriptor()); return new LightClassConstructionContext(bindingContext, moduleDescriptor);
} }
private static void forceResolvePackageDeclarations(@NotNull Collection<JetFile> files, @NotNull KotlinCodeAnalyzer session) { 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.openapi.project.Project
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.* import org.jetbrains.kotlin.load.java.structure.impl.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver 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.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.scopes.JetScope 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> { override fun getData(resolverProvider: ModuleResolverProvider): (PsiElement) -> Pair<JavaDescriptorResolver, BindingContext> {
return { return {
val resolverForModule = resolverProvider.resolverByModule(it.getModuleInfo()) as JvmResolverForModule val componentProvider = resolverProvider.resolverByModule(it.getModuleInfo()).componentProvider
Pair(resolverForModule.javaDescriptorResolver, resolverForModule.lazyResolveSession.getBindingContext()) 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.psi.search.GlobalSearchScope
import com.intellij.util.PathUtil import com.intellij.util.PathUtil
import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.descriptors.ModuleParameters 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.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl 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.idea.framework.KotlinJavaScriptLibraryDetectionUtil
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.js.resolve.JsPlatform 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.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.types.DynamicTypesAllowed
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
public class JsResolverForModule( public object JsAnalyzerFacade : AnalyzerFacade<PlatformAnalysisParameters> {
override val lazyResolveSession: ResolveSession,
override val packageFragmentProvider: PackageFragmentProvider
) : ResolverForModule
public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAnalysisParameters> {
override fun <M : ModuleInfo> createResolverForModule( override fun <M : ModuleInfo> createResolverForModule(
moduleInfo: M, moduleInfo: M,
@@ -51,16 +45,16 @@ public object JsAnalyzerFacade : AnalyzerFacade<JsResolverForModule, PlatformAna
moduleContent: ModuleContent, moduleContent: ModuleContent,
platformParameters: PlatformAnalysisParameters, platformParameters: PlatformAnalysisParameters,
targetEnvironment: TargetEnvironment, targetEnvironment: TargetEnvironment,
resolverForProject: ResolverForProject<M, JsResolverForModule> resolverForProject: ResolverForProject<M>
): JsResolverForModule { ): ResolverForModule {
val (syntheticFiles, moduleContentScope) = moduleContent val (syntheticFiles, moduleContentScope) = moduleContent
val project = moduleContext.project val project = moduleContext.project
val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
project, moduleContext.storageManager, syntheticFiles, if (moduleInfo.isLibrary) GlobalSearchScope.EMPTY_SCOPE else moduleContentScope project, moduleContext.storageManager, syntheticFiles, if (moduleInfo.isLibrary) GlobalSearchScope.EMPTY_SCOPE else moduleContentScope
) )
val resolveSession = createLazyResolveSession(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment) val container = createContainerForLazyResolve(moduleContext, declarationProviderFactory, BindingTraceContext(), JsPlatform, targetEnvironment)
var packageFragmentProvider = resolveSession.getPackageFragmentProvider() var packageFragmentProvider = container.get<ResolveSession>().getPackageFragmentProvider()
if (moduleInfo is LibraryInfo && KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(moduleInfo.library)) { if (moduleInfo is LibraryInfo && KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(moduleInfo.library)) {
val providers = moduleInfo.library.getFiles(OrderRootType.CLASSES) 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 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.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.project.AnalyzerFacadeProvider 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.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.js.resolve.JsPlatform 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.*
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode 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.resolve.scopes.JetScope
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
import kotlin.platform.platformStatic 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() val file = element.getContainingJetFile()
return getCacheToAnalyzeFiles(listOf(file)).getLazyResolveSession(file) 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 { 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 { 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 { 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) 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> { override fun resolveImportReference(moduleDescriptor: ModuleDescriptor, fqName: FqName): Collection<DeclarationDescriptor> {
val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false)) val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false))
val resolveSession = cache.getLazyResolveSession(moduleDescriptor) val qualifiedExpressionResolver = this.getService<QualifiedExpressionResolver>(moduleDescriptor)
val resolver = resolveSession.getQualifiedExpressionResolver() return qualifiedExpressionResolver.processImportReference(
return resolver.processImportReference(
importDirective, moduleDescriptor, BindingTraceContext(), QualifiedExpressionResolver.LookupMode.EVERYTHING).getAllDescriptors() 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.AnalysisResult
import org.jetbrains.kotlin.analyzer.analyzeInContext import org.jetbrains.kotlin.analyzer.analyzeInContext
import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.container.ComponentProvider
import org.jetbrains.kotlin.container.get 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.withModule
import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.frontend.di.createContainerForLazyBodyResolve 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.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode 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.resolve.util.getScopeAndDataFlowForAnalyzeFragment
import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.TypeUtils
import java.util.HashMap import java.util.HashMap
@@ -61,11 +63,31 @@ private class KotlinResolveCache(
val moduleResolverProvider: ModuleResolverProvider val moduleResolverProvider: ModuleResolverProvider
get() = resolverCache.getValue() get() = resolverCache.getValue()
public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies { public fun getLazyResolveSession(element: JetElement): ResolveSession {
return moduleResolverProvider.resolveSessionForBodiesByModule(element.getModuleInfo()) 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) return moduleResolverProvider.resolveSessionForBodiesByDescriptor(moduleDescriptor)
} }
@@ -78,7 +100,7 @@ private class KotlinResolveCache(
val resolverProvider = moduleResolverProvider val resolverProvider = moduleResolverProvider
val results = object : SLRUCache<JetFile, PerFileAnalysisCache>(2, 3) { val results = object : SLRUCache<JetFile, PerFileAnalysisCache>(2, 3) {
override fun createValue(file: JetFile?): PerFileAnalysisCache { 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) 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 val cache = HashMap<PsiElement, AnalysisResult>()
private fun lookUp(analyzableElement: JetElement): AnalysisResult? { private fun lookUp(analyzableElement: JetElement): AnalysisResult? {
@@ -156,7 +178,7 @@ private class PerFileAnalysisCache(val file: JetFile, val resolveSession: Resolv
} }
try { try {
return KotlinResolveDataProvider.analyze(project, resolveSession, analyzableElement) return KotlinResolveDataProvider.analyze(project, componentProvider, analyzableElement)
} }
catch (e: ProcessCanceledException) { catch (e: ProcessCanceledException) {
throw e throw e
@@ -210,11 +232,11 @@ private object KotlinResolveDataProvider {
?: element.getContainingJetFile() ?: element.getContainingJetFile()
} }
fun analyze(project: Project, resolveSession: ResolveSessionForBodies, analyzableElement: JetElement): AnalysisResult { fun analyze(project: Project, componentProvider: ComponentProvider, analyzableElement: JetElement): AnalysisResult {
try { try {
val module = resolveSession.getModuleDescriptor() val module = componentProvider.get<ModuleDescriptor>()
if (analyzableElement is JetCodeFragment) { if (analyzableElement is JetCodeFragment) {
return AnalysisResult.success(analyzeExpressionCodeFragment(resolveSession, analyzableElement), module) return AnalysisResult.success(analyzeExpressionCodeFragment(componentProvider, analyzableElement), module)
} }
val file = analyzableElement.getContainingJetFile() val file = analyzableElement.getContainingJetFile()
@@ -223,17 +245,18 @@ private object KotlinResolveDataProvider {
file.putUserData(LibrarySourceHacks.SKIP_TOP_LEVEL_MEMBERS, true) file.putUserData(LibrarySourceHacks.SKIP_TOP_LEVEL_MEMBERS, true)
} }
val resolveSession = componentProvider.get<ResolveSession>()
val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + analyzableElement) val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + analyzableElement)
val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.getContainingJetFile()) val targetPlatform = TargetPlatformDetector.getPlatform(analyzableElement.getContainingJetFile())
val globalContext = SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker())
val moduleContext = globalContext.withProject(project).withModule(module)
val lazyTopDownAnalyzer = createContainerForLazyBodyResolve( val lazyTopDownAnalyzer = createContainerForLazyBodyResolve(
moduleContext, //TODO: should get ModuleContext
componentProvider.get<GlobalContext>().withProject(project).withModule(module),
resolveSession, resolveSession,
trace, trace,
targetPlatform, targetPlatform,
resolveSession.getBodyResolveCache() componentProvider.get<BodyResolveCache>()
).get<LazyTopDownAnalyzerForTopLevel>() ).get<LazyTopDownAnalyzerForTopLevel>()
lazyTopDownAnalyzer.analyzeDeclarations( 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() val codeFragmentExpression = codeFragment.getContentElement()
if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY
val resolveSession = componentProvider.get<ResolveSession>()
val (scopeForContextElement, dataFlowInfo) = codeFragment.getScopeAndDataFlowForAnalyzeFragment(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 } ?: return BindingContext.EMPTY
@@ -22,22 +22,22 @@ import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootManager
import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.*
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.withProject import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.project.IdeEnvironment 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.JavaClass
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.storage.ExceptionTracker import org.jetbrains.kotlin.storage.ExceptionTracker
import org.jetbrains.kotlin.utils.keysToMap
fun createModuleResolverProvider( fun createModuleResolverProvider(
project: Project, project: Project,
globalContext: GlobalContextImpl, globalContext: GlobalContextImpl,
analyzerFacade: AnalyzerFacade<out ResolverForModule, JvmPlatformParameters>, analyzerFacade: AnalyzerFacade<JvmPlatformParameters>,
syntheticFiles: Collection<JetFile>, syntheticFiles: Collection<JetFile>,
delegateProvider: ModuleResolverProvider, delegateProvider: ModuleResolverProvider,
moduleFilter: (IdeaModuleInfo) -> Boolean moduleFilter: (IdeaModuleInfo) -> Boolean
@@ -51,7 +51,7 @@ fun createModuleResolverProvider(
val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter) val modulesToCreateResolversFor = allModuleInfos.filter(moduleFilter)
fun createResolverForProject(): ResolverForProject<IdeaModuleInfo, ResolverForModule> { fun createResolverForProject(): ResolverForProject<IdeaModuleInfo> {
val modulesContent = { module: IdeaModuleInfo -> val modulesContent = { module: IdeaModuleInfo ->
ModuleContent(syntheticFilesByModule[module] ?: listOf(), module.contentScope()) ModuleContent(syntheticFilesByModule[module] ?: listOf(), module.contentScope())
} }
@@ -71,17 +71,8 @@ fun createModuleResolverProvider(
val resolverForProject = createResolverForProject() 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( return ModuleResolverProviderImpl(
resolverForProject, resolverForProject,
resolveSessionsForBodyByDescriptor,
globalContext, globalContext,
delegateProvider delegateProvider
) )
@@ -116,36 +107,34 @@ interface ModuleResolverProvider {
val exceptionTracker: ExceptionTracker val exceptionTracker: ExceptionTracker
fun resolverByModule(module: IdeaModuleInfo): ResolverForModule = resolverForProject.resolverForModule(module) fun resolverByModule(module: IdeaModuleInfo): ResolverForModule = resolverForProject.resolverForModule(module)
fun resolveSessionForBodiesByModule(module: IdeaModuleInfo): ResolveSessionForBodies { fun resolveSessionForBodiesByModule(module: IdeaModuleInfo): ResolveSession {
return resolveSessionForBodiesByDescriptor(resolverForProject.descriptorForModule(module)) return resolveSessionForBodiesByDescriptor(resolverForProject.descriptorForModule(module))
} }
fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSessionForBodies fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSession
val resolverForProject: ResolverForProject<IdeaModuleInfo, ResolverForModule> val resolverForProject: ResolverForProject<IdeaModuleInfo>
} }
object EmptyModuleResolverProvider: ModuleResolverProvider { object EmptyModuleResolverProvider: ModuleResolverProvider {
override val exceptionTracker: ExceptionTracker override val exceptionTracker: ExceptionTracker
get() = throw IllegalStateException("Should not be called") 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") throw IllegalStateException("Trying to obtain resolve session for $descriptor not present in this resolver")
} }
} }
class ModuleResolverProviderImpl( class ModuleResolverProviderImpl(
override val resolverForProject: ResolverForProject<IdeaModuleInfo, ResolverForModule>, override val resolverForProject: ResolverForProject<IdeaModuleInfo>,
private val bodiesResolveByDescriptor: Map<ModuleDescriptor, () -> ResolveSessionForBodies>,
val globalContext: GlobalContextImpl, val globalContext: GlobalContextImpl,
val delegateProvider: ModuleResolverProvider = EmptyModuleResolverProvider val delegateProvider: ModuleResolverProvider = EmptyModuleResolverProvider
): ModuleResolverProvider { ): ModuleResolverProvider {
override val exceptionTracker: ExceptionTracker = globalContext.exceptionTracker override val exceptionTracker: ExceptionTracker = globalContext.exceptionTracker
override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSessionForBodies { override fun resolveSessionForBodiesByDescriptor(descriptor: ModuleDescriptor): ResolveSession {
val computation = bodiesResolveByDescriptor[descriptor] ?: return delegateProvider.resolveSessionForBodiesByDescriptor(descriptor) return resolverForProject.resolverForModuleDescriptor(descriptor).componentProvider.get<ResolveSession>()
return computation()
} }
} }
@@ -44,6 +44,14 @@ public interface ResolutionFacade {
public fun <T> get(extension: CacheExtension<T>): T 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 { 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 ) //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 // 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 package org.jetbrains.kotlin.idea.project
import org.jetbrains.kotlin.analyzer.AnalyzerFacade import org.jetbrains.kotlin.analyzer.AnalyzerFacade
import org.jetbrains.kotlin.analyzer.ResolverForModule
import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade
import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -28,7 +27,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
public object AnalyzerFacadeProvider { public object AnalyzerFacadeProvider {
//NOTE: it's convenient that JS backend doesn't have platform parameters (for now) //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 // 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) { return when (targetPlatform) {
JvmPlatform -> JvmAnalyzerFacade JvmPlatform -> JvmAnalyzerFacade
JsPlatform -> JsAnalyzerFacade 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();
}
}