[lc] KotlinAsJavaSupportBase: introduce LightClassCachedValue

to extract common logic with cached values

^KT-50241
This commit is contained in:
Dmitry Gridin
2022-09-08 13:14:03 +02:00
committed by Space
parent 2611be0436
commit 7102be7720
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.psi.*
abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project) : KotlinAsJavaSupport() { abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project) : KotlinAsJavaSupport() {
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
fun createLightFacade(file: KtFile): Pair<KtLightClassForFacade?, ModificationTracker>? { fun createLightFacade(file: KtFile): LightClassCachedValue<KtLightClassForFacade>? {
if (!file.facadeIsPossible()) return null if (!file.facadeIsPossible()) return null
val module = file.findModule().takeIf { facadeIsApplicable(it, file) } ?: return null val module = file.findModule().takeIf { facadeIsApplicable(it, file) } ?: return null
@@ -37,11 +37,11 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
return when { return when {
facadeFiles.none(KtFile::hasTopLevelCallables) -> null facadeFiles.none(KtFile::hasTopLevelCallables) -> null
facadeFiles.none(KtFile::isCompiled) -> { facadeFiles.none(KtFile::isCompiled) -> {
createInstanceOfLightFacade(facadeFqName, facadeFiles) to outOfBlockModificationTracker(file) LightClassCachedValue(createInstanceOfLightFacade(facadeFqName, facadeFiles), outOfBlockModificationTracker(file))
} }
facadeFiles.all(KtFile::isCompiled) -> { facadeFiles.all(KtFile::isCompiled) -> {
createInstanceOfDecompiledLightFacade(facadeFqName, facadeFiles) to librariesTracker(file) LightClassCachedValue(createInstanceOfDecompiledLightFacade(facadeFqName, facadeFiles), librariesTracker(file))
} }
else -> error("Source and compiled files are mixed: $facadeFiles") else -> error("Source and compiled files are mixed: $facadeFiles")
@@ -79,8 +79,7 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
override fun getLightFacade(file: KtFile): KtLightClassForFacade? = ifValid(file) { override fun getLightFacade(file: KtFile): KtLightClassForFacade? = ifValid(file) {
CachedValuesManager.getCachedValue(file) { CachedValuesManager.getCachedValue(file) {
val (facade, tracker) = createLightFacade(file) ?: (null to projectWideOutOfBlockModificationTracker()) cachedValueResult(createLightFacade(file))
CachedValueProvider.Result.createSingleDependency(facade, tracker)
} }
} }
@@ -128,17 +127,17 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
} }
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
fun createLightClass(classOrObject: KtClassOrObject): Pair<KtLightClass?, ModificationTracker>? { fun createLightClass(classOrObject: KtClassOrObject): LightClassCachedValue<KtLightClass>? {
if (classOrObject.shouldNotBeVisibleAsLightClass()) return null if (classOrObject.shouldNotBeVisibleAsLightClass()) return null
val containingFile = classOrObject.containingKtFile val containingFile = classOrObject.containingKtFile
when (declarationLocation(containingFile)) { when (declarationLocation(containingFile)) {
DeclarationLocation.ProjectSources -> { DeclarationLocation.ProjectSources -> {
return createInstanceOfLightClass(classOrObject) to outOfBlockModificationTracker(classOrObject) return LightClassCachedValue(createInstanceOfLightClass(classOrObject), outOfBlockModificationTracker(classOrObject))
} }
DeclarationLocation.LibraryClasses -> { DeclarationLocation.LibraryClasses -> {
return createInstanceOfDecompiledLightClass(classOrObject) to librariesTracker(classOrObject) return LightClassCachedValue(createInstanceOfDecompiledLightClass(classOrObject), librariesTracker(classOrObject))
} }
DeclarationLocation.LibrarySources -> { DeclarationLocation.LibrarySources -> {
@@ -150,14 +149,14 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
guardedRun { getLightClass(it) } guardedRun { getLightClass(it) }
} }
return value to librariesTracker(classOrObject) return LightClassCachedValue(value, librariesTracker(classOrObject))
} }
null -> Unit null -> Unit
} }
if (containingFile.analysisContext != null || containingFile.originalFile.virtualFile != null) { if (containingFile.analysisContext != null || containingFile.originalFile.virtualFile != null) {
return createInstanceOfLightClass(classOrObject) to outOfBlockModificationTracker(classOrObject) return LightClassCachedValue(createInstanceOfLightClass(classOrObject), outOfBlockModificationTracker(classOrObject))
} }
return null return null
@@ -173,33 +172,39 @@ abstract class KotlinAsJavaSupportBase<TModule>(protected val project: Project)
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = ifValid(classOrObject) { override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = ifValid(classOrObject) {
CachedValuesManager.getCachedValue(classOrObject) { CachedValuesManager.getCachedValue(classOrObject) {
val (clazz, tracker) = createLightClass(classOrObject) ?: (null to projectWideOutOfBlockModificationTracker()) cachedValueResult(createLightClass(classOrObject))
CachedValueProvider.Result.createSingleDependency(clazz, tracker)
} }
} }
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
fun createLightScript(script: KtScript): Pair<KtLightClass?, ModificationTracker>? { fun createLightScript(script: KtScript): LightClassCachedValue<KtLightClass>? {
val containingFile = script.containingFile val containingFile = script.containingFile
if (containingFile is KtCodeFragment) { if (containingFile is KtCodeFragment) {
// Avoid building light classes for code fragments // Avoid building light classes for code fragments
return null return null
} }
return createInstanceOfLightScript(script) to projectWideOutOfBlockModificationTracker() return LightClassCachedValue(createInstanceOfLightScript(script), projectWideOutOfBlockModificationTracker())
} }
protected abstract fun createInstanceOfLightScript(script: KtScript): KtLightClass? protected abstract fun createInstanceOfLightScript(script: KtScript): KtLightClass?
override fun getLightClassForScript(script: KtScript): KtLightClass? = ifValid(script) { override fun getLightClassForScript(script: KtScript): KtLightClass? = ifValid(script) {
CachedValuesManager.getCachedValue(script) { CachedValuesManager.getCachedValue(script) {
val (lightScript, tracker) = createLightScript(script) ?: (null to projectWideOutOfBlockModificationTracker()) cachedValueResult(createLightScript(script))
CachedValueProvider.Result.createSingleDependency(lightScript, tracker)
} }
} }
private fun <T : KtLightClass> cachedValueResult(lightClassCachedValue: LightClassCachedValue<T>?): CachedValueProvider.Result<T> {
val value = lightClassCachedValue?.value
val tracker = lightClassCachedValue?.tracker ?: projectWideOutOfBlockModificationTracker()
return CachedValueProvider.Result.createSingleDependency(value, tracker)
}
} }
private inline fun <T : PsiElement, V> ifValid(element: T, action: () -> V?): V? { private inline fun <T : PsiElement, V> ifValid(element: T, action: () -> V?): V? {
if (!element.isValid) return null if (!element.isValid) return null
return action() return action()
} }
class LightClassCachedValue<T : KtLightClass>(val value: T?, val tracker: ModificationTracker)