Add cache to KLightClassForFacade
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user