diff --git a/idea/idea-completion/testData/basic/common/InEmptyPackage.kt b/idea/idea-completion/testData/basic/common/InEmptyPackage.kt index a354b39f5be..411d250bb90 100644 --- a/idea/idea-completion/testData/basic/common/InEmptyPackage.kt +++ b/idea/idea-completion/testData/basic/common/InEmptyPackage.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package // EXIST: kotlin diff --git a/idea/idea-completion/testData/basic/common/InMiddleOfPackage.kt b/idea/idea-completion/testData/basic/common/InMiddleOfPackage.kt index 26b86184cfe..039bda1772e 100644 --- a/idea/idea-completion/testData/basic/common/InMiddleOfPackage.kt +++ b/idea/idea-completion/testData/basic/common/InMiddleOfPackage.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package kotlin.properties. import kotlin.properties.Delegates diff --git a/idea/idea-completion/testData/basic/common/InMiddleOfPackageDirective.kt b/idea/idea-completion/testData/basic/common/InMiddleOfPackageDirective.kt index 020ba806ac0..00eb2f6101d 100644 --- a/idea/idea-completion/testData/basic/common/InMiddleOfPackageDirective.kt +++ b/idea/idea-completion/testData/basic/common/InMiddleOfPackageDirective.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package testdata.kotlin.data class TestSample() { diff --git a/idea/idea-completion/testData/basic/common/InPackage.kt b/idea/idea-completion/testData/basic/common/InPackage.kt index 33fe1724eb4..791f5c8833e 100644 --- a/idea/idea-completion/testData/basic/common/InPackage.kt +++ b/idea/idea-completion/testData/basic/common/InPackage.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package kotlin. diff --git a/idea/idea-completion/testData/basic/common/SubpackageInFun.kt b/idea/idea-completion/testData/basic/common/SubpackageInFun.kt index e7a281c7a73..96993c06477 100644 --- a/idea/idea-completion/testData/basic/common/SubpackageInFun.kt +++ b/idea/idea-completion/testData/basic/common/SubpackageInFun.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package Test.MyTest fun test() { diff --git a/idea/idea-completion/testData/basic/common/annotations/TopLevelAnnotation1.kt b/idea/idea-completion/testData/basic/common/annotations/TopLevelAnnotation1.kt index 3f3092629a9..98491ef8e7c 100644 --- a/idea/idea-completion/testData/basic/common/annotations/TopLevelAnnotation1.kt +++ b/idea/idea-completion/testData/basic/common/annotations/TopLevelAnnotation1.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package java annotation class Hello diff --git a/idea/idea-completion/testData/basic/common/typeArgsOrNot/LessThan.kt b/idea/idea-completion/testData/basic/common/typeArgsOrNot/LessThan.kt index 564e044914b..4135dd9bdc0 100644 --- a/idea/idea-completion/testData/basic/common/typeArgsOrNot/LessThan.kt +++ b/idea/idea-completion/testData/basic/common/typeArgsOrNot/LessThan.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON val v = 1 fun f() = 2 diff --git a/idea/idea-completion/testData/basic/common/typeArgsOrNot/SecondTypeArg2.kt b/idea/idea-completion/testData/basic/common/typeArgsOrNot/SecondTypeArg2.kt index 0183a9ba74d..804a283d56a 100644 --- a/idea/idea-completion/testData/basic/common/typeArgsOrNot/SecondTypeArg2.kt +++ b/idea/idea-completion/testData/basic/common/typeArgsOrNot/SecondTypeArg2.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON fun foo() { val v = HashMap> } diff --git a/idea/idea-completion/testData/basic/java/CompletionForExcludedWhenInternalUse.kt b/idea/idea-completion/testData/basic/java/CompletionForExcludedWhenInternalUse.kt index 97445bbb299..00d4d0e06df 100644 --- a/idea/idea-completion/testData/basic/java/CompletionForExcludedWhenInternalUse.kt +++ b/idea/idea-completion/testData/basic/java/CompletionForExcludedWhenInternalUse.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package kotlin fun some() { diff --git a/idea/idea-completion/testData/basic/java/InPackage.kt b/idea/idea-completion/testData/basic/java/InPackage.kt index f03942798b5..d905f42f907 100644 --- a/idea/idea-completion/testData/basic/java/InPackage.kt +++ b/idea/idea-completion/testData/basic/java/InPackage.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package java.util. // EXIST: concurrent diff --git a/idea/idea-completion/testData/basic/java/JavaPackage.kt b/idea/idea-completion/testData/basic/java/JavaPackage.kt index 3879365ae51..9284d0927ce 100644 --- a/idea/idea-completion/testData/basic/java/JavaPackage.kt +++ b/idea/idea-completion/testData/basic/java/JavaPackage.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package Tests class A : java. diff --git a/idea/idea-completion/testData/basic/java/PackageDirective.kt b/idea/idea-completion/testData/basic/java/PackageDirective.kt index d045442403e..e2ca17035de 100644 --- a/idea/idea-completion/testData/basic/java/PackageDirective.kt +++ b/idea/idea-completion/testData/basic/java/PackageDirective.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON package java.lang. // EXIST: annotation diff --git a/idea/idea-fir-fe10-binding/src/org/jetbrains/kotlin/idea/fir/fe10/FE10BindingContext.kt b/idea/idea-fir-fe10-binding/src/org/jetbrains/kotlin/idea/fir/fe10/FE10BindingContext.kt index 5b586e8e0a7..102f3955905 100644 --- a/idea/idea-fir-fe10-binding/src/org/jetbrains/kotlin/idea/fir/fe10/FE10BindingContext.kt +++ b/idea/idea-fir-fe10-binding/src/org/jetbrains/kotlin/idea/fir/fe10/FE10BindingContext.kt @@ -86,7 +86,7 @@ class FE10BindingContextImpl( private val moduleInfo = ktElement.getModuleInfo() @OptIn(InvalidWayOfUsingAnalysisSession::class) - override val ktAnalysisSessionFacade = KtAnalysisSessionFe10BindingHolder.create(ktElement.getResolveState(), token) + override val ktAnalysisSessionFacade = KtAnalysisSessionFe10BindingHolder.create(ktElement.getResolveState(), token, ktElement) override val moduleDescriptor: ModuleDescriptor = KtSymbolBasedModuleDescriptorImpl(this, moduleInfo) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt index 321a9908d53..e5b0a8e871b 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt @@ -60,20 +60,24 @@ private object KotlinFirCompletionProvider : CompletionProvider { complete(keywordContributor, positionContext) + complete(packageCompletionContributor, positionContext) complete(callableContributor, positionContext) complete(classifierContributor, positionContext) } is FirTypeNameReferencePositionContext -> { complete(keywordContributor, positionContext) + complete(packageCompletionContributor, positionContext) complete(classifierContributor, positionContext) } is FirAnnotationTypeNameReferencePositionContext -> { complete(keywordContributor, positionContext) + complete(packageCompletionContributor, positionContext) complete(annotationsContributor, positionContext) } diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt index a64103847c1..74e08db2579 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirLookupElementFactory.kt @@ -53,6 +53,16 @@ internal class KotlinFirLookupElementFactory { .withIcon(KotlinFirIconProvider.getIconFor(symbol)) } + fun createPackageLookupElement(packageFqName: FqName): LookupElement { + return LookupElementBuilder.create(PackageLookupObject(packageFqName), packageFqName.shortName().asString()) + .withInsertHandler(QuotedNamesAwareInsertionHandler()) + .let { + if (!packageFqName.parent().isRoot) { + it.appendTailText(" (${packageFqName.asString()})", true) + } else it + } + } + fun KtAnalysisSession.createLookupElementForClassLikeSymbol(symbol: KtClassLikeSymbol, insertFqName: Boolean = true): LookupElement? { if (symbol !is KtNamedSymbol) return null return classLookupElementFactory.createLookup(symbol, insertFqName) @@ -76,6 +86,13 @@ private interface KotlinLookupObject { val shortName: Name } +private data class PackageLookupObject( + val packageFqName: FqName, +) : KotlinLookupObject { + override val shortName: Name = packageFqName.shortName() +} + + private data class ClassifierLookupObject(override val shortName: Name, val classId: ClassId?, val insertFqName: Boolean) : KotlinLookupObject /** diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/context/FirBasicCompletionContext.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/context/FirBasicCompletionContext.kt index ff5dac04f94..9bcd53e53d0 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/context/FirBasicCompletionContext.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/context/FirBasicCompletionContext.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.idea.caches.project.getModuleInfo import org.jetbrains.kotlin.idea.completion.KotlinFirLookupElementFactory import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper import org.jetbrains.kotlin.idea.project.TargetPlatformDetector +import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtFile @@ -27,6 +28,8 @@ internal class FirBasicCompletionContext( val indexHelper: IndexHelper, val lookupElementFactory: KotlinFirLookupElementFactory = KotlinFirLookupElementFactory(), ) { + val visibleScope = KotlinSourceFilterScope.projectSourceAndClassFiles(originalKtFile.resolveScope, project) + companion object { fun createFromParameters(parameters: CompletionParameters, result: CompletionResultSet): FirBasicCompletionContext? { val prefixMatcher = result.prefixMatcher diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt index 7fd8199eef7..265b6a0f751 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/scopes/KtScope.kt @@ -92,4 +92,12 @@ interface KtDeclarationScope : KtScope { interface KtPackageScope : KtScope { val fqName: FqName + + fun getPackageSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence + + override fun getAllSymbols(): Sequence = withValidityAssertion { + super.getAllSymbols() + getPackageSymbols() + } + + override fun getConstructors(): Sequence = withValidityAssertion { emptySequence() } } \ No newline at end of file diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt index 527d4296f32..6ebd9fada31 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/symbols/KtSymbolProvider.kt @@ -48,6 +48,9 @@ abstract class KtSymbolProvider : KtAnalysisSessionComponent() { abstract fun getClassOrObjectSymbolByClassId(classId: ClassId): KtClassOrObjectSymbol? abstract fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): Sequence + + @Suppress("PropertyName") + abstract val ROOT_PACKAGE_SYMBOL: KtPackageSymbol } interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn { @@ -111,4 +114,7 @@ interface KtSymbolProviderMixIn : KtAnalysisSessionMixIn { fun FqName.getContainingCallableSymbolsWithName(name: Name): Sequence = analysisSession.symbolProvider.getTopLevelCallableSymbols(this, name) + @Suppress("PropertyName") + val ROOT_PACKAGE_SYMBOL: KtPackageSymbol + get() = analysisSession.symbolProvider.ROOT_PACKAGE_SYMBOL } \ 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 c3b93cb96b1..6fea53c8d1d 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 @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.idea.fir.low.level.api.api.* @@ -19,6 +21,8 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirOverrideInfoProvi import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken +import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope +import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @@ -28,6 +32,7 @@ private constructor( val firResolveState: FirModuleResolveState, internal val firSymbolBuilder: KtSymbolByFirBuilder, token: ValidityToken, + element: KtElement, private val mode: AnalysisSessionMode, ) : KtAnalysisSession(token) { @@ -90,19 +95,23 @@ private constructor( contextResolveState, firSymbolBuilder.createReadOnlyCopy(contextResolveState), token, + originalKtFile, AnalysisSessionMode.DEPENDENT_COPY ) } val rootModuleSession: FirSession get() = firResolveState.rootModuleSession val firSymbolProvider: FirSymbolProvider get() = rootModuleSession.symbolProvider + val targetPlatform: TargetPlatform get() = rootModuleSession.moduleData.platform + val searchScope: GlobalSearchScope = KotlinSourceFilterScope.projectSourceAndClassFiles(element.resolveScope, project) companion object { @InvalidWayOfUsingAnalysisSession @Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze") internal fun createAnalysisSessionByResolveState( firResolveState: FirModuleResolveState, - token: ValidityToken + token: ValidityToken, + element: KtElement, ): KtFirAnalysisSession { val project = firResolveState.project val firSymbolBuilder = KtSymbolByFirBuilder( @@ -115,7 +124,8 @@ private constructor( firResolveState, firSymbolBuilder, token, - AnalysisSessionMode.REGULAR + element, + AnalysisSessionMode.REGULAR, ) } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSessionProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSessionProvider.kt index 93bc7251944..0ac2c9a9f06 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSessionProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSessionProvider.kt @@ -31,7 +31,7 @@ class KtFirAnalysisSessionProvider(private val project: Project) : KtAnalysisSes return cache.getAnalysisSession(resolveState to factory.identifier) { val validityToken = factory.create(project) @Suppress("DEPRECATION") - KtFirAnalysisSession.createAnalysisSessionByResolveState(resolveState, validityToken) + KtFirAnalysisSession.createAnalysisSessionByResolveState(resolveState, validityToken, contextElement) } } 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 d3f0f58f8e3..2cf74befecd 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir import com.google.common.collect.MapMaker import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.builtins.functions.FunctionClassKind import org.jetbrains.kotlin.fir.* @@ -112,10 +113,16 @@ internal class KtSymbolByFirBuilder private constructor( fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? { - val exists = PackageIndexUtil.packageExists(packageFqName, GlobalSearchScope.allScope(project), project) + val exists = + PackageIndexUtil.packageExists(packageFqName, GlobalSearchScope.allScope(project), project) + || JavaPsiFacade.getInstance(project).findPackage(packageFqName.asString()) != null if (!exists) { return null } + return createPackageSymbol(packageFqName) + } + + fun createPackageSymbol(packageFqName: FqName): KtFirPackageSymbol { return KtFirPackageSymbol(packageFqName, project, token) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirScopeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirScopeProvider.kt index c643e03dac4..572753ec0fb 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirScopeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirScopeProvider.kt @@ -107,15 +107,22 @@ internal class KtFirScopeProvider( override fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope = withValidityAssertion { packageMemberScopeCache.getOrPut(packageSymbol) { - val firPackageScope = - FirPackageMemberScope( - packageSymbol.fqName, - firResolveState.rootModuleSession/*TODO use correct session here*/ - ).also(firScopeStorage::register) - KtFirPackageScope(firPackageScope, project, builder, token) + KtFirPackageScope( + packageSymbol.fqName, + project, + builder, + this, + token, + analysisSession.searchScope, + analysisSession.targetPlatform + ) } } + fun registerScope(scope: FirScope) { + firScopeStorage.register(scope) + } + override fun getCompositeScope(subScopes: List): KtCompositeScope = withValidityAssertion { KtFirCompositeScope(subScopes, token) } @@ -179,7 +186,15 @@ internal class KtFirScopeProvider( return when (firScope) { is FirAbstractSimpleImportingScope -> KtFirNonStarImportingScope(firScope, builder, token) is FirAbstractStarImportingScope -> KtFirStarImportingScope(firScope, builder, project, token) - is FirPackageMemberScope -> KtFirPackageScope(firScope, project, builder, token) + is FirPackageMemberScope -> KtFirPackageScope( + firScope.fqName, + project, + builder, + this, + token, + analysisSession.searchScope, + analysisSession.targetPlatform + ) is FirContainingNamesAwareScope -> KtFirDelegatingScopeImpl(firScope, builder, token) is FirMemberTypeParameterScope -> KtFirDelegatingScopeImpl(firScope, builder, token) else -> TODO(firScope::class.toString()) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt index 95eaf466138..1abce5296f2 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt @@ -6,32 +6,45 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.scopes import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.idea.fir.low.level.api.api.searchScope import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder +import org.jetbrains.kotlin.idea.frontend.api.fir.components.KtFirScopeProvider +import org.jetbrains.kotlin.idea.frontend.api.fir.utils.lazyThreadUnsafeWeakRef import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef import org.jetbrains.kotlin.idea.frontend.api.scopes.KtPackageScope import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassifierSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion -import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelClassByPackageIndex -import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionByPackageIndex -import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyByPackageIndex -import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasByPackageIndex +import org.jetbrains.kotlin.idea.search.getKotlinFqName +import org.jetbrains.kotlin.idea.stubindex.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.jvm.isJvm internal class KtFirPackageScope( - firScope: FirPackageMemberScope, + override val fqName: FqName, private val project: Project, private val builder: KtSymbolByFirBuilder, + _scopeProvider: KtFirScopeProvider, override val token: ValidityToken, + private val searchScope: GlobalSearchScope, + private val targetPlatform: TargetPlatform, ) : KtPackageScope { - private val firScope by weakRef(firScope) - override val fqName: FqName get() = firScope.fqName + private val scopeProvider by weakRef(_scopeProvider) + + private val firScope: FirPackageMemberScope by lazyThreadUnsafeWeakRef { + val scope = FirPackageMemberScope(fqName, builder.rootSession) + scopeProvider.registerScope(scope) + scope + } override fun getPossibleCallableNames() = withValidityAssertion { hashSetOf().apply { @@ -58,5 +71,22 @@ internal class KtFirPackageScope( firScope.getClassifierSymbols(getPossibleClassifierNames().filter(nameFilter), builder) } - override fun getConstructors(): Sequence = emptySequence() + override fun getPackageSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion { + sequence { + PackageIndexUtil + .getSubPackageFqNames(fqName, searchScope, project, nameFilter) + .forEach { + yield(builder.createPackageSymbol(it)) + } + + if (targetPlatform.isJvm()) { + JavaPsiFacade.getInstance(project).findPackage(fqName.asString())?.getSubPackages(searchScope)?.forEach { psiPackage -> + val fqName = psiPackage.getKotlinFqName() ?: return@forEach + if (nameFilter(fqName.shortName())) { + yield(builder.createPackageSymbol(fqName)) + } + } + } + } + } } 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 index 964a6c4e484..a87863d86a3 100644 --- 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.impl.file.PsiPackageImpl diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt index 6916b9dfdaf..ec7474a5a15 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirSymbolProvider.kt @@ -131,4 +131,6 @@ internal class KtFirSymbolProvider( val firs = firSymbolProvider.getTopLevelCallableSymbols(packageFqName, name) return firs.asSequence().map { firSymbol -> firSymbolBuilder.buildSymbol(firSymbol.fir) } } + + override val ROOT_PACKAGE_SYMBOL: KtPackageSymbol = KtFirPackageSymbol(FqName.ROOT, resolveState.project, token) } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/KtAnalysisSessionFe10BindingHolder.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/KtAnalysisSessionFe10BindingHolder.kt index 79b7f09cf09..4b05a43bf42 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/KtAnalysisSessionFe10BindingHolder.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/KtAnalysisSessionFe10BindingHolder.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.ir.util.IdSignature +import org.jetbrains.kotlin.psi.KtElement class KtAnalysisSessionFe10BindingHolder private constructor( @@ -46,8 +47,8 @@ class KtAnalysisSessionFe10BindingHolder private constructor( companion object { @InvalidWayOfUsingAnalysisSession - fun create(firResolveState: FirModuleResolveState, token: ValidityToken): KtAnalysisSessionFe10BindingHolder { - val firAnalysisSession = KtFirAnalysisSession.createAnalysisSessionByResolveState(firResolveState, token) + fun create(firResolveState: FirModuleResolveState, token: ValidityToken, ktElement: KtElement): KtAnalysisSessionFe10BindingHolder { + val firAnalysisSession = KtFirAnalysisSession.createAnalysisSessionByResolveState(firResolveState, token, ktElement) return KtAnalysisSessionFe10BindingHolder(firAnalysisSession) } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/LazyOnlyWeakRef.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/LazyOnlyWeakRef.kt new file mode 100644 index 00000000000..ce3be9a1b4c --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/LazyOnlyWeakRef.kt @@ -0,0 +1,30 @@ +/* + * 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.utils + +import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken +import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner +import java.lang.ref.WeakReference +import kotlin.reflect.KProperty + +class ReadOnlyWeakRef +@Deprecated("Consider suing ValidityTokenOwner.weakRef instead") +constructor(value: V, val token: ValidityToken) { + val weakRef = WeakReference(value) + + @Suppress("NOTHING_TO_INLINE") + inline operator fun getValue(thisRef: Any, property: KProperty<*>): V = + weakRef.get() ?: if (token.isValid()) { + throw EntityWasGarbageCollectedException(property.toString()) + } else { + error("Accessing the invalid value of $property") + } +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun ValidityTokenOwner.weakRef(value: V) = ReadOnlyWeakRef(value, token) + +internal inline fun ValidityTokenOwner.weakRef(value: () -> V) = ReadOnlyWeakRef(value(), token) \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt index ce3be9a1b4c..ff136d99d91 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ReadOnlyWeakRef.kt @@ -10,21 +10,23 @@ import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner import java.lang.ref.WeakReference import kotlin.reflect.KProperty -class ReadOnlyWeakRef -@Deprecated("Consider suing ValidityTokenOwner.weakRef instead") -constructor(value: V, val token: ValidityToken) { - val weakRef = WeakReference(value) +internal class LazyThreadUnsafeWeakRef +constructor(_createValue: () -> V, val token: ValidityToken) { + private var createValue: (() -> V)? = _createValue + private var weakRef: WeakReference? = null @Suppress("NOTHING_TO_INLINE") - inline operator fun getValue(thisRef: Any, property: KProperty<*>): V = - weakRef.get() ?: if (token.isValid()) { + inline operator fun getValue(thisRef: Any, property: KProperty<*>): V { + if (weakRef == null) { + weakRef = WeakReference(createValue!!()) + createValue = null + } + return weakRef!!.get() ?: if (token.isValid()) { throw EntityWasGarbageCollectedException(property.toString()) } else { error("Accessing the invalid value of $property") } + } } -@Suppress("NOTHING_TO_INLINE") -internal inline fun ValidityTokenOwner.weakRef(value: V) = ReadOnlyWeakRef(value, token) - -internal inline fun ValidityTokenOwner.weakRef(value: () -> V) = ReadOnlyWeakRef(value(), token) \ No newline at end of file +internal fun ValidityTokenOwner.lazyThreadUnsafeWeakRef(createValue: () -> V) = LazyThreadUnsafeWeakRef(createValue, token) \ No newline at end of file