diff --git a/plugins/compose/intellij.compose.ide.plugin.iml b/plugins/compose/intellij.compose.ide.plugin.iml
index 81132ce2a0bd..b271ca4e03ec 100644
--- a/plugins/compose/intellij.compose.ide.plugin.iml
+++ b/plugins/compose/intellij.compose.ide.plugin.iml
@@ -14,5 +14,7 @@
+
+
\ No newline at end of file
diff --git a/plugins/compose/resources/META-INF/plugin.xml b/plugins/compose/resources/META-INF/plugin.xml
index b7e854182367..31bc8b1f6707 100644
--- a/plugins/compose/resources/META-INF/plugin.xml
+++ b/plugins/compose/resources/META-INF/plugin.xml
@@ -18,6 +18,7 @@
-
+
+
diff --git a/plugins/compose/src/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilter.kt b/plugins/compose/src/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilter.kt
new file mode 100644
index 000000000000..802d4f51e2e2
--- /dev/null
+++ b/plugins/compose/src/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilter.kt
@@ -0,0 +1,21 @@
+package com.intellij.compose.ide.plugin
+
+import com.intellij.codeInsight.generation.OverrideImplementsAnnotationsFilter
+import com.intellij.psi.PsiFile
+import org.jetbrains.kotlin.psi.KtFile
+
+/**
+ * Extension for [OverrideImplementsAnnotationsFilter], which checks if the "Composable" annotation is on the classpath,
+ * and if that's the case - retains it while doing overrides.
+ * This is more generic than the Android's `com.android.tools.compose.ComposeOverrideImplementsAnnotationsFilter` that only checks
+ * module's `usesCompose` flag, which only works for Android modules, but not for multiplatform.
+ */
+internal class ComposeOverrideImplementsAnnotationsFilter : OverrideImplementsAnnotationsFilter {
+ override fun getAnnotations(file: PsiFile): Array {
+ return if (file is KtFile && isKotlinClassAvailable(file, COMPOSABLE_ANNOTATION_CLASS_ID)) {
+ arrayOf(COMPOSABLE_ANNOTATION_FQ_NAME.asString())
+ } else {
+ arrayOf()
+ }
+ }
+}
diff --git a/plugins/compose/src/com/intellij/compose/ide/plugin/IndexUtils.kt b/plugins/compose/src/com/intellij/compose/ide/plugin/IndexUtils.kt
new file mode 100644
index 000000000000..8d2ac4228cc5
--- /dev/null
+++ b/plugins/compose/src/com/intellij/compose/ide/plugin/IndexUtils.kt
@@ -0,0 +1,20 @@
+package com.intellij.compose.ide.plugin
+
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.psi.PsiFile
+import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
+import org.jetbrains.kotlin.name.ClassId
+
+/**
+ * Checks if the given Kotlin class is accessible from the specified call site.
+ *
+ * @param callSite The PSI file representing the call site.
+ * @param classId The identifier of the class to check accessibility for.
+ * @return `true` if the class is accessible, `false` otherwise.
+ */
+internal fun isKotlinClassAvailable(callSite: PsiFile, classId: ClassId): Boolean {
+ val module = ModuleUtilCore.findModuleForPsiElement(callSite) ?: return false
+ val moduleScope = module.getModuleWithDependenciesAndLibrariesScope(/*includeTests = */true)
+ val foundClasses = KotlinFullClassNameIndex[classId.asFqNameString(), module.project, moduleScope]
+ return foundClasses.isNotEmpty()
+}
diff --git a/plugins/compose/tests/intellij.compose.ide.plugin.tests.iml b/plugins/compose/tests/intellij.compose.ide.plugin.tests.iml
index 60ea0cae2107..b9b6ba0fe7e9 100644
--- a/plugins/compose/tests/intellij.compose.ide.plugin.tests.iml
+++ b/plugins/compose/tests/intellij.compose.ide.plugin.tests.iml
@@ -14,6 +14,7 @@
+
\ No newline at end of file
diff --git a/plugins/compose/tests/test/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilterTest.kt b/plugins/compose/tests/test/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilterTest.kt
new file mode 100644
index 000000000000..9eb87bbb477d
--- /dev/null
+++ b/plugins/compose/tests/test/com/intellij/compose/ide/plugin/ComposeOverrideImplementsAnnotationsFilterTest.kt
@@ -0,0 +1,106 @@
+package com.intellij.compose.ide.plugin
+
+import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
+
+class ComposeOverrideImplementsAnnotationsFilterTest : KotlinLightCodeInsightFixtureTestCase() {
+ private val filter = ComposeOverrideImplementsAnnotationsFilter()
+
+ fun testKotlinFileWithComposeDependency() {
+ // Prepare
+ myFixture.addFileToProject(
+ "Composable.kt",
+ """
+ package androidx.compose.runtime
+
+ annotation class Composable
+ """.trimIndent()
+ )
+ val file = myFixture.addFileToProject(
+ "MyFile.kt",
+ """
+ package test
+
+ import androidx.compose.runtime.Composable
+
+ interface Base {
+ @Composable
+ fun view()
+ }
+
+ class BaseImpl : Base
+ """.trimIndent()
+ )
+
+ // Do
+ val annotations = filter.getAnnotations(file)
+
+ // Check
+ assertEquals(listOf(COMPOSABLE_ANNOTATION_FQ_NAME.asString()), annotations.toList())
+ }
+
+ fun testKotlinFileWithoutComposeDependency() {
+ // Prepare
+ val file = myFixture.addFileToProject(
+ "MyFile.kt",
+ """
+ package test
+
+ import androidx.compose.runtime.Composable
+
+ interface Base {
+ @Composable
+ fun view()
+ }
+
+ class BaseImpl : Base {}
+ """.trimIndent()
+ )
+
+ // Do
+ val annotations = filter.getAnnotations(file)
+
+ // Check
+ assertEquals(emptyList(), annotations.toList())
+ }
+
+ fun testJavaFile() {
+ // Prepare
+ myFixture.addFileToProject(
+ "Composable.kt",
+ """
+ package androidx.compose.runtime
+
+ annotation class Composable
+ """.trimIndent()
+ )
+ myFixture.addFileToProject(
+ "Base.kt",
+ """
+ package test
+
+ import androidx.compose.runtime.Composable
+
+ interface Base {
+ @Composable
+ fun view()
+ }
+ """.trimIndent()
+ )
+ val file = myFixture.addFileToProject(
+ "BaseImpl.java",
+ """
+ package test;
+
+ import androidx.compose.runtime.Composable;
+
+ class BaseImpl implements Base {}
+ """.trimIndent()
+ )
+
+ // Do
+ val annotations = filter.getAnnotations(file)
+
+ // Check
+ assertEquals(emptyList(), annotations.toList())
+ }
+}