FIR IDE: introduce package symbol

This commit is contained in:
Ilya Kirillov
2020-06-29 00:08:12 +03:00
parent 18d46a86ae
commit f10f6c6360
5 changed files with 92 additions and 6 deletions
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.frontend.api.symbols
import org.jetbrains.kotlin.name.FqName
abstract class KtPackageSymbol : KtSymbol {
abstract val fqName: FqName
}
@@ -40,6 +40,7 @@ class KtFirAnalysisSession(
internal val firSymbolBuilder = KtSymbolByFirBuilder(
element.session.firSymbolProvider,
ConeTypeCheckerContext(isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, element.session),
element.project,
validityToken
)
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.idea.frontend.api.fir
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
@@ -28,6 +30,10 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.name.FqName
internal class KtSymbolByFirBuilder(
firProvider: FirSymbolProvider,
@@ -99,7 +105,7 @@ internal class KtSymbolByFirBuilder(
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
val exists = firProvider.getPackage(packageFqName) != null
val exists = PackageIndexUtil.packageExists(packageFqName, GlobalSearchScope.allScope(project), project)
if (!exists) {
return null
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.frontend.api.fir.symbols
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.file.PsiPackageImpl
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner
import org.jetbrains.kotlin.idea.frontend.api.ValidityOwnerByValidityToken
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.symbols.symbolPointer
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.name.FqName
class KtFirPackageSymbol(
override val fqName: FqName,
private val project: Project,
override val token: ValidityOwner
) : KtPackageSymbol(), ValidityOwnerByValidityToken {
override val psi: PsiElement by cached {
KtPackage(PsiManager.getInstance(project), fqName, GlobalSearchScope.allScope(project))
}
override val origin: KtSymbolOrigin
get() = KtSymbolOrigin.SOURCE // TODO
override fun createPointer(): KtSymbolPointer<KtPackageSymbol> = symbolPointer { session ->
check(session is KtFirAnalysisSession)
session.firSymbolBuilder.createPackageSymbolIfOneExists(fqName)
}
}
class KtPackage(
manager: PsiManager,
private val fqName: FqName,
private val scope: GlobalSearchScope
) : PsiPackageImpl(manager, fqName.asString()) {
override fun copy() = KtPackage(manager, fqName, scope)
override fun isValid(): Boolean = PackageIndexUtil.packageExists(fqName, scope, project)
}
@@ -20,10 +20,15 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.idea.fir.*
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.buildSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirPackageSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
internal object FirReferenceResolveHelper {
fun FirResolvedTypeRef.toTargetSymbol(session: FirSession, symbolBuilder: KtSymbolByFirBuilder): KtSymbol? {
@@ -81,6 +86,20 @@ internal object FirReferenceResolveHelper {
}
}
private fun getPackageSymbolFor(expression: KtSimpleNameExpression, symbolBuilder: KtSymbolByFirBuilder): KtFirPackageSymbol? {
val fqName = when (val qualified = expression.getQualifiedExpressionForSelector()) {
null -> FqName(expression.getReferencedName())
else -> {
qualified
.collectDescendantsOfType<KtSimpleNameExpression>()
.joinToString(separator = ".") { it.getReferencedName() }
.let(::FqName)
}
}
return symbolBuilder.createPackageSymbolIfOneExists(fqName)
}
internal fun resolveSimpleNameReference(
ref: KtFirSimpleNameReference,
symbolBuilder: KtSymbolByFirBuilder
@@ -135,12 +154,11 @@ internal object FirReferenceResolveHelper {
if (parent.selectorExpression !== expression) {
// Special: package reference in the middle of import directive
// import a.<caret>b.c.SomeClass
// TODO: return reference to PsiPackage
// return listOf(expression)
return emptyList()
return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder)?.let { return listOf(it) })
}
parent = parent.parent
}
val classId = fir.resolvedClassId
if (classId != null) {
return listOfNotNull(classId.toTargetPsi(session, symbolBuilder))
@@ -162,8 +180,7 @@ internal object FirReferenceResolveHelper {
is FirFile -> {
if (expression.getNonStrictParentOfType<KtPackageDirective>() != null) {
// Special: package reference in the middle of package directive
return emptyList()
// return listOf(expression)
return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder))
}
return listOf(symbolBuilder.buildSymbol(fir))
}