From 0da66cc52f755c7b537d3bc152c2e42285c3f66e Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 21 Jun 2022 18:31:44 +0200 Subject: [PATCH] [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 --- .../low/level/api/fir/providers/LLFirProviderHelper.kt | 9 ++++++--- ...lementFinder.kt => FirNonLocalDeclarationSearcher.kt} | 8 ++------ .../analysis/low/level/api/fir/util/declarationUtils.kt | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) rename analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/{FirElementFinder.kt => FirNonLocalDeclarationSearcher.kt} (89%) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt index 36f4a0549b4..e4453d58564 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLFirProviderHelper.kt @@ -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(firFile) { classifier -> - classifier.symbol.classId == classId - } + val classifier = FirElementFinder.findElementIn( + 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() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirNonLocalDeclarationSearcher.kt similarity index 89% rename from analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt rename to analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirNonLocalDeclarationSearcher.kt index d898ad47225..32b1c60bfb0 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirElementFinder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/FirNonLocalDeclarationSearcher.kt @@ -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 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 findElementByPsiIn(container: FirElement, ktElement: KtElement): E? = - findElementIn(container) { it.psi === ktElement } } \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index cabf0e1fde6..316f8310c1b 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -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 } }