[PSI] KtPsiFactory: respect `eventSystemEnabled` for code fragments

KtPsiFactory already uses eventSystemEnabled when it creates ordinary
files, but code fragment factories skipped that value because the light
file view provider always enabled the event system. This made fragments
physical even for factories created with eventSystemEnabled = false, so
import mutation took the physical PSI path and required a command.

Pass the factory flag through type, expression, and block fragment
creation while keeping the existing public constructors event-enabled by
default. Add regression coverage for physical state and block fragment
import updates.

^KT-86869 Fixed
diff --git a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtBlockCodeFragment.kt b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtBlockCodeFragment.kt
index 56fd4ae..a6d6a1d 100644
--- a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtBlockCodeFragment.kt
+++ b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtBlockCodeFragment.kt
@@ -34,7 +34,20 @@
         imports: String?,
         context: PsiElement?
     ) : this(
-        createFileViewProviderForLightFile(project, name, text),
+        createFileViewProviderForLightFile(project, name, text, eventSystemEnabled = true),
+        imports,
+        context,
+    )
+
+    internal constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        imports: String?,
+        context: PsiElement?,
+        eventSystemEnabled: Boolean,
+    ) : this(
+        createFileViewProviderForLightFile(project, name, text, eventSystemEnabled),
         imports,
         context,
     )
diff --git a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt
index 0ed5146..40adc4e 100644
--- a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt
+++ b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt
@@ -35,7 +35,22 @@
         elementType: IElementType,
         context: PsiElement?
     ) : this(
-        createFileViewProviderForLightFile(project, name, text),
+        createFileViewProviderForLightFile(project, name, text, eventSystemEnabled = true),
+        imports,
+        elementType,
+        context,
+    )
+
+    internal constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        imports: String?,
+        elementType: IElementType,
+        context: PsiElement?,
+        eventSystemEnabled: Boolean,
+    ) : this(
+        createFileViewProviderForLightFile(project, name, text, eventSystemEnabled),
         imports,
         elementType,
         context,
@@ -228,11 +243,16 @@
 
         val FAKE_CONTEXT_FOR_JAVA_FILE: Key<Function0<KtElement>> = Key.create("FAKE_CONTEXT_FOR_JAVA_FILE")
 
-        internal fun createFileViewProviderForLightFile(project: Project, name: String, text: CharSequence): FileViewProvider {
+        internal fun createFileViewProviderForLightFile(
+            project: Project,
+            name: String,
+            text: CharSequence,
+            eventSystemEnabled: Boolean,
+        ): FileViewProvider {
             val psiManager = PsiManager.getInstance(project) as PsiManagerEx
             return psiManager.fileManager.createFileViewProvider(
                 LightVirtualFile(name, KotlinFileType.INSTANCE, text),
-                /* eventSystemEnabled = */true
+                eventSystemEnabled
             )
         }
 
@@ -242,4 +262,4 @@
 
 fun interface KotlinCodeFragmentImportModificationListener {
     fun onCodeFragmentImportsModification(codeFragment: KtCodeFragment)
-}
\ No newline at end of file
+}
diff --git a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtExpressionCodeFragment.kt b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtExpressionCodeFragment.kt
index 3754cfe..f1fc56a 100644
--- a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtExpressionCodeFragment.kt
+++ b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtExpressionCodeFragment.kt
@@ -20,13 +20,26 @@
 import com.intellij.psi.PsiElement
 import org.jetbrains.kotlin.KtNodeTypes
 
-class KtExpressionCodeFragment(
-    project: Project,
-    name: String,
-    text: CharSequence,
-    imports: String?,
-    context: PsiElement?
-) : KtCodeFragment(project, name, text, imports, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, context) {
+class KtExpressionCodeFragment : KtCodeFragment {
+    /**
+     * Creates an expression code fragment from [text] with optional [imports] and [context].
+     */
+    constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        imports: String?,
+        context: PsiElement?
+    ) : super(project, name, text, imports, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, context)
+
+    internal constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        imports: String?,
+        context: PsiElement?,
+        eventSystemEnabled: Boolean,
+    ) : super(project, name, text, imports, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, context, eventSystemEnabled)
 
     override fun getContentElement() = findChildByClass(KtExpression::class.java)
 }
