FIR: add symbol provider for IDE #KT-24097 Fixed
Functions & properties aren't yet supported
This commit is contained in:
committed by
Mikhail Glukhikh
parent
12ee81358c
commit
5cef869d36
@@ -18,8 +18,10 @@ import org.jetbrains.kotlin.fir.resolve.impl.FirLibrarySymbolProviderImpl
|
||||
class FirJavaModuleBasedSession(
|
||||
moduleInfo: ModuleInfo,
|
||||
override val sessionProvider: FirProjectSessionProvider,
|
||||
scope: GlobalSearchScope
|
||||
scope: GlobalSearchScope,
|
||||
dependenciesProvider: FirSymbolProvider? = null
|
||||
) : FirModuleBasedSession(moduleInfo) {
|
||||
|
||||
init {
|
||||
sessionProvider.sessionCache[moduleInfo] = this
|
||||
registerComponent(
|
||||
@@ -28,7 +30,8 @@ class FirJavaModuleBasedSession(
|
||||
listOf(
|
||||
service<FirProvider>(),
|
||||
JavaSymbolProvider(this, sessionProvider.project, scope),
|
||||
FirDependenciesSymbolProviderImpl(this)
|
||||
FirLibrarySymbolProviderImpl(this),
|
||||
dependenciesProvider ?: FirDependenciesSymbolProviderImpl(this)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -36,6 +36,8 @@ dependencies {
|
||||
compile(project(":j2k"))
|
||||
compile(project(":idea:formatter"))
|
||||
compile(project(":idea:fir-view"))
|
||||
compile(project(":compiler:fir:resolve"))
|
||||
compile(project(":compiler:fir:java"))
|
||||
compile(project(":idea:idea-core"))
|
||||
compile(project(":idea:ide-common"))
|
||||
compile(project(":idea:idea-jps-common"))
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.AbstractFirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeSymbol
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
|
||||
class IdeFirDependenciesSymbolProvider(
|
||||
val moduleInfo: ModuleSourceInfo,
|
||||
val project: Project,
|
||||
private val sessionProvider: FirProjectSessionProvider
|
||||
) : AbstractFirSymbolProvider() {
|
||||
|
||||
// TODO: Our special scope here?
|
||||
private val depScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(moduleInfo.module)
|
||||
|
||||
private val javaSymbolProvider by lazy { JavaSymbolProvider(sessionProvider.getSession(moduleInfo)!!, project, depScope) }
|
||||
|
||||
|
||||
private fun buildKotlinClassOnRequest(file: KtFile, classId: ClassId, session: FirSession): ConeClassLikeSymbol? {
|
||||
val impl = FirProvider.getInstance(session) as FirProviderImpl
|
||||
val classifier = impl.getClassLikeSymbolByFqName(classId)
|
||||
if (classifier != null) {
|
||||
return classifier
|
||||
}
|
||||
|
||||
val builder = RawFirBuilder(session, stubMode = true)
|
||||
impl.recordFile(builder.buildFirFile(file))
|
||||
return impl.getClassLikeSymbolByFqName(classId)
|
||||
}
|
||||
|
||||
private fun selectNearest(classesPsi: Collection<KtDeclaration>, typeAliasesPsi: Collection<KtTypeAlias>): KtDeclaration? {
|
||||
return when {
|
||||
typeAliasesPsi.isEmpty() -> classesPsi.firstOrNull()
|
||||
classesPsi.isEmpty() -> typeAliasesPsi.firstOrNull()
|
||||
else -> (classesPsi.asSequence() + typeAliasesPsi.asSequence()).minWith(Comparator { o1, o2 ->
|
||||
depScope.compare(o1.containingFile.virtualFile, o2.containingFile.virtualFile)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryKotlin(classId: ClassId): ConeClassLikeSymbol? {
|
||||
return classCache.lookupCacheOrCalculate(classId) {
|
||||
val index = KotlinFullClassNameIndex.getInstance()
|
||||
|
||||
val fqNameString = classId.packageFqName.asString() + "." + classId.relativeClassName.asString()
|
||||
val classesPsi = index[fqNameString, project, depScope]
|
||||
val typeAliasesPsi = KotlinTopLevelTypeAliasFqNameIndex.getInstance()[fqNameString, project, depScope]
|
||||
|
||||
val psi = selectNearest(classesPsi, typeAliasesPsi) ?: return@lookupCacheOrCalculate null
|
||||
|
||||
val module = psi.getModuleInfo()
|
||||
if (psi.containingKtFile.isCompiled) {
|
||||
// TODO: WTF? Resolving libraries in current session
|
||||
val session = sessionProvider.getSession(moduleInfo) ?: return@lookupCacheOrCalculate null
|
||||
return@lookupCacheOrCalculate buildKotlinClassOnRequest(psi.containingKtFile, classId, session)
|
||||
}
|
||||
|
||||
val session = sessionProvider.getSession(module) ?: return@lookupCacheOrCalculate null
|
||||
session.service<FirProvider>().getClassLikeSymbolByFqName(classId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryJava(classId: ClassId): ConeClassLikeSymbol? {
|
||||
return javaSymbolProvider.getClassLikeSymbolByFqName(classId)
|
||||
}
|
||||
|
||||
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {
|
||||
return tryKotlin(classId) ?: tryJava(classId)
|
||||
}
|
||||
|
||||
override fun getCallableSymbols(callableId: CallableId): List<ConeCallableSymbol> {
|
||||
// TODO
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? {
|
||||
|
||||
if (PackageIndexUtil.packageExists(fqName, depScope, project)) {
|
||||
return fqName
|
||||
}
|
||||
return javaSymbolProvider.getPackage(fqName)
|
||||
}
|
||||
}
|
||||
@@ -14,18 +14,14 @@ import com.intellij.testFramework.ModuleTestCase
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
|
||||
import org.jetbrains.kotlin.fir.doFirResolveTestBench
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.service
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.isLibraryClasses
|
||||
import org.jetbrains.kotlin.idea.caches.project.productionSourceInfo
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
@@ -60,13 +56,11 @@ class FirTotalKotlinResolveInIdeTest : ModuleTestCase() {
|
||||
private fun createSession(): FirSession {
|
||||
val moduleInfo = module.productionSourceInfo()!!
|
||||
val sessionProvider = FirProjectSessionProvider(project)
|
||||
moduleInfo.dependenciesWithoutSelf().forEach {
|
||||
if (it is IdeaModuleInfo && it.isLibraryClasses()) {
|
||||
FirLibrarySession(it, sessionProvider, it.contentScope())
|
||||
}
|
||||
}
|
||||
|
||||
return FirJavaModuleBasedSession(moduleInfo, sessionProvider, moduleInfo.contentScope())
|
||||
return FirJavaModuleBasedSession(
|
||||
moduleInfo, sessionProvider, moduleInfo.contentScope(),
|
||||
IdeFirDependenciesSymbolProvider(moduleInfo, project, sessionProvider)
|
||||
)
|
||||
}
|
||||
|
||||
fun testTotalKotlin() {
|
||||
|
||||
@@ -35,6 +35,7 @@ val projectsToShadow by extra(listOf(
|
||||
":compiler:fir:cones",
|
||||
":compiler:fir:resolve",
|
||||
":compiler:fir:tree",
|
||||
":compiler:fir:java",
|
||||
":compiler:fir:psi2fir",
|
||||
":idea:fir-view"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user