From 32919489f45901f9a81164d26f054c23689f0f16 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 14 Jun 2021 16:27:25 +0200 Subject: [PATCH] FIR IDE: separate index helper in LL API and completion --- .../context/FirBasicCompletionContext.kt | 6 +- .../FirCallableCompletionContributor.kt | 4 +- .../FirCompletionContributorBase.kt | 4 +- .../FirContextCompletionContributorBase.kt | 1 - .../helpers/FirClassifierProvider.kt | 4 +- .../jetbrains/kotlin/idea/fir/IndexHelper.kt | 113 ++++++++++++++++++ .../idea/quickfix/fixes/ImportQuickFix.kt | 12 +- .../idea/fir/low/level/api/IndexHelper.kt | 76 +----------- 8 files changed, 129 insertions(+), 91 deletions(-) create mode 100644 idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/IndexHelper.kt 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 90355f3bd6f..288e465702f 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 @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.idea.caches.project.getModuleInfo import org.jetbrains.kotlin.idea.completion.KotlinFirCompletionParameters import org.jetbrains.kotlin.idea.completion.LookupElementSink import org.jetbrains.kotlin.idea.completion.lookups.factories.KotlinFirLookupElementFactory -import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper +import org.jetbrains.kotlin.idea.fir.HLIndexHelper import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.platform.TargetPlatform @@ -28,7 +28,7 @@ internal class FirBasicCompletionContext( val fakeKtFile: KtFile, val project: Project, val targetPlatform: TargetPlatform, - val indexHelper: IndexHelper, + val indexHelper: HLIndexHelper, val lookupElementFactory: KotlinFirLookupElementFactory = KotlinFirLookupElementFactory(), ) { val visibleScope = KotlinSourceFilterScope.projectSourceAndClassFiles(originalKtFile.resolveScope, project) @@ -55,7 +55,7 @@ internal class FirBasicCompletionContext( ) } - private fun createIndexHelper(parameters: CompletionParameters) = IndexHelper( + private fun createIndexHelper(parameters: CompletionParameters) = HLIndexHelper( parameters.position.project, parameters.position.getModuleInfo().contentScope() ) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt index bdfb5578bf1..9c3e6752d0a 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker import org.jetbrains.kotlin.idea.completion.checkers.ExtensionApplicabilityChecker import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext -import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper +import org.jetbrains.kotlin.idea.fir.HLIndexHelper import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeContext import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope @@ -168,7 +168,7 @@ internal class FirCallableCompletionContributor( implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } } } -private class TypeNamesProvider(private val indexHelper: IndexHelper) { +private class TypeNamesProvider(private val indexHelper: HLIndexHelper) { fun KtAnalysisSession.findAllNames(type: KtType): Set { if (type !is KtNonErrorClassType) return emptySet() diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt index 948e8d654f8..0b66912b4c0 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy import org.jetbrains.kotlin.idea.completion.lookups.factories.KotlinFirLookupElementFactory import org.jetbrains.kotlin.idea.completion.weighers.Weighers -import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper +import org.jetbrains.kotlin.idea.fir.HLIndexHelper import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter import org.jetbrains.kotlin.idea.frontend.api.symbols.* @@ -37,7 +37,7 @@ internal abstract class FirCompletionContributorBase = sequence { yieldAll( diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/IndexHelper.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/IndexHelper.kt new file mode 100644 index 00000000000..f992696b79a --- /dev/null +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/IndexHelper.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2010-2021 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.fir + +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.stubs.StringStubIndexExtension +import com.intellij.psi.stubs.StubIndex +import com.intellij.psi.stubs.StubIndexKey +import org.jetbrains.kotlin.idea.stubindex.* +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* + +/* +* Move to another module +*/ +class HLIndexHelper(val project: Project, private val scope: GlobalSearchScope) { + fun getClassNamesInPackage(packageFqName: FqName): Set = + KotlinTopLevelClassByPackageIndex.getInstance() + .get(packageFqName.asStringForIndexes(), project, scope) + .mapNotNullTo(hashSetOf()) { it.nameAsName } + + fun getKotlinClasses( + nameFilter: (Name) -> Boolean, + psiFilter: (element: KtClassOrObject) -> Boolean = { true } + ): Collection { + val index = KotlinFullClassNameIndex.getInstance() + return index.getAllKeys(project).asSequence() + .onEach { ProgressManager.checkCanceled() } + .filter { fqName -> nameFilter(getShortName(fqName)) } + .flatMap { fqName -> index[fqName, project, scope] } + .filter(psiFilter) + .toList() + } + + fun getTopLevelCallables(nameFilter: (Name) -> Boolean): Collection { + fun sequenceOfElements(index: StringStubIndexExtension): Sequence = + index.getAllKeys(project).asSequence() + .onEach { ProgressManager.checkCanceled() } + .filter { fqName -> nameFilter(getShortName(fqName)) } + .flatMap { fqName -> index[fqName, project, scope] } + .filter { it.receiverTypeReference == null } + + val functions = sequenceOfElements(KotlinTopLevelFunctionFqnNameIndex.getInstance()) + val properties = sequenceOfElements(KotlinTopLevelPropertyFqnNameIndex.getInstance()) + + return (functions + properties).toList() + } + + fun getKotlinCallablesByName(name: Name): Collection { + val functions: Sequence = + KotlinFunctionShortNameIndex.getInstance().get(name.asString(), project, scope).asSequence() + + val properties: Sequence = + KotlinPropertyShortNameIndex.getInstance().get(name.asString(), project, scope).asSequence() + + return (functions + properties) + .filterIsInstance() + .toList() + } + + fun getKotlinClassesByName(name: Name): Collection { + return KotlinClassShortNameIndex.getInstance().get(name.asString(), project, scope) + } + + fun getTopLevelExtensions(nameFilter: (Name) -> Boolean, receiverTypeNames: Set): Collection { + val index = KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE + + return index.getAllKeys(project).asSequence() + .onEach { ProgressManager.checkCanceled() } + .filter { KotlinTopLevelExtensionsByReceiverTypeIndex.receiverTypeNameFromKey(it) in receiverTypeNames } + .filter { nameFilter(Name.identifier(KotlinTopLevelExtensionsByReceiverTypeIndex.callableNameFromKey(it))) } + .flatMap { key -> index[key, project, scope] } + .toList() + } + + fun getPossibleTypeAliasExpansionNames(originalTypeName: String): Set { + val index = KotlinTypeAliasByExpansionShortNameIndex.INSTANCE + val out = mutableSetOf() + + fun searchRecursively(typeName: String) { + ProgressManager.checkCanceled() + index[typeName, project, scope].asSequence() + .mapNotNull { it.name } + .filter { out.add(it) } + .forEach(::searchRecursively) + } + + searchRecursively(originalTypeName) + return out + } + + companion object { + private fun CallableId.asStringForIndexes(): String = + (if (packageName.isRoot) callableName.asString() else toString()).replace('/', '.') + + private fun FqName.asStringForIndexes(): String = + asString().replace('/', '.') + + private fun ClassId.asStringForIndexes(): String = + asSingleFqName().asStringForIndexes() + + private fun getShortName(fqName: String) = Name.identifier(fqName.substringAfterLast('.')) + } +} diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt index d084ce14d11..8c625c80e8b 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/quickfix/fixes/ImportQuickFix.kt @@ -19,8 +19,8 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.PsiModificationTracker import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.project.getModuleInfo +import org.jetbrains.kotlin.idea.fir.HLIndexHelper import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory -import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper import org.jetbrains.kotlin.idea.fir.low.level.api.util.createScopeForModuleLibraries import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic @@ -137,7 +137,7 @@ internal class ImportQuickFix( val FACTORY = diagnosticFixFactory(KtFirDiagnostic.UnresolvedReference::class) { diagnostic -> val element = diagnostic.psi - val indexHelper = IndexHelper(element.project, createSearchScope(element)) + val indexHelper = HLIndexHelper(element.project, createSearchScope(element)) val quickFix = when (element) { is KtTypeReference -> createImportTypeFix(indexHelper, element) @@ -157,7 +157,7 @@ internal class ImportQuickFix( } private fun KtAnalysisSession.createImportNameFix( - indexHelper: IndexHelper, + indexHelper: HLIndexHelper, element: KtNameReferenceExpression ): ImportQuickFix? { if (isSelectorInQualified(element)) return null @@ -177,7 +177,7 @@ internal class ImportQuickFix( return ImportQuickFix(element, importCandidates) } - private fun KtAnalysisSession.createImportTypeFix(indexHelper: IndexHelper, element: KtTypeReference): ImportQuickFix? { + private fun KtAnalysisSession.createImportTypeFix(indexHelper: HLIndexHelper, element: KtTypeReference): ImportQuickFix? { val firFile = element.containingKtFile.getFileSymbol() val unresolvedName = element.typeName ?: return null @@ -191,7 +191,7 @@ internal class ImportQuickFix( } private fun KtAnalysisSession.collectCallableCandidates( - indexHelper: IndexHelper, + indexHelper: HLIndexHelper, unresolvedName: Name, isVisible: (KtCallableSymbol) -> Boolean ): List { @@ -206,7 +206,7 @@ internal class ImportQuickFix( } private fun KtAnalysisSession.collectTypesCandidates( - indexHelper: IndexHelper, + indexHelper: HLIndexHelper, unresolvedName: Name, isVisible: (KtNamedClassOrObjectSymbol) -> Boolean ): List { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/IndexHelper.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/IndexHelper.kt index d12532f0cf8..c8027b89025 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/IndexHelper.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/IndexHelper.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.* /* * Move to another module */ -public class IndexHelper(val project: Project, private val scope: GlobalSearchScope) { +internal class IndexHelper(val project: Project, private val scope: GlobalSearchScope) { private val stubIndex: StubIndex = StubIndex.getInstance() private inline fun firstMatchingOrNull( @@ -64,86 +64,12 @@ public class IndexHelper(val project: Project, private val scope: GlobalSearchSc fun getTopLevelFunctions(callableId: CallableId): Collection = KotlinTopLevelFunctionFqnNameIndex.getInstance()[callableId.asStringForIndexes(), project, scope] - fun getTopLevelPropertiesInPackage(packageFqName: FqName): Collection = - KotlinTopLevelPropertyByPackageIndex.getInstance().get(packageFqName.asStringForIndexes(), project, scope) - - fun getTopLevelFunctionsInPackage(packageFqName: FqName): Collection = - KotlinTopLevelFunctionByPackageIndex.getInstance().get(packageFqName.asStringForIndexes(), project, scope) fun getClassNamesInPackage(packageFqName: FqName): Set = KotlinTopLevelClassByPackageIndex.getInstance() .get(packageFqName.asStringForIndexes(), project, scope) .mapNotNullTo(hashSetOf()) { it.nameAsName } - fun getKotlinClasses( - nameFilter: (Name) -> Boolean, - psiFilter: (element: KtClassOrObject) -> Boolean = { true } - ): Collection { - val index = KotlinFullClassNameIndex.getInstance() - return index.getAllKeys(project).asSequence() - .onEach { ProgressManager.checkCanceled() } - .filter { fqName -> nameFilter(getShortName(fqName)) } - .flatMap { fqName -> index[fqName, project, scope] } - .filter(psiFilter) - .toList() - } - - fun getTopLevelCallables(nameFilter: (Name) -> Boolean): Collection { - fun sequenceOfElements(index: StringStubIndexExtension): Sequence = - index.getAllKeys(project).asSequence() - .onEach { ProgressManager.checkCanceled() } - .filter { fqName -> nameFilter(getShortName(fqName)) } - .flatMap { fqName -> index[fqName, project, scope] } - .filter { it.receiverTypeReference == null } - - val functions = sequenceOfElements(KotlinTopLevelFunctionFqnNameIndex.getInstance()) - val properties = sequenceOfElements(KotlinTopLevelPropertyFqnNameIndex.getInstance()) - - return (functions + properties).toList() - } - - fun getKotlinCallablesByName(name: Name): Collection { - val functions: Sequence = - KotlinFunctionShortNameIndex.getInstance().get(name.asString(), project, scope).asSequence() - - val properties: Sequence = - KotlinPropertyShortNameIndex.getInstance().get(name.asString(), project, scope).asSequence() - - return (functions + properties) - .filterIsInstance() - .toList() - } - - fun getKotlinClassesByName(name: Name): Collection { - return KotlinClassShortNameIndex.getInstance().get(name.asString(), project, scope) - } - - fun getTopLevelExtensions(nameFilter: (Name) -> Boolean, receiverTypeNames: Set): Collection { - val index = KotlinTopLevelExtensionsByReceiverTypeIndex.INSTANCE - - return index.getAllKeys(project).asSequence() - .onEach { ProgressManager.checkCanceled() } - .filter { KotlinTopLevelExtensionsByReceiverTypeIndex.receiverTypeNameFromKey(it) in receiverTypeNames } - .filter { nameFilter(Name.identifier(KotlinTopLevelExtensionsByReceiverTypeIndex.callableNameFromKey(it))) } - .flatMap { key -> index[key, project, scope] } - .toList() - } - - fun getPossibleTypeAliasExpansionNames(originalTypeName: String): Set { - val index = KotlinTypeAliasByExpansionShortNameIndex.INSTANCE - val out = mutableSetOf() - - fun searchRecursively(typeName: String) { - ProgressManager.checkCanceled() - index[typeName, project, scope].asSequence() - .mapNotNull { it.name } - .filter { out.add(it) } - .forEach(::searchRecursively) - } - - searchRecursively(originalTypeName) - return out - } companion object { private fun CallableId.asStringForIndexes(): String =