coroutine and direnv fixes

This commit is contained in:
FalsePattern 2024-11-04 02:52:33 +01:00
parent 3b619922b5
commit 8ca3ffc11a
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
4 changed files with 87 additions and 69 deletions

View file

@ -64,8 +64,12 @@ object DirenvCmd {
return emptyEnv return emptyEnv
} }
} }
if (runOutput.output.isBlank()) {
return emptyEnv
} else {
return Env(Json.decodeFromString<Map<String, String>>(runOutput.output)) return Env(Json.decodeFromString<Map<String, String>>(runOutput.output))
} }
}
private suspend fun run(project: Project, workDir: Path, vararg args: String): DirenvOutput { private suspend fun run(project: Project, workDir: Path, vararg args: String): DirenvOutput {
val cli = GeneralCommandLine("direnv", *args).withWorkingDirectory(workDir) val cli = GeneralCommandLine("direnv", *args).withWorkingDirectory(workDir)

View file

@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.project.newproject
import com.falsepattern.zigbrains.Icons import com.falsepattern.zigbrains.Icons
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.facet.ui.ValidationResult import com.intellij.facet.ui.ValidationResult
import com.intellij.ide.util.projectWizard.AbstractNewProjectStep import com.intellij.ide.util.projectWizard.AbstractNewProjectStep
import com.intellij.ide.util.projectWizard.CustomStepProjectGenerator import com.intellij.ide.util.projectWizard.CustomStepProjectGenerator
@ -33,7 +34,8 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.wm.impl.welcomeScreen.AbstractActionWithPanel import com.intellij.openapi.wm.impl.welcomeScreen.AbstractActionWithPanel
import com.intellij.platform.DirectoryProjectGenerator import com.intellij.platform.DirectoryProjectGenerator
import com.intellij.platform.ProjectGeneratorPeer import com.intellij.platform.ProjectGeneratorPeer
import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.withModalProgress
import kotlinx.coroutines.launch
import javax.swing.Icon import javax.swing.Icon
class ZigDirectoryProjectGenerator: DirectoryProjectGenerator<ZigProjectConfigurationData>, CustomStepProjectGenerator<ZigProjectConfigurationData> { class ZigDirectoryProjectGenerator: DirectoryProjectGenerator<ZigProjectConfigurationData>, CustomStepProjectGenerator<ZigProjectConfigurationData> {
@ -54,10 +56,12 @@ class ZigDirectoryProjectGenerator: DirectoryProjectGenerator<ZigProjectConfigur
} }
override fun generateProject(project: Project, baseDir: VirtualFile, settings: ZigProjectConfigurationData, module: Module) { override fun generateProject(project: Project, baseDir: VirtualFile, settings: ZigProjectConfigurationData, module: Module) {
runModalOrBlocking({ ModalTaskOwner.project(project)}, {"ZigDirectoryProjectGenerator.generateProject"}) { project.zigCoroutineScope.launch {
withModalProgress(project, "Generating Project") {
settings.generateProject(this, project, baseDir, false) settings.generateProject(this, project, baseDir, false)
} }
} }
}
override fun createStep( override fun createStep(
projectGenerator: DirectoryProjectGenerator<ZigProjectConfigurationData>?, projectGenerator: DirectoryProjectGenerator<ZigProjectConfigurationData>?,

View file

@ -29,15 +29,23 @@ import com.falsepattern.zigbrains.project.settings.zigProjectSettings
import com.falsepattern.zigbrains.project.template.ZigInitTemplate import com.falsepattern.zigbrains.project.template.ZigInitTemplate
import com.falsepattern.zigbrains.project.template.ZigProjectTemplate import com.falsepattern.zigbrains.project.template.ZigProjectTemplate
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.notification.Notification import com.intellij.notification.Notification
import com.intellij.notification.NotificationType import com.intellij.notification.NotificationType
import com.intellij.openapi.GitRepositoryInitializer import com.intellij.openapi.GitRepositoryInitializer
import com.intellij.openapi.application.writeAction
import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.toNioPathOrNull import com.intellij.openapi.vfs.toNioPathOrNull
import com.intellij.platform.util.progress.reportProgress
import com.intellij.util.ResourceUtil import com.intellij.util.ResourceUtil
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.concurrency.annotations.RequiresWriteLock
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@JvmRecord @JvmRecord
@ -47,14 +55,15 @@ data class ZigProjectConfigurationData(
val zlsConf: ZLSSettings, val zlsConf: ZLSSettings,
val selectedTemplate: ZigProjectTemplate val selectedTemplate: ZigProjectTemplate
) { ) {
@RequiresBackgroundThread
suspend fun generateProject(requestor: Any, project: Project, baseDir: VirtualFile, forceGitignore: Boolean): Boolean { suspend fun generateProject(requestor: Any, project: Project, baseDir: VirtualFile, forceGitignore: Boolean): Boolean {
withEDTContext { return reportProgress { reporter ->
project.zigProjectSettings.loadState(projConf) project.zigProjectSettings.loadState(projConf)
project.zlsSettings.loadState(zlsConf) project.zlsSettings.loadState(zlsConf)
}
val template = selectedTemplate val template = selectedTemplate
if (!reporter.indeterminateStep("Initializing project") {
if (template is ZigInitTemplate) { if (template is ZigInitTemplate) {
val toolchain = projConf.toolchain ?: run { val toolchain = projConf.toolchain ?: run {
Notification( Notification(
@ -62,7 +71,7 @@ data class ZigProjectConfigurationData(
"Tried to generate project with zig init, but zig toolchain is invalid", "Tried to generate project with zig init, but zig toolchain is invalid",
NotificationType.ERROR NotificationType.ERROR
).notify(project) ).notify(project)
return false return@indeterminateStep false
} }
val zig = toolchain.zig val zig = toolchain.zig
val workDir = baseDir.toNioPathOrNull() ?: run { val workDir = baseDir.toNioPathOrNull() ?: run {
@ -71,7 +80,7 @@ data class ZigProjectConfigurationData(
"Tried to generate project with zig init, but base directory is invalid", "Tried to generate project with zig init, but base directory is invalid",
NotificationType.ERROR NotificationType.ERROR
).notify(project) ).notify(project)
return false return@indeterminateStep false
} }
val result = zig.callWithArgs(workDir, "init") val result = zig.callWithArgs(workDir, "init")
if (result.exitCode != 0) { if (result.exitCode != 0) {
@ -81,17 +90,17 @@ data class ZigProjectConfigurationData(
NotificationType.ERROR NotificationType.ERROR
) )
System.err.println(result.stderr) System.err.println(result.stderr)
return false return@indeterminateStep false
} }
return@indeterminateStep true
} else { } else {
writeAction {
val projectName = project.name val projectName = project.name
for (fileTemplate in template.fileTemplates()) { for (fileTemplate in template.fileTemplates()) {
val (fileName, parentDir) = fileTemplate.key.let { val (fileName, parentDir) = fileTemplate.key.let {
if (it.contains("/")) { if (it.contains("/")) {
val slashIndex = it.indexOf("/") val slashIndex = it.indexOf("/")
val parentDir = withEDTContext { val parentDir = baseDir.createChildDirectory(requestor, it.substring(0, slashIndex))
baseDir.createChildDirectory(requestor, it.substring(0, slashIndex))
}
Pair(it.substring(slashIndex + 1), parentDir) Pair(it.substring(slashIndex + 1), parentDir)
} else { } else {
Pair(it, baseDir) Pair(it, baseDir)
@ -101,34 +110,35 @@ data class ZigProjectConfigurationData(
val resourceData = getResourceString("project-gen/$templateDir/$fileName.template") val resourceData = getResourceString("project-gen/$templateDir/$fileName.template")
?.replace("@@PROJECT_NAME@@", projectName) ?.replace("@@PROJECT_NAME@@", projectName)
?: continue ?: continue
withEDTContext {
val targetFile = parentDir.createChildData(requestor, fileName) val targetFile = parentDir.createChildData(requestor, fileName)
VfsUtil.saveText(targetFile, resourceData) VfsUtil.saveText(targetFile, resourceData)
} }
} }
return@indeterminateStep true
} }
}) return@reportProgress false
if (git) { if (git) {
withContext(Dispatchers.IO) { project.zigCoroutineScope.launch {
GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir) GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir)
createGitIgnoreFile(project, baseDir, requestor)
} }
} else if (forceGitignore) {
createGitIgnoreFile(project, baseDir, requestor)
} }
if (git || forceGitignore) { return@reportProgress true
createGitIgnoreFile(baseDir, requestor)
} }
return true
} }
} }
private suspend fun createGitIgnoreFile(projectDir: VirtualFile, requestor: Any) { private suspend fun createGitIgnoreFile(project: Project, projectDir: VirtualFile, requestor: Any) {
if (projectDir.findChild(".gitignore") != null) { if (projectDir.findChild(".gitignore") != null) {
return return
} }
withContext(Dispatchers.IO) { writeAction {
ZigProjectConfigurationData::class.java.getResourceAsStream("/fileTemplates/internal/gitignore")?.use { ZigProjectConfigurationData::class.java.getResourceAsStream("/fileTemplates/internal/gitignore")?.use {
val file = projectDir.createChildData(requestor, ".gitignore") val file = projectDir.createChildData(requestor, ".gitignore")
file.setCharset(Charsets.UTF_8) file.setCharset(Charsets.UTF_8)

View file

@ -58,6 +58,6 @@ suspend inline fun <T> runInterruptibleEDT(state: ModalityState = ModalityState.
return runInterruptible(Dispatchers.EDT + state.asContextElement(), block = targetAction) return runInterruptible(Dispatchers.EDT + state.asContextElement(), block = targetAction)
} }
fun CoroutineScope.launchWithEDT(state: ModalityState = ModalityState.defaultModalityState(), block: suspend CoroutineScope.() -> Unit) { fun CoroutineScope.launchWithEDT(state: ModalityState = ModalityState.defaultModalityState(), block: suspend CoroutineScope.() -> Unit): Job {
launch(Dispatchers.EDT + state.asContextElement(), block = block) return launch(Dispatchers.EDT + state.asContextElement(), block = block)
} }