diff --git a/.idea/modules.xml b/.idea/modules.xml
index 5948daff878a..134d91c10557 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -1193,6 +1193,7 @@
+
diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt
index 81461169b90c..09670385dc83 100644
--- a/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt
+++ b/platform/build-scripts/src/org/jetbrains/intellij/build/kotlin/KotlinPluginBuilder.kt
@@ -195,7 +195,8 @@ object KotlinPluginBuilder {
"kotlin.refactorings.rename.k2",
"kotlin.performanceExtendedPlugin",
"kotlin.bundled-compiler-plugins-support",
- "kotlin.jsr223"
+ "kotlin.jsr223",
+ "kotlin.k2.internal",
)
private val KOTLIN_SCRIPTING_LIBRARIES = java.util.List.of(
diff --git a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml
index 04bc5ad25631..ada9aa63d6e9 100644
--- a/plugins/kotlin/intellij.kotlin.plugin.community.main.iml
+++ b/plugins/kotlin/intellij.kotlin.plugin.community.main.iml
@@ -212,5 +212,6 @@
+
\ No newline at end of file
diff --git a/plugins/kotlin/internal/kotlin.k2.internal.iml b/plugins/kotlin/internal/kotlin.k2.internal.iml
new file mode 100644
index 000000000000..ab12f45984b9
--- /dev/null
+++ b/plugins/kotlin/internal/kotlin.k2.internal.iml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/kotlin/internal/resources/kotlin.k2.internal.xml b/plugins/kotlin/internal/resources/kotlin.k2.internal.xml
new file mode 100644
index 000000000000..71608e2244a1
--- /dev/null
+++ b/plugins/kotlin/internal/resources/kotlin.k2.internal.xml
@@ -0,0 +1,13 @@
+
+ messages.KotlinInternalBundle
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/kotlin/internal/resources/messages/KotlinInternalBundle.properties b/plugins/kotlin/internal/resources/messages/KotlinInternalBundle.properties
new file mode 100644
index 000000000000..99566913f5df
--- /dev/null
+++ b/plugins/kotlin/internal/resources/messages/KotlinInternalBundle.properties
@@ -0,0 +1,14 @@
+action.InvalidateK2CachesInternalAction.text=Invalidate Kotlin Plugin K2 Mode Caches
+internal.kotlin.plugin.actions.notification.group=Internal Kotlin plugin actions
+notification.content.kotlin.internal.resolution.caches.were.invalidated.title=Kotlin caches are invalidated.
+dialog.title.invalidate.caches=Invalidate Caches
+button.source.library.caches=Source and Library Caches
+button.source.caches=Source Caches
+notification.content.source.caches=Source caches
+notification.content.source.library.caches=Source and library caches
+invalidate.source.caches.tooltip=Invalidates all K2 plugin source and script caches.
\
+ Library caches are kept intact.
\
+ Invoking this action should be equivalent to performing an out-of-block modification in each module simultaneously.
+invalidate.source.library.caches.tooltip=Invalidates all K2 plugin source, script, builtins, and library caches.
\
+ Invoking this action should be equivalent to removing and re-adding all project libraries, \
+ as well as performing an out-of-block modification in each module simultaneously.
\ No newline at end of file
diff --git a/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/InvalidateK2CachesInternalAction.kt b/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/InvalidateK2CachesInternalAction.kt
new file mode 100644
index 000000000000..000d71d59cfa
--- /dev/null
+++ b/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/InvalidateK2CachesInternalAction.kt
@@ -0,0 +1,134 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.internal.actions
+
+import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
+import com.intellij.icons.AllIcons
+import com.intellij.java.library.JavaLibraryModificationTracker
+import com.intellij.notification.Notification
+import com.intellij.notification.NotificationType
+import com.intellij.notification.Notifications
+import com.intellij.openapi.actionSystem.ActionUpdateThread
+import com.intellij.openapi.actionSystem.AnAction
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.ui.DialogWrapper
+import com.intellij.openapi.util.NlsContexts
+import com.intellij.ui.dsl.builder.panel
+import org.jetbrains.kotlin.analysis.api.platform.analysisMessageBus
+import org.jetbrains.kotlin.analysis.api.platform.modification.KotlinModificationTopics
+import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
+import org.jetbrains.kotlin.analysis.low.level.api.fir.projectStructure.LLFirBuiltinsSessionFactory
+import org.jetbrains.kotlin.idea.KotlinIcons
+import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginModeProvider
+import org.jetbrains.kotlin.idea.caches.trackers.KotlinIDEModificationTrackerService
+import org.jetbrains.kotlin.idea.util.application.isApplicationInternalMode
+import org.jetbrains.kotlin.idea.util.application.runWriteAction
+import javax.swing.JComponent
+
+internal class InvalidateK2CachesInternalAction : AnAction() {
+ override fun getActionUpdateThread() = ActionUpdateThread.BGT
+
+ override fun actionPerformed(e: AnActionEvent) {
+ val project = e.project ?: return
+ val invalidationMode = InvalidateCachesDialog.show() ?: return
+ invalidateCaches(project, invalidationMode)
+ DaemonCodeAnalyzer.getInstance(project).restart()
+
+ showNotificationAboutInvalidatedCaches(project, invalidationMode)
+ }
+
+ @OptIn(LLFirInternals::class)
+ @Suppress("TestOnlyProblems")
+ private fun invalidateCaches(project: Project, invalidationMode: InvalidationMode) = runWriteAction {
+ if (invalidationMode.invalidateSources) {
+ KotlinIDEModificationTrackerService.invalidateCaches(project)
+ project.analysisMessageBus.apply {
+ syncPublisher(KotlinModificationTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).onModification()
+ syncPublisher(KotlinModificationTopics.GLOBAL_SCRIPT_MODULE_STATE_MODIFICATION).onModification()
+ }
+ }
+ if (invalidationMode.invalidateLibraries) {
+ LLFirBuiltinsSessionFactory.getInstance(project).clearForTheNextTest()
+ JavaLibraryModificationTracker.incModificationCount(project)
+ project.analysisMessageBus.apply {
+ syncPublisher(KotlinModificationTopics.GLOBAL_MODULE_STATE_MODIFICATION).onModification()
+ }
+ }
+ }
+
+ private fun showNotificationAboutInvalidatedCaches(project: Project, invalidationMode: InvalidationMode) {
+ val content: @NlsContexts.NotificationContent String = when (invalidationMode) {
+ InvalidationMode.OnlySourceCaches -> KotlinInternalBundle.message("notification.content.source.caches")
+ InvalidationMode.LibraryAndSourceCaches -> KotlinInternalBundle.message("notification.content.source.library.caches")
+ }
+ val notification = Notification(
+ "Internal Kotlin Plugin Actions",
+ KotlinInternalBundle.message("notification.content.kotlin.internal.resolution.caches.were.invalidated.title"),
+ content,
+ NotificationType.INFORMATION
+ ).apply {
+ icon = KotlinIcons.FIR
+ }
+
+ Notifications.Bus.notify(notification, project)
+ }
+
+ override fun update(e: AnActionEvent) {
+ e.presentation.isEnabledAndVisible =
+ e.project != null
+ && isApplicationInternalMode()
+ && KotlinPluginModeProvider.isK2Mode()
+ }
+}
+
+private class InvalidateCachesDialog : DialogWrapper(true) {
+ private var result: InvalidationMode? = null
+
+ init {
+ init()
+ title = KotlinInternalBundle.message("dialog.title.invalidate.caches")
+ }
+
+ override fun isResizable(): Boolean {
+ return false
+ }
+
+ override fun createCenterPanel(): JComponent = panel {
+ row {
+ button(KotlinInternalBundle.message("button.source.caches")) {
+ result = InvalidationMode.OnlySourceCaches
+ close(OK_EXIT_CODE)
+ }.applyToComponent {
+ icon = AllIcons.Actions.ModuleDirectory
+ toolTipText = KotlinInternalBundle.message("invalidate.source.caches.tooltip")
+ }
+ button(KotlinInternalBundle.message("button.source.library.caches")) {
+ result = InvalidationMode.LibraryAndSourceCaches
+ close(OK_EXIT_CODE)
+ }.applyToComponent {
+ icon = AllIcons.Nodes.Library
+ toolTipText = KotlinInternalBundle.message("invalidate.source.library.caches.tooltip")
+ }
+ }
+ }
+
+ override fun createSouthPanel(): JComponent = panel {}
+
+
+ companion object {
+ fun show(): InvalidationMode? {
+ val dialog = InvalidateCachesDialog()
+ if (!dialog.showAndGet()) return null
+ return dialog.result
+ }
+ }
+}
+
+
+private enum class InvalidationMode(
+ val invalidateSources: Boolean,
+ val invalidateLibraries: Boolean,
+) {
+ LibraryAndSourceCaches(invalidateSources = true, invalidateLibraries = true),
+ OnlySourceCaches(invalidateSources = true, invalidateLibraries = false),
+}
diff --git a/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/KotlinInternalBundle.kt b/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/KotlinInternalBundle.kt
new file mode 100644
index 000000000000..9f67927e2891
--- /dev/null
+++ b/plugins/kotlin/internal/src/org/jetbrains/kotlin/idea/internal/actions/KotlinInternalBundle.kt
@@ -0,0 +1,16 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package org.jetbrains.kotlin.idea.internal.actions
+
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.NonNls
+import org.jetbrains.annotations.PropertyKey
+import org.jetbrains.kotlin.util.AbstractKotlinBundle
+
+@NonNls
+private const val BUNDLE = "messages.KotlinInternalBundle"
+
+internal object KotlinInternalBundle : AbstractKotlinBundle(BUNDLE) {
+ @Nls
+ @JvmStatic
+ fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
+}
\ No newline at end of file
diff --git a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml
index ebe878e318e7..29f2100c010e 100644
--- a/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml
+++ b/plugins/kotlin/plugin/k2/kotlin.plugin.k2.iml
@@ -123,5 +123,6 @@
+
\ No newline at end of file
diff --git a/plugins/kotlin/plugin/k2/resources/kotlin.plugin.k2.xml b/plugins/kotlin/plugin/k2/resources/kotlin.plugin.k2.xml
index 992106439775..3f9b9b6282ed 100644
--- a/plugins/kotlin/plugin/k2/resources/kotlin.plugin.k2.xml
+++ b/plugins/kotlin/plugin/k2/resources/kotlin.plugin.k2.xml
@@ -272,6 +272,7 @@
+
diff --git a/plugins/kotlin/plugin/plugin-content.yaml b/plugins/kotlin/plugin/plugin-content.yaml
index 815f7319e035..0496c15865f5 100644
--- a/plugins/kotlin/plugin/plugin-content.yaml
+++ b/plugins/kotlin/plugin/plugin-content.yaml
@@ -256,6 +256,7 @@
- name: kotlin.performanceExtendedPlugin
- name: kotlin.bundled-compiler-plugins-support
- name: kotlin.jsr223
+ - name: kotlin.k2.internal
- name: kotlin-ultimate.common-native
- name: kotlin-ultimate.javascript.debugger
- name: kotlin-ultimate.javascript.nodeJs