[kotlin] K2: introduce ScriptAfterRunCallbackProvider and improve main.kts script execution

#KTIJ-34672 Fixed

(cherry picked from commit 7d8f174a68035601c32119812d9d2dc82ec7b657)

GitOrigin-RevId: f7d41f1572389b272e3759b73a7e2bf2ab4a6912
This commit is contained in:
Vlad Koshkin
2025-06-25 01:06:41 +02:00
committed by intellij-monorepo-bot
parent 6923750881
commit 8ef830aae9
8 changed files with 87 additions and 9 deletions

View File

@@ -69,6 +69,8 @@
</extensions>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<scriptAfterRunCallbackProvider implementation="org.jetbrains.kotlin.idea.core.script.k2.MainKtsAfterRunCallbackProvider"/>
<ktModuleFactory implementation="org.jetbrains.kotlin.idea.core.script.k2.modules.ScriptingKaModuleFactory"/>
<scriptDefinitionsSource
id="StandardScriptDefinitionContributor"

View File

@@ -0,0 +1,45 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.core.script.k2
import com.intellij.execution.runners.ProgramRunner
import com.intellij.openapi.actionSystem.ActionPlaces
import com.intellij.openapi.actionSystem.ActionUiKind
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.ex.ActionUtil
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
import com.intellij.openapi.application.edtWriteAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.PsiManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.kotlin.idea.ScriptAfterRunCallbackProvider
import org.jetbrains.kotlin.psi.KtFile
import kotlin.io.path.Path
class MainKtsAfterRunCallbackProvider(val project: Project, val scope: CoroutineScope) : ScriptAfterRunCallbackProvider {
override fun provide(scriptPath: String): ProgramRunner.Callback? {
val script = VfsUtil.findFile(Path( scriptPath), true) ?: return null
if (!script.name.endsWith(".main.kts")) return null
val ktFile = PsiManager.getInstance(project).findFile(script) as? KtFile ?: return null
val action = ActionUtil.getAction("LoadMainKtsConfiguration") ?: return null
return ProgramRunner.Callback { _ ->
val context = SimpleDataContext.builder()
.add(CommonDataKeys.PSI_FILE, ktFile)
.add(CommonDataKeys.PROJECT, project)
.build()
val event = AnActionEvent.createEvent(
action, context, null, ActionPlaces.RUN_CONFIGURATIONS_COMBOBOX, ActionUiKind.NONE, null
)
scope.launch {
edtWriteAction {
ActionUtil.performAction(action, event)
}
}
}
}
}

View File

@@ -21,8 +21,9 @@ internal class ReloadMainKtsScriptDependenciesAction : AnAction() {
override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
val editor = e.getData(CommonDataKeys.EDITOR) ?: return
val ktFile = getKotlinScriptFile(editor) ?: return
val ktFile = e.getData(CommonDataKeys.EDITOR)?.let {
getKotlinScriptFile(it)
} ?: e.getData(CommonDataKeys.PSI_FILE) as? KtFile ?: return
MainKtsScriptConfigurationProvider.getInstance(project).removeConfiguration(ktFile.alwaysVirtualFile)
DefaultScriptResolutionStrategy.getInstance(project).execute(ktFile)

View File

@@ -0,0 +1,20 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea
import com.intellij.execution.runners.ProgramRunner
import com.intellij.openapi.extensions.ProjectExtensionPointName
import com.intellij.openapi.project.Project
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
interface ScriptAfterRunCallbackProvider {
fun provide(scriptPath: String): ProgramRunner.Callback?
companion object {
val EP_NAME: ProjectExtensionPointName<ScriptAfterRunCallbackProvider> =
ProjectExtensionPointName<ScriptAfterRunCallbackProvider>("org.jetbrains.kotlin.scriptAfterRunCallbackProvider")
fun getCallback(project: Project, scriptPath: String): ProgramRunner.Callback? =
EP_NAME.getExtensions(project).firstNotNullOfOrNull { it.provide(scriptPath) }
}
}

View File

@@ -23,6 +23,12 @@
interface="org.jetbrains.kotlin.idea.script.ScriptDiagnosticFixProvider"
dynamic="true"/>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.scriptAfterRunCallbackProvider"
interface="org.jetbrains.kotlin.idea.ScriptAfterRunCallbackProvider"
area="IDEA_PROJECT"
dynamic="true"/>
<extensionPoint
qualifiedName="org.jetbrains.kotlin.scripting.definitions.scriptDefinitionProvider"
interface="org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider"

View File

@@ -10,7 +10,7 @@ script.choose.file=Choose Script File
could.not.find.script.file.0=Could not find script file: {0}
file.was.not.specified=File was not specified
run.kotlin.script=Run Kotlin script
name.kotlin.script=Kotlin script (Beta)
name.kotlin.script=Kotlin script
language.name.kotlin=Kotlin

View File

@@ -27,6 +27,7 @@ import com.intellij.util.PathUtil
import org.jdom.Element
import org.jetbrains.annotations.Nls
import org.jetbrains.kotlin.idea.KotlinRunConfigurationsBundle
import org.jetbrains.kotlin.idea.ScriptAfterRunCallbackProvider
import org.jetbrains.kotlin.idea.base.plugin.artifacts.KotlinArtifacts
import org.jetbrains.kotlin.idea.base.projectStructure.RootKindFilter
import org.jetbrains.kotlin.idea.base.projectStructure.matches
@@ -60,8 +61,12 @@ class KotlinStandaloneScriptRunConfiguration(
val systemIndependentPath: String?
get() = filePath?.let { FileUtil.toSystemIndependentName(it) }
override fun getState(executor: Executor, executionEnvironment: ExecutionEnvironment): RunProfileState =
ScriptCommandLineState(executionEnvironment, this)
override fun getState(executor: Executor, executionEnvironment: ExecutionEnvironment): RunProfileState {
systemIndependentPath?.let {
executionEnvironment.callback = ScriptAfterRunCallbackProvider.getCallback(project, it)
}
return ScriptCommandLineState(executionEnvironment, this)
}
override fun suggestedName() = filePath?.substringAfterLast('/')

View File

@@ -21,11 +21,10 @@ class KotlinStandaloneScriptRunConfigurationType : SimpleConfigurationType(
"KotlinStandaloneScriptRunConfigurationType",
KotlinRunConfigurationsBundle.message("name.kotlin.script"),
KotlinRunConfigurationsBundle.message("run.kotlin.script"),
NotNullLazyValue.createValue { KotlinIcons.SMALL_LOGO }
NotNullLazyValue.createValue { KotlinIcons.SCRIPT }
) {
override fun createTemplateConfiguration(project: Project): RunConfiguration {
return KotlinStandaloneScriptRunConfiguration(project, this, "")
}
override fun createTemplateConfiguration(project: Project): RunConfiguration =
KotlinStandaloneScriptRunConfiguration(project, this, "")
override fun getOptionsClass() = JvmMainMethodRunConfigurationOptions::class.java