diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt new file mode 100644 index 00000000000..53c89de7865 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtPackageSymbol.kt @@ -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 +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index 9461a11acec..129c53191c5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -40,6 +40,7 @@ class KtFirAnalysisSession( internal val firSymbolBuilder = KtSymbolByFirBuilder( element.session.firSymbolProvider, ConeTypeCheckerContext(isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, element.session), + element.project, validityToken ) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt index cac7f815a92..e9dee388b76 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtSymbolByFirBuilder.kt @@ -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 } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt new file mode 100644 index 00000000000..c46afb6a61c --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt @@ -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 = 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) +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index ea2310088c9..9d1935d9163 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -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() + .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.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() != 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)) }