BuiltInsReferenceResolver: cleanup and convert to service

This commit is contained in:
Dmitry Jemerov
2015-07-30 18:14:26 +02:00
parent 79bbb820bd
commit 1c3f30bd8e
5 changed files with 60 additions and 87 deletions
@@ -51,14 +51,14 @@ public object DescriptorToSourceUtilsIde {
// References in library sources should be resolved to corresponding decompiled declarations, // References in library sources should be resolved to corresponding decompiled declarations,
// therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations // therefore we put both source declaration and decompiled declaration to stream, and afterwards we filter it in getAllDeclarations
sequenceOfLazyValues( sequenceOfLazyValues(
{ DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) }, { DescriptorToSourceUtils.getSourceFromDescriptor(effectiveReferenced) },
{ findBuiltinDeclaration(project, effectiveReferenced) ?: DecompiledNavigationUtils.getDeclarationFromDecompiledClassFile(project, effectiveReferenced) } { findBuiltinDeclaration(project, effectiveReferenced) ?: DecompiledNavigationUtils.getDeclarationFromDecompiledClassFile(project, effectiveReferenced) }
) )
}.filterNotNull() }.filterNotNull()
} }
private fun findBuiltinDeclaration(project: Project, descriptor: DeclarationDescriptor): PsiElement? { private fun findBuiltinDeclaration(project: Project, descriptor: DeclarationDescriptor): PsiElement? {
val libraryReferenceResolver = project.getComponent(javaClass<BuiltInsReferenceResolver>()) val libraryReferenceResolver = BuiltInsReferenceResolver.getInstance(project)
return libraryReferenceResolver!!.resolveBuiltInSymbol(descriptor) return libraryReferenceResolver.resolveBuiltInSymbol(descriptor)
} }
} }
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.idea.references package org.jetbrains.kotlin.idea.references
import com.google.common.collect.Sets
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.AbstractProjectComponent import com.intellij.openapi.components.AbstractProjectComponent
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupManager import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VfsUtilCore
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.context.*
import org.jetbrains.kotlin.context.MutableModuleContext import org.jetbrains.kotlin.context.MutableModuleContext
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.frontend.di.* import org.jetbrains.kotlin.frontend.di.*
import org.jetbrains.kotlin.idea.util.application.runReadAction
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.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
@@ -59,19 +60,15 @@ import java.util.HashSet
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
public class BuiltInsReferenceResolver(project: Project) : AbstractProjectComponent(project) { public class BuiltInsReferenceResolver(val project: Project, val startupManager: StartupManager) {
volatile private var moduleDescriptor: ModuleDescriptor? = null volatile private var moduleDescriptor: ModuleDescriptor? = null
volatile public var builtInsSources: Set<JetFile>? = null volatile public var builtInsSources: Set<JetFile>? = null
private set private set
volatile private var builtinsPackageFragment: PackageFragmentDescriptor? = null volatile private var builtinsPackageFragment: PackageFragmentDescriptor? = null
override fun initComponent() { init {
StartupManager.getInstance(myProject).registerPostStartupActivity(object : Runnable { startupManager.runWhenProjectIsInitialized { initialize() }
override fun run() {
initialize()
}
})
} }
private fun initialize() { private fun initialize() {
@@ -79,43 +76,39 @@ public class BuiltInsReferenceResolver(project: Project) : AbstractProjectCompon
val jetBuiltInsFiles = getJetBuiltInsFiles() val jetBuiltInsFiles = getJetBuiltInsFiles()
val initializeRunnable = object : Runnable { val initializeRunnable = { ->
override fun run() { val newModuleContext = ContextForNewModule(project, Name.special("<built-ins resolver module>"), ModuleParameters.Empty)
val newModuleContext = ContextForNewModule(myProject, Name.special("<built-ins resolver module>"), ModuleParameters.Empty) newModuleContext.setDependencies(newModuleContext.module)
newModuleContext.setDependencies(newModuleContext.module)
val declarationFactory = FileBasedDeclarationProviderFactory(newModuleContext.storageManager, jetBuiltInsFiles) val declarationFactory = FileBasedDeclarationProviderFactory(newModuleContext.storageManager, jetBuiltInsFiles)
val resolveSession = createLazyResolveSession( val resolveSession = createLazyResolveSession(
newModuleContext, newModuleContext,
declarationFactory, BindingTraceContext(), declarationFactory, BindingTraceContext(),
TargetPlatform.Default) TargetPlatform.Default)
newModuleContext.initializeModuleContents(resolveSession.getPackageFragmentProvider()) newModuleContext.initializeModuleContents(resolveSession.getPackageFragmentProvider())
if (!ApplicationManager.getApplication().isUnitTestMode()) { if (!ApplicationManager.getApplication().isUnitTestMode()) {
// Use lazy initialization in tests // Use lazy initialization in tests
resolveSession.forceResolveAll() resolveSession.forceResolveAll()
}
val packageView = newModuleContext.module.getPackage(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
val fragments = packageView.fragments
this@BuiltInsReferenceResolver.moduleDescriptor = newModuleContext.module
builtinsPackageFragment = fragments.single()
builtInsSources = Sets.newHashSet(jetBuiltInsFiles)
} }
val packageView = newModuleContext.module.getPackage(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
val fragments = packageView.fragments
this@BuiltInsReferenceResolver.moduleDescriptor = newModuleContext.module
builtinsPackageFragment = fragments.single()
builtInsSources = jetBuiltInsFiles
} }
if (ApplicationManager.getApplication().isUnitTestMode()) { if (ApplicationManager.getApplication().isUnitTestMode()) {
initializeRunnable.run() initializeRunnable()
} }
else { else {
ApplicationManager.getApplication().executeOnPooledThread(object : Runnable { ApplicationManager.getApplication().executeOnPooledThread {
override fun run() { runReadAction { initializeRunnable() }
ApplicationManager.getApplication().runReadAction(initializeRunnable) }
}
})
} }
} }
@@ -128,18 +121,17 @@ public class BuiltInsReferenceResolver(project: Project) : AbstractProjectCompon
// But in tests, sources of built-ins are not added to the classpath automatically, so we manually specify URLs for both: // But in tests, sources of built-ins are not added to the classpath automatically, so we manually specify URLs for both:
// LightClassUtil.getBuiltInsDirUrl() does so for native built-ins and the code below for compilable built-ins // LightClassUtil.getBuiltInsDirUrl() does so for native built-ins and the code below for compilable built-ins
try { try {
builtIns.addAll(getBuiltInSourceFiles(BUILT_INS_COMPILABLE_SRC_DIR.toURI().toURL())) return builtIns + getBuiltInSourceFiles(BUILT_INS_COMPILABLE_SRC_DIR.toURI().toURL())
} }
catch (e: MalformedURLException) { catch (e: MalformedURLException) {
throw rethrow(e) throw rethrow(e)
} }
} }
return builtIns return builtIns
} }
private fun getBuiltInSourceFiles(url: URL): MutableSet<JetFile> { private fun getBuiltInSourceFiles(url: URL): Set<JetFile> {
val fromUrl = VfsUtilCore.convertFromUrl(url) val fromUrl = VfsUtilCore.convertFromUrl(url)
val vf = VirtualFileManager.getInstance().findFileByUrl(fromUrl) val vf = VirtualFileManager.getInstance().findFileByUrl(fromUrl)
assert(vf != null) { "Virtual file not found by URL: $url" } assert(vf != null) { "Virtual file not found by URL: $url" }
@@ -149,13 +141,9 @@ public class BuiltInsReferenceResolver(project: Project) : AbstractProjectCompon
vf.refresh(false, true) vf.refresh(false, true)
PathUtil.getLocalFile(vf).refresh(false, true) PathUtil.getLocalFile(vf).refresh(false, true)
val psiDirectory = PsiManager.getInstance(myProject).findDirectory(vf) val psiDirectory = PsiManager.getInstance(project).findDirectory(vf)
assert(psiDirectory != null) { "No PsiDirectory for $vf" } assert(psiDirectory != null) { "No PsiDirectory for $vf" }
return HashSet(ContainerUtil.mapNotNull(psiDirectory!!.getFiles(), object : Function<PsiFile, JetFile> { return psiDirectory!!.getFiles().filterIsInstance<JetFile>().toHashSet()
override fun `fun`(file: PsiFile): JetFile? {
return if (file is JetFile) file else null
}
}))
} }
private fun findCurrentDescriptorForMember(originalDescriptor: MemberDescriptor): DeclarationDescriptor? { private fun findCurrentDescriptorForMember(originalDescriptor: MemberDescriptor): DeclarationDescriptor? {
@@ -172,33 +160,28 @@ public class BuiltInsReferenceResolver(project: Project) : AbstractProjectCompon
else { else {
descriptors = memberScope.getAllDescriptors() descriptors = memberScope.getAllDescriptors()
} }
for (member in descriptors) {
if (renderedOriginal == DescriptorRenderer.FQ_NAMES_IN_TYPES.render(member)) { return descriptors.firstOrNull { renderedOriginal == DescriptorRenderer.FQ_NAMES_IN_TYPES.render(it) }
return member
}
}
return null
} }
private fun findCurrentDescriptor(originalDescriptor: DeclarationDescriptor): DeclarationDescriptor? { private fun findCurrentDescriptor(originalDescriptor: DeclarationDescriptor): DeclarationDescriptor? = when(originalDescriptor) {
if (originalDescriptor is ClassDescriptor) { is ClassDescriptor -> {
return if (isFromBuiltinModule(originalDescriptor)) if (isFromBuiltinModule(originalDescriptor))
moduleDescriptor!!.findClassAcrossModuleDependencies(originalDescriptor.classId) moduleDescriptor!!.findClassAcrossModuleDependencies(originalDescriptor.classId)
else else
null null
} }
else if (originalDescriptor is PackageFragmentDescriptor) {
return if (isFromBuiltinModule(originalDescriptor) && KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME == originalDescriptor.fqName) is PackageFragmentDescriptor -> {
if (isFromBuiltinModule(originalDescriptor) && KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME == originalDescriptor.fqName)
builtinsPackageFragment builtinsPackageFragment
else else
null null
} }
else if (originalDescriptor is MemberDescriptor) {
return findCurrentDescriptorForMember(originalDescriptor) is MemberDescriptor -> findCurrentDescriptorForMember(originalDescriptor)
}
else { else -> null
return null
}
} }
public fun resolveBuiltInSymbol(declarationDescriptor: DeclarationDescriptor): PsiElement? { public fun resolveBuiltInSymbol(declarationDescriptor: DeclarationDescriptor): PsiElement? {
@@ -216,27 +199,22 @@ public class BuiltInsReferenceResolver(project: Project) : AbstractProjectCompon
companion object { companion object {
private val BUILT_INS_COMPILABLE_SRC_DIR = File("core/builtins/src", KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString()) private val BUILT_INS_COMPILABLE_SRC_DIR = File("core/builtins/src", KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString())
public fun getInstance(project: Project): BuiltInsReferenceResolver =
ServiceManager.getService(project, javaClass<BuiltInsReferenceResolver>())
private fun isFromBuiltinModule(originalDescriptor: DeclarationDescriptor): Boolean { private fun isFromBuiltinModule(originalDescriptor: DeclarationDescriptor): Boolean {
// TODO This is optimization only // TODO This is optimization only
// It should be rewritten by checking declarationDescriptor.getSource(), when the latter returns something non-trivial for builtins. // It should be rewritten by checking declarationDescriptor.getSource(), when the latter returns something non-trivial for builtins.
return KotlinBuiltIns.getInstance().getBuiltInsModule() == DescriptorUtils.getContainingModule(originalDescriptor) return KotlinBuiltIns.getInstance().getBuiltInsModule() == DescriptorUtils.getContainingModule(originalDescriptor)
} }
public fun isFromBuiltIns(element: PsiElement): Boolean { public fun isFromBuiltIns(element: PsiElement): Boolean =
//noinspection SuspiciousMethodCalls getInstance(element.project).builtInsSources!!.contains(element.getContainingFile())
return element.getProject().getComponent(javaClass<BuiltInsReferenceResolver>())!!.builtInsSources!!.contains(element.getContainingFile())
}
private fun getMemberScope(parent: DeclarationDescriptor?): JetScope? { private fun getMemberScope(parent: DeclarationDescriptor?): JetScope? = when(parent) {
if (parent is ClassDescriptor) { is ClassDescriptor -> parent.getDefaultType().getMemberScope()
return parent.getDefaultType().getMemberScope() is PackageFragmentDescriptor -> parent.getMemberScope()
} else -> null
else if (parent is PackageFragmentDescriptor) {
return parent.getMemberScope()
}
else {
return null
}
} }
} }
} }
@@ -80,7 +80,7 @@ public fun closeAndDeleteProject(): Unit =
ApplicationManager.getApplication().runWriteAction() { LightPlatformTestCase.closeAndDeleteProject() } ApplicationManager.getApplication().runWriteAction() { LightPlatformTestCase.closeAndDeleteProject() }
public fun unInvalidateBuiltins(project: Project, runnable: RunnableWithException) { public fun unInvalidateBuiltins(project: Project, runnable: RunnableWithException) {
val builtInsSources = project.getComponent<org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver>(javaClass<BuiltInsReferenceResolver>())!!.builtInsSources!! val builtInsSources = BuiltInsReferenceResolver.getInstance(project).builtInsSources!!
runnable.run() runnable.run()
+3 -3
View File
@@ -21,9 +21,6 @@
<component> <component>
<implementation-class>org.jetbrains.kotlin.idea.compiler.JetCompilerManager</implementation-class> <implementation-class>org.jetbrains.kotlin.idea.compiler.JetCompilerManager</implementation-class>
</component> </component>
<component>
<implementation-class>org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver</implementation-class>
</component>
<component> <component>
<implementation-class>org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification</implementation-class> <implementation-class>org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification</implementation-class>
</component> </component>
@@ -233,6 +230,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade" <projectService serviceInterface="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"
serviceImplementation="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"/> serviceImplementation="org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver"
serviceImplementation="org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver"/>
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/> <errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
<internalFileTemplate name="Kotlin File"/> <internalFileTemplate name="Kotlin File"/>
@@ -31,12 +31,8 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.StubUpdatingIndex; import com.intellij.psi.stubs.StubUpdatingIndex;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.file.impl.FileManager;
import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.rt.execution.junit.FileComparisonFailure;
import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.indexing.FileBasedIndex;
import kotlin.KotlinPackage; import kotlin.KotlinPackage;
@@ -45,7 +41,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.KotlinLightQuickFixTestCase; import org.jetbrains.kotlin.idea.KotlinLightQuickFixTestCase;
import org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager; import org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager;
import org.jetbrains.kotlin.idea.references.BuiltInsReferenceResolver;
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil;
import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils; import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils;
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;