[Low Level API FIR] fix invalid traverse of supertypes list

the supertypes list should not be traversed without proper locking,
otherwise some transformer may transform it concurrently

In case of looking for a declaration by class id it just should not be traversed

^KTIJ-21791
This commit is contained in:
Ilya Kirillov
2022-06-21 18:31:44 +02:00
committed by teamcity
parent 6cf085aafb
commit 0da66cc52f
3 changed files with 9 additions and 11 deletions
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBui
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeOrReturnDefaultValueOnPCE
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -39,9 +40,11 @@ internal class LLFirProviderHelper(
?: return@computeIfAbsent Optional.empty()
if (ktClass.getClassId() == null) return@computeIfAbsent Optional.empty()
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile)
val classifier = FirElementFinder.findElementIn<FirClassLikeDeclaration>(firFile) { classifier ->
classifier.symbol.classId == classId
}
val classifier = FirElementFinder.findElementIn<FirClassLikeDeclaration>(
firFile,
canGoInside = { it is FirRegularClass },
predicate = { it.symbol.classId == classId },
)
?: error("Classifier $classId was found in file ${ktClass.containingKtFile.virtualFilePath} but was not found in FirFile")
Optional.of(classifier)
}.getOrNull()
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.KtElement
@@ -17,7 +16,7 @@ import org.jetbrains.kotlin.psi.KtElement
object FirElementFinder {
inline fun <reified E : FirElement> findElementIn(
container: FirElement,
crossinline goInside: (E) -> Boolean = { true },
crossinline canGoInside: (E) -> Boolean = { true },
crossinline predicate: (E) -> Boolean,
): E? {
var result: E? = null
@@ -31,7 +30,7 @@ object FirElementFinder {
predicate(element) -> {
result = element
}
goInside(element) -> {
canGoInside(element) -> {
element.acceptChildren(this)
}
}
@@ -61,7 +60,4 @@ object FirElementFinder {
})
return result
}
inline fun <reified E : FirElement> findElementByPsiIn(container: FirElement, ktElement: KtElement): E? =
findElementIn(container) { it.psi === ktElement }
}
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -63,7 +62,7 @@ private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTre
): FirDeclaration? {
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
val originalDeclaration = originalDeclaration
return FirElementFinder.findElementIn(firFile, goInside = { it is FirRegularClass }) { firDeclaration ->
return FirElementFinder.findElementIn(firFile, canGoInside = { it is FirRegularClass }) { firDeclaration ->
firDeclaration.psi == this || firDeclaration.psi == originalDeclaration
}
}