diff --git a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
index a93f9ce..879abc3 100644
--- a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
+++ b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtPsiFactory.kt
@@ -607,15 +607,15 @@
     fun createLabeledExpression(@NonNls labelName: String): KtLabeledExpression = createExpression("$labelName@ 1") as KtLabeledExpression
 
     fun createTypeCodeFragment(@NonNls text: String, context: PsiElement?): KtTypeCodeFragment {
-        return KtTypeCodeFragment(project, "fragment.kt", text, context)
+        return KtTypeCodeFragment(project, "fragment.kt", text, context, eventSystemEnabled)
     }
 
     fun createExpressionCodeFragment(@NonNls text: String, context: PsiElement?): KtExpressionCodeFragment {
-        return KtExpressionCodeFragment(project, "fragment.kt", text, null, context)
+        return KtExpressionCodeFragment(project, "fragment.kt", text, null, context, eventSystemEnabled)
     }
 
     fun createBlockCodeFragment(@NonNls text: String, context: PsiElement?): KtBlockCodeFragment {
-        return KtBlockCodeFragment(project, "fragment.kt", text, null, context)
+        return KtBlockCodeFragment(project, "fragment.kt", text, null, context, eventSystemEnabled)
     }
 
     fun createIf(condition: KtExpression, thenExpr: KtExpression, elseExpr: KtExpression? = null): KtIfExpression {
diff --git a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtTypeCodeFragment.kt b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtTypeCodeFragment.kt
index 1e824a3..0df5337 100644
--- a/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtTypeCodeFragment.kt
+++ b/compiler/psi/psi-api/src/org/jetbrains/kotlin/psi/KtTypeCodeFragment.kt
@@ -20,11 +20,24 @@
 import com.intellij.psi.PsiElement
 import org.jetbrains.kotlin.KtNodeTypes
 
-class KtTypeCodeFragment(
-    project: Project,
-    name: String,
-    text: CharSequence,
-    context: PsiElement?
-) : KtCodeFragment(project, name, text, null, KtNodeTypes.TYPE_CODE_FRAGMENT, context) {
+class KtTypeCodeFragment : KtCodeFragment {
+    /**
+     * Creates a type code fragment from [text] with optional [context].
+     */
+    constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        context: PsiElement?
+    ) : super(project, name, text, null, KtNodeTypes.TYPE_CODE_FRAGMENT, context)
+
+    internal constructor(
+        project: Project,
+        name: String,
+        text: CharSequence,
+        context: PsiElement?,
+        eventSystemEnabled: Boolean,
+    ) : super(project, name, text, null, KtNodeTypes.TYPE_CODE_FRAGMENT, context, eventSystemEnabled)
+
     override fun getContentElement() = findChildByClass(KtTypeReference::class.java)
 }
diff --git a/compiler/psi/psi-impl/tests/org/jetbrains/kotlin/psi/KtCodeFragmentTest.kt b/compiler/psi/psi-impl/tests/org/jetbrains/kotlin/psi/KtCodeFragmentTest.kt
index a81c217..1c25f77 100644
--- a/compiler/psi/psi-impl/tests/org/jetbrains/kotlin/psi/KtCodeFragmentTest.kt
+++ b/compiler/psi/psi-impl/tests/org/jetbrains/kotlin/psi/KtCodeFragmentTest.kt
@@ -12,6 +12,8 @@
 import org.jetbrains.kotlin.analysis.test.framework.test.configurators.DummyAnalysisApiTestConfigurator
 import org.junit.jupiter.api.Test
 import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
 
 class KtCodeFragmentTest : AbstractAnalysisApiBasedTest() {
     override val configurator: AnalysisApiTestConfigurator get() = DummyAnalysisApiTestConfigurator
@@ -74,6 +76,37 @@
     }
 
     @Test
+    fun testFactoryCreatesCodeFragmentsWithDisabledEventSystem() = runCodeFragmentTest { project ->
+        val psiFactory = KtPsiFactory(project, markGenerated = true, eventSystemEnabled = false)
+
+        assertFalse(psiFactory.createTypeCodeFragment("String", context = null).isPhysical)
+        assertFalse(psiFactory.createExpressionCodeFragment("foo()", context = null).isPhysical)
+        assertFalse(psiFactory.createBlockCodeFragment("val a = 5", context = null).isPhysical)
+    }
+
+    @Test
+    fun testFactoryCreatesCodeFragmentsWithEnabledEventSystem() = runCodeFragmentTest { project ->
+        val psiFactory = KtPsiFactory(project, markGenerated = true, eventSystemEnabled = true)
+
+        assertTrue(psiFactory.createTypeCodeFragment("String", context = null).isPhysical)
+        assertTrue(psiFactory.createExpressionCodeFragment("foo()", context = null).isPhysical)
+        assertTrue(psiFactory.createBlockCodeFragment("val a = 5", context = null).isPhysical)
+    }
+
+    @Test
+    fun testAddImportsToBlockCodeFragmentWithDisabledEventSystem() = runCodeFragmentTest { project ->
+        val context = KtPsiFactory(project).createExpression("context")
+        val codeFragment = KtPsiFactory(project, markGenerated = true, eventSystemEnabled = false)
+            .createBlockCodeFragment("val a = 5", context)
+
+        assertFalse(codeFragment.isPhysical)
+
+        codeFragment.addImportsFromString("foo.bar")
+
+        assertEquals(listOf("import foo.bar"), codeFragment.importDirectives.map { it.text })
+    }
+
+    @Test
     fun testClone() = runCodeFragmentTest { project ->
         val context = KtPsiFactory(project).createNameIdentifier("context")
         val codeFragment = KtExpressionCodeFragment(project, "fragment.kt", "foo()", "import lib.foo", context)