[Analysis API] implement API to extend Kotlin resolution by generated declarations

^KT-57930 fixed
This commit is contained in:
Ilya Kirillov
2023-04-17 18:12:00 +02:00
committed by Space Team
parent 0dbc948616
commit d68587de77
12 changed files with 571 additions and 14 deletions
@@ -5,12 +5,20 @@
package org.jetbrains.kotlin.analysis.api.impl.base.components
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.components.KtAnalysisScopeProvider
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtModuleStructureInternals
import org.jetbrains.kotlin.analysis.project.structure.allDirectDependencies
import org.jetbrains.kotlin.analysis.project.structure.analysisExtensionFileContextModule
import org.jetbrains.kotlin.analysis.providers.KotlinResolutionScopeProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.contains
class KtAnalysisScopeProviderImpl(
@@ -18,13 +26,40 @@ class KtAnalysisScopeProviderImpl(
override val token: KtLifetimeToken
) : KtAnalysisScopeProvider() {
private val scope by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val baseResolveScope by lazy(LazyThreadSafetyMode.PUBLICATION) {
KotlinResolutionScopeProvider.getInstance(analysisSession.useSiteModule.project).getResolutionScope(analysisSession.useSiteModule)
}
override fun getAnalysisScope(): GlobalSearchScope = scope
private val resolveScope by lazy(LazyThreadSafetyMode.PUBLICATION) {
KtAnalysisScopeProviderResolveScope(baseResolveScope, analysisSession.useSiteModule)
}
override fun getAnalysisScope(): GlobalSearchScope = resolveScope
override fun canBeAnalysed(psi: PsiElement): Boolean {
return scope.contains(psi)
return baseResolveScope.contains(psi)
|| psi.isFromGeneratedModule()
}
private fun PsiElement.isFromGeneratedModule(): Boolean {
val ktFile = containingFile as? KtFile ?: return false
return ktFile.virtualFile?.isFromGeneratedModule(analysisSession.useSiteModule) == true
}
}
private class KtAnalysisScopeProviderResolveScope(
private val base: GlobalSearchScope,
private val useSiteModule: KtModule
) : GlobalSearchScope() {
override fun getProject(): Project? = base.project
override fun isSearchInModuleContent(aModule: Module): Boolean = base.isSearchInModuleContent(aModule)
override fun isSearchInLibraries(): Boolean = base.isSearchInLibraries
override fun contains(file: VirtualFile): Boolean = base.contains(file) || file.isFromGeneratedModule(useSiteModule)
}
@OptIn(KtModuleStructureInternals::class)
private fun VirtualFile.isFromGeneratedModule(useSiteModule: KtModule): Boolean {
val analysisContextModule = analysisExtensionFileContextModule ?: return false
if (analysisContextModule == useSiteModule) return true
return analysisContextModule in useSiteModule.allDirectDependencies()
}