diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt index 8562cd99d24..c2c0c372022 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLFirResolveExtensionTool.kt @@ -8,8 +8,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions import com.intellij.openapi.util.Key import com.intellij.openapi.util.ModificationTracker import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.analysis.api.KtAnalysisAllowanceManager import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtension import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionFile +import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionReferencePsiTargetsProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.FileBasedKotlinDeclarationProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession @@ -70,27 +72,27 @@ private class LLFirResolveExtensionToolNameCache( private val packageFilter: LLFirResolveExtensionToolPackageFilter, private val fileProvider: LLFirResolveExtensionsFileProvider, ) : LLFirSymbolProviderNameCache() { - override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set? { + override fun getTopLevelClassifierNamesInPackage(packageFqName: FqName): Set? = forbidAnalysis { if (!packageFilter.packageExists(packageFqName)) return emptySet() return fileProvider.getFilesByPackage(packageFqName) .flatMap { it.getTopLevelClassifierNames() } .mapTo(mutableSetOf()) { it.asString() } } - override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set { + override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set = forbidAnalysis { if (!packageFilter.packageExists(packageFqName)) return emptySet() return fileProvider.getFilesByPackage(packageFqName) .flatMapTo(mutableSetOf()) { it.getTopLevelCallableNames() } } - override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean { + override fun mayHaveTopLevelClassifier(classId: ClassId, mayHaveFunctionClass: Boolean): Boolean = forbidAnalysis { if (!packageFilter.packageExists(classId.packageFqName)) return false return fileProvider.getFilesByPackage(classId.packageFqName) .any { it.mayHaveTopLevelClassifier(classId.getTopLevelShortClassName()) } } - override fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean { + override fun mayHaveTopLevelCallable(packageFqName: FqName, name: Name): Boolean = forbidAnalysis { if (!packageFilter.packageExists(packageFqName)) return false return fileProvider.getFilesByPackage(packageFqName) @@ -102,7 +104,9 @@ private class LLFirResolveExtensionToolPackageFilter( private val extensions: List ) { val allPackages: Set by lazy { - extensions.flatMapTo(mutableSetOf()) { it.getContainedPackages() } + forbidAnalysis { + extensions.flatMapTo(mutableSetOf()) { it.getContainedPackages() } + } } fun packageExists(packageFqName: FqName): Boolean { @@ -118,52 +122,52 @@ private class LLFirResolveExtensionToolDeclarationProvider( private val extensionFileToDeclarationProvider: ConcurrentHashMap = ConcurrentHashMap() - override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? { + override fun getClassLikeDeclarationByClassId(classId: ClassId): KtClassLikeDeclaration? = forbidAnalysis { return getDeclarationProvidersByPackage(classId.packageFqName) { it.mayHaveTopLevelClassifier(classId.getTopLevelShortClassName()) } .firstNotNullOfOrNull { it.getClassLikeDeclarationByClassId(classId) } } - override fun getAllClassesByClassId(classId: ClassId): Collection { + override fun getAllClassesByClassId(classId: ClassId): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(classId.packageFqName) { it.mayHaveTopLevelClassifier(classId.getTopLevelShortClassName()) } .flatMapTo(mutableListOf()) { it.getAllClassesByClassId(classId) } } - override fun getAllTypeAliasesByClassId(classId: ClassId): Collection { + override fun getAllTypeAliasesByClassId(classId: ClassId): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(classId.packageFqName) { it.mayHaveTopLevelClassifier(classId.getTopLevelShortClassName()) } .flatMapTo(mutableListOf()) { it.getAllTypeAliasesByClassId(classId) } } - override fun getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName: FqName): Set { + override fun getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName: FqName): Set = forbidAnalysis { return getDeclarationProvidersByPackage(packageFqName) { true } .flatMapTo(mutableSetOf()) { it.getTopLevelKotlinClassLikeDeclarationNamesInPackage(packageFqName) } } - override fun getTopLevelProperties(callableId: CallableId): Collection { + override fun getTopLevelProperties(callableId: CallableId): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(callableId.packageName) { it.mayHaveTopLevelCallable(callableId.callableName) } .flatMapTo(mutableListOf()) { it.getTopLevelProperties(callableId) } } - override fun getTopLevelFunctions(callableId: CallableId): Collection { + override fun getTopLevelFunctions(callableId: CallableId): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(callableId.packageName) { it.mayHaveTopLevelCallable(callableId.callableName) } .flatMapTo(mutableListOf()) { it.getTopLevelFunctions(callableId) } } - override fun getTopLevelCallableFiles(callableId: CallableId): Collection { + override fun getTopLevelCallableFiles(callableId: CallableId): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(callableId.packageName) { it.mayHaveTopLevelCallable(callableId.callableName) } .mapTo(mutableListOf()) { it.kotlinFile } } - override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set { + override fun getTopLevelCallableNamesInPackage(packageFqName: FqName): Set = forbidAnalysis { return extensionProvider.getFilesByPackage(packageFqName).flatMapTo(mutableSetOf()) { it.getTopLevelClassifierNames() } } - override fun findFilesForFacadeByPackage(packageFqName: FqName): Collection { + override fun findFilesForFacadeByPackage(packageFqName: FqName): Collection = forbidAnalysis { return getDeclarationProvidersByPackage(packageFqName) { file -> file.getTopLevelCallableNames().isNotEmpty() }.mapTo(mutableListOf()) { it.kotlinFile } } - override fun findFilesForFacade(facadeFqName: FqName): Collection { + override fun findFilesForFacade(facadeFqName: FqName): Collection = forbidAnalysis { if (facadeFqName.isRoot) return emptyList() val packageFqName = facadeFqName.parent() return getDeclarationProvidersByPackage(packageFqName) { file -> @@ -172,7 +176,7 @@ private class LLFirResolveExtensionToolDeclarationProvider( .mapTo(mutableListOf()) { it.kotlinFile } } - override fun findInternalFilesForFacade(facadeFqName: FqName): Collection { + override fun findInternalFilesForFacade(facadeFqName: FqName): Collection = forbidAnalysis { // no decompiled files here (see the `org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider.findInternalFilesForFacade` KDoc) return emptyList() } @@ -180,13 +184,13 @@ private class LLFirResolveExtensionToolDeclarationProvider( private inline fun getDeclarationProvidersByPackage( packageFqName: FqName, crossinline filter: (KtResolveExtensionFile) -> Boolean - ): Sequence { + ): Sequence = forbidAnalysis { return extensionProvider.getFilesByPackage(packageFqName) .filter { filter(it) } .map { createDeclarationProviderByFile(it) } } - private fun createDeclarationProviderByFile(file: KtResolveExtensionFile): FileBasedKotlinDeclarationProvider { + private fun createDeclarationProviderByFile(file: KtResolveExtensionFile): FileBasedKotlinDeclarationProvider = forbidAnalysis { return extensionFileToDeclarationProvider.getOrPut(file) { val factory = KtPsiFactory( ktModule.project, @@ -219,7 +223,7 @@ private class LLFirResolveExtensionToolDeclarationProvider( private class LLFirResolveExtensionsFileProvider( val extensions: List, ) { - fun getFilesByPackage(packageFqName: FqName): Sequence { + fun getFilesByPackage(packageFqName: FqName): Sequence = forbidAnalysis { return extensions .asSequence() .filter { packageFqName in it.getContainedPackages() } @@ -287,3 +291,7 @@ private fun KtResolveExtensionFile.mayHaveTopLevelCallable(name: Name): Boolean @KtModuleStructureInternals public var VirtualFile.psiTargetsProvider: KtResolveExtensionReferencePsiTargetsProvider? by UserDataProperty(Key.create("KT_RESOLVE_EXTENSION_PSI_TARGETS_PROVIDER")) + +private inline fun forbidAnalysis(action: () -> R): R { + return KtAnalysisAllowanceManager.forbidAnalysisInside(KtResolveExtensionProvider::class.java.simpleName, action) +} \ No newline at end of file