Add cache to KLightClassForFacade
This commit is contained in:
@@ -39,7 +39,7 @@ class CliKotlinAsJavaSupport(
|
||||
return findFacadeFilesInPackage(packageFqName, scope)
|
||||
.groupBy { it.javaFileFacadeFqName }
|
||||
.mapNotNull { (facadeClassFqName, files) ->
|
||||
KtLightClassForFacade.createForFacade(psiManager, facadeClassFqName, scope, files)
|
||||
KtLightClassForFacade.createForFacade(psiManager, facadeClassFqName, scope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,7 @@ class CliKotlinAsJavaSupport(
|
||||
.orEmpty()
|
||||
|
||||
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
val filesForFacade = findFilesForFacade(facadeFqName, scope)
|
||||
if (filesForFacade.isEmpty()) return emptyList()
|
||||
|
||||
return listOfNotNull(
|
||||
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade)
|
||||
)
|
||||
return listOfNotNull(KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope))
|
||||
}
|
||||
|
||||
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.intellij.util.lang.UrlClassLoader
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.classes.FacadeCache
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
@@ -679,7 +680,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
fun registerProjectServices(project: MockProject) {
|
||||
with(project) {
|
||||
registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this))
|
||||
registerService(KtLightClassForFacade.FacadeStubCache::class.java, KtLightClassForFacade.FacadeStubCache(this))
|
||||
registerService(FacadeCache::class.java, FacadeCache(this))
|
||||
registerService(ModuleAnnotationsResolver::class.java, CliModuleAnnotationsResolver())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.asJava.classes
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.util.containers.SLRUCache
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
||||
|
||||
private data class ValueWrapper(val value: KtLightClassForFacade?) {
|
||||
companion object {
|
||||
val Null = ValueWrapper(null)
|
||||
}
|
||||
}
|
||||
|
||||
class FacadeCache(private val project: Project) {
|
||||
private inner class FacadeCacheData {
|
||||
val cache = object : SLRUCache<StubCacheKey, ValueWrapper>(20, 30) {
|
||||
override fun createValue(key: StubCacheKey): ValueWrapper {
|
||||
|
||||
val (fqName, searchScope) = key
|
||||
|
||||
val sources = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(key.fqName, key.searchScope)
|
||||
.filterNot { it.isCompiled }
|
||||
|
||||
if (sources.isEmpty()) return ValueWrapper.Null
|
||||
|
||||
val ultraLightEnabled =
|
||||
!KtUltraLightSupport.forceUsingOldLightClasses && Registry.`is`("kotlin.use.ultra.light.classes", true)
|
||||
|
||||
val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, fqName, searchScope)
|
||||
val stubValue = CachedValuesManager.getManager(project)
|
||||
.createCachedValue(stubProvider, false)
|
||||
|
||||
val manager = PsiManager.getInstance(project)
|
||||
|
||||
val ultraLightClass = if (ultraLightEnabled)
|
||||
LightClassGenerationSupport.getInstance(project)
|
||||
.createUltraLightClassForFacade(manager, fqName, stubValue, sources)
|
||||
else null
|
||||
|
||||
val result = ultraLightClass ?: KtLightClassForFacade(manager, fqName, stubValue, sources)
|
||||
|
||||
return ValueWrapper(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val cachedValue: CachedValue<FacadeCacheData> = CachedValuesManager.getManager(project).createCachedValue(
|
||||
{ CachedValueProvider.Result.create(FacadeCacheData(), PsiModificationTracker.MODIFICATION_COUNT) }, false
|
||||
)
|
||||
|
||||
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): KtLightClassForFacade? {
|
||||
synchronized(cachedValue) {
|
||||
return cachedValue.value.cache.get(StubCacheKey(qualifiedName, searchScope)).value
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): FacadeCache {
|
||||
return ServiceManager.getService(project, FacadeCache::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-75
@@ -16,26 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.asJava.classes
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Comparing
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.light.LightEmptyImplementsList
|
||||
import com.intellij.psi.impl.light.LightModifierList
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
|
||||
import com.intellij.util.containers.SLRUCache
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
|
||||
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
|
||||
import org.jetbrains.kotlin.codegen.inline.getOrPut
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
@@ -49,43 +41,13 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import javax.swing.Icon
|
||||
|
||||
open class KtLightClassForFacade protected constructor(
|
||||
open class KtLightClassForFacade constructor(
|
||||
manager: PsiManager,
|
||||
protected val facadeClassFqName: FqName,
|
||||
protected open val lightClassDataCache: CachedValue<LightClassDataHolder.ForFacade>,
|
||||
files: Collection<KtFile>
|
||||
) : KtLazyLightClass(manager) {
|
||||
|
||||
private data class StubCacheKey(val fqName: FqName, val searchScope: GlobalSearchScope)
|
||||
|
||||
class FacadeStubCache(private val project: Project) {
|
||||
private inner class FacadeCacheData {
|
||||
val cache = object : SLRUCache<StubCacheKey, CachedValue<LightClassDataHolder.ForFacade>>(20, 30) {
|
||||
override fun createValue(key: StubCacheKey): CachedValue<LightClassDataHolder.ForFacade> {
|
||||
val stubProvider = LightClassDataProviderForFileFacade.ByProjectSource(project, key.fqName, key.searchScope)
|
||||
return CachedValuesManager.getManager(project)
|
||||
.createCachedValue<LightClassDataHolder.ForFacade>(stubProvider, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val cachedValue: CachedValue<FacadeCacheData> = CachedValuesManager.getManager(project).createCachedValue<FacadeCacheData>(
|
||||
{ CachedValueProvider.Result.create(FacadeCacheData(), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) }, false
|
||||
)
|
||||
|
||||
operator fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<LightClassDataHolder.ForFacade> {
|
||||
synchronized(cachedValue) {
|
||||
return cachedValue.value.cache.get(StubCacheKey(qualifiedName, searchScope))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): FacadeStubCache {
|
||||
return ServiceManager.getService<FacadeStubCache>(project, FacadeStubCache::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val files: Collection<KtFile> = files.toSet() // needed for hashCode
|
||||
|
||||
private val firstFileInFacade by lazyPub { files.iterator().next() }
|
||||
@@ -254,42 +216,6 @@ open class KtLightClassForFacade protected constructor(
|
||||
|
||||
override fun toString() = "${KtLightClassForFacade::class.java.simpleName}:$facadeClassFqName"
|
||||
|
||||
companion object {
|
||||
|
||||
fun createForFacade(
|
||||
manager: PsiManager,
|
||||
facadeClassFqName: FqName,
|
||||
searchScope: GlobalSearchScope,
|
||||
files: Collection<KtFile>
|
||||
): KtLightClassForFacade {
|
||||
assert(files.isNotEmpty()) { "No files for facade $facadeClassFqName" }
|
||||
|
||||
val ultraLightEnabled =
|
||||
!KtUltraLightSupport.forceUsingOldLightClasses && Registry.`is`("kotlin.use.ultra.light.classes", true)
|
||||
|
||||
val lightClassDataCache = FacadeStubCache.getInstance(manager.project).get(facadeClassFqName, searchScope)
|
||||
|
||||
val ultraLightClass = if (ultraLightEnabled)
|
||||
LightClassGenerationSupport.getInstance(manager.project)
|
||||
.createUltraLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
|
||||
else null
|
||||
|
||||
return ultraLightClass ?: KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
|
||||
}
|
||||
|
||||
fun createForSyntheticFile(
|
||||
manager: PsiManager,
|
||||
facadeClassFqName: FqName,
|
||||
file: KtFile
|
||||
): KtLightClassForFacade {
|
||||
// TODO: refactor, using cached value doesn't make sense for this case
|
||||
val cachedValue = CachedValuesManager.getManager(manager.project).createCachedValue<LightClassDataHolder.ForFacade>(
|
||||
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), /*trackValue = */false
|
||||
)
|
||||
return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file))
|
||||
}
|
||||
}
|
||||
|
||||
override val originKind: LightClassOriginKind
|
||||
get() = LightClassOriginKind.SOURCE
|
||||
|
||||
@@ -302,4 +228,26 @@ open class KtLightClassForFacade protected constructor(
|
||||
override fun getStartOffsetInParent() = firstFileInFacade.startOffsetInParent
|
||||
|
||||
override fun isWritable() = firstFileInFacade.isWritable
|
||||
|
||||
companion object {
|
||||
fun createForFacade(
|
||||
manager: PsiManager,
|
||||
facadeClassFqName: FqName,
|
||||
searchScope: GlobalSearchScope
|
||||
): KtLightClassForFacade? {
|
||||
return FacadeCache.getInstance(manager.project).get(facadeClassFqName, searchScope)
|
||||
}
|
||||
|
||||
fun createForSyntheticFile(
|
||||
manager: PsiManager,
|
||||
facadeClassFqName: FqName,
|
||||
file: KtFile
|
||||
): KtLightClassForFacade {
|
||||
// TODO: refactor, using cached value doesn't make sense for this case
|
||||
val cachedValue = CachedValuesManager.getManager(manager.project).createCachedValue(
|
||||
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), false
|
||||
)
|
||||
return KtLightClassForFacade(manager, facadeClassFqName, cachedValue, listOf(file))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ class KtUltraLightClassForFacade(
|
||||
|
||||
private val ownFieldsForNotTooComplex: List<KtLightField> by lazyPub {
|
||||
hashSetOf<String>().let { nameCache ->
|
||||
filesToSupportsToMemberCreators.flatMap { (file, support, creator) ->
|
||||
filesToSupportsToMemberCreators.flatMap { (file, _, creator) ->
|
||||
file.declarations.filterIsInstance<KtProperty>().mapNotNull {
|
||||
creator.createPropertyField(it, nameCache, forceStatic = true)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.asJava
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
@@ -36,9 +38,14 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
||||
fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? {
|
||||
fun getDiagnosticsForFileFacade(file: KtFile): Diagnostics? {
|
||||
val project = file.project
|
||||
val cache = KtLightClassForFacade.FacadeStubCache.getInstance(project)
|
||||
|
||||
val facadeFqName = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
|
||||
return cache[facadeFqName, moduleScope].value?.extraDiagnostics
|
||||
|
||||
//TODO Maybe it is better to cache this item
|
||||
return LightClassDataProviderForFileFacade.ByProjectSource(project, facadeFqName, moduleScope)
|
||||
.compute()
|
||||
?.value
|
||||
?.extraDiagnostics
|
||||
}
|
||||
|
||||
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
||||
|
||||
+2
-1
@@ -142,7 +142,8 @@ sealed class LazyLightClassDataHolder(
|
||||
}
|
||||
|
||||
private fun <T : PsiMember> T?.assertMatches(dummyMember: T, containingClass: KtLightClass): T {
|
||||
if (this == null) throw LazyLightClassMemberMatchingError.NoMatch(dummyMember, containingClass)
|
||||
if (this == null)
|
||||
throw LazyLightClassMemberMatchingError.NoMatch(dummyMember, containingClass)
|
||||
|
||||
val parameterCountMatches = (this as? PsiMethod)?.parameterList?.parametersCount ?: 0 ==
|
||||
(dummyMember as? PsiMethod)?.parameterList?.parametersCount ?: 0
|
||||
|
||||
+8
-10
@@ -143,13 +143,12 @@ class IDEKotlinAsJavaSupport(private val project: Project) : KotlinAsJavaSupport
|
||||
KtLightClassForScript.create(script)
|
||||
|
||||
private fun withFakeLightClasses(
|
||||
lightClassForFacade: KtLightClassForFacade,
|
||||
facadeFiles: List<KtFile>
|
||||
lightClassForFacade: KtLightClassForFacade
|
||||
): List<PsiClass> {
|
||||
val lightClasses = ArrayList<PsiClass>()
|
||||
lightClasses.add(lightClassForFacade)
|
||||
if (facadeFiles.size > 1) {
|
||||
lightClasses.addAll(facadeFiles.map {
|
||||
if (lightClassForFacade.files.size > 1) {
|
||||
lightClasses.addAll(lightClassForFacade.files.map {
|
||||
FakeLightClassForFileOfPackage(lightClassForFacade, it)
|
||||
})
|
||||
}
|
||||
@@ -208,24 +207,23 @@ class IDEKotlinAsJavaSupport(private val project: Project) : KotlinAsJavaSupport
|
||||
facadeFiles: List<KtFile>,
|
||||
moduleInfo: IdeaModuleInfo
|
||||
): List<PsiClass> {
|
||||
val (clsFiles, sourceFiles) = facadeFiles.partition { it is KtClsFile }
|
||||
val (clsFiles, _) = facadeFiles.partition { it is KtClsFile }
|
||||
val facadesFromCls = clsFiles.mapNotNull { createLightClassForDecompiledKotlinFile(it as KtClsFile) }
|
||||
val facadesFromSources = createFacadesForSourceFiles(moduleInfo, sourceFiles, facadeFqName)
|
||||
val facadesFromSources = createFacadesForSourceFiles(moduleInfo, facadeFqName)
|
||||
return facadesFromSources + facadesFromCls
|
||||
}
|
||||
|
||||
private fun createFacadesForSourceFiles(
|
||||
moduleInfo: IdeaModuleInfo,
|
||||
sourceFiles: List<KtFile>,
|
||||
facadeFqName: FqName
|
||||
): List<PsiClass> {
|
||||
if (sourceFiles.isEmpty()) return listOf()
|
||||
if (moduleInfo !is ModuleSourceInfo && moduleInfo !is PlatformModuleInfo) return listOf()
|
||||
|
||||
val lightClassForFacade = KtLightClassForFacade.createForFacade(
|
||||
psiManager, facadeFqName, moduleInfo.contentScope(), sourceFiles
|
||||
psiManager, facadeFqName, moduleInfo.contentScope()
|
||||
)
|
||||
return withFakeLightClasses(lightClassForFacade, sourceFiles)
|
||||
|
||||
return if (lightClassForFacade !== null) withFakeLightClasses(lightClassForFacade) else emptyList()
|
||||
}
|
||||
|
||||
override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile> {
|
||||
|
||||
@@ -307,8 +307,8 @@
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerWorkspaceSettings"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade$FacadeStubCache"
|
||||
serviceImplementation="org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade$FacadeStubCache"/>
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.asJava.classes.FacadeCache"
|
||||
serviceImplementation="org.jetbrains.kotlin.asJava.classes.FacadeCache"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactoryService"/>
|
||||
|
||||
Reference in New Issue
Block a user