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(