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,7 +64,11 @@ object DirenvCmd {
return emptyEnv return emptyEnv
} }
} }
return Env(Json.decodeFromString<Map<String, String>>(runOutput.output)) if (runOutput.output.isBlank()) {
return emptyEnv
} else {
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 {

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,8 +56,10 @@ 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 {
settings.generateProject(this, project, baseDir, false) withModalProgress(project, "Generating Project") {
settings.generateProject(this, project, baseDir, false)
}
} }
} }

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,88 +55,90 @@ 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 (template is ZigInitTemplate) { if (!reporter.indeterminateStep("Initializing project") {
val toolchain = projConf.toolchain ?: run { if (template is ZigInitTemplate) {
Notification( val toolchain = projConf.toolchain ?: run {
"zigbrains", Notification(
"Tried to generate project with zig init, but zig toolchain is invalid", "zigbrains",
NotificationType.ERROR "Tried to generate project with zig init, but zig toolchain is invalid",
).notify(project) NotificationType.ERROR
return false ).notify(project)
} return@indeterminateStep false
val zig = toolchain.zig
val workDir = baseDir.toNioPathOrNull() ?: run {
Notification(
"zigbrains",
"Tried to generate project with zig init, but base directory is invalid",
NotificationType.ERROR
).notify(project)
return false
}
val result = zig.callWithArgs(workDir, "init")
if (result.exitCode != 0) {
Notification(
"zigbrains",
"\"zig init\" failed with exit code ${result.exitCode}! Check the IDE log files!",
NotificationType.ERROR
)
System.err.println(result.stderr)
return false
}
} else {
val projectName = project.name
for (fileTemplate in template.fileTemplates()) {
val (fileName, parentDir) = fileTemplate.key.let {
if (it.contains("/")) {
val slashIndex = it.indexOf("/")
val parentDir = withEDTContext {
baseDir.createChildDirectory(requestor, it.substring(0, slashIndex))
}
Pair(it.substring(slashIndex + 1), parentDir)
} else {
Pair(it, baseDir)
} }
val zig = toolchain.zig
val workDir = baseDir.toNioPathOrNull() ?: run {
Notification(
"zigbrains",
"Tried to generate project with zig init, but base directory is invalid",
NotificationType.ERROR
).notify(project)
return@indeterminateStep false
}
val result = zig.callWithArgs(workDir, "init")
if (result.exitCode != 0) {
Notification(
"zigbrains",
"\"zig init\" failed with exit code ${result.exitCode}! Check the IDE log files!",
NotificationType.ERROR
)
System.err.println(result.stderr)
return@indeterminateStep false
}
return@indeterminateStep true
} else {
writeAction {
val projectName = project.name
for (fileTemplate in template.fileTemplates()) {
val (fileName, parentDir) = fileTemplate.key.let {
if (it.contains("/")) {
val slashIndex = it.indexOf("/")
val parentDir = baseDir.createChildDirectory(requestor, it.substring(0, slashIndex))
Pair(it.substring(slashIndex + 1), parentDir)
} else {
Pair(it, baseDir)
}
}
val templateDir = fileTemplate.value
val resourceData = getResourceString("project-gen/$templateDir/$fileName.template")
?.replace("@@PROJECT_NAME@@", projectName)
?: continue
val targetFile = parentDir.createChildData(requestor, fileName)
VfsUtil.saveText(targetFile, resourceData)
}
}
return@indeterminateStep true
} }
val templateDir = fileTemplate.value }) return@reportProgress false
val resourceData = getResourceString("project-gen/$templateDir/$fileName.template")
?.replace("@@PROJECT_NAME@@", projectName) if (git) {
?: continue project.zigCoroutineScope.launch {
withEDTContext { GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir)
val targetFile = parentDir.createChildData(requestor, fileName) createGitIgnoreFile(project, baseDir, requestor)
VfsUtil.saveText(targetFile, resourceData)
} }
} else if (forceGitignore) {
createGitIgnoreFile(project, baseDir, requestor)
} }
}
if (git) { return@reportProgress true
withContext(Dispatchers.IO) {
GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir)
}
} }
if (git || forceGitignore) {
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)
} }