diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml b/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml index 6c5433815f99..6f1a21de1126 100644 --- a/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/kotlin.base.analysis-api.utils.iml @@ -30,6 +30,7 @@ + @@ -39,7 +40,5 @@ - - \ No newline at end of file diff --git a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt index e52a64d8dd39..5b1f826c8b8e 100644 --- a/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt +++ b/plugins/kotlin/base/analysis-api/analysis-api-utils/src/org/jetbrains/kotlin/idea/base/analysis/api/utils/KtSymbolFromIndexProvider.kt @@ -11,15 +11,19 @@ import com.intellij.psi.PsiMethod import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.PsiShortNamesCache import com.intellij.util.Processor +import org.jetbrains.annotations.ApiStatus import org.jetbrains.kotlin.analysis.api.KaExperimentalApi +import org.jetbrains.kotlin.analysis.api.KaPlatformInterface import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.components.KaBuiltinTypes +import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider +import org.jetbrains.kotlin.analysis.api.projectStructure.KaDanglingFileModule +import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule +import org.jetbrains.kotlin.analysis.api.projectStructure.KaSourceModule import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.* import org.jetbrains.kotlin.base.analysis.isExcludedFromAutoImport -import org.jetbrains.kotlin.idea.base.facet.implementingModules import org.jetbrains.kotlin.idea.base.psi.kotlinFqName -import org.jetbrains.kotlin.idea.base.util.module import org.jetbrains.kotlin.idea.stubindex.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.isMultiPlatform @@ -46,7 +50,7 @@ class KtSymbolFromIndexProvider( return true } - if (isIgnoredExpectDeclaration(file)) { + if (isIgnoredExpectDeclaration()) { // filter out expect declarations outside of common modules return false } @@ -483,15 +487,42 @@ private fun MutableSet.createNamesProcessor( true } +/** + * Returns whether the module can declare expect declarations that could be implemented by an implementing module. + */ +private fun KaModule.canHaveExpectDeclarations(): Boolean { + if (targetPlatform.isMultiPlatform()) return true + + @OptIn(KaPlatformInterface::class) + val contextModule = (this as? KaDanglingFileModule)?.contextModule ?: this + // We return true in this case out of caution, because we do not know for sure. + if (contextModule !is KaSourceModule) return true + + // We can assume that only modules that have some implementing module can have expect declarations because otherwise + // they do not make sense. + return KotlinProjectStructureProvider.getInstance(project) + .getImplementingModules(contextModule) + .isNotEmpty() +} + /** * We ignore expect declarations within completion in leaf modules because they will already be filled by their (more relevant) * actual counterpart. */ context(KaSession) -private fun KtDeclaration.isIgnoredExpectDeclaration(contextFile: KtFile): Boolean { +@ApiStatus.Internal +fun KaDeclarationSymbol.isIgnoredExpectDeclaration(): Boolean { + if (!isExpect) return false + return !useSiteModule.canHaveExpectDeclarations() +} + + +/** + * See [KaDeclarationSymbol.isIgnoredExpectDeclaration]. + */ +context(KaSession) +@ApiStatus.Internal +fun KtDeclaration.isIgnoredExpectDeclaration(): Boolean { if (!isExpectDeclaration()) return false - // Modules that have multiple targetPlatforms might have expect declarations without actuals in libraries, so we cannot ignore them. - if (useSiteModule.targetPlatform.isMultiPlatform()) return false - // We can only safely ignore expect declarations if we are in a leaf module without implementing modules. - return contextFile.module?.implementingModules?.isEmpty() == true + return !useSiteModule.canHaveExpectDeclarations() } \ No newline at end of file diff --git a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt index e3d07c8648c7..33e09af98caf 100644 --- a/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt +++ b/plugins/kotlin/completion/impl-k2/src/org/jetbrains/kotlin/idea/completion/impl/k2/contributors/FirCallableCompletionContributor.kt @@ -22,13 +22,8 @@ import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.KaErrorType import org.jetbrains.kotlin.analysis.api.types.KaType import org.jetbrains.kotlin.analysis.api.types.KaTypeNullability -import org.jetbrains.kotlin.idea.base.analysis.api.utils.collectReceiverTypesForExplicitReceiverExpression -import org.jetbrains.kotlin.idea.base.analysis.api.utils.isJavaSourceOrLibrary -import org.jetbrains.kotlin.idea.base.analysis.api.utils.isPossiblySubTypeOf -import org.jetbrains.kotlin.idea.base.analysis.api.utils.resolveToExpandedSymbol -import org.jetbrains.kotlin.idea.base.facet.implementingModules +import org.jetbrains.kotlin.idea.base.analysis.api.utils.* import org.jetbrains.kotlin.idea.base.psi.isInsideAnnotationEntryArgumentList -import org.jetbrains.kotlin.idea.base.util.module import org.jetbrains.kotlin.idea.codeinsight.utils.canBeUsedAsExtension import org.jetbrains.kotlin.idea.codeinsight.utils.isEnum import org.jetbrains.kotlin.idea.completion.KotlinFirCompletionParameters @@ -49,7 +44,6 @@ import org.jetbrains.kotlin.idea.util.positionContext.KotlinNameReferencePositio import org.jetbrains.kotlin.idea.util.positionContext.KotlinSimpleNameReferencePositionContext import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.name.StandardClassIds -import org.jetbrains.kotlin.platform.isMultiPlatform import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.nextSiblingOfSameType import org.jetbrains.kotlin.resolve.ArrayFqNames @@ -93,10 +87,7 @@ internal open class FirCallableCompletionContributor( ) context(KaSession) - protected open fun filter(symbol: KaCallableSymbol): Boolean = - targetPlatform.isMultiPlatform() - || !symbol.isExpect - || symbol.psi?.module?.implementingModules?.isNotEmpty() == true + protected open fun filter(symbol: KaCallableSymbol): Boolean = !symbol.isIgnoredExpectDeclaration() // todo replace with a sealed hierarchy; too many arguments protected data class CallableWithMetadataForCompletion